diff --git a/README.md b/README.md index 69e39c73..c86b6376 100644 --- a/README.md +++ b/README.md @@ -694,6 +694,27 @@ These are the available config options for making requests. Only the `url` is re return data; }], + // `parseReviver` is an optional function that will be passed as the + // second argument (reviver) to JSON.parse() + parseReviver: function (key, value, context) { + // In modern environments, context.source provides the raw JSON string + // allowing for precision-safe parsing of BigInt + if (typeof value === 'number' && context?.source) { + const isInteger = Number.isInteger(value); + const isUnsafe = !Number.isSafeInteger(value); + const isValidIntegerString = /^-?\d+$/.test(context.source); + + if (isInteger && isUnsafe && isValidIntegerString) { + try { + return BigInt(context.source); + } catch { + // Fallback: return original value if parsing fails + } + } + } + return value; + }, + // `headers` are custom headers to be sent headers: {'X-Requested-With': 'XMLHttpRequest'}, diff --git a/docs/pages/advanced/request-config.md b/docs/pages/advanced/request-config.md index eeee6801..3e07cdda 100644 --- a/docs/pages/advanced/request-config.md +++ b/docs/pages/advanced/request-config.md @@ -26,6 +26,49 @@ The `transformRequest` function allows you to modify the request data before it The `transformResponse` function allows you to modify the response data before it is passed to the `then` or `catch` functions. This function is called with the response data as its only argument. +### `parseReviver` + +The `parseReviver` function allows you to provide a custom "reviver" function directly to the native `JSON.parse()` call used by the default `transformResponse`. + +This is particularly useful for performing high-performance type hydration (e.g., converting ISO strings to `Temporal` or `Date` objects) or preventing precision loss during parsing. + +In modern environments (ES2023+), the reviver function receives a third `context` argument. This provides access to the raw JSON `source`, allowing for precise conversion of large integers (BigInt) that would otherwise lose precision if parsed as standard JavaScript numbers. + +> Note: `Temporal` is not yet available in all environments. Consider using a polyfill if needed. + +```js +const client = axios.create({ + parseReviver: (key, value, context) => { + // Example: Precision-safe BigInt parsing + if (typeof value === 'number' && context?.source) { + const isInteger = Number.isInteger(value); + const isUnsafe = !Number.isSafeInteger(value); + const isValidIntegerString = /^-?\d+$/.test(context.source); + + if (isInteger && isUnsafe && isValidIntegerString) { + try { + return BigInt(context.source); + } catch { + // Fallback: return original value if parsing fails + } + } + } + + // Example: Hydrating dates into Temporal objects + if ( + typeof value === 'string' && + /^\d{4}-\d{2}-\d{2}$/.test(value) && + typeof Temporal !== 'undefined' && + Temporal?.PlainDate + ) { + return Temporal.PlainDate.from(value); + } + + return value; + }, +}); +``` + ### `headers` The `headers` are the HTTP headers to be sent with the request. The `Content-Type` header is set to `application/json` by default. @@ -170,7 +213,7 @@ Restricts which socket paths may be used via `socketPath`. Accepts a string or a ```js const client = axios.create({ - allowedSocketPaths: ['/var/run/docker.sock'] + allowedSocketPaths: ['/var/run/docker.sock'], }); // allowed diff --git a/index.d.cts b/index.d.cts index 9133f055..016f6cfc 100644 --- a/index.d.cts +++ b/index.d.cts @@ -544,6 +544,7 @@ declare namespace axios { | LookupAddress >); withXSRFToken?: boolean | ((config: InternalAxiosRequestConfig) => boolean | undefined); + parseReviver?: (this: any, key: string, value: any, context?: { source: string }) => any; fetchOptions?: | Omit | Record; diff --git a/index.d.ts b/index.d.ts index 18fa3292..100da68b 100644 --- a/index.d.ts +++ b/index.d.ts @@ -441,7 +441,7 @@ export interface AxiosRequestConfig { [address: LookupAddressEntry | LookupAddressEntry[], family?: AddressFamily] | LookupAddress >); withXSRFToken?: boolean | ((config: InternalAxiosRequestConfig) => boolean | undefined); - parseReviver?: (this: any, key: string, value: any) => any; + parseReviver?: (this: any, key: string, value: any, context?: { source: string }) => any; fetchOptions?: Omit | Record; httpVersion?: 1 | 2; http2Options?: Record & {