@gcmdev/faxios 0.1.0 → 0.2.1
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/LICENSE +1 -0
- package/README.md +40 -1774
- package/dist/index.d.ts +9 -6
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/adapters/fetch-helpers.d.ts +1 -0
- package/dist/lib/adapters/fetch-helpers.d.ts.map +1 -0
- package/dist/lib/adapters/fetch.d.ts +1 -0
- package/dist/lib/adapters/fetch.d.ts.map +1 -0
- package/dist/lib/adapters/fetch.js +23 -3
- package/dist/lib/adapters/fetch.js.map +1 -1
- package/dist/lib/cancel/CanceledError.d.ts +1 -0
- package/dist/lib/cancel/CanceledError.d.ts.map +1 -0
- package/dist/lib/cancel/isCancel.d.ts +3 -1
- package/dist/lib/cancel/isCancel.d.ts.map +1 -0
- package/dist/lib/cancel/isCancel.js +3 -0
- package/dist/lib/cancel/isCancel.js.map +1 -1
- package/dist/lib/core/Faxios.d.ts +6 -17
- package/dist/lib/core/Faxios.d.ts.map +1 -0
- package/dist/lib/core/Faxios.js +144 -76
- package/dist/lib/core/Faxios.js.map +1 -1
- package/dist/lib/core/FaxiosError.d.ts +19 -6
- package/dist/lib/core/FaxiosError.d.ts.map +1 -0
- package/dist/lib/core/FaxiosError.js +16 -1
- package/dist/lib/core/FaxiosError.js.map +1 -1
- package/dist/lib/core/FaxiosHeaders.d.ts +12 -8
- package/dist/lib/core/FaxiosHeaders.d.ts.map +1 -0
- package/dist/lib/core/FaxiosHeaders.js +1 -0
- package/dist/lib/core/FaxiosHeaders.js.map +1 -1
- package/dist/lib/core/buildFullPath.d.ts +1 -0
- package/dist/lib/core/buildFullPath.d.ts.map +1 -0
- package/dist/lib/core/define.d.ts +19 -2
- package/dist/lib/core/define.d.ts.map +1 -0
- package/dist/lib/core/define.js.map +1 -1
- package/dist/lib/core/dispatchRequest.d.ts +1 -0
- package/dist/lib/core/dispatchRequest.d.ts.map +1 -0
- package/dist/lib/core/dispatchRequest.js +4 -0
- package/dist/lib/core/dispatchRequest.js.map +1 -1
- package/dist/lib/core/mergeConfig.d.ts +1 -0
- package/dist/lib/core/mergeConfig.d.ts.map +1 -0
- package/dist/lib/core/prepareRequest.d.ts +1 -0
- package/dist/lib/core/prepareRequest.d.ts.map +1 -0
- package/dist/lib/core/prepareRequest.js +1 -20
- package/dist/lib/core/prepareRequest.js.map +1 -1
- package/dist/lib/core/route.d.ts +11 -2
- package/dist/lib/core/route.d.ts.map +1 -0
- package/dist/lib/core/route.js.map +1 -1
- package/dist/lib/core/settle.d.ts +1 -0
- package/dist/lib/core/settle.d.ts.map +1 -0
- package/dist/lib/core/transformData.d.ts +1 -0
- package/dist/lib/core/transformData.d.ts.map +1 -0
- package/dist/lib/core/validateSchema.d.ts +1 -0
- package/dist/lib/core/validateSchema.d.ts.map +1 -0
- package/dist/lib/defaults/index.d.ts +1 -0
- package/dist/lib/defaults/index.d.ts.map +1 -0
- package/dist/lib/defaults/index.js +3 -3
- package/dist/lib/defaults/index.js.map +1 -1
- package/dist/lib/defaults/transitional.d.ts +1 -1
- package/dist/lib/defaults/transitional.d.ts.map +1 -0
- package/dist/lib/defaults/transitional.js +0 -1
- package/dist/lib/defaults/transitional.js.map +1 -1
- package/dist/lib/env/data.d.ts +2 -1
- package/dist/lib/env/data.d.ts.map +1 -0
- package/dist/lib/env/data.js +1 -1
- package/dist/lib/env/data.js.map +1 -1
- package/dist/lib/faxios.d.ts +115 -48
- package/dist/lib/faxios.d.ts.map +1 -0
- package/dist/lib/faxios.js +14 -2
- package/dist/lib/faxios.js.map +1 -1
- package/dist/lib/helpers/FaxiosURLSearchParams.d.ts +3 -1
- package/dist/lib/helpers/FaxiosURLSearchParams.d.ts.map +1 -0
- package/dist/lib/helpers/FaxiosURLSearchParams.js.map +1 -1
- package/dist/lib/helpers/HttpStatusCode.d.ts +1 -0
- package/dist/lib/helpers/HttpStatusCode.d.ts.map +1 -0
- package/dist/lib/helpers/buildURL.d.ts +1 -0
- package/dist/lib/helpers/buildURL.d.ts.map +1 -0
- package/dist/lib/helpers/buildURL.js +7 -1
- package/dist/lib/helpers/buildURL.js.map +1 -1
- package/dist/lib/helpers/cloneConfig.d.ts +4 -0
- package/dist/lib/helpers/cloneConfig.d.ts.map +1 -0
- package/dist/lib/helpers/cloneConfig.js +21 -0
- package/dist/lib/helpers/cloneConfig.js.map +1 -0
- package/dist/lib/helpers/combineURLs.d.ts +1 -0
- package/dist/lib/helpers/combineURLs.d.ts.map +1 -0
- package/dist/lib/helpers/composeSignals.d.ts +1 -0
- package/dist/lib/helpers/composeSignals.d.ts.map +1 -0
- package/dist/lib/helpers/composeSignals.js +8 -1
- package/dist/lib/helpers/composeSignals.js.map +1 -1
- package/dist/lib/helpers/cookies.d.ts +1 -0
- package/dist/lib/helpers/cookies.d.ts.map +1 -0
- package/dist/lib/helpers/estimateDataURLDecodedBytes.d.ts +1 -0
- package/dist/lib/helpers/estimateDataURLDecodedBytes.d.ts.map +1 -0
- package/dist/lib/helpers/formDataToJSON.d.ts +1 -0
- package/dist/lib/helpers/formDataToJSON.d.ts.map +1 -0
- package/dist/lib/helpers/isAbsoluteURL.d.ts +1 -0
- package/dist/lib/helpers/isAbsoluteURL.d.ts.map +1 -0
- package/dist/lib/helpers/isFaxiosError.d.ts +8 -2
- package/dist/lib/helpers/isFaxiosError.d.ts.map +1 -0
- package/dist/lib/helpers/isFaxiosError.js +5 -1
- package/dist/lib/helpers/isFaxiosError.js.map +1 -1
- package/dist/lib/helpers/isURLSameOrigin.d.ts +1 -0
- package/dist/lib/helpers/isURLSameOrigin.d.ts.map +1 -0
- package/dist/lib/helpers/parseHeaders.d.ts +1 -0
- package/dist/lib/helpers/parseHeaders.d.ts.map +1 -0
- package/dist/lib/helpers/progressEventReducer.d.ts +1 -0
- package/dist/lib/helpers/progressEventReducer.d.ts.map +1 -0
- package/dist/lib/helpers/sanitizeHeaderValue.d.ts +1 -0
- package/dist/lib/helpers/sanitizeHeaderValue.d.ts.map +1 -0
- package/dist/lib/helpers/speedometer.d.ts +1 -0
- package/dist/lib/helpers/speedometer.d.ts.map +1 -0
- package/dist/lib/helpers/substitutePathParams.d.ts +1 -0
- package/dist/lib/helpers/substitutePathParams.d.ts.map +1 -0
- package/dist/lib/helpers/throttle.d.ts +1 -0
- package/dist/lib/helpers/throttle.d.ts.map +1 -0
- package/dist/lib/helpers/toFormData.d.ts +1 -0
- package/dist/lib/helpers/toFormData.d.ts.map +1 -0
- package/dist/lib/helpers/toURLEncodedForm.d.ts +1 -0
- package/dist/lib/helpers/toURLEncodedForm.d.ts.map +1 -0
- package/dist/lib/helpers/trackStream.d.ts +1 -0
- package/dist/lib/helpers/trackStream.d.ts.map +1 -0
- package/dist/lib/helpers/validator.d.ts +1 -0
- package/dist/lib/helpers/validator.d.ts.map +1 -0
- package/dist/lib/platform.d.ts +2 -1
- package/dist/lib/platform.d.ts.map +1 -0
- package/dist/lib/plugins/attempt.d.ts +2 -0
- package/dist/lib/plugins/attempt.d.ts.map +1 -0
- package/dist/lib/plugins/attempt.js +4 -0
- package/dist/lib/plugins/attempt.js.map +1 -0
- package/dist/lib/plugins/authBearer.d.ts +31 -0
- package/dist/lib/plugins/authBearer.d.ts.map +1 -0
- package/dist/lib/plugins/authBearer.js +99 -0
- package/dist/lib/plugins/authBearer.js.map +1 -0
- package/dist/lib/plugins/definePlugin.d.ts +22 -0
- package/dist/lib/plugins/definePlugin.d.ts.map +1 -0
- package/dist/lib/plugins/definePlugin.js +14 -0
- package/dist/lib/plugins/definePlugin.js.map +1 -0
- package/dist/lib/plugins/retry.d.ts +66 -0
- package/dist/lib/plugins/retry.d.ts.map +1 -0
- package/dist/lib/plugins/retry.js +168 -0
- package/dist/lib/plugins/retry.js.map +1 -0
- package/dist/lib/plugins/timing.d.ts +32 -0
- package/dist/lib/plugins/timing.d.ts.map +1 -0
- package/dist/lib/plugins/timing.js +53 -0
- package/dist/lib/plugins/timing.js.map +1 -0
- package/dist/lib/types/standard-schema.d.ts +1 -0
- package/dist/lib/types/standard-schema.d.ts.map +1 -0
- package/dist/lib/types.d.ts +125 -34
- package/dist/lib/types.d.ts.map +1 -0
- package/dist/lib/utils.d.ts +1 -0
- package/dist/lib/utils.d.ts.map +1 -0
- package/package.json +42 -19
- package/skills/configure-requests/SKILL.md +380 -0
- package/skills/configure-requests/references/axios-differences.md +67 -0
- package/skills/configure-requests/references/plugins.md +127 -0
- package/src/index.ts +57 -0
- package/src/lib/adapters/fetch-helpers.ts +167 -0
- package/src/lib/adapters/fetch.ts +810 -0
- package/src/lib/cancel/CanceledError.ts +23 -0
- package/src/lib/cancel/isCancel.ts +10 -0
- package/src/lib/core/Faxios.ts +513 -0
- package/src/lib/core/FaxiosError.ts +283 -0
- package/src/lib/core/FaxiosHeaders.ts +529 -0
- package/src/lib/core/buildFullPath.ts +51 -0
- package/src/lib/core/define.ts +127 -0
- package/src/lib/core/dispatchRequest.ts +171 -0
- package/src/lib/core/mergeConfig.ts +175 -0
- package/src/lib/core/prepareRequest.ts +155 -0
- package/src/lib/core/route.ts +68 -0
- package/src/lib/core/settle.ts +20 -0
- package/src/lib/core/transformData.ts +23 -0
- package/src/lib/core/validateSchema.ts +53 -0
- package/src/lib/defaults/index.ts +221 -0
- package/src/lib/defaults/transitional.ts +9 -0
- package/src/lib/env/data.ts +1 -0
- package/src/lib/faxios.ts +306 -0
- package/src/lib/helpers/FaxiosURLSearchParams.ts +52 -0
- package/src/lib/helpers/HttpStatusCode.ts +77 -0
- package/src/lib/helpers/buildURL.ts +77 -0
- package/src/lib/helpers/cloneConfig.ts +23 -0
- package/src/lib/helpers/combineURLs.ts +11 -0
- package/src/lib/helpers/composeSignals.ts +74 -0
- package/src/lib/helpers/cookies.ts +68 -0
- package/src/lib/helpers/deprecatedMethod.ts +32 -0
- package/src/lib/helpers/estimateDataURLDecodedBytes.ts +95 -0
- package/src/lib/helpers/formDataToJSON.ts +122 -0
- package/src/lib/helpers/isAbsoluteURL.ts +13 -0
- package/src/lib/helpers/isFaxiosError.ts +19 -0
- package/src/lib/helpers/isURLSameOrigin.ts +16 -0
- package/src/lib/helpers/parseHeaders.ts +76 -0
- package/src/lib/helpers/progressEventReducer.ts +57 -0
- package/src/lib/helpers/sanitizeHeaderValue.ts +61 -0
- package/src/lib/helpers/speedometer.ts +55 -0
- package/src/lib/helpers/substitutePathParams.ts +13 -0
- package/src/lib/helpers/throttle.ts +45 -0
- package/src/lib/helpers/toFormData.ts +296 -0
- package/src/lib/helpers/toURLEncodedForm.ts +14 -0
- package/src/lib/helpers/trackStream.ts +123 -0
- package/src/lib/helpers/validator.ts +114 -0
- package/src/lib/platform.ts +44 -0
- package/src/lib/plugins/attempt.ts +3 -0
- package/src/lib/plugins/authBearer.ts +124 -0
- package/src/lib/plugins/definePlugin.ts +34 -0
- package/src/lib/plugins/retry.ts +245 -0
- package/src/lib/plugins/timing.ts +76 -0
- package/src/lib/types/standard-schema.ts +58 -0
- package/src/lib/types.ts +496 -0
- package/src/lib/utils.ts +932 -0
- package/dist/lib/core/InterceptorManager.d.ts +0 -9
- package/dist/lib/core/InterceptorManager.js +0 -28
- package/dist/lib/core/InterceptorManager.js.map +0 -1
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import type { ParamEncoder } from "../types.js";
|
|
4
|
+
import utils from "../utils.js";
|
|
5
|
+
import FaxiosURLSearchParams from "./FaxiosURLSearchParams.js";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* It replaces URL-encoded forms of `:`, `$`, `,`, and spaces with
|
|
9
|
+
* their plain counterparts (`:`, `$`, `,`, `+`).
|
|
10
|
+
*
|
|
11
|
+
* @param {string} val The value to be encoded.
|
|
12
|
+
*
|
|
13
|
+
* @returns {string} The encoded value.
|
|
14
|
+
*/
|
|
15
|
+
export function encode(val: string): string {
|
|
16
|
+
return encodeURIComponent(val)
|
|
17
|
+
.replace(/%3A/gi, ":")
|
|
18
|
+
.replace(/%24/g, "$")
|
|
19
|
+
.replace(/%2C/gi, ",")
|
|
20
|
+
.replace(/%20/g, "+");
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// The request path validates `paramsSerializer.encode` as a function; this
|
|
24
|
+
// guard narrows the untyped option to ParamEncoder without asserting it.
|
|
25
|
+
function isParamEncoder(value: unknown): value is ParamEncoder {
|
|
26
|
+
return typeof value === "function";
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Build a URL by appending params to the end
|
|
31
|
+
*
|
|
32
|
+
* @param {string} url The base of the url (e.g., http://www.google.com)
|
|
33
|
+
* @param {object} [params] The params to be appended
|
|
34
|
+
* @param {?(object|Function)} options
|
|
35
|
+
*
|
|
36
|
+
* @returns {string} The formatted url
|
|
37
|
+
*/
|
|
38
|
+
export default function buildURL(url: string, params?: unknown, options?: unknown): string {
|
|
39
|
+
if (!params) {
|
|
40
|
+
return url;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const _options = utils.isFunction(options)
|
|
44
|
+
? {
|
|
45
|
+
serialize: options,
|
|
46
|
+
}
|
|
47
|
+
: options;
|
|
48
|
+
|
|
49
|
+
// Read serializer options pollution-safely: own properties and methods on a
|
|
50
|
+
// class/template prototype are honored, but values injected onto a polluted
|
|
51
|
+
// Object.prototype are ignored.
|
|
52
|
+
const customEncode = utils.getSafeProp(_options, "encode");
|
|
53
|
+
const _encode: ParamEncoder = isParamEncoder(customEncode) ? customEncode : encode;
|
|
54
|
+
const serializeFn = utils.getSafeProp(_options, "serialize") as ((params: unknown, options: unknown) => string) | undefined;
|
|
55
|
+
|
|
56
|
+
let serializedParams: string | undefined;
|
|
57
|
+
|
|
58
|
+
if (serializeFn) {
|
|
59
|
+
serializedParams = serializeFn(params, _options);
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
serializedParams = utils.isURLSearchParams(params)
|
|
63
|
+
? (params as { toString: () => string; }).toString()
|
|
64
|
+
: new FaxiosURLSearchParams(params, _options).toString(_encode);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (serializedParams) {
|
|
68
|
+
const hashmarkIndex = url.indexOf("#");
|
|
69
|
+
|
|
70
|
+
if (hashmarkIndex !== -1) {
|
|
71
|
+
url = url.slice(0, hashmarkIndex);
|
|
72
|
+
}
|
|
73
|
+
url += (url.indexOf("?") === -1 ? "?" : "&") + serializedParams;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return url;
|
|
77
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { FaxiosRequestConfig } from "../types.js";
|
|
2
|
+
|
|
3
|
+
export const DANGEROUS_KEYS = new Set([ "__proto__", "constructor", "prototype" ]);
|
|
4
|
+
|
|
5
|
+
// ponytail: null-proto shallow clone; replaces mergeConfig({}, config) which ran the full
|
|
6
|
+
// two-config merge machinery just to get a defensive copy. Security invariants preserved:
|
|
7
|
+
// null-proto so fetch.ts destructuring can't inherit Object.prototype gadgets, and
|
|
8
|
+
// dangerous keys filtered to block prototype-pollution write paths.
|
|
9
|
+
export default function cloneConfig<T extends FaxiosRequestConfig>(src: T): T & Record<string, unknown> {
|
|
10
|
+
const dst = Object.create(null) as T & Record<string, unknown>;
|
|
11
|
+
Object.defineProperty(dst, "hasOwnProperty", Object.assign(Object.create(null) as PropertyDescriptor, {
|
|
12
|
+
value: Object.prototype.hasOwnProperty,
|
|
13
|
+
writable: true,
|
|
14
|
+
configurable: true,
|
|
15
|
+
enumerable: false,
|
|
16
|
+
}));
|
|
17
|
+
for (const key of Object.keys(src)) {
|
|
18
|
+
if (!DANGEROUS_KEYS.has(key)) {
|
|
19
|
+
(dst as Record<string, unknown>)[key] = (src as Record<string, unknown>)[key];
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return dst;
|
|
23
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
export default function combineURLs(baseURL: string, relativeURL?: string): string {
|
|
4
|
+
if (!relativeURL) return baseURL;
|
|
5
|
+
// Scan indices, slice once — no regex (ReDoS risk on 100k-slash inputs in browser engines)
|
|
6
|
+
let i = baseURL.length - 1;
|
|
7
|
+
while (i >= 0 && baseURL.charCodeAt(i) === 47) i--;
|
|
8
|
+
let j = 0;
|
|
9
|
+
while (j < relativeURL.length && relativeURL.charCodeAt(j) === 47) j++;
|
|
10
|
+
return baseURL.slice(0, i + 1) + "/" + relativeURL.slice(j);
|
|
11
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import CanceledError from "../cancel/CanceledError.js";
|
|
2
|
+
import FaxiosError from "../core/FaxiosError.js";
|
|
3
|
+
import utils from "../utils.js";
|
|
4
|
+
|
|
5
|
+
type AbortHandler = (this: AbortSignal & { reason?: unknown; }, reason: unknown) => void;
|
|
6
|
+
type EventListenerFn = (event: unknown) => void;
|
|
7
|
+
type SignalLike = {
|
|
8
|
+
unsubscribe?: (() => void) | ((handler: AbortHandler) => void);
|
|
9
|
+
addEventListener: (type: string, listener: EventListenerFn) => void;
|
|
10
|
+
removeEventListener: (type: string, listener: EventListenerFn) => void;
|
|
11
|
+
aborted: boolean;
|
|
12
|
+
reason?: unknown;
|
|
13
|
+
};
|
|
14
|
+
export type ExtendedAbortSignal = AbortSignal & { unsubscribe?: (() => void) | ((handler: AbortHandler) => void); };
|
|
15
|
+
|
|
16
|
+
const composeSignals = (signals: Array<unknown> | null | undefined, timeout?: number, timeoutMessage?: string): ExtendedAbortSignal | undefined => {
|
|
17
|
+
let activeSignals: Array<SignalLike> | null = signals ? (signals.filter(Boolean) as Array<SignalLike>) : [];
|
|
18
|
+
|
|
19
|
+
if (!timeout && !activeSignals.length) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const controller = new AbortController();
|
|
24
|
+
|
|
25
|
+
let aborted = false;
|
|
26
|
+
|
|
27
|
+
const onabort: AbortHandler = function (this: AbortSignal & { reason?: unknown; }, reason: unknown) {
|
|
28
|
+
if (!aborted) {
|
|
29
|
+
aborted = true;
|
|
30
|
+
unsubscribe();
|
|
31
|
+
const err = reason instanceof Error ? reason : this.reason;
|
|
32
|
+
const errMsg = err instanceof Error ? err.message : (err as string | undefined);
|
|
33
|
+
const abortErr = err instanceof FaxiosError ? err : new CanceledError(errMsg, undefined, undefined);
|
|
34
|
+
controller.abort(abortErr);
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
let timer: ReturnType<typeof setTimeout> | null =
|
|
39
|
+
timeout
|
|
40
|
+
? setTimeout(() => {
|
|
41
|
+
timer = null;
|
|
42
|
+
onabort.call(controller.signal, new FaxiosError(timeoutMessage || `timeout of ${timeout}ms exceeded`, FaxiosError.ETIMEDOUT));
|
|
43
|
+
}, timeout)
|
|
44
|
+
: null;
|
|
45
|
+
|
|
46
|
+
const unsubscribe = () => {
|
|
47
|
+
if (!activeSignals) { return; }
|
|
48
|
+
if (timer) { clearTimeout(timer); }
|
|
49
|
+
timer = null;
|
|
50
|
+
activeSignals.forEach(signal => {
|
|
51
|
+
signal.unsubscribe
|
|
52
|
+
? (signal.unsubscribe)(onabort)
|
|
53
|
+
: signal.removeEventListener("abort", onabort);
|
|
54
|
+
});
|
|
55
|
+
activeSignals = null;
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
// An already-aborted input never fires "abort" again, so propagate it now.
|
|
59
|
+
for (const signal of activeSignals) {
|
|
60
|
+
if (signal.aborted) {
|
|
61
|
+
onabort.call(signal as unknown as AbortSignal, signal.reason);
|
|
62
|
+
break;
|
|
63
|
+
}
|
|
64
|
+
signal.addEventListener("abort", onabort);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const { signal } = controller;
|
|
68
|
+
|
|
69
|
+
(signal as ExtendedAbortSignal).unsubscribe = () => utils.asap(unsubscribe);
|
|
70
|
+
|
|
71
|
+
return signal;
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
export default composeSignals;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import platform from "../platform.js";
|
|
2
|
+
import utils from "../utils.js";
|
|
3
|
+
|
|
4
|
+
type CookieManager = {
|
|
5
|
+
write: (name: string, value: string, expires?: number, path?: string, domain?: string, secure?: boolean, sameSite?: string) => void;
|
|
6
|
+
read: (name: string) => string | null;
|
|
7
|
+
remove: (name: string) => void;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
const _globalThis = globalThis as { document?: { cookie?: string; }; };
|
|
11
|
+
|
|
12
|
+
export default platform.hasStandardBrowserEnv
|
|
13
|
+
? // Standard browser envs support document.cookie
|
|
14
|
+
{
|
|
15
|
+
write(name: string, value: string, expires?: number, path?: string, domain?: string, secure?: boolean, sameSite?: string) {
|
|
16
|
+
if (!_globalThis.document) return;
|
|
17
|
+
|
|
18
|
+
const cookie = [ `${name}=${encodeURIComponent(value)}` ];
|
|
19
|
+
|
|
20
|
+
if (utils.isNumber(expires)) {
|
|
21
|
+
cookie.push(`expires=${new Date(expires!).toUTCString()}`);
|
|
22
|
+
}
|
|
23
|
+
if (utils.isString(path)) {
|
|
24
|
+
cookie.push(`path=${path}`);
|
|
25
|
+
}
|
|
26
|
+
if (utils.isString(domain)) {
|
|
27
|
+
cookie.push(`domain=${domain}`);
|
|
28
|
+
}
|
|
29
|
+
if (secure === true) {
|
|
30
|
+
cookie.push("secure");
|
|
31
|
+
}
|
|
32
|
+
if (utils.isString(sameSite)) {
|
|
33
|
+
cookie.push(`SameSite=${sameSite}`);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
_globalThis.document.cookie = cookie.join("; ");
|
|
37
|
+
},
|
|
38
|
+
|
|
39
|
+
read(name: string): string | null {
|
|
40
|
+
if (!_globalThis.document) return null;
|
|
41
|
+
// Match name=value by splitting on the semicolon separator instead of building a
|
|
42
|
+
// RegExp from `name` — interpolating an unescaped string into a RegExp would let
|
|
43
|
+
// metacharacters (e.g. `.+?` in an attacker-influenced cookie name) cause ReDoS or
|
|
44
|
+
// match the wrong cookie. Browsers may serialize cookie pairs as either ";" or
|
|
45
|
+
// "; ", so ignore optional whitespace before each cookie name.
|
|
46
|
+
const cookies = (_globalThis.document.cookie ?? "").split(";");
|
|
47
|
+
for (let i = 0; i < cookies.length; i++) {
|
|
48
|
+
const cookie = cookies[i]!.replace(/^\s+/, "");
|
|
49
|
+
const eq = cookie.indexOf("=");
|
|
50
|
+
if (eq !== -1 && cookie.slice(0, eq) === name) {
|
|
51
|
+
return decodeURIComponent(cookie.slice(eq + 1));
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return null;
|
|
55
|
+
},
|
|
56
|
+
|
|
57
|
+
remove(name: string) {
|
|
58
|
+
this.write(name, "", Date.now() - 86400000, "/");
|
|
59
|
+
},
|
|
60
|
+
} satisfies CookieManager
|
|
61
|
+
: // Non-standard browser env (web workers, react-native) lack needed support.
|
|
62
|
+
{
|
|
63
|
+
write() {},
|
|
64
|
+
read(): null {
|
|
65
|
+
return null;
|
|
66
|
+
},
|
|
67
|
+
remove() {},
|
|
68
|
+
} satisfies CookieManager;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/*eslint no-console:0*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Supply a warning to the developer that a method they are using
|
|
7
|
+
* has been deprecated.
|
|
8
|
+
*
|
|
9
|
+
* @param {string} method The name of the deprecated method
|
|
10
|
+
* @param {string} [instead] The alternate method to use if applicable
|
|
11
|
+
* @param {string} [docs] The documentation URL to get further details
|
|
12
|
+
*
|
|
13
|
+
* @returns {void}
|
|
14
|
+
*/
|
|
15
|
+
export default function deprecatedMethod(method: string, instead?: string, docs?: string) {
|
|
16
|
+
try {
|
|
17
|
+
console.warn(
|
|
18
|
+
"DEPRECATED method `" +
|
|
19
|
+
method +
|
|
20
|
+
"`." +
|
|
21
|
+
(instead ? " Use `" + instead + "` instead." : "") +
|
|
22
|
+
" This method will be removed in a future release."
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
if (docs) {
|
|
26
|
+
console.warn("For more information about usage see " + docs);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
/* Ignore */
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Estimate decoded byte length of a data:// URL *without* allocating large buffers.
|
|
3
|
+
* - For base64: compute exact decoded size using length and padding;
|
|
4
|
+
* handle %XX at the character-count level (no string allocation).
|
|
5
|
+
* - For non-base64: compute the exact percent-decoded UTF-8 byte length.
|
|
6
|
+
*
|
|
7
|
+
* @param {string} url
|
|
8
|
+
* @returns {number}
|
|
9
|
+
*/
|
|
10
|
+
const isHexDigit = (charCode: number) =>
|
|
11
|
+
(charCode >= 48 && charCode <= 57) ||
|
|
12
|
+
(charCode >= 65 && charCode <= 70) ||
|
|
13
|
+
(charCode >= 97 && charCode <= 102);
|
|
14
|
+
|
|
15
|
+
const isPercentEncodedByte = (str: string, i: number, len: number) =>
|
|
16
|
+
i + 2 < len &&
|
|
17
|
+
isHexDigit(str.charCodeAt(i + 1)) &&
|
|
18
|
+
isHexDigit(str.charCodeAt(i + 2));
|
|
19
|
+
|
|
20
|
+
function countBase64Padding(body: string, len: number): number {
|
|
21
|
+
let pad = 0;
|
|
22
|
+
let i = len;
|
|
23
|
+
while (pad < 2 && i > 0) {
|
|
24
|
+
if (body.charCodeAt(i - 1) === 61 /* '=' */) {
|
|
25
|
+
pad++;
|
|
26
|
+
i--;
|
|
27
|
+
}
|
|
28
|
+
else if (i >= 3 && body.charCodeAt(i - 3) === 37 /* '%' */ && body.charCodeAt(i - 2) === 51 /* '3' */ &&
|
|
29
|
+
(body.charCodeAt(i - 1) === 68 || body.charCodeAt(i - 1) === 100) /* 'D'|'d' */) {
|
|
30
|
+
pad++;
|
|
31
|
+
i -= 3;
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
break;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return pad;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function estimateBase64DecodedBytes(body: string): number {
|
|
41
|
+
let effectiveLen = body.length;
|
|
42
|
+
const len = body.length;
|
|
43
|
+
|
|
44
|
+
for (let i = 0; i < len; i++) {
|
|
45
|
+
if (body.charCodeAt(i) === 37 /* '%' */ && i + 2 < len) {
|
|
46
|
+
const a = body.charCodeAt(i + 1);
|
|
47
|
+
const b = body.charCodeAt(i + 2);
|
|
48
|
+
if (isHexDigit(a) && isHexDigit(b)) {
|
|
49
|
+
effectiveLen -= 2;
|
|
50
|
+
i += 2;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const pad = countBase64Padding(body, len);
|
|
56
|
+
const bytes = Math.floor(effectiveLen / 4) * 3 - pad;
|
|
57
|
+
return bytes > 0 ? bytes : 0;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Returns [utf8Bytes, extraCharsToSkip]
|
|
61
|
+
function utf8CharBytes(body: string, i: number, len: number): [number, number] {
|
|
62
|
+
const c = body.charCodeAt(i);
|
|
63
|
+
if (c === 37 /* '%' */ && isPercentEncodedByte(body, i, len)) return [ 1, 2 ];
|
|
64
|
+
if (c < 0x80) return [ 1, 0 ];
|
|
65
|
+
if (c < 0x800) return [ 2, 0 ];
|
|
66
|
+
if (c >= 0xd800 && c <= 0xdbff && i + 1 < len) {
|
|
67
|
+
const next = body.charCodeAt(i + 1);
|
|
68
|
+
if (next >= 0xdc00 && next <= 0xdfff) return [ 4, 1 ];
|
|
69
|
+
}
|
|
70
|
+
return [ 3, 0 ];
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Compute UTF-8 byte length directly from UTF-16 code units without allocating
|
|
74
|
+
// a byte buffer (TextEncoder.encode would defeat the DoS guard on large bodies).
|
|
75
|
+
function estimateUtf8BodyBytes(body: string): number {
|
|
76
|
+
let bytes = 0;
|
|
77
|
+
for (let i = 0, len = body.length; i < len; i++) {
|
|
78
|
+
const [ b, skip ] = utf8CharBytes(body, i, len);
|
|
79
|
+
bytes += b;
|
|
80
|
+
i += skip;
|
|
81
|
+
}
|
|
82
|
+
return bytes;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export default function estimateDataURLDecodedBytes(url: string): number {
|
|
86
|
+
if (!url || typeof url !== "string") return 0;
|
|
87
|
+
if (!url.startsWith("data:")) return 0;
|
|
88
|
+
|
|
89
|
+
const comma = url.indexOf(",");
|
|
90
|
+
if (comma < 0) return 0;
|
|
91
|
+
|
|
92
|
+
const meta = url.slice(5, comma);
|
|
93
|
+
const body = url.slice(comma + 1);
|
|
94
|
+
return /;base64/i.test(meta) ? estimateBase64DecodedBytes(body) : estimateUtf8BodyBytes(body);
|
|
95
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import FaxiosError from "../core/FaxiosError.js";
|
|
4
|
+
import utils from "../utils.js";
|
|
5
|
+
import { DEFAULT_FORM_DATA_MAX_DEPTH } from "./toFormData.js";
|
|
6
|
+
|
|
7
|
+
const MAX_DEPTH = DEFAULT_FORM_DATA_MAX_DEPTH;
|
|
8
|
+
|
|
9
|
+
function throwIfDepthExceeded(index: number): void {
|
|
10
|
+
if (index > MAX_DEPTH) {
|
|
11
|
+
throw new FaxiosError(
|
|
12
|
+
"FormData field is too deeply nested (" + index + " levels). Max depth: " + MAX_DEPTH,
|
|
13
|
+
FaxiosError.ERR_FORM_DATA_DEPTH_EXCEEDED
|
|
14
|
+
);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* It takes a string like `foo[x][y][z]` and returns an array like `['foo', 'x', 'y', 'z']
|
|
20
|
+
*
|
|
21
|
+
* @param {string} name - The name of the property to get.
|
|
22
|
+
*
|
|
23
|
+
* @returns An array of strings.
|
|
24
|
+
*/
|
|
25
|
+
function parsePropPath(name: string): Array<string> {
|
|
26
|
+
// foo[x][y][z]
|
|
27
|
+
// foo.x.y.z
|
|
28
|
+
// foo-x-y-z
|
|
29
|
+
// foo x y z
|
|
30
|
+
const path: Array<string> = [];
|
|
31
|
+
const pattern = /\w+|\[(\w*)]/g;
|
|
32
|
+
let match: RegExpExecArray | null;
|
|
33
|
+
|
|
34
|
+
while ((match = pattern.exec(name)) !== null) {
|
|
35
|
+
throwIfDepthExceeded(path.length);
|
|
36
|
+
path.push(match[0] === "[]" ? "" : (match[1] ?? match[0]));
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return path;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Convert an array to an object.
|
|
44
|
+
*
|
|
45
|
+
* @param {Array<any>} arr - The array to convert to an object.
|
|
46
|
+
*
|
|
47
|
+
* @returns An object with the same keys and values as the array.
|
|
48
|
+
*/
|
|
49
|
+
function arrayToObject(arr: Array<unknown>): Record<string, unknown> {
|
|
50
|
+
const obj: Record<string, unknown> = {};
|
|
51
|
+
const keys = Object.keys(arr);
|
|
52
|
+
let i: number;
|
|
53
|
+
const len = keys.length;
|
|
54
|
+
let key: string;
|
|
55
|
+
for (i = 0; i < len; i++) {
|
|
56
|
+
key = keys[i]!;
|
|
57
|
+
obj[key] = (arr as unknown as Record<string, unknown>)[key];
|
|
58
|
+
}
|
|
59
|
+
return obj;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* It takes a FormData object and returns a JavaScript object
|
|
64
|
+
*
|
|
65
|
+
* @param {string} formData The FormData object to convert to JSON.
|
|
66
|
+
*
|
|
67
|
+
* @returns {Object<string, any> | null} The converted object.
|
|
68
|
+
*/
|
|
69
|
+
function formDataToJSON(formData: unknown): Record<string, unknown> | null {
|
|
70
|
+
function buildPath(path: Array<string>, value: unknown, target: Record<string, unknown>, index: number): boolean {
|
|
71
|
+
throwIfDepthExceeded(index);
|
|
72
|
+
|
|
73
|
+
let name: string | number = path[index++]!;
|
|
74
|
+
|
|
75
|
+
if (name === "__proto__") return true;
|
|
76
|
+
|
|
77
|
+
const isNumericKey = Number.isFinite(+name);
|
|
78
|
+
const isLast = index >= path.length;
|
|
79
|
+
name = !name && utils.isArray(target) ? (target as Array<unknown>).length : name;
|
|
80
|
+
|
|
81
|
+
const key = String(name);
|
|
82
|
+
|
|
83
|
+
if (isLast) {
|
|
84
|
+
if (utils.hasOwnProp(target, key)) {
|
|
85
|
+
target[key] = utils.isArray(target[key])
|
|
86
|
+
? (target[key] as Array<unknown>).concat(value)
|
|
87
|
+
: [ target[key], value ];
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
target[key] = value;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return !isNumericKey;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (!utils.hasOwnProp(target, key) || !utils.isObject(target[key])) {
|
|
97
|
+
target[key] = [];
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const result = buildPath(path, value, target[key] as Record<string, unknown>, index);
|
|
101
|
+
|
|
102
|
+
if (result && utils.isArray(target[key])) {
|
|
103
|
+
target[key] = arrayToObject(target[key] as Array<unknown>);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return !isNumericKey;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (utils.isFormData(formData) && utils.isFunction((formData as { entries?: unknown; }).entries)) {
|
|
110
|
+
const obj: Record<string, unknown> = {};
|
|
111
|
+
|
|
112
|
+
utils.forEachEntry(formData, (name: unknown, value: unknown) => {
|
|
113
|
+
buildPath(parsePropPath(name as string), value, obj, 0);
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
return obj;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return null;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export default formDataToJSON;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
// ponytail: protocol-relative URLs (//) intentionally not supported — HTTPS-era fork
|
|
4
|
+
export default function isAbsoluteURL(url: unknown): boolean {
|
|
5
|
+
if (typeof url !== "string") return false;
|
|
6
|
+
try {
|
|
7
|
+
new URL(url);
|
|
8
|
+
return true;
|
|
9
|
+
}
|
|
10
|
+
catch {
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import type FaxiosError from "../core/FaxiosError.js";
|
|
4
|
+
import utils from "../utils.js";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Determines whether the payload is an error thrown by Faxios.
|
|
8
|
+
*
|
|
9
|
+
* Checks the `isFaxiosError` brand, not `instanceof`, so errors from another
|
|
10
|
+
* copy of faxios still match. `T` and `D` type `response.data` and
|
|
11
|
+
* `config.data`; they are not checked at runtime.
|
|
12
|
+
*
|
|
13
|
+
* @param {*} payload The value to test
|
|
14
|
+
*
|
|
15
|
+
* @returns {boolean} True if the payload is an error thrown by Faxios, otherwise false
|
|
16
|
+
*/
|
|
17
|
+
export default function isFaxiosError<T = unknown, D = unknown>(payload: unknown): payload is FaxiosError<T, D> {
|
|
18
|
+
return utils.isObject(payload) && (payload as Record<string, unknown>).isFaxiosError === true;
|
|
19
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import platform from "../platform.js";
|
|
2
|
+
|
|
3
|
+
export default platform.hasStandardBrowserEnv
|
|
4
|
+
? ((origin, isMSIE) => (url: string) => {
|
|
5
|
+
const _url = new URL(url, platform.origin);
|
|
6
|
+
|
|
7
|
+
return (
|
|
8
|
+
origin.protocol === _url.protocol &&
|
|
9
|
+
origin.host === _url.host &&
|
|
10
|
+
(isMSIE || origin.port === _url.port)
|
|
11
|
+
);
|
|
12
|
+
})(
|
|
13
|
+
new URL(platform.origin),
|
|
14
|
+
!!(/(msie|trident)/i.test(platform.navigator?.userAgent ?? ""))
|
|
15
|
+
)
|
|
16
|
+
: () => true;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import utils from "../utils.js";
|
|
4
|
+
|
|
5
|
+
// RawFaxiosHeaders whose duplicates are ignored by node
|
|
6
|
+
// c.f. https://nodejs.org/api/http.html#http_message_headers
|
|
7
|
+
const ignoreDuplicateOf = utils.toObjectSet([
|
|
8
|
+
"age",
|
|
9
|
+
"authorization",
|
|
10
|
+
"content-length",
|
|
11
|
+
"content-type",
|
|
12
|
+
"etag",
|
|
13
|
+
"expires",
|
|
14
|
+
"from",
|
|
15
|
+
"host",
|
|
16
|
+
"if-modified-since",
|
|
17
|
+
"if-unmodified-since",
|
|
18
|
+
"last-modified",
|
|
19
|
+
"location",
|
|
20
|
+
"max-forwards",
|
|
21
|
+
"proxy-authorization",
|
|
22
|
+
"referer",
|
|
23
|
+
"retry-after",
|
|
24
|
+
"user-agent",
|
|
25
|
+
], "");
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Parse headers into an object
|
|
29
|
+
*
|
|
30
|
+
* ```
|
|
31
|
+
* Date: Wed, 27 Aug 2014 08:58:49 GMT
|
|
32
|
+
* Content-Type: application/json
|
|
33
|
+
* Connection: keep-alive
|
|
34
|
+
* Transfer-Encoding: chunked
|
|
35
|
+
* ```
|
|
36
|
+
*
|
|
37
|
+
* @param {String} rawHeaders Headers needing to be parsed
|
|
38
|
+
*
|
|
39
|
+
* @returns {Object} Headers parsed into an object
|
|
40
|
+
*/
|
|
41
|
+
export default (rawHeaders: string): Record<string, string | Array<string>> => {
|
|
42
|
+
const parsed: Record<string, string | Array<string>> = {};
|
|
43
|
+
let key: string;
|
|
44
|
+
let val: string;
|
|
45
|
+
let i: number;
|
|
46
|
+
|
|
47
|
+
rawHeaders &&
|
|
48
|
+
rawHeaders.split("\n")
|
|
49
|
+
.forEach(function parser(line) {
|
|
50
|
+
// eslint-disable-next-line big-o/no-array-lookup-in-loop
|
|
51
|
+
i = line.indexOf(":");
|
|
52
|
+
key = line.substring(0, i).trim()
|
|
53
|
+
.toLowerCase();
|
|
54
|
+
val = line.substring(i + 1).trim();
|
|
55
|
+
|
|
56
|
+
if (!key || (parsed[key] !== undefined && ignoreDuplicateOf[key] !== undefined)) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (key === "set-cookie") {
|
|
61
|
+
const existing = parsed[key];
|
|
62
|
+
if (existing) {
|
|
63
|
+
(existing as Array<string>).push(val);
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
parsed[key] = [ val ];
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
const existing = parsed[key] as string | undefined;
|
|
71
|
+
parsed[key] = existing ? existing + ", " + val : val;
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
return parsed;
|
|
76
|
+
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { FaxiosProgressEvent } from "../types.js";
|
|
2
|
+
import utils from "../utils.js";
|
|
3
|
+
import speedometer from "./speedometer.js";
|
|
4
|
+
import throttle from "./throttle.js";
|
|
5
|
+
|
|
6
|
+
export const progressEventReducer = (listener: (data: FaxiosProgressEvent) => void, isDownloadStream: boolean, freq = 3) => {
|
|
7
|
+
let bytesNotified = 0;
|
|
8
|
+
const _speedometer = speedometer(50, 250);
|
|
9
|
+
|
|
10
|
+
return throttle((e: unknown) => {
|
|
11
|
+
if (!e || typeof (e as Record<string, unknown>).loaded !== "number") {
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
const ev = e as { loaded: number; total?: number; lengthComputable?: boolean; };
|
|
15
|
+
const rawLoaded = ev.loaded;
|
|
16
|
+
const total = ev.lengthComputable ? ev.total : undefined;
|
|
17
|
+
const loaded = total != null ? Math.min(rawLoaded, total) : rawLoaded;
|
|
18
|
+
const progressBytes = Math.max(0, loaded - bytesNotified);
|
|
19
|
+
const rate = _speedometer(progressBytes);
|
|
20
|
+
|
|
21
|
+
bytesNotified = Math.max(bytesNotified, loaded);
|
|
22
|
+
|
|
23
|
+
const data: FaxiosProgressEvent = {
|
|
24
|
+
loaded,
|
|
25
|
+
total,
|
|
26
|
+
progress: total ? loaded / total : undefined,
|
|
27
|
+
bytes: progressBytes,
|
|
28
|
+
rate: rate ? rate : undefined,
|
|
29
|
+
estimated: rate && total ? (total - loaded) / rate : undefined,
|
|
30
|
+
event: e,
|
|
31
|
+
lengthComputable: total != null,
|
|
32
|
+
download: isDownloadStream ? true : undefined,
|
|
33
|
+
upload: isDownloadStream ? undefined : true,
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
listener(data);
|
|
37
|
+
}, freq);
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export const progressEventDecorator = (total: number | undefined, throttled: ReturnType<typeof throttle>): [(loaded: number) => void, () => void] => {
|
|
41
|
+
const lengthComputable = total != null;
|
|
42
|
+
|
|
43
|
+
return [
|
|
44
|
+
(loaded: number) =>
|
|
45
|
+
throttled[0]({
|
|
46
|
+
lengthComputable,
|
|
47
|
+
total,
|
|
48
|
+
loaded,
|
|
49
|
+
}),
|
|
50
|
+
throttled[1],
|
|
51
|
+
];
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
export const asyncDecorator =
|
|
55
|
+
(fn: (...args: Array<unknown>) => unknown) =>
|
|
56
|
+
(...args: Array<unknown>) =>
|
|
57
|
+
utils.asap(() => fn(...args));
|