@gcmdev/faxios 0.2.1 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/adapters/fetch-helpers.d.ts +1 -1
- package/dist/lib/adapters/fetch-helpers.d.ts.map +1 -1
- package/dist/lib/adapters/fetch.d.ts +4 -1
- package/dist/lib/adapters/fetch.d.ts.map +1 -1
- package/dist/lib/adapters/fetch.js +210 -92
- package/dist/lib/adapters/fetch.js.map +1 -1
- package/dist/lib/cancel/CanceledError.d.ts +1 -1
- package/dist/lib/cancel/CanceledError.d.ts.map +1 -1
- package/dist/lib/core/Faxios.d.ts +3 -3
- package/dist/lib/core/Faxios.d.ts.map +1 -1
- package/dist/lib/core/Faxios.js +8 -4
- package/dist/lib/core/Faxios.js.map +1 -1
- package/dist/lib/core/FaxiosError.d.ts +2 -2
- package/dist/lib/core/FaxiosError.d.ts.map +1 -1
- package/dist/lib/core/FaxiosHeaders.d.ts +8 -8
- package/dist/lib/core/FaxiosHeaders.d.ts.map +1 -1
- package/dist/lib/core/FaxiosHeaders.js +31 -7
- package/dist/lib/core/FaxiosHeaders.js.map +1 -1
- package/dist/lib/core/define.d.ts +3 -3
- package/dist/lib/core/define.d.ts.map +1 -1
- package/dist/lib/core/dispatchRequest.d.ts +1 -1
- package/dist/lib/core/dispatchRequest.d.ts.map +1 -1
- package/dist/lib/core/dispatchRequest.js +6 -1
- package/dist/lib/core/dispatchRequest.js.map +1 -1
- package/dist/lib/core/mergeConfig.d.ts +2 -2
- package/dist/lib/core/mergeConfig.d.ts.map +1 -1
- package/dist/lib/core/mergeConfig.js +40 -2
- package/dist/lib/core/mergeConfig.js.map +1 -1
- package/dist/lib/core/route.d.ts +1 -1
- package/dist/lib/core/route.d.ts.map +1 -1
- package/dist/lib/core/route.js +2 -5
- package/dist/lib/core/route.js.map +1 -1
- package/dist/lib/core/transformData.d.ts +2 -2
- package/dist/lib/core/transformData.d.ts.map +1 -1
- package/dist/lib/core/validateSchema.d.ts +2 -2
- package/dist/lib/core/validateSchema.d.ts.map +1 -1
- package/dist/lib/env/data.d.ts +1 -1
- package/dist/lib/env/data.js +1 -1
- package/dist/lib/faxios.d.ts +50 -50
- package/dist/lib/faxios.d.ts.map +1 -1
- package/dist/lib/helpers/cloneConfig.d.ts +0 -1
- package/dist/lib/helpers/cloneConfig.d.ts.map +1 -1
- package/dist/lib/helpers/cloneConfig.js +2 -2
- package/dist/lib/helpers/cloneConfig.js.map +1 -1
- package/dist/lib/helpers/cookies.d.ts +1 -1
- package/dist/lib/helpers/cookies.d.ts.map +1 -1
- package/dist/lib/helpers/formDataToJSON.d.ts +1 -1
- package/dist/lib/helpers/formDataToJSON.d.ts.map +1 -1
- package/dist/lib/helpers/formDataToJSON.js +1 -1
- package/dist/lib/helpers/formDataToJSON.js.map +1 -1
- package/dist/lib/helpers/parseHeaders.d.ts +1 -1
- package/dist/lib/helpers/parseHeaders.d.ts.map +1 -1
- package/dist/lib/helpers/progressEventReducer.d.ts.map +1 -1
- package/dist/lib/helpers/progressEventReducer.js +14 -1
- package/dist/lib/helpers/progressEventReducer.js.map +1 -1
- package/dist/lib/helpers/substitutePathParams.d.ts.map +1 -1
- package/dist/lib/helpers/substitutePathParams.js +11 -3
- package/dist/lib/helpers/substitutePathParams.js.map +1 -1
- package/dist/lib/helpers/toFormData.d.ts.map +1 -1
- package/dist/lib/helpers/toFormData.js +16 -20
- package/dist/lib/helpers/toFormData.js.map +1 -1
- package/dist/lib/helpers/trackStream.d.ts.map +1 -1
- package/dist/lib/helpers/trackStream.js +27 -3
- package/dist/lib/helpers/trackStream.js.map +1 -1
- package/dist/lib/helpers/validator.d.ts +1 -1
- package/dist/lib/helpers/validator.d.ts.map +1 -1
- package/dist/lib/platform.d.ts.map +1 -1
- package/dist/lib/plugins/authBearer.d.ts +9 -5
- package/dist/lib/plugins/authBearer.d.ts.map +1 -1
- package/dist/lib/plugins/authBearer.js +6 -0
- package/dist/lib/plugins/authBearer.js.map +1 -1
- package/dist/lib/plugins/definePlugin.d.ts +3 -3
- package/dist/lib/plugins/definePlugin.d.ts.map +1 -1
- package/dist/lib/plugins/retry.d.ts +23 -23
- package/dist/lib/plugins/retry.d.ts.map +1 -1
- package/dist/lib/plugins/timing.d.ts +8 -8
- package/dist/lib/plugins/timing.d.ts.map +1 -1
- package/dist/lib/types/standard-schema.d.ts +6 -6
- package/dist/lib/types/standard-schema.d.ts.map +1 -1
- package/dist/lib/types.d.ts +106 -92
- package/dist/lib/types.d.ts.map +1 -1
- package/dist/lib/utils.d.ts +4 -3
- package/dist/lib/utils.d.ts.map +1 -1
- package/dist/lib/utils.js +18 -5
- package/dist/lib/utils.js.map +1 -1
- package/package.json +7 -4
- package/skills/configure-requests/SKILL.md +14 -8
- package/skills/configure-requests/references/axios-differences.md +1 -1
- package/skills/configure-requests/references/plugins.md +37 -6
- package/src/index.ts +15 -15
- package/src/lib/adapters/fetch-helpers.ts +3 -3
- package/src/lib/adapters/fetch.ts +263 -144
- package/src/lib/cancel/CanceledError.ts +1 -1
- package/src/lib/core/Faxios.ts +17 -13
- package/src/lib/core/FaxiosError.ts +3 -3
- package/src/lib/core/FaxiosHeaders.ts +50 -23
- package/src/lib/core/define.ts +7 -7
- package/src/lib/core/dispatchRequest.ts +8 -3
- package/src/lib/core/mergeConfig.ts +42 -4
- package/src/lib/core/prepareRequest.ts +1 -1
- package/src/lib/core/route.ts +3 -6
- package/src/lib/core/transformData.ts +2 -2
- package/src/lib/core/validateSchema.ts +4 -4
- package/src/lib/defaults/index.ts +1 -1
- package/src/lib/env/data.ts +1 -1
- package/src/lib/faxios.ts +55 -55
- package/src/lib/helpers/HttpStatusCode.ts +1 -1
- package/src/lib/helpers/cloneConfig.ts +2 -3
- package/src/lib/helpers/composeSignals.ts +4 -4
- package/src/lib/helpers/cookies.ts +3 -3
- package/src/lib/helpers/formDataToJSON.ts +4 -4
- package/src/lib/helpers/parseHeaders.ts +2 -2
- package/src/lib/helpers/progressEventReducer.ts +15 -2
- package/src/lib/helpers/sanitizeHeaderValue.ts +1 -1
- package/src/lib/helpers/substitutePathParams.ts +13 -3
- package/src/lib/helpers/throttle.ts +1 -1
- package/src/lib/helpers/toFormData.ts +26 -28
- package/src/lib/helpers/trackStream.ts +40 -12
- package/src/lib/helpers/validator.ts +3 -3
- package/src/lib/platform.ts +4 -4
- package/src/lib/plugins/authBearer.ts +14 -9
- package/src/lib/plugins/definePlugin.ts +3 -3
- package/src/lib/plugins/retry.ts +27 -27
- package/src/lib/plugins/timing.ts +5 -5
- package/src/lib/types/standard-schema.ts +6 -6
- package/src/lib/types.ts +139 -125
- package/src/lib/utils.ts +30 -15
package/dist/index.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ import type { CreateFaxiosDefaults } from "./lib/types.js";
|
|
|
4
4
|
export { default as Faxios } from "./lib/core/Faxios.js";
|
|
5
5
|
export { default as FaxiosError, isSchemaValidationError } from "./lib/core/FaxiosError.js";
|
|
6
6
|
export type { SchemaValidationError } from "./lib/core/FaxiosError.js";
|
|
7
|
-
export { default as
|
|
7
|
+
export { default as Cancel, default as CanceledError } from "./lib/cancel/CanceledError.js";
|
|
8
8
|
export { default as isCancel } from "./lib/cancel/isCancel.js";
|
|
9
9
|
export { default as isFaxiosError } from "./lib/helpers/isFaxiosError.js";
|
|
10
10
|
export { default as toFormData } from "./lib/helpers/toFormData.js";
|
|
@@ -15,8 +15,8 @@ export { VERSION } from "./lib/env/data.js";
|
|
|
15
15
|
export type { FaxiosInstance, FaxiosStatic } from "./lib/faxios.js";
|
|
16
16
|
export type { StandardSchemaV1 } from "./lib/types/standard-schema.js";
|
|
17
17
|
export type { BasePerCallConfig, DefineConfig, DefinedEndpoint, FaxiosLike, PerCallConfig } from "./lib/core/define.js";
|
|
18
|
-
export type { RouteConfig, RouteMethodConfig
|
|
19
|
-
export type {
|
|
18
|
+
export type { RouteBuilder, RouteConfig, RouteMethodConfig } from "./lib/core/route.js";
|
|
19
|
+
export type { CreateFaxiosDefaults, FaxiosConfigHeaders, FaxiosContext, FaxiosHeaderValue, FaxiosMiddleware, FaxiosNext, FaxiosPlugin, FaxiosPromise, FaxiosRequestConfig, FaxiosRequestHeaders, FaxiosResponse, FaxiosResponseHeadersLike, GenericHTMLFormElement, HeadersDefaults, InternalFaxiosRequestConfig, Method, RawFaxiosRequestConfig, RawFaxiosRequestHeaders, ResponseType } from "./lib/types.js";
|
|
20
20
|
export declare const all: FaxiosStatic["all"];
|
|
21
21
|
export declare const formToJSON: FaxiosStatic["formToJSON"];
|
|
22
22
|
export declare const create: (instanceConfig?: CreateFaxiosDefaults) => FaxiosInstance;
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,MAAM,wBAAwB;AACrC,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,wBAAwB;AACpE,OAAO,KAAK,EAAE,oBAAoB,EAAE,uBAAuB;AAM3D,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,6BAA6B;AACzD,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,uBAAuB,EAAE,kCAAkC;AAC5F,YAAY,EAAE,qBAAqB,EAAE,kCAAkC;AACvE,OAAO,EAAE,OAAO,IAAI,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,MAAM,wBAAwB;AACrC,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,wBAAwB;AACpE,OAAO,KAAK,EAAE,oBAAoB,EAAE,uBAAuB;AAM3D,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,6BAA6B;AACzD,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,uBAAuB,EAAE,kCAAkC;AAC5F,YAAY,EAAE,qBAAqB,EAAE,kCAAkC;AACvE,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,OAAO,IAAI,aAAa,EAAE,sCAAsC;AAC5F,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,iCAAiC;AAC/D,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,uCAAuC;AAC1E,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,oCAAoC;AACpE,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,oCAAoC;AACvE,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,wCAAwC;AAC5E,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,kCAAkC;AACnE,OAAO,EAAE,OAAO,EAAE,0BAA0B;AAE5C,YAAY,EAAE,cAAc,EAAE,YAAY,EAAE,wBAAwB;AACpE,YAAY,EAAE,gBAAgB,EAAE,uCAAuC;AACvE,YAAY,EAAE,iBAAiB,EAAE,YAAY,EAAE,eAAe,EAAE,UAAU,EAAE,aAAa,EAAE,6BAA6B;AACxH,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,iBAAiB,EAAE,4BAA4B;AAExF,YAAY,EACV,oBAAoB,EACpB,mBAAmB,EACnB,aAAa,EACb,iBAAiB,EACjB,gBAAgB,EAChB,UAAU,EACV,YAAY,EACZ,aAAa,EACb,mBAAmB,EACnB,oBAAoB,EACpB,cAAc,EACd,yBAAyB,EACzB,sBAAsB,EACtB,eAAe,EACf,2BAA2B,EAC3B,MAAM,EACN,sBAAsB,EACtB,uBAAuB,EACvB,YAAY,EACb,uBAAuB;AAKxB,eAAO,MAAM,GAAG,EAAE,YAAY,CAAC,KAAK,CAAc,CAAC;AACnD,eAAO,MAAM,UAAU,EAAE,YAAY,CAAC,YAAY,CAAqB,CAAC;AACxE,eAAO,MAAM,MAAM,EAAE,CAAC,cAAc,CAAC,EAAE,oBAAoB,KAAK,cAA8B,CAAC;AAE/F,OAAO,EAAE,MAAM,IAAI,OAAO,EAAE,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -7,7 +7,7 @@ import faxios from "./lib/faxios.js";
|
|
|
7
7
|
// runtime instance forced TS to emit the broken inline `import("./x.ts")` form.
|
|
8
8
|
export { default as Faxios } from "./lib/core/Faxios.js";
|
|
9
9
|
export { default as FaxiosError, isSchemaValidationError } from "./lib/core/FaxiosError.js";
|
|
10
|
-
export { default as
|
|
10
|
+
export { default as Cancel, default as CanceledError } from "./lib/cancel/CanceledError.js";
|
|
11
11
|
export { default as isCancel } from "./lib/cancel/isCancel.js";
|
|
12
12
|
export { default as isFaxiosError } from "./lib/helpers/isFaxiosError.js";
|
|
13
13
|
export { default as toFormData } from "./lib/helpers/toFormData.js";
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,oDAAoD;AACpD,OAAO,MAAM,wBAAwB;AAIrC,oEAAoE;AACpE,wEAAwE;AACxE,0EAA0E;AAC1E,gFAAgF;AAChF,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,6BAA6B;AACzD,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,uBAAuB,EAAE,kCAAkC;AAE5F,OAAO,EAAE,OAAO,IAAI,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,oDAAoD;AACpD,OAAO,MAAM,wBAAwB;AAIrC,oEAAoE;AACpE,wEAAwE;AACxE,0EAA0E;AAC1E,gFAAgF;AAChF,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,6BAA6B;AACzD,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,uBAAuB,EAAE,kCAAkC;AAE5F,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,OAAO,IAAI,aAAa,EAAE,sCAAsC;AAC5F,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,iCAAiC;AAC/D,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,uCAAuC;AAC1E,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,oCAAoC;AACpE,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,oCAAoC;AACvE,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,wCAAwC;AAC5E,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,kCAAkC;AACnE,OAAO,EAAE,OAAO,EAAE,0BAA0B;AA6B5C,gFAAgF;AAChF,+EAA+E;AAC/E,yFAAyF;AACzF,MAAM,CAAC,MAAM,GAAG,GAAwB,MAAM,CAAC,GAAG,CAAC;AACnD,MAAM,CAAC,MAAM,UAAU,GAA+B,MAAM,CAAC,UAAU,CAAC;AACxE,MAAM,CAAC,MAAM,MAAM,GAA8D,MAAM,CAAC,MAAM,CAAC;AAE/F,OAAO,EAAE,MAAM,IAAI,OAAO,EAAE,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import FaxiosError from "../core/FaxiosError.js";
|
|
2
2
|
import type FaxiosHeaders from "../core/FaxiosHeaders.js";
|
|
3
|
-
import type {
|
|
3
|
+
import type { FaxiosRequestHeaders, InternalFaxiosRequestConfig } from "../types.js";
|
|
4
4
|
export type ComposedSignal = AbortSignal & {
|
|
5
5
|
unsubscribe?: () => void;
|
|
6
6
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fetch-helpers.d.ts","sourceRoot":"","sources":["../../../src/lib/adapters/fetch-helpers.ts"],"names":[],"mappings":"AAEA,OAAO,WAAW,+BAA+B;AACjD,OAAO,KAAK,aAAa,iCAAiC;AAC1D,OAAO,KAAK,EACV,
|
|
1
|
+
{"version":3,"file":"fetch-helpers.d.ts","sourceRoot":"","sources":["../../../src/lib/adapters/fetch-helpers.ts"],"names":[],"mappings":"AAEA,OAAO,WAAW,+BAA+B;AACjD,OAAO,KAAK,aAAa,iCAAiC;AAC1D,OAAO,KAAK,EACV,oBAAoB,EAEpB,2BAA2B,EAC5B,oBAAoB;AAGrB,MAAM,MAAM,cAAc,GAAG,WAAW,GAAG;IAAE,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;CAAE,CAAC;AACzE,MAAM,MAAM,mBAAmB,GAAG;IAAE,KAAK,EAAE,CAAC,WAAW,GAAG;QAAE,OAAO,CAAC,EAAE,OAAO,CAAC;KAAE,CAAC,GAAG,IAAI,CAAC;CAAE,CAAC;AAM5F,eAAO,MAAM,0BAA0B,GACrC,iBAAiB,aAAa,EAC9B,qBAAqB,OAAO,EAC5B,kBAAkB,MAAM,EACxB,QAAQ,2BAA2B,EACnC,SAAS,OAAO,KACf,IAaF,CAAC;AAGF,eAAO,MAAM,qBAAqB,GAChC,cAAc,OAAO,EACrB,qBAAqB,OAAO,EAC5B,kBAAkB,MAAM,EACxB,kBAAkB,OAAO,EACzB,wBAAwB,OAAO,EAC/B,QAAQ,2BAA2B,EACnC,SAAS,OAAO,KACf,IAwBF,CAAC;AAGF,eAAO,MAAM,sBAAsB,GACjC,KAAK,OAAO,EACZ,gBAAgB,cAAc,GAAG,SAAS,EAC1C,qBAAqB,mBAAmB,EACxC,QAAQ,2BAA2B,EACnC,SAAS,OAAO,KACf,KAyDF,CAAC;AAGF,eAAO,MAAM,wBAAwB,GACnC,MAAM,OAAO,EACb,SAAS,oBAAoB,KAC5B,IAWF,CAAC;AAGF,eAAO,MAAM,kBAAkB,GAC7B,MAAM,OAAO,EACb,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,QAAQ,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,CAAC,GAAG,UAAU,KACxD,OAAO,CAAC,OAAO,CAAC,GAAG,OAIrB,CAAC"}
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
+
import type { InternalFaxiosRequestConfig } from "../types.js";
|
|
2
|
+
type FetchAdapter = (config: InternalFaxiosRequestConfig) => Promise<unknown>;
|
|
1
3
|
export declare const getFetch: (config?: {
|
|
2
4
|
env?: Record<string, unknown>;
|
|
3
|
-
}) =>
|
|
5
|
+
}) => false | FetchAdapter;
|
|
6
|
+
export {};
|
|
4
7
|
//# sourceMappingURL=fetch.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../../../src/lib/adapters/fetch.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../../../src/lib/adapters/fetch.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAEV,2BAA2B,EAC5B,oBAAoB;AA6JrB,KAAK,YAAY,GAAG,CAAC,MAAM,EAAE,2BAA2B,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;AAytB9E,eAAO,MAAM,QAAQ,GAAI,SAAS;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAAE,KAAG,KAAK,GAAG,YAsB9E,CAAC"}
|
|
@@ -5,20 +5,37 @@ import { settle } from "../core/settle.js";
|
|
|
5
5
|
import { VERSION } from "../env/data.js";
|
|
6
6
|
import composeSignals from "../helpers/composeSignals.js";
|
|
7
7
|
import estimateDataURLDecodedBytes from "../helpers/estimateDataURLDecodedBytes.js";
|
|
8
|
-
import {
|
|
8
|
+
import { asyncDecorator, progressEventDecorator, progressEventReducer } from "../helpers/progressEventReducer.js";
|
|
9
9
|
import { toByteStringHeaderObject } from "../helpers/sanitizeHeaderValue.js";
|
|
10
10
|
import { trackStream } from "../helpers/trackStream.js";
|
|
11
11
|
import platform from "../platform.js";
|
|
12
12
|
import utils from "../utils.js";
|
|
13
|
-
import { checkDeclaredContentLength, checkMaterializedSize,
|
|
13
|
+
import { checkDeclaredContentLength, checkMaterializedSize, cleanFormDataContentType, encodeBodyIfNeeded, handleFetchCaughtError } from "./fetch-helpers.js";
|
|
14
14
|
// btoa is a global in Node 16+ and browsers; accessed via globalThis for no-DOM lib compat
|
|
15
15
|
const _btoa = globalThis["btoa"];
|
|
16
16
|
const DEFAULT_CHUNK_SIZE = 64 * 1024;
|
|
17
17
|
const { isFunction } = utils;
|
|
18
|
+
// Web stream bodies this adapter has sent. fetch can read a stream without leaving it locked,
|
|
19
|
+
// and there's no portable "disturbed" check, so a second send is caught here.
|
|
20
|
+
const sentStreamBodies = new WeakSet();
|
|
21
|
+
// A stream body can be read once. Middleware that calls next() again after a try read it
|
|
22
|
+
// would send an empty body (Node stream) or get an uncoded TypeError from fetch (web stream).
|
|
23
|
+
const rejectUsedStreamBody = (data, config) => {
|
|
24
|
+
const body = data;
|
|
25
|
+
const isWebStream = utils.isReadableStream(data);
|
|
26
|
+
if ((isWebStream && (body.locked === true || sentStreamBodies.has(body))) ||
|
|
27
|
+
((utils.isRequest(data) || utils.isResponse(data)) && body.bodyUsed === true) ||
|
|
28
|
+
(utils.isStream(data) && (body.readableDidRead === true || body.readableEnded === true || body.destroyed === true))) {
|
|
29
|
+
throw new FaxiosError("Request body stream was already used and can't be sent again; pass a new body for each try", FaxiosError.ERR_BAD_REQUEST, config);
|
|
30
|
+
}
|
|
31
|
+
if (isWebStream)
|
|
32
|
+
sentStreamBodies.add(body);
|
|
33
|
+
};
|
|
34
|
+
const isBrowserRuntime = platform.hasStandardBrowserEnv || platform.hasStandardBrowserWebWorkerEnv;
|
|
18
35
|
// Server runtimes default User-Agent to their own (e.g. "node"), so name faxios there.
|
|
19
36
|
// Browsers send their own User-Agent; setting one makes every cross-origin request
|
|
20
37
|
// need a CORS preflight that most APIs don't allow.
|
|
21
|
-
const setsUserAgent = !
|
|
38
|
+
const setsUserAgent = !isBrowserRuntime;
|
|
22
39
|
const applyDefaultUserAgent = (headers) => {
|
|
23
40
|
if (setsUserAgent)
|
|
24
41
|
headers.set("User-Agent", "faxios/" + VERSION, false);
|
|
@@ -61,28 +78,68 @@ const maybeWithAuthCredentials = (url) => {
|
|
|
61
78
|
// Only `@` indicates credentials in the authority; `:` alone is a port separator.
|
|
62
79
|
return urlToCheck.includes("@");
|
|
63
80
|
};
|
|
64
|
-
//
|
|
81
|
+
// RequestInit members faxios sets itself; the same keys in `fetchOptions` are ignored.
|
|
82
|
+
const FAXIOS_INIT_KEYS = {
|
|
83
|
+
body: true,
|
|
84
|
+
credentials: true,
|
|
85
|
+
duplex: true,
|
|
86
|
+
headers: true,
|
|
87
|
+
method: true,
|
|
88
|
+
signal: true,
|
|
89
|
+
};
|
|
90
|
+
// Spec defaults written as own init members when the caller sets none. undici converts the init
|
|
91
|
+
// into a plain dictionary and reads absent members from it, so an absent member still picks up a
|
|
92
|
+
// polluted Object.prototype value; an own default leaves nothing to inherit.
|
|
93
|
+
const REQUEST_INIT_DEFAULTS = {
|
|
94
|
+
cache: "default",
|
|
95
|
+
integrity: "",
|
|
96
|
+
keepalive: false,
|
|
97
|
+
mode: "cors",
|
|
98
|
+
redirect: "follow",
|
|
99
|
+
referrer: "about:client",
|
|
100
|
+
referrerPolicy: "",
|
|
101
|
+
};
|
|
102
|
+
// Where undici (Node's fetch) keeps its global dispatcher.
|
|
103
|
+
const UNDICI_GLOBAL_DISPATCHER = Symbol.for("undici.globalDispatcher.1");
|
|
104
|
+
// Own reads only: a polluted Object.prototype.fetch must never become the transport.
|
|
105
|
+
const readOwn = (obj, key) => typeof obj === "object" && obj !== null && utils.hasOwnProp(obj, key) ? Reflect.get(obj, key) : undefined;
|
|
106
|
+
const ownEnv = (config, key) => readOwn(readOwn(config, "env"), key);
|
|
107
|
+
// Feature detection depends only on the Request and Response constructors, so one adapter
|
|
108
|
+
// serves every `env.fetch`. `env.fetch` is read for each request.
|
|
65
109
|
const factory = (env) => {
|
|
66
110
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
67
111
|
const globalObject = utils.global ?? globalThis;
|
|
68
112
|
const ReadableStream = globalObject["ReadableStream"];
|
|
69
113
|
const TextEncoder = globalObject["TextEncoder"];
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
Request: globalObject["Request"],
|
|
74
|
-
Response: globalObject["Response"],
|
|
75
|
-
}, env);
|
|
76
|
-
const { fetch: envFetch, Request, Response, } = env;
|
|
77
|
-
const _globalFetch = globalThis["fetch"];
|
|
78
|
-
const isFetchSupported = envFetch
|
|
79
|
-
? isFunction(envFetch)
|
|
80
|
-
: isFunction(_globalFetch);
|
|
114
|
+
// `undefined` falls back to the global constructor; `null` disables it.
|
|
115
|
+
const Request = (env.Request === undefined ? globalObject["Request"] : env.Request);
|
|
116
|
+
const Response = (env.Response === undefined ? globalObject["Response"] : env.Response);
|
|
81
117
|
const isRequestSupported = isFunction(Request);
|
|
82
118
|
const isResponseSupported = isFunction(Response);
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
119
|
+
// Only members this runtime's Request exposes, so an engine that rejects members it doesn't
|
|
120
|
+
// implement (Cloudflare Workers) is never sent one.
|
|
121
|
+
const requestInitDefaults = Object.entries(REQUEST_INIT_DEFAULTS).filter(([key]) => isRequestSupported && utils.hasOwnInPrototypeChain(Request.prototype, key));
|
|
122
|
+
// Null prototype: WebIDL reads every RequestInit member with Get, which walks the prototype
|
|
123
|
+
// chain, so a plain object literal would let a polluted Object.prototype.redirect, .integrity,
|
|
124
|
+
// .mode or undici .dispatcher apply to every request. Every own enumerable key of fetchOptions
|
|
125
|
+
// is copied, so runtime extensions (Next.js `next`, Workers `cf`, Bun `tls`) still pass through;
|
|
126
|
+
// inherited keys never do. The caller sets signal, method, headers, body, duplex, credentials.
|
|
127
|
+
const initFromFetchOptions = (fetchOptions, envFetch) => {
|
|
128
|
+
const init = Object.create(null);
|
|
129
|
+
for (const [key, value] of requestInitDefaults)
|
|
130
|
+
init[key] = value;
|
|
131
|
+
// Node's global fetch reads `dispatcher` the same way; pin it to undici's own global one.
|
|
132
|
+
if (!envFetch && utils.hasOwnProp(globalThis, UNDICI_GLOBAL_DISPATCHER)) {
|
|
133
|
+
init["dispatcher"] = globalThis[UNDICI_GLOBAL_DISPATCHER];
|
|
134
|
+
}
|
|
135
|
+
if (utils.isObject(fetchOptions)) {
|
|
136
|
+
for (const key of Object.keys(fetchOptions)) {
|
|
137
|
+
if (!utils.hasOwnProp(FAXIOS_INIT_KEYS, key))
|
|
138
|
+
init[key] = fetchOptions[key];
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return init;
|
|
142
|
+
};
|
|
86
143
|
const isReadableStreamSupported = isFunction(ReadableStream);
|
|
87
144
|
const encodeText = typeof TextEncoder === "function"
|
|
88
145
|
? ((encoder) => (str) => encoder.encode(str))(new TextEncoder())
|
|
@@ -119,26 +176,27 @@ const factory = (env) => {
|
|
|
119
176
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
120
177
|
return duplexAccessed && !hasContentType;
|
|
121
178
|
});
|
|
179
|
+
// Outside browsers a FormData body under maxBodyLength is streamed and counted as fetch reads it;
|
|
180
|
+
// browsers can't send a stream body (see buildUploadStream).
|
|
181
|
+
const countsFormDataWhileSent = !isBrowserRuntime && supportsRequestStream;
|
|
182
|
+
// Bodies counted as fetch reads them when maxBodyLength is set.
|
|
183
|
+
const isCountedWhileSent = (body) => utils.isReadableStream(body) || utils.isStream(body) || (countsFormDataWhileSent && utils.isSpecCompliantForm(body));
|
|
122
184
|
const supportsResponseStream = isResponseSupported &&
|
|
123
185
|
isReadableStreamSupported &&
|
|
124
186
|
test(() => utils.isReadableStream(new Response("").body));
|
|
125
187
|
const resolvers = {
|
|
126
188
|
stream: supportsResponseStream && ((res) => res.body),
|
|
127
189
|
};
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
return method.call(res);
|
|
137
|
-
}
|
|
138
|
-
throw new FaxiosError(`Response type '${type}' is not supported`, FaxiosError.ERR_NOT_SUPPORT, config);
|
|
139
|
-
});
|
|
190
|
+
["text", "arrayBuffer", "blob", "formData", "stream"].forEach(type => {
|
|
191
|
+
!resolvers[type] &&
|
|
192
|
+
(resolvers[type] = (res, config) => {
|
|
193
|
+
const method = res[type];
|
|
194
|
+
if (method) {
|
|
195
|
+
return method.call(res);
|
|
196
|
+
}
|
|
197
|
+
throw new FaxiosError(`Response type '${type}' is not supported`, FaxiosError.ERR_NOT_SUPPORT, config);
|
|
140
198
|
});
|
|
141
|
-
|
|
199
|
+
});
|
|
142
200
|
const getBodyLength = async (body) => {
|
|
143
201
|
if (body == null) {
|
|
144
202
|
return 0;
|
|
@@ -146,13 +204,6 @@ const factory = (env) => {
|
|
|
146
204
|
if (utils.isBlob(body)) {
|
|
147
205
|
return body.size;
|
|
148
206
|
}
|
|
149
|
-
if (utils.isSpecCompliantForm(body)) {
|
|
150
|
-
const _request = new Request(platform.origin, {
|
|
151
|
-
method: "POST",
|
|
152
|
-
body,
|
|
153
|
-
});
|
|
154
|
-
return (await _request.arrayBuffer()).byteLength;
|
|
155
|
-
}
|
|
156
207
|
if (utils.isArrayBufferView(body) || utils.isArrayBuffer(body)) {
|
|
157
208
|
return body.byteLength;
|
|
158
209
|
}
|
|
@@ -164,6 +215,22 @@ const factory = (env) => {
|
|
|
164
215
|
}
|
|
165
216
|
return undefined;
|
|
166
217
|
};
|
|
218
|
+
// The bytes of a FormData body's field values and files, from their sizes, without reading the
|
|
219
|
+
// body. A lower bound: the multipart body adds boundaries and part headers. Undefined for any
|
|
220
|
+
// other body.
|
|
221
|
+
const getFormDataFieldsLength = async (body) => {
|
|
222
|
+
if (!utils.isSpecCompliantForm(body)) {
|
|
223
|
+
return undefined;
|
|
224
|
+
}
|
|
225
|
+
let length = 0;
|
|
226
|
+
for (const [, value] of body) {
|
|
227
|
+
// A FormData value is a string or a File.
|
|
228
|
+
const size = utils.isString(value) ? undefined : utils.getSafeProp(value, "size");
|
|
229
|
+
// eslint-disable-next-line no-await-in-loop
|
|
230
|
+
length += typeof size === "number" ? size : (await encodeText(String(value))).byteLength;
|
|
231
|
+
}
|
|
232
|
+
return length;
|
|
233
|
+
};
|
|
167
234
|
const resolveBodyLength = async (headers, body) => {
|
|
168
235
|
const length = utils.toFiniteNumber(headers.getContentLength());
|
|
169
236
|
return length == null ? getBodyLength(body) : length;
|
|
@@ -220,10 +287,13 @@ const factory = (env) => {
|
|
|
220
287
|
}
|
|
221
288
|
// Enforce maxBodyLength against known-size bodies before dispatch using
|
|
222
289
|
// the body's actual size — never a caller-declared Content-Length.
|
|
290
|
+
// A FormData body isn't measured, since that buffers it whole: its values alone over the limit
|
|
291
|
+
// reject it here, and where it's streamed the byte counter covers the multipart framing too.
|
|
223
292
|
if (hasMaxBodyLength && method !== "get" && method !== "head") {
|
|
224
293
|
const outboundLength = await getBodyLength(data);
|
|
225
|
-
|
|
226
|
-
|
|
294
|
+
const checkedLength = outboundLength ?? await getFormDataFieldsLength(data);
|
|
295
|
+
if (typeof checkedLength === "number" && isFinite(checkedLength)) {
|
|
296
|
+
if (checkedLength > maxBodyLength) {
|
|
227
297
|
throw new FaxiosError("Request body larger than maxBodyLength limit", FaxiosError.ERR_BAD_REQUEST, config, request);
|
|
228
298
|
}
|
|
229
299
|
return outboundLength;
|
|
@@ -248,6 +318,10 @@ const factory = (env) => {
|
|
|
248
318
|
};
|
|
249
319
|
// Set up request body streaming with upload progress and/or maxBodyLength enforcement.
|
|
250
320
|
const buildUploadStream = async (data, url, method, headers, onUploadProgress, mustEnforceStreamBody, requestContentLength, hasMaxBodyLength, maxBodyLength, config, request, pendingBodyErrorRef) => {
|
|
321
|
+
// Browsers can't be given a stream body for upload progress: Chromium sends one only over
|
|
322
|
+
// HTTP/2 or later and WebKit not at all, so the upload would fail. onUploadProgress isn't
|
|
323
|
+
// called there (#209).
|
|
324
|
+
const uploadProgress = isBrowserRuntime ? undefined : onUploadProgress;
|
|
251
325
|
const _makeBodyLengthError = () => new FaxiosError("Request body larger than maxBodyLength limit", FaxiosError.ERR_BAD_REQUEST, config, request);
|
|
252
326
|
const _trackStream = (stream, onProgress, flush) => trackStream(stream, DEFAULT_CHUNK_SIZE, (loadedBytes) => {
|
|
253
327
|
if (hasMaxBodyLength && loadedBytes > maxBodyLength) {
|
|
@@ -255,11 +329,18 @@ const factory = (env) => {
|
|
|
255
329
|
throw pendingBodyErrorRef.value;
|
|
256
330
|
}
|
|
257
331
|
onProgress && onProgress(loadedBytes);
|
|
258
|
-
},
|
|
332
|
+
}, (err) => {
|
|
333
|
+
// A chunk trackStream rejected (not bytes) surfaces as the coded error, not ERR_NETWORK.
|
|
334
|
+
if (err instanceof FaxiosError && !pendingBodyErrorRef.value) {
|
|
335
|
+
err.config = config;
|
|
336
|
+
pendingBodyErrorRef.value = err;
|
|
337
|
+
}
|
|
338
|
+
flush && flush();
|
|
339
|
+
});
|
|
259
340
|
if (supportsRequestStream &&
|
|
260
341
|
method !== "get" &&
|
|
261
342
|
method !== "head" &&
|
|
262
|
-
(
|
|
343
|
+
(uploadProgress || mustEnforceStreamBody)) {
|
|
263
344
|
requestContentLength =
|
|
264
345
|
requestContentLength == null
|
|
265
346
|
? await resolveBodyLength(headers, data)
|
|
@@ -272,7 +353,7 @@ const factory = (env) => {
|
|
|
272
353
|
body: data,
|
|
273
354
|
duplex: "half",
|
|
274
355
|
});
|
|
275
|
-
data = applyUploadProgress(_request, data, headers, requestContentLength,
|
|
356
|
+
data = applyUploadProgress(_request, data, headers, requestContentLength, uploadProgress, _trackStream);
|
|
276
357
|
}
|
|
277
358
|
}
|
|
278
359
|
else if (mustEnforceStreamBody &&
|
|
@@ -292,8 +373,8 @@ const factory = (env) => {
|
|
|
292
373
|
return { data, requestContentLength };
|
|
293
374
|
};
|
|
294
375
|
// Wrap the response body stream with download progress tracking and maxContentLength enforcement.
|
|
295
|
-
const buildDownloadStream = (response, responseHeaders, onDownloadProgress, hasMaxContentLength, maxContentLength, isStreamResponse,
|
|
296
|
-
const needsWrapping = onDownloadProgress || hasMaxContentLength ||
|
|
376
|
+
const buildDownloadStream = (response, responseHeaders, onDownloadProgress, hasMaxContentLength, maxContentLength, isStreamResponse, release, config, request) => {
|
|
377
|
+
const needsWrapping = !!onDownloadProgress || hasMaxContentLength || isStreamResponse;
|
|
297
378
|
if (!supportsResponseStream || !response.body || !needsWrapping) {
|
|
298
379
|
return response;
|
|
299
380
|
}
|
|
@@ -301,7 +382,13 @@ const factory = (env) => {
|
|
|
301
382
|
["status", "statusText", "headers"].forEach(prop => {
|
|
302
383
|
options[prop] = response[prop];
|
|
303
384
|
});
|
|
304
|
-
|
|
385
|
+
// Content-Length is the encoded size; the stream yields decoded bytes, so
|
|
386
|
+
// the total is unknown when the body is content-encoded.
|
|
387
|
+
const contentEncoding = String(responseHeaders.get("content-encoding") ?? "").trim()
|
|
388
|
+
.toLowerCase();
|
|
389
|
+
const responseContentLength = contentEncoding && contentEncoding !== "identity"
|
|
390
|
+
? undefined
|
|
391
|
+
: utils.toFiniteNumber(responseHeaders.getContentLength());
|
|
305
392
|
const [onProgress, flush] = onDownloadProgress
|
|
306
393
|
? progressEventDecorator(responseContentLength, progressEventReducer(asyncDecorator(onDownloadProgress), true))
|
|
307
394
|
: [];
|
|
@@ -315,14 +402,15 @@ const factory = (env) => {
|
|
|
315
402
|
}
|
|
316
403
|
onProgress && onProgress(loadedBytes);
|
|
317
404
|
};
|
|
318
|
-
return new Response(trackStream(response.body, DEFAULT_CHUNK_SIZE, onChunkProgress, () => {
|
|
405
|
+
return new Response(trackStream(response.body, DEFAULT_CHUNK_SIZE, onChunkProgress, (err) => {
|
|
319
406
|
flush && flush();
|
|
320
|
-
|
|
407
|
+
release(err);
|
|
321
408
|
}), options);
|
|
322
409
|
};
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
410
|
+
// A stream body releases the request when it ends; a response without a body has nothing to wait for.
|
|
411
|
+
const unsubscribeOnComplete = (isStreamResponse, response, unsubscribe) => {
|
|
412
|
+
if (!isStreamResponse || response.body == null)
|
|
413
|
+
unsubscribe();
|
|
326
414
|
};
|
|
327
415
|
return async (config) => {
|
|
328
416
|
const _resolved = prepareRequest(config);
|
|
@@ -334,22 +422,26 @@ const factory = (env) => {
|
|
|
334
422
|
const own = (key) => utils.hasOwnProp(config, key)
|
|
335
423
|
? config[key]
|
|
336
424
|
: undefined;
|
|
425
|
+
const envFetch = ownEnv(config, "fetch");
|
|
337
426
|
const _fetch = (envFetch || globalThis["fetch"]);
|
|
338
427
|
if (timeout != null && !Number.isFinite(Number(timeout))) {
|
|
339
428
|
throw new FaxiosError("error trying to parse `config.timeout` to int", FaxiosError.ERR_BAD_OPTION_VALUE, config);
|
|
340
429
|
}
|
|
341
430
|
responseType = (responseType ? (responseType + "").toLowerCase() : "text");
|
|
342
|
-
|
|
343
|
-
|
|
431
|
+
// Owns the request's cleanup: aborting it on a failure aborts fetch, which releases the
|
|
432
|
+
// connection and any body still being sent or received.
|
|
433
|
+
const requestController = new AbortController();
|
|
434
|
+
const composedSignal = composeSignals([signal, requestController.signal], timeout, timeoutErrorMessage);
|
|
435
|
+
const unsubscribe = composedSignal.unsubscribe.bind(composedSignal);
|
|
344
436
|
let request = null;
|
|
345
437
|
const pendingBodyErrorRef = { value: null };
|
|
346
438
|
try {
|
|
439
|
+
rejectUsedStreamBody(data, config);
|
|
347
440
|
url = applyAuthToRequest(url, headers, own);
|
|
348
441
|
const preflightContentLength = await checkPreflightLimits(url, data, method, hasMaxContentLength, maxContentLength, hasMaxBodyLength, maxBodyLength, config, request);
|
|
349
442
|
// A streamed body under maxBodyLength must be counted as fetch consumes
|
|
350
443
|
// it; its size is never trusted from a caller-declared Content-Length.
|
|
351
|
-
const
|
|
352
|
-
const mustEnforceStreamBody = hasMaxBodyLength && isStreamLike;
|
|
444
|
+
const mustEnforceStreamBody = hasMaxBodyLength && isCountedWhileSent(data);
|
|
353
445
|
({ data } = await buildUploadStream(data, url, method, headers, onUploadProgress, mustEnforceStreamBody, preflightContentLength, hasMaxBodyLength, maxBodyLength, config, request, pendingBodyErrorRef));
|
|
354
446
|
withCredentials = normalizeCredentials(withCredentials);
|
|
355
447
|
// Cloudflare Workers throws when credentials are defined
|
|
@@ -364,23 +456,18 @@ const factory = (env) => {
|
|
|
364
456
|
// Encoding as Uint8Array prevents the browser from injecting a content-type.
|
|
365
457
|
// Case-insensitive check: toByteStringHeaderObject may normalize to lowercase.
|
|
366
458
|
data = toWebStream(await encodeBodyIfNeeded(data, serializedHeaders, encodeText));
|
|
367
|
-
const resolvedOptions =
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
credentials: isCredentialsSupported ? withCredentials : undefined,
|
|
375
|
-
};
|
|
459
|
+
const resolvedOptions = initFromFetchOptions(fetchOptions, envFetch);
|
|
460
|
+
resolvedOptions["signal"] = composedSignal;
|
|
461
|
+
resolvedOptions["method"] = method.toUpperCase();
|
|
462
|
+
resolvedOptions["headers"] = serializedHeaders;
|
|
463
|
+
resolvedOptions["body"] = data;
|
|
464
|
+
resolvedOptions["duplex"] = "half";
|
|
465
|
+
resolvedOptions["credentials"] = isCredentialsSupported ? withCredentials : undefined;
|
|
376
466
|
request = isRequestSupported
|
|
377
467
|
? new Request(url, resolvedOptions)
|
|
378
468
|
: null;
|
|
379
|
-
// Pass resolvedOptions
|
|
380
|
-
//
|
|
381
|
-
// headers, body, credentials) off Object.prototype when init is absent,
|
|
382
|
-
// so a polluted Object.prototype.method would override the Request's verb.
|
|
383
|
-
// An explicit own-property init neutralizes every such gadget.
|
|
469
|
+
// Pass resolvedOptions as the fetch init even when a Request object is supplied, so the
|
|
470
|
+
// same null-prototype members apply to both calls.
|
|
384
471
|
let response = await (isRequestSupported
|
|
385
472
|
? _fetch(request, resolvedOptions)
|
|
386
473
|
: _fetch(url, resolvedOptions));
|
|
@@ -388,17 +475,26 @@ const factory = (env) => {
|
|
|
388
475
|
checkDeclaredContentLength(responseHeaders, hasMaxContentLength, maxContentLength, config, request);
|
|
389
476
|
const isStreamResponse = supportsResponseStream &&
|
|
390
477
|
(responseType === "stream" || responseType === "response");
|
|
391
|
-
|
|
478
|
+
// A stream body outlives this call, so its end, error or cancel releases the request.
|
|
479
|
+
// A buffered body is released below, or by the catch on failure.
|
|
480
|
+
const releaseStreamBody = (bodyErr) => {
|
|
481
|
+
if (!isStreamResponse)
|
|
482
|
+
return;
|
|
483
|
+
if (bodyErr !== undefined)
|
|
484
|
+
requestController.abort(bodyErr);
|
|
485
|
+
unsubscribe();
|
|
486
|
+
};
|
|
487
|
+
response = buildDownloadStream(response, responseHeaders, onDownloadProgress, hasMaxContentLength, maxContentLength, isStreamResponse, releaseStreamBody, config, request);
|
|
392
488
|
responseType = responseType || "text";
|
|
393
489
|
const resolverKey = utils.findKey(resolvers, responseType) || "text";
|
|
394
490
|
const resolver = resolvers[resolverKey];
|
|
395
491
|
const responseData = await (resolver && resolver(response, config));
|
|
396
492
|
checkMaterializedSize(responseData, hasMaxContentLength, maxContentLength, isStreamResponse, supportsResponseStream, config, request);
|
|
397
|
-
unsubscribeOnComplete(isStreamResponse, unsubscribe);
|
|
493
|
+
unsubscribeOnComplete(isStreamResponse, response, unsubscribe);
|
|
398
494
|
return await new Promise((resolve, reject) => {
|
|
399
495
|
settle(resolve, reject, {
|
|
400
496
|
data: responseData,
|
|
401
|
-
headers:
|
|
497
|
+
headers: responseHeaders,
|
|
402
498
|
status: response.status,
|
|
403
499
|
statusText: response.statusText,
|
|
404
500
|
config,
|
|
@@ -407,31 +503,53 @@ const factory = (env) => {
|
|
|
407
503
|
});
|
|
408
504
|
}
|
|
409
505
|
catch (err) {
|
|
410
|
-
|
|
411
|
-
|
|
506
|
+
let error = err;
|
|
507
|
+
try {
|
|
508
|
+
handleFetchCaughtError(err, composedSignal, pendingBodyErrorRef, config, request);
|
|
509
|
+
}
|
|
510
|
+
catch (classified) {
|
|
511
|
+
error = classified;
|
|
512
|
+
}
|
|
513
|
+
// Classify first: the abort below sets the composed signal's reason.
|
|
514
|
+
requestController.abort(error);
|
|
515
|
+
unsubscribe();
|
|
516
|
+
throw error;
|
|
412
517
|
}
|
|
413
518
|
};
|
|
414
519
|
};
|
|
415
|
-
|
|
520
|
+
// One adapter per Request/Response pair. Weak keys let a per-request `env.Request` or
|
|
521
|
+
// `env.Response` be collected. `undefined` (use the global) and any non-function (disabled)
|
|
522
|
+
// get stand-in keys.
|
|
523
|
+
const GLOBAL_CTOR = {};
|
|
524
|
+
const NO_CTOR = {};
|
|
525
|
+
const adapters = new WeakMap();
|
|
526
|
+
const ctorKey = (ctor) => {
|
|
527
|
+
if (ctor === undefined)
|
|
528
|
+
return GLOBAL_CTOR;
|
|
529
|
+
return isFunction(ctor) ? ctor : NO_CTOR;
|
|
530
|
+
};
|
|
531
|
+
// `false` tells dispatchRequest that this runtime has no fetch.
|
|
532
|
+
// eslint-disable-next-line sonarjs/function-return-type
|
|
416
533
|
export const getFetch = (config) => {
|
|
417
|
-
const
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
534
|
+
const fetch = ownEnv(config, "fetch");
|
|
535
|
+
if (!isFunction(fetch || globalThis["fetch"])) {
|
|
536
|
+
return false;
|
|
537
|
+
}
|
|
538
|
+
const Request = ownEnv(config, "Request");
|
|
539
|
+
const Response = ownEnv(config, "Response");
|
|
540
|
+
const requestKey = ctorKey(Request);
|
|
541
|
+
const responseKey = ctorKey(Response);
|
|
542
|
+
let byResponse = adapters.get(requestKey);
|
|
543
|
+
if (!byResponse) {
|
|
544
|
+
byResponse = new WeakMap();
|
|
545
|
+
adapters.set(requestKey, byResponse);
|
|
546
|
+
}
|
|
547
|
+
let adapter = byResponse.get(responseKey);
|
|
548
|
+
if (!adapter) {
|
|
549
|
+
adapter = factory({ Request, Response });
|
|
550
|
+
byResponse.set(responseKey, adapter);
|
|
433
551
|
}
|
|
434
|
-
return
|
|
552
|
+
return adapter;
|
|
435
553
|
};
|
|
436
554
|
getFetch();
|
|
437
555
|
//# sourceMappingURL=fetch.js.map
|