Skip to content

Commit

Permalink
Refactored module exports; (#5162)
Browse files Browse the repository at this point in the history
* Refactored build pipeline;
Added module exports tests;
Added missing ESM export for parity with Axios factory;
Added `toFormData`, `formToJSON`, `isAxiosError`, `spread`, `isCancel`, `all` as named export to `index.d.ts`;

* Added ESM entry test;

* Updated README.md `installing` section;

* Added TypeScript importing test;
Added missed `CanceledError` & `AxiosHeaders` to `AxiosStatic` interface;

* Exclude `/test/module/` from tslint;
  • Loading branch information
DigitalBrainJS committed Oct 30, 2022
1 parent 5666ee4 commit 0c3a1e9
Show file tree
Hide file tree
Showing 19 changed files with 481 additions and 40 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Expand Up @@ -7,3 +7,6 @@ typings/
coverage/
test/typescript/axios.js*
sauce_connect.log
test/module/cjs/node_modules/
test/module/cjs/package-lock.json
backup/
1 change: 1 addition & 0 deletions .npmignore
Expand Up @@ -16,3 +16,4 @@ Gruntfile.js
karma.conf.js
webpack.*.js
sauce_connect.log
backup/
50 changes: 39 additions & 11 deletions README.md
Expand Up @@ -35,6 +35,8 @@
- [Features](#features)
- [Browser Support](#browser-support)
- [Installing](#installing)
- [Package manager](#package-manager)
- [CDN](#cdn)
- [Example](#example)
- [Axios API](#axios-api)
- [Request method aliases](#request-method-aliases)
Expand Down Expand Up @@ -93,6 +95,8 @@ Latest ✔ | Latest ✔ | Latest ✔ | Latest ✔ | Latest ✔ | 11 ✔ |

## Installing

### Package manager

Using npm:

```bash
Expand All @@ -117,7 +121,39 @@ Using pnpm:
$ pnpm add axios
```

Using jsDelivr CDN:
Once the package is installed, you can import the library using `import` or `require` approach:

```js
import axios, {isCancel, AxiosError} from 'axios';
```

You can also use the default export, since the named export is just a re-export from the Axios factory:

```js
import axios from 'axios';

console.log(axios.isCancel('something'));
````

If you use `require` for importing, **only default export is available**:

```js
const axios = require('axios');
console.log(axios.isCancel('something'));
```

For cases where something went wrong when trying to import a module into a custom or legacy environment,
you can try importing the module package directly:

```js
const axios = require('axios/dist/browser/axios.cjs'); // browser commonJS bundle (ES2017)
// const axios = require('axios/dist/node/axios.cjs'); // node commonJS bundle (ES2017)
```

### CDN

Using jsDelivr CDN (ES5 UMD browser module):

```html
<script src="https://cdn.jsdelivr.net/npm/axios@1.1.2/dist/axios.min.js"></script>
Expand All @@ -131,19 +167,11 @@ Using unpkg CDN:

## Example

### note: CommonJS usage
In order to gain the TypeScript typings (for intellisense / autocomplete) while using CommonJS imports with `require()` use the following approach:

```js
const axios = require('axios').default;

// axios.<method> will now provide autocomplete and parameter typings
```

Performing a `GET` request

```js
const axios = require('axios').default;
import axios from 'axios';
//const axios = require('axios'); // legacy way
// Make a request for a user with a given ID
axios.get('/user?ID=12345')
Expand Down
26 changes: 20 additions & 6 deletions index.d.ts
Expand Up @@ -463,19 +463,33 @@ export interface GenericHTMLFormElement {
submit(): void;
}

export function toFormData(sourceObj: object, targetFormData?: GenericFormData, options?: FormSerializerOptions): GenericFormData;

export function formToJSON(form: GenericFormData|GenericHTMLFormElement): object;

export function isAxiosError<T = any, D = any>(payload: any): payload is AxiosError<T, D>;

export function spread<T, R>(callback: (...args: T[]) => R): (array: T[]) => R;

export function isCancel(value: any): value is Cancel;

export function all<T>(values: Array<T | Promise<T>>): Promise<T[]>;

export interface AxiosStatic extends AxiosInstance {
create(config?: CreateAxiosDefaults): AxiosInstance;
Cancel: CancelStatic;
CancelToken: CancelTokenStatic;
Axios: typeof Axios;
AxiosError: typeof AxiosError;
readonly VERSION: string;
isCancel(value: any): value is Cancel;
all<T>(values: Array<T | Promise<T>>): Promise<T[]>;
spread<T, R>(callback: (...args: T[]) => R): (array: T[]) => R;
isAxiosError<T = any, D = any>(payload: any): payload is AxiosError<T, D>;
toFormData(sourceObj: object, targetFormData?: GenericFormData, options?: FormSerializerOptions): GenericFormData;
formToJSON(form: GenericFormData|GenericHTMLFormElement): object;
isCancel: typeof isCancel;
all: typeof all;
spread: typeof spread;
isAxiosError: typeof isAxiosError;
toFormData: typeof toFormData;
formToJSON: typeof formToJSON;
CanceledError: typeof CanceledError;
AxiosHeaders: typeof AxiosHeaders;
}

declare const axios: AxiosStatic;
Expand Down
11 changes: 8 additions & 3 deletions index.js
@@ -1,5 +1,6 @@
import axios from './lib/axios.js';

// This module is intended to unwrap Axios default export as named.
// Keep top-level export same with static properties
// so that it can keep same with es module or cjs
const {
Expand All @@ -13,11 +14,13 @@ const {
Cancel,
isAxiosError,
spread,
toFormData
toFormData,
AxiosHeaders,
formToJSON
} = axios;

export default axios;
export {
axios as default,
Axios,
AxiosError,
CanceledError,
Expand All @@ -28,5 +31,7 @@ export {
Cancel,
isAxiosError,
spread,
toFormData
toFormData,
AxiosHeaders,
formToJSON
}
8 changes: 5 additions & 3 deletions lib/axios.js
Expand Up @@ -14,6 +14,7 @@ import toFormData from './helpers/toFormData.js';
import AxiosError from './core/AxiosError.js';
import spread from './helpers/spread.js';
import isAxiosError from './helpers/isAxiosError.js';
import AxiosHeaders from "./core/AxiosHeaders.js";

/**
* Create an instance of Axios
Expand Down Expand Up @@ -69,8 +70,9 @@ axios.spread = spread;
// Expose isAxiosError
axios.isAxiosError = isAxiosError;

axios.formToJSON = thing => {
return formDataToJSON(utils.isHTMLForm(thing) ? new FormData(thing) : thing);
};
axios.AxiosHeaders = AxiosHeaders;

axios.formToJSON = thing => formDataToJSON(utils.isHTMLForm(thing) ? new FormData(thing) : thing);

// this module should only have a default export
export default axios
10 changes: 6 additions & 4 deletions package.json
Expand Up @@ -6,22 +6,24 @@
"exports": {
".": {
"browser": {
"require": "./dist/node/axios.cjs",
"require": "./dist/browser/axios.cjs",
"default": "./index.js"
},
"default": {
"require": "./dist/node/axios.cjs",
"default": "./index.js"
}
}
},
"./package.json": "./package.json"
},
"type": "module",
"types": "index.d.ts",
"scripts": {
"test": "npm run test:eslint && npm run test:mocha && npm run test:karma && npm run test:dtslint",
"test": "npm run test:eslint && npm run test:mocha && npm run test:karma && npm run test:exports && npm run test:dtslint",
"test:eslint": "node bin/ssl_hotfix.js eslint lib/**/*.js",
"test:dtslint": "node bin/ssl_hotfix.js dtslint",
"test:mocha": "node bin/ssl_hotfix.js mocha test/unit/**/*.js --timeout 30000 --exit",
"test:exports": "node bin/ssl_hotfix.js mocha test/module/test.js --timeout 30000 --exit",
"test:karma": "node bin/ssl_hotfix.js cross-env LISTEN_ADDR=:: karma start karma.conf.cjs --single-run",
"test:karma:server": "node bin/ssl_hotfix.js cross-env karma start karma.conf.cjs",
"start": "node ./sandbox/server.js",
Expand Down Expand Up @@ -131,4 +133,4 @@
"Ben Carp (https://github.com/carpben)",
"Daniel Lopretto (https://github.com/timemachine3030)"
]
}
}
47 changes: 37 additions & 10 deletions rollup.config.js
Expand Up @@ -5,20 +5,28 @@ import json from '@rollup/plugin-json';
import { babel } from '@rollup/plugin-babel';
import autoExternal from 'rollup-plugin-auto-external';
import bundleSize from 'rollup-plugin-bundle-size'
import path from 'path';

const lib = require("./package.json");
const outputFileName = 'axios';
const name = "axios";
const input = './lib/axios.js';
const namedInput = './index.js';
const defaultInput = './lib/axios.js';

const buildConfig = ({es5, browser = true, minifiedVersion = true, ...config}) => {
const {file} = config.output;
const ext = path.extname(file);
const basename = path.basename(file, ext);
const extArr = ext.split('.');
extArr.shift();


const build = ({minified}) => ({
input,
input: namedInput,
...config,
output: {
...config.output,
file: `${config.output.file}.${minified ? "min.js" : "js"}`
file: `${path.dirname(file)}/${basename}.${(minified ? ['min', ...extArr] : extArr).join('.')}`
},
plugins: [
json(),
Expand Down Expand Up @@ -50,29 +58,48 @@ export default async () => {
const banner = `// Axios v${lib.version} Copyright (c) ${year} ${lib.author} and contributors`;

return [
// browser ESM bundle for CDN
...buildConfig({
input: namedInput,
output: {
file: `dist/esm/${outputFileName}.js`,
format: "esm",
preferConst: true,
exports: "named",
banner
}
}),

// Browser UMD bundle for CDN
...buildConfig({
input: defaultInput,
es5: true,
output: {
file: `dist/${outputFileName}`,
file: `dist/${outputFileName}.js`,
name,
format: "umd",
exports: "default",
banner
}
}),

// Browser CJS bundle
...buildConfig({
input: defaultInput,
es5: false,
minifiedVersion: false,
output: {
file: `dist/esm/${outputFileName}`,
format: "esm",
preferConst: true,
exports: "named",
file: `dist/browser/${name}.cjs`,
name,
format: "cjs",
exports: "default",
banner
}
}),
// Node.js commonjs build

// Node.js commonjs bundle
{
input,
input: defaultInput,
output: {
file: `dist/node/${name}.cjs`,
format: "cjs",
Expand Down
11 changes: 11 additions & 0 deletions test/module/cjs/index.js
@@ -0,0 +1,11 @@
const axios = require('axios');
const assert = require('assert');

const {CanceledError, AxiosError, AxiosHeaders} = axios;

assert.strictEqual(typeof axios, 'function');
assert.strictEqual(typeof CanceledError, 'function');
assert.strictEqual(typeof AxiosError, 'function');
assert.strictEqual(typeof AxiosHeaders, 'function');

console.log('CommonJS importing test passed');
15 changes: 15 additions & 0 deletions test/module/cjs/package.json
@@ -0,0 +1,15 @@
{
"name": "cjs-entrypoint-test",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "npm i --no-save --no-package-lock && node index.js"
},
"keywords": [],
"author": "",
"license": "MIT",
"dependencies": {
"axios": "file:../../.."
}
}
13 changes: 13 additions & 0 deletions test/module/esm/index.js
@@ -0,0 +1,13 @@
import assert from 'assert';
import axios, {CanceledError, AxiosError, AxiosHeaders} from 'axios';

assert.strictEqual(typeof axios, 'function');
assert.strictEqual(typeof CanceledError, 'function');
assert.strictEqual(typeof AxiosError, 'function');
assert.strictEqual(typeof AxiosHeaders, 'function');

assert.strictEqual(axios.CanceledError, CanceledError);
assert.strictEqual(axios.AxiosError, AxiosError);
assert.strictEqual(axios.AxiosHeaders, AxiosHeaders);

console.log('ESM importing test passed');
16 changes: 16 additions & 0 deletions test/module/esm/package.json
@@ -0,0 +1,16 @@
{
"name": "esm-entrypoint-test",
"version": "1.0.0",
"description": "",
"main": "index.js",
"type": "module",
"scripts": {
"test": "npm i --no-save --no-package-lock && node index.js"
},
"keywords": [],
"author": "",
"license": "MIT",
"dependencies": {
"axios": "file:../../.."
}
}

0 comments on commit 0c3a1e9

Please sign in to comment.