Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
181 changes: 98 additions & 83 deletions package-lock.json

Large diffs are not rendered by default.

142 changes: 142 additions & 0 deletions recipes/axios-to-whatwg-fetch/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
# Axios to WHATWG Fetch Codemod

## Description

This codemod transforms code using Axios to leverage the WHATWG Fetch API, which is now natively available in Node.js. By replacing Axios with Fetch, you can reduce dependencies, mitigate risks, and improve performance.

## Supported Transformations

The codemod supports the following Axios methods and converts them to their Fetch equivalents:

- `axios.request(config)`
- `axios.get(url[, config])`
- `axios.delete(url[, config])`
- `axios.head(url[, config])`
- `axios.options(url[, config])`
- `axios.post(url[, data[, config]])`
- `axios.put(url[, data[, config]])`
- `axios.patch(url[, data[, config]])`
- `axios.postForm(url[, data[, config]])`
- `axios.putForm(url[, data[, config]])`
- `axios.patchForm(url[, data[, config]])`
- `axios.request(config)`

### Examples

#### GET Request

```diff
const base = 'https://dummyjson.com/todos';

- const all = await axios.get(base);
+ const all = await fetch(base).then(async (res) => Object.assign(res, { data: await res.json() })).catch(() => null);
console.log('\nGET /todos ->', all.status);
console.log(`Preview: ${all.data.todos.length} todos`);
```

#### POST Request

```diff
const base = 'https://dummyjson.com/todos';

- const created = await axios.post(
- `${base}/add`, {
- todo: 'Use DummyJSON in the project',
- completed: false,
- userId: 5,
- }, {
- headers: { 'Content-Type': 'application/json' }
- }
- );
+ const created = await fetch(`${base}/add`, {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({
+ todo: 'Use DummyJSON in the project',
+ completed: false,
+ userId: 5,
+ }),
+ }).then(async (res) => Object.assign(res, { data: await res.json() }));
console.log('\nPOST /todos/add ->', created.status);
console.log('Preview:', created.data?.id ? `created id ${created.data.id}` : JSON.stringify(created.data).slice(0,200));
```

#### POST Form Request

```diff
const formEndpoint = '/submit';

- const created = await axios.postForm(formEndpoint, {
- title: 'Form Demo',
- completed: false,
- });
+ const created = await fetch(formEndpoint, {
+ method: 'POST',
+ body: new URLSearchParams({
+ title: 'Form Demo',
+ completed: false,
+ }),
+ }).then(async (res) => Object.assign(res, { data: await res.json() }));
console.log('Preview:', created.data);
```

#### PUT Request

```diff
const base = 'https://dummyjson.com/todos';

- const updatedPut = await axios.put(
- `${base}/1`,
- { completed: false },
- { headers: { 'Content-Type': 'application/json' } }
- );
+ const updatedPut = await fetch(`${base}/1`, {
+ method: 'PUT',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({ completed: false }),
+ }).then(async (res) => Object.assign(res, { data: await res.json() }));
console.log('\nPUT /todos/1 ->', updatedPut.status);
console.log('Preview:', updatedPut.data?.completed !== undefined ? `completed=${updatedPut.data.completed}` : JSON.stringify(updatedPut.data).slice(0,200));
```

#### DELETE Request

```diff
const base = 'https://dummyjson.com/todos';

- const deleted = await axios.delete(`${base}/1`);
+ const deleted = await fetch(`${base}/1`, { method: 'DELETE' })
+ .then(async (res) => Object.assign(res, { data: await res.json() }));
console.log('\nDELETE /todos/1 ->', deleted.status);
console.log('Preview:', deleted.data ? JSON.stringify(deleted.data).slice(0,200) : typeof deleted.data);
```

#### `request` axios Method

```diff
const base = 'https://dummyjson.com/todos';

- const customRequest = await axios.request({
- url: `${base}/1`,
- method: 'PATCH',
- headers: { 'Content-Type': 'application/json' },
- data: { completed: true },
- });
+ const customRequest = await fetch(`${base}/1`, {
+ method: 'PATCH',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({ completed: true }),
+ }).then(async (res) => Object.assign(res, { data: await res.json() }));
console.log('\nPATCH /todos/1 ->', customRequest.status);
console.log('Preview:', customRequest.data?.completed !== undefined ? `completed=${customRequest.data.completed}` : JSON.stringify(customRequest.data).slice(0,200));
```

## Unsupported APIs

The codemod does not yet cover Axios features outside of direct request helpers, such as interceptors, cancel tokens, or instance configuration from `axios.create()`.

## References

- [Fetch Spec](https://fetch.spec.whatwg.org)
- [Axios Documentation](https://axios-http.com)
- [Node.js Documentation](https://nodejs.org/docs/latest/api/globals.html#fetch)
21 changes: 21 additions & 0 deletions recipes/axios-to-whatwg-fetch/codemod.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
schema_version: "1.0"
name: "@nodejs/util-print-to-console-log"
version: 1.0.0
description: Replace `axios` with `fetch`
author: Bruno Rodrigues
license: MIT
workflow: workflow.yaml
category: migration

targets:
languages:
- javascript
- typescript

keywords:
- transformation
- migration

registry:
access: public
visibility: public
25 changes: 25 additions & 0 deletions recipes/axios-to-whatwg-fetch/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"name": "@nodejs/axios-to-whatwg-fetch",
"version": "1.0.0",
"description": "Replace `axios` with `fetch`",
"type": "module",
"scripts": {
"test": "npx codemod jssg test -l tsx ./src/workflow.ts ./"
},
"repository": {
"type": "git",
"url": "git+https://github.com/nodejs/userland-migrations.git",
"directory": "recipes/axios-to-whatwg-fetch",
"bugs": "https://github.com/nodejs/userland-migrations/issues"
},
"author": "Bruno Rodrigues",
"license": "MIT",
"homepage": "https://github.com/nodejs/userland-migrations/blob/main/recipes/axios-to-whatwg-fetch/README.md",
"devDependencies": {
"@codemod.com/jssg-types": "^1.0.9"
},
"dependencies": {
"@nodejs/codemod-utils": "*",
"dedent": "^1.7.0"
}
}
Loading