diff --git a/README.md b/README.md index 019a15cee2..239fbe8c79 100644 --- a/README.md +++ b/README.md @@ -1278,6 +1278,12 @@ try { } ``` +Because axios dual publishes with an ESM default export and a CJS `module.exports`, there are some caveats. +The recommended setting is to use `"moduleResolution": "node16"` (this is implied by `"module": "node16"`). Note that this requires TypeScript 4.7 or greater. +If use ESM, your settings should be fine. +If you compile TypeScript to CJS and you can’t use `"moduleResolution": "node 16"`, you have to enable `esModuleInterop`. +If you use TypeScript to type check CJS JavaScript code, your only option is to use `"moduleResolution": "node16"`. + ## Online one-click setup You can use Gitpod, an online IDE(which is free for Open Source) for contributing or running the examples online. diff --git a/index.d.cts b/index.d.cts new file mode 100644 index 0000000000..21a763f08a --- /dev/null +++ b/index.d.cts @@ -0,0 +1,490 @@ +type AxiosHeaderValue = AxiosHeaders | string | string[] | number | boolean | null; +type RawAxiosHeaders = Record; + +type MethodsHeaders = { + [Key in axios.Method as Lowercase]: AxiosHeaders; +}; + +interface CommonHeaders { + common: AxiosHeaders; +} + +type AxiosHeaderMatcher = (this: AxiosHeaders, value: string, name: string, headers: RawAxiosHeaders) => boolean; + +type AxiosHeaderSetter = (value: AxiosHeaderValue, rewrite?: boolean | AxiosHeaderMatcher) => AxiosHeaders; + +type AxiosHeaderGetter = ((parser?: RegExp) => RegExpExecArray | null) | + ((matcher?: AxiosHeaderMatcher) => AxiosHeaderValue); + +type AxiosHeaderTester = (matcher?: AxiosHeaderMatcher) => boolean; + +type MaxUploadRate = number; + +type MaxDownloadRate = number; + +type Milliseconds = number; + +declare class AxiosHeaders { + constructor( + headers?: RawAxiosHeaders | AxiosHeaders, + defaultHeaders?: RawAxiosHeaders | AxiosHeaders + ); + + set(headerName?: string, value?: AxiosHeaderValue, rewrite?: boolean | AxiosHeaderMatcher): AxiosHeaders; + set(headers?: RawAxiosHeaders | AxiosHeaders, rewrite?: boolean): AxiosHeaders; + + get(headerName: string, parser: RegExp): RegExpExecArray | null; + get(headerName: string, matcher?: true | AxiosHeaderMatcher): AxiosHeaderValue; + + has(header: string, matcher?: true | AxiosHeaderMatcher): boolean; + + delete(header: string | string[], matcher?: AxiosHeaderMatcher): boolean; + + clear(): boolean; + + normalize(format: boolean): AxiosHeaders; + + toJSON(asStrings?: boolean): RawAxiosHeaders; + + static from(thing?: AxiosHeaders | RawAxiosHeaders | string): AxiosHeaders; + + static accessor(header: string | string[]): AxiosHeaders; + + setContentType: AxiosHeaderSetter; + getContentType: AxiosHeaderGetter; + hasContentType: AxiosHeaderTester; + + setContentLength: AxiosHeaderSetter; + getContentLength: AxiosHeaderGetter; + hasContentLength: AxiosHeaderTester; + + setAccept: AxiosHeaderSetter; + getAccept: AxiosHeaderGetter; + hasAccept: AxiosHeaderTester; + + setUserAgent: AxiosHeaderSetter; + getUserAgent: AxiosHeaderGetter; + hasUserAgent: AxiosHeaderTester; + + setContentEncoding: AxiosHeaderSetter; + getContentEncoding: AxiosHeaderGetter; + hasContentEncoding: AxiosHeaderTester; +} + +declare class AxiosError extends Error { + constructor( + message?: string, + code?: string, + config?: axios.AxiosRequestConfig, + request?: any, + response?: axios.AxiosResponse + ); + + config?: axios.AxiosRequestConfig; + code?: string; + request?: any; + response?: axios.AxiosResponse; + isAxiosError: boolean; + status?: number; + toJSON: () => object; + cause?: Error; + static readonly ERR_FR_TOO_MANY_REDIRECTS = "ERR_FR_TOO_MANY_REDIRECTS"; + static readonly ERR_BAD_OPTION_VALUE = "ERR_BAD_OPTION_VALUE"; + static readonly ERR_BAD_OPTION = "ERR_BAD_OPTION"; + static readonly ERR_NETWORK = "ERR_NETWORK"; + static readonly ERR_DEPRECATED = "ERR_DEPRECATED"; + static readonly ERR_BAD_RESPONSE = "ERR_BAD_RESPONSE"; + static readonly ERR_BAD_REQUEST = "ERR_BAD_REQUEST"; + static readonly ERR_NOT_SUPPORT = "ERR_NOT_SUPPORT"; + static readonly ERR_INVALID_URL = "ERR_INVALID_URL"; + static readonly ERR_CANCELED = "ERR_CANCELED"; + static readonly ECONNABORTED = "ECONNABORTED"; + static readonly ETIMEDOUT = "ETIMEDOUT"; +} + +declare class CanceledError extends AxiosError { +} + +declare class Axios { + constructor(config?: axios.AxiosRequestConfig); + defaults: axios.AxiosDefaults; + interceptors: { + request: axios.AxiosInterceptorManager; + response: axios.AxiosInterceptorManager; + }; + getUri(config?: axios.AxiosRequestConfig): string; + request, D = any>(config: axios.AxiosRequestConfig): Promise; + get, D = any>(url: string, config?: axios.AxiosRequestConfig): Promise; + delete, D = any>(url: string, config?: axios.AxiosRequestConfig): Promise; + head, D = any>(url: string, config?: axios.AxiosRequestConfig): Promise; + options, D = any>(url: string, config?: axios.AxiosRequestConfig): Promise; + post, D = any>(url: string, data?: D, config?: axios.AxiosRequestConfig): Promise; + put, D = any>(url: string, data?: D, config?: axios.AxiosRequestConfig): Promise; + patch, D = any>(url: string, data?: D, config?: axios.AxiosRequestConfig): Promise; + postForm, D = any>(url: string, data?: D, config?: axios.AxiosRequestConfig): Promise; + putForm, D = any>(url: string, data?: D, config?: axios.AxiosRequestConfig): Promise; + patchForm, D = any>(url: string, data?: D, config?: axios.AxiosRequestConfig): Promise; +} + +declare enum HttpStatusCode { + Continue = 100, + SwitchingProtocols = 101, + Processing = 102, + EarlyHints = 103, + Ok = 200, + Created = 201, + Accepted = 202, + NonAuthoritativeInformation = 203, + NoContent = 204, + ResetContent = 205, + PartialContent = 206, + MultiStatus = 207, + AlreadyReported = 208, + ImUsed = 226, + MultipleChoices = 300, + MovedPermanently = 301, + Found = 302, + SeeOther = 303, + NotModified = 304, + UseProxy = 305, + Unused = 306, + TemporaryRedirect = 307, + PermanentRedirect = 308, + BadRequest = 400, + Unauthorized = 401, + PaymentRequired = 402, + Forbidden = 403, + NotFound = 404, + MethodNotAllowed = 405, + NotAcceptable = 406, + ProxyAuthenticationRequired = 407, + RequestTimeout = 408, + Conflict = 409, + Gone = 410, + LengthRequired = 411, + PreconditionFailed = 412, + PayloadTooLarge = 413, + UriTooLong = 414, + UnsupportedMediaType = 415, + RangeNotSatisfiable = 416, + ExpectationFailed = 417, + ImATeapot = 418, + MisdirectedRequest = 421, + UnprocessableEntity = 422, + Locked = 423, + FailedDependency = 424, + TooEarly = 425, + UpgradeRequired = 426, + PreconditionRequired = 428, + TooManyRequests = 429, + RequestHeaderFieldsTooLarge = 431, + UnavailableForLegalReasons = 451, + InternalServerError = 500, + NotImplemented = 501, + BadGateway = 502, + ServiceUnavailable = 503, + GatewayTimeout = 504, + HttpVersionNotSupported = 505, + VariantAlsoNegotiates = 506, + InsufficientStorage = 507, + LoopDetected = 508, + NotExtended = 510, + NetworkAuthenticationRequired = 511, +} + +type InternalAxiosError = AxiosError; + +declare namespace axios { + type AxiosError = InternalAxiosError; + + type RawAxiosRequestHeaders = Partial; + + type AxiosRequestHeaders = Partial & AxiosHeaders; + + type RawAxiosResponseHeaders = Partial & { + "set-cookie"?: string[] + }>; + + type AxiosResponseHeaders = RawAxiosResponseHeaders & AxiosHeaders; + + interface AxiosRequestTransformer { + (this: AxiosRequestConfig, data: any, headers: AxiosRequestHeaders): any; + } + + interface AxiosResponseTransformer { + (this: AxiosRequestConfig, data: any, headers: AxiosResponseHeaders, status?: number): any; + } + + interface AxiosAdapter { + (config: AxiosRequestConfig): AxiosPromise; + } + + interface AxiosBasicCredentials { + username: string; + password: string; + } + + interface AxiosProxyConfig { + host: string; + port: number; + auth?: { + username: string; + password: string; + }; + protocol?: string; + } + + type Method = + | 'get' | 'GET' + | 'delete' | 'DELETE' + | 'head' | 'HEAD' + | 'options' | 'OPTIONS' + | 'post' | 'POST' + | 'put' | 'PUT' + | 'patch' | 'PATCH' + | 'purge' | 'PURGE' + | 'link' | 'LINK' + | 'unlink' | 'UNLINK'; + + type ResponseType = + | 'arraybuffer' + | 'blob' + | 'document' + | 'json' + | 'text' + | 'stream'; + + type responseEncoding = + | 'ascii' | 'ASCII' + | 'ansi' | 'ANSI' + | 'binary' | 'BINARY' + | 'base64' | 'BASE64' + | 'base64url' | 'BASE64URL' + | 'hex' | 'HEX' + | 'latin1' | 'LATIN1' + | 'ucs-2' | 'UCS-2' + | 'ucs2' | 'UCS2' + | 'utf-8' | 'UTF-8' + | 'utf8' | 'UTF8' + | 'utf16le' | 'UTF16LE'; + + interface TransitionalOptions { + silentJSONParsing?: boolean; + forcedJSONParsing?: boolean; + clarifyTimeoutError?: boolean; + } + + interface GenericAbortSignal { + readonly aborted: boolean; + onabort?: ((...args: any) => any) | null; + addEventListener?: (...args: any) => any; + removeEventListener?: (...args: any) => any; + } + + interface FormDataVisitorHelpers { + defaultVisitor: SerializerVisitor; + convertValue: (value: any) => any; + isVisitable: (value: any) => boolean; + } + + interface SerializerVisitor { + ( + this: GenericFormData, + value: any, + key: string | number, + path: null | Array, + helpers: FormDataVisitorHelpers + ): boolean; + } + + interface SerializerOptions { + visitor?: SerializerVisitor; + dots?: boolean; + metaTokens?: boolean; + indexes?: boolean | null; + } + + // tslint:disable-next-line + interface FormSerializerOptions extends SerializerOptions { + } + + interface ParamEncoder { + (value: any, defaultEncoder: (value: any) => any): any; + } + + interface CustomParamsSerializer { + (params: Record, options?: ParamsSerializerOptions): string; + } + + interface ParamsSerializerOptions extends SerializerOptions { + encode?: ParamEncoder; + serialize?: CustomParamsSerializer; + } + + interface AxiosProgressEvent { + loaded: number; + total?: number; + progress?: number; + bytes: number; + rate?: number; + estimated?: number; + upload?: boolean; + download?: boolean; + } + + interface AxiosRequestConfig { + url?: string; + method?: Method | string; + baseURL?: string; + transformRequest?: AxiosRequestTransformer | AxiosRequestTransformer[]; + transformResponse?: AxiosResponseTransformer | AxiosResponseTransformer[]; + headers?: RawAxiosRequestHeaders; + params?: any; + paramsSerializer?: ParamsSerializerOptions; + data?: D; + timeout?: Milliseconds; + timeoutErrorMessage?: string; + withCredentials?: boolean; + adapter?: AxiosAdapter; + auth?: AxiosBasicCredentials; + responseType?: ResponseType; + responseEncoding?: responseEncoding | string; + xsrfCookieName?: string; + xsrfHeaderName?: string; + onUploadProgress?: (progressEvent: AxiosProgressEvent) => void; + onDownloadProgress?: (progressEvent: AxiosProgressEvent) => void; + maxContentLength?: number; + validateStatus?: ((status: number) => boolean) | null; + maxBodyLength?: number; + maxRedirects?: number; + maxRate?: number | [MaxUploadRate, MaxDownloadRate]; + beforeRedirect?: (options: Record, responseDetails: {headers: Record}) => void; + socketPath?: string | null; + httpAgent?: any; + httpsAgent?: any; + proxy?: AxiosProxyConfig | false; + cancelToken?: CancelToken; + decompress?: boolean; + transitional?: TransitionalOptions; + signal?: GenericAbortSignal; + insecureHTTPParser?: boolean; + env?: { + FormData?: new (...args: any[]) => object; + }; + formSerializer?: FormSerializerOptions; + } + + interface HeadersDefaults { + common: RawAxiosRequestHeaders; + delete: RawAxiosRequestHeaders; + get: RawAxiosRequestHeaders; + head: RawAxiosRequestHeaders; + post: RawAxiosRequestHeaders; + put: RawAxiosRequestHeaders; + patch: RawAxiosRequestHeaders; + options?: RawAxiosRequestHeaders; + purge?: RawAxiosRequestHeaders; + link?: RawAxiosRequestHeaders; + unlink?: RawAxiosRequestHeaders; + } + + interface AxiosDefaults extends Omit, 'headers'> { + headers: HeadersDefaults; + } + + interface CreateAxiosDefaults extends Omit, 'headers'> { + headers?: RawAxiosRequestHeaders | Partial; + } + + interface AxiosResponse { + data: T; + status: number; + statusText: string; + headers: RawAxiosResponseHeaders | AxiosResponseHeaders; + config: AxiosRequestConfig; + request?: any; + } + + type AxiosPromise = Promise>; + + interface CancelStatic { + new (message?: string): Cancel; + } + + interface Cancel { + message: string | undefined; + } + + interface Canceler { + (message?: string, config?: AxiosRequestConfig, request?: any): void; + } + + interface CancelTokenStatic { + new (executor: (cancel: Canceler) => void): CancelToken; + source(): CancelTokenSource; + } + + interface CancelToken { + promise: Promise; + reason?: Cancel; + throwIfRequested(): void; + } + + interface CancelTokenSource { + token: CancelToken; + cancel: Canceler; + } + + interface AxiosInterceptorOptions { + synchronous?: boolean; + runWhen?: (config: AxiosRequestConfig) => boolean; + } + + interface AxiosInterceptorManager { + use(onFulfilled?: (value: V) => V | Promise, onRejected?: (error: any) => any, options?: AxiosInterceptorOptions): number; + eject(id: number): void; + clear(): void; + } + + interface AxiosInstance extends Axios { + , D = any>(config: AxiosRequestConfig): Promise; + , D = any>(url: string, config?: AxiosRequestConfig): Promise; + + defaults: Omit & { + headers: HeadersDefaults & { + [key: string]: AxiosHeaderValue + } + }; + } + + interface GenericFormData { + append(name: string, value: any, options?: any): any; + } + + interface GenericHTMLFormElement { + name: string; + method: string; + submit(): void; + } + + interface AxiosStatic extends AxiosInstance { + create(config?: CreateAxiosDefaults): AxiosInstance; + Cancel: CancelStatic; + CancelToken: CancelTokenStatic; + Axios: typeof Axios; + AxiosError: typeof AxiosError; + CanceledError: typeof CanceledError; + HttpStatusCode: typeof HttpStatusCode; + readonly VERSION: string; + isCancel(value: any): value is Cancel; + all(values: Array>): Promise; + spread(callback: (...args: T[]) => R): (array: T[]) => R; + isAxiosError(payload: any): payload is AxiosError; + toFormData(sourceObj: object, targetFormData?: GenericFormData, options?: FormSerializerOptions): GenericFormData; + formToJSON(form: GenericFormData|GenericHTMLFormElement): object; + } +} + +declare const axios: axios.AxiosStatic; + +export = axios; diff --git a/index.d.ts b/index.d.ts index 0b1f1c7fcb..58212167ab 100644 --- a/index.d.ts +++ b/index.d.ts @@ -1,4 +1,4 @@ -// TypeScript Version: 4.1 +// TypeScript Version: 4.7 type AxiosHeaderValue = AxiosHeaders | string | string[] | number | boolean | null; type RawAxiosHeaders = Record; diff --git a/package-lock.json b/package-lock.json index a4f39b7a0c..e9a327fdb6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -56,7 +56,7 @@ "sinon": "^4.5.0", "stream-throttle": "^0.1.3", "terser-webpack-plugin": "^4.2.3", - "typescript": "^4.6.3", + "typescript": "^4.8.4", "url-search-params": "^0.10.0" } }, @@ -16318,9 +16318,9 @@ "dev": true }, "node_modules/typescript": { - "version": "4.6.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.3.tgz", - "integrity": "sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw==", + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz", + "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -31357,9 +31357,9 @@ "dev": true }, "typescript": { - "version": "4.6.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.3.tgz", - "integrity": "sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw==", + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz", + "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==", "dev": true }, "ua-parser-js": { diff --git a/package.json b/package.json index e39cf61975..25dffa713e 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,10 @@ "main": "index.js", "exports": { ".": { + "types": { + "require": "./index.d.cts", + "default": "./index.d.ts" + }, "browser": { "require": "./dist/browser/axios.cjs", "default": "./index.js" @@ -96,7 +100,7 @@ "sinon": "^4.5.0", "stream-throttle": "^0.1.3", "terser-webpack-plugin": "^4.2.3", - "typescript": "^4.6.3", + "typescript": "^4.8.4", "url-search-params": "^0.10.0" }, "browser": { diff --git a/test/typescript/axios.cts b/test/typescript/axios.cts new file mode 100644 index 0000000000..6d25deedfa --- /dev/null +++ b/test/typescript/axios.cts @@ -0,0 +1,443 @@ +import axios = require('axios'); + +const config: axios.AxiosRequestConfig = { + url: '/user', + method: 'get', + baseURL: 'https://api.example.com/', + transformRequest: (data: any) => '{"foo":"bar"}', + transformResponse: [ + (data: any) => ({ baz: 'qux' }) + ], + headers: { 'X-FOO': 'bar' }, + params: { id: 12345 }, + paramsSerializer: { + indexes: true, + encode: (value: any) => value, + serialize: (value: Record, options?: axios.ParamsSerializerOptions) => String(value) + }, + data: { foo: 'bar' }, + timeout: 10000, + withCredentials: true, + auth: { + username: 'janedoe', + password: 's00pers3cret' + }, + responseType: 'json', + xsrfCookieName: 'XSRF-TOKEN', + xsrfHeaderName: 'X-XSRF-TOKEN', + onUploadProgress: (progressEvent: axios.AxiosProgressEvent) => {}, + onDownloadProgress: (progressEvent: axios.AxiosProgressEvent) => {}, + maxContentLength: 2000, + maxBodyLength: 2000, + validateStatus: (status: number) => status >= 200 && status < 300, + maxRedirects: 5, + proxy: { + host: '127.0.0.1', + port: 9000 + }, + cancelToken: new axios.CancelToken((cancel: axios.Canceler) => {}) +}; + +const nullValidateStatusConfig: axios.AxiosRequestConfig = { + validateStatus: null +}; + +const undefinedValidateStatusConfig: axios.AxiosRequestConfig = { + validateStatus: undefined +}; + +const handleResponse = (response: axios.AxiosResponse) => { + console.log(response.data); + console.log(response.status); + console.log(response.statusText); + console.log(response.headers); + console.log(response.config); +}; + +const handleError = (error: axios.AxiosError) => { + if (error.response) { + console.log(error.response.data); + console.log(error.response.status); + console.log(error.response.headers); + } else { + console.log(error.message); + } +}; + +axios(config) + .then(handleResponse) + .catch(handleError); + +axios.get('/user?id=12345') + .then(handleResponse) + .catch(handleError); + +axios.get('/user', { params: { id: 12345 } }) + .then(handleResponse) + .catch(handleError); + +axios.head('/user') + .then(handleResponse) + .catch(handleError); + +axios.options('/user') + .then(handleResponse) + .catch(handleError); + +axios.delete('/user') + .then(handleResponse) + .catch(handleError); + +axios.post('/user', { foo: 'bar' }) + .then(handleResponse) + .catch(handleError); + +axios.post('/user', { foo: 'bar' }, { headers: { 'X-FOO': 'bar' } }) + .then(handleResponse) + .catch(handleError); + +axios.put('/user', { foo: 'bar' }) + .then(handleResponse) + .catch(handleError); + +axios.patch('/user', { foo: 'bar' }) + .then(handleResponse) + .catch(handleError); + +// Typed methods +interface UserCreationDef { + name: string; +} + +interface User { + id: number; + name: string; +} + +// with default axios.AxiosResponse result + +const handleUserResponse = (response: axios.AxiosResponse) => { + console.log(response.data.id); + console.log(response.data.name); + console.log(response.status); + console.log(response.statusText); + console.log(response.headers); + console.log(response.config); +}; + +axios.get('/user?id=12345') + .then(handleUserResponse) + .catch(handleError); + +axios.get('/user', { params: { id: 12345 } }) + .then(handleUserResponse) + .catch(handleError); + +axios.head('/user') + .then(handleUserResponse) + .catch(handleError); + +axios.options('/user') + .then(handleUserResponse) + .catch(handleError); + +axios.delete('/user') + .then(handleUserResponse) + .catch(handleError); + +axios.post('/user', { name: 'foo', id: 1 }) + .then(handleUserResponse) + .catch(handleError); + +axios.post('/user', { name: 'foo', id: 1 }, { headers: { 'X-FOO': 'bar' } }) + .then(handleUserResponse) + .catch(handleError); + +axios.put('/user', { name: 'foo', id: 1 }) + .then(handleUserResponse) + .catch(handleError); + +axios.patch('/user', { name: 'foo', id: 1 }) + .then(handleUserResponse) + .catch(handleError); + +// (Typed methods) with custom response type + +const handleStringResponse = (response: string) => { + console.log(response); +}; + +axios.get('/user?id=12345') + .then(handleStringResponse) + .catch(handleError); + +axios.get('/user', { params: { id: 12345 } }) + .then(handleStringResponse) + .catch(handleError); + +axios.head('/user') + .then(handleStringResponse) + .catch(handleError); + +axios.options('/user') + .then(handleStringResponse) + .catch(handleError); + +axios.delete('/user') + .then(handleStringResponse) + .catch(handleError); + +axios.post, string>('/user', { name: 'foo' }) + .then(handleStringResponse) + .catch(handleError); + +axios.post, string>('/user', { name: 'foo' }, { headers: { 'X-FOO': 'bar' } }) + .then(handleStringResponse) + .catch(handleError); + +axios.put, string>('/user', { name: 'foo' }) + .then(handleStringResponse) + .catch(handleError); + +axios.patch, string>('/user', { name: 'foo' }) + .then(handleStringResponse) + .catch(handleError); + +axios.request({ + method: 'get', + url: '/user?id=12345' +}) + .then(handleStringResponse) + .catch(handleError); + +// Instances + +const instance1: axios.AxiosInstance = axios.create(); +const instance2: axios.AxiosInstance = axios.create(config); + +instance1(config) + .then(handleResponse) + .catch(handleError); + +instance1.request(config) + .then(handleResponse) + .catch(handleError); + +instance1.get('/user?id=12345') + .then(handleResponse) + .catch(handleError); + +instance1.options('/user') + .then(handleResponse) + .catch(handleError); + +instance1.get('/user', { params: { id: 12345 } }) + .then(handleResponse) + .catch(handleError); + +instance1.post('/user', { foo: 'bar' }) + .then(handleResponse) + .catch(handleError); + +instance1.post('/user', { foo: 'bar' }, { headers: { 'X-FOO': 'bar' } }) + .then(handleResponse) + .catch(handleError); + +// Defaults + +axios.defaults.headers['X-FOO']; + +axios.defaults.baseURL = 'https://api.example.com/'; +axios.defaults.headers.common['Accept'] = 'application/json'; +axios.defaults.headers.post['X-FOO'] = 'bar'; +axios.defaults.timeout = 2500; + +instance1.defaults.baseURL = 'https://api.example.com/'; +instance1.defaults.headers.common['Accept'] = 'application/json'; +instance1.defaults.headers.post['X-FOO'] = 'bar'; +instance1.defaults.timeout = 2500; + +// axios create defaults + +axios.create({ headers: { foo: 'bar' } }); +axios.create({ headers: { common: { foo: 'bar' } } }); +axios.create({ + headers: { + 'Content-Type': 'application/json', + }, + formSerializer: { + indexes: null, + }, + paramsSerializer: { + indexes: null, + }, +}); + +// Interceptors + +const requestInterceptorId: number = axios.interceptors.request.use( + (config: axios.AxiosRequestConfig) => config, + (error: any) => Promise.reject(error) +); + +axios.interceptors.request.eject(requestInterceptorId); + +axios.interceptors.request.use( + (config: axios.AxiosRequestConfig) => Promise.resolve(config), + (error: any) => Promise.reject(error) +); + +axios.interceptors.request.use((config: axios.AxiosRequestConfig) => config); +axios.interceptors.request.use((config: axios.AxiosRequestConfig) => Promise.resolve(config)); + +const responseInterceptorId: number = axios.interceptors.response.use( + (response: axios.AxiosResponse) => response, + (error: any) => Promise.reject(error) +); + +axios.interceptors.response.eject(responseInterceptorId); + +axios.interceptors.response.use( + (response: axios.AxiosResponse) => Promise.resolve(response), + (error: any) => Promise.reject(error) +); + +const voidRequestInterceptorId = axios.interceptors.request.use( + // @ts-expect-error -- Must return an axios.AxiosRequestConfig (or throw) + (_response) => {}, + (error: any) => Promise.reject(error) +); +const voidResponseInterceptorId = axios.interceptors.response.use( + // @ts-expect-error -- Must return an axios.AxiosResponse (or throw) + (_response) => {}, + (error: any) => Promise.reject(error) +); +axios.interceptors.request.eject(voidRequestInterceptorId); +axios.interceptors.response.eject(voidResponseInterceptorId); + +axios.interceptors.response.use((response: axios.AxiosResponse) => response); +axios.interceptors.response.use((response: axios.AxiosResponse) => Promise.resolve(response)); + +axios.interceptors.request.clear(); +axios.interceptors.response.clear(); + +// Adapters + +const adapter: axios.AxiosAdapter = (config: axios.AxiosRequestConfig) => { + const response: axios.AxiosResponse = { + data: { foo: 'bar' }, + status: 200, + statusText: 'OK', + headers: { 'X-FOO': 'bar' }, + config + }; + return Promise.resolve(response); +}; + +axios.defaults.adapter = adapter; + +// axios.all + +const promises = [ + Promise.resolve(1), + Promise.resolve(2) +]; + +const promise: Promise = axios.all(promises); + +// axios.spread + +const fn1 = (a: number, b: number, c: number) => `${a}-${b}-${c}`; +const fn2: (arr: number[]) => string = axios.spread(fn1); + +// Promises + +axios.get('/user') + .then((response: axios.AxiosResponse) => 'foo') + .then((value: string) => {}); + +axios.get('/user') + .then((response: axios.AxiosResponse) => Promise.resolve('foo')) + .then((value: string) => {}); + +axios.get('/user') + .then((response: axios.AxiosResponse) => 'foo', (error: any) => 'bar') + .then((value: string) => {}); + +axios.get('/user') + .then((response: axios.AxiosResponse) => 'foo', (error: any) => 123) + .then((value: string | number) => {}); + +axios.get('/user') + .catch((error: any) => 'foo') + .then((value) => {}); + +axios.get('/user') + .catch((error: any) => Promise.resolve('foo')) + .then((value) => {}); + +// axios.Cancellation + +const source: axios.CancelTokenSource = axios.CancelToken.source(); + +axios.get('/user', { + cancelToken: source.token +}).catch((thrown: axios.AxiosError | axios.Cancel) => { + if (axios.isCancel(thrown)) { + const cancel: axios.Cancel = thrown; + console.log(cancel.message); + } +}); + +source.cancel('Operation has been axios.Canceled.'); + +// axios.AxiosError + +axios.get('/user') + .catch((error) => { + if (axios.isAxiosError(error)) { + const axiosError: axios.AxiosError = error; + } + }); + +// FormData + +axios.toFormData({x: 1}, new FormData()); + +// AbortSignal + +axios.get('/user', {signal: new AbortController().signal}); + +// AxiosHeaders methods + +axios.get('/user', { + transformRequest: (data, headers) => { + headers.setContentType('text/plain'); + headers['Foo'] = 'bar'; + }, + + transformResponse: (data, headers) => { + headers.has('foo'); + } +}); + +// Max Rate + +axios.get('/user', { + maxRate: 1000 +}); + +axios.get('/user', { + maxRate: [1000, 1000], +}); + +// Node progress + +axios.get('/user', { + onUploadProgress: (e) => { + console.log(e.loaded); + console.log(e.total); + console.log(e.progress); + console.log(e.rate); + } +}); diff --git a/test/typescript/axios.ts b/test/typescript/axios.ts index 01d32915f8..9aeecbfbd6 100644 --- a/test/typescript/axios.ts +++ b/test/typescript/axios.ts @@ -6,7 +6,9 @@ import axios, { AxiosAdapter, Cancel, CancelTokenSource, - Canceler, AxiosProgressEvent, ParamsSerializerOptions, + Canceler, + AxiosProgressEvent, + ParamsSerializerOptions, toFormData, formToJSON, all, @@ -263,12 +265,12 @@ instance1.post('/user', { foo: 'bar' }, { headers: { 'X-FOO': 'bar' } }) axios.defaults.headers['X-FOO']; axios.defaults.baseURL = 'https://api.example.com/'; -axios.defaults.headers.common['Authorization'] = 'token'; +axios.defaults.headers.common['Accept'] = 'application/json'; axios.defaults.headers.post['X-FOO'] = 'bar'; axios.defaults.timeout = 2500; instance1.defaults.baseURL = 'https://api.example.com/'; -instance1.defaults.headers.common['Authorization'] = 'token'; +instance1.defaults.headers.common['Accept'] = 'application/json'; instance1.defaults.headers.post['X-FOO'] = 'bar'; instance1.defaults.timeout = 2500; @@ -437,8 +439,6 @@ axios.get('/user') const axiosError: AxiosError = error; } - // named export - if (isAxiosError(error)) { const axiosError: AxiosError = error; } diff --git a/tsconfig.json b/tsconfig.json index 6665188255..a67190e86d 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,14 +1,9 @@ { "compilerOptions": { - "module": "es2015", + "module": "node16", "lib": ["dom", "es2015"], "types": [], - "moduleResolution": "node", "strict": true, - "noEmit": true, - "baseUrl": ".", - "paths": { - "axios": ["."] - } + "noEmit": true } }