@gcmdev/faxios 0.2.0 → 0.2.2
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 +8 -0
- package/dist/index.d.ts +4 -3
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/adapters/fetch-helpers.d.ts +2 -1
- 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 +86 -26
- package/dist/lib/adapters/fetch.js.map +1 -1
- package/dist/lib/cancel/CanceledError.d.ts +2 -1
- package/dist/lib/cancel/CanceledError.d.ts.map +1 -0
- package/dist/lib/cancel/isCancel.d.ts +1 -0
- package/dist/lib/cancel/isCancel.d.ts.map +1 -0
- package/dist/lib/core/Faxios.d.ts +4 -3
- package/dist/lib/core/Faxios.d.ts.map +1 -0
- package/dist/lib/core/Faxios.js +8 -4
- package/dist/lib/core/Faxios.js.map +1 -1
- package/dist/lib/core/FaxiosError.d.ts +3 -2
- package/dist/lib/core/FaxiosError.d.ts.map +1 -0
- package/dist/lib/core/FaxiosHeaders.d.ts +9 -8
- package/dist/lib/core/FaxiosHeaders.d.ts.map +1 -0
- 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 +20 -3
- 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 +2 -1
- package/dist/lib/core/dispatchRequest.d.ts.map +1 -0
- package/dist/lib/core/mergeConfig.d.ts +3 -2
- package/dist/lib/core/mergeConfig.d.ts.map +1 -0
- package/dist/lib/core/mergeConfig.js +40 -2
- package/dist/lib/core/mergeConfig.js.map +1 -1
- package/dist/lib/core/prepareRequest.d.ts +1 -0
- package/dist/lib/core/prepareRequest.d.ts.map +1 -0
- package/dist/lib/core/route.d.ts +10 -1
- package/dist/lib/core/route.d.ts.map +1 -0
- package/dist/lib/core/route.js +2 -5
- 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 +3 -2
- package/dist/lib/core/transformData.d.ts.map +1 -0
- package/dist/lib/core/validateSchema.d.ts +3 -2
- 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/transitional.d.ts +1 -0
- package/dist/lib/defaults/transitional.d.ts.map +1 -0
- 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/faxios.d.ts +59 -38
- package/dist/lib/faxios.d.ts.map +1 -0
- package/dist/lib/faxios.js.map +1 -1
- package/dist/lib/helpers/FaxiosURLSearchParams.d.ts +1 -0
- package/dist/lib/helpers/FaxiosURLSearchParams.d.ts.map +1 -0
- 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/cloneConfig.d.ts +1 -1
- package/dist/lib/helpers/cloneConfig.d.ts.map +1 -0
- package/dist/lib/helpers/cloneConfig.js +2 -2
- package/dist/lib/helpers/cloneConfig.js.map +1 -1
- 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/cookies.d.ts +2 -1
- 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 +2 -1
- package/dist/lib/helpers/formDataToJSON.d.ts.map +1 -0
- package/dist/lib/helpers/formDataToJSON.js +1 -1
- package/dist/lib/helpers/formDataToJSON.js.map +1 -1
- 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 +1 -0
- package/dist/lib/helpers/isFaxiosError.d.ts.map +1 -0
- 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 +2 -1
- 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/substitutePathParams.js +11 -3
- package/dist/lib/helpers/substitutePathParams.js.map +1 -1
- 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/toFormData.js +4 -2
- package/dist/lib/helpers/toFormData.js.map +1 -1
- 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 +2 -1
- package/dist/lib/helpers/validator.d.ts.map +1 -0
- package/dist/lib/platform.d.ts +1 -0
- package/dist/lib/platform.d.ts.map +1 -0
- package/dist/lib/plugins/attempt.d.ts +1 -0
- package/dist/lib/plugins/attempt.d.ts.map +1 -0
- package/dist/lib/plugins/authBearer.d.ts +10 -5
- package/dist/lib/plugins/authBearer.d.ts.map +1 -0
- package/dist/lib/plugins/authBearer.js +6 -0
- package/dist/lib/plugins/authBearer.js.map +1 -1
- package/dist/lib/plugins/definePlugin.d.ts +4 -3
- package/dist/lib/plugins/definePlugin.d.ts.map +1 -0
- package/dist/lib/plugins/retry.d.ts +24 -23
- package/dist/lib/plugins/retry.d.ts.map +1 -0
- package/dist/lib/plugins/timing.d.ts +9 -8
- package/dist/lib/plugins/timing.d.ts.map +1 -0
- package/dist/lib/types/standard-schema.d.ts +7 -6
- package/dist/lib/types/standard-schema.d.ts.map +1 -0
- package/dist/lib/types.d.ts +104 -92
- package/dist/lib/types.d.ts.map +1 -0
- package/dist/lib/utils.d.ts +5 -3
- package/dist/lib/utils.d.ts.map +1 -0
- package/dist/lib/utils.js +9 -2
- package/dist/lib/utils.js.map +1 -1
- package/package.json +8 -4
- package/skills/configure-requests/SKILL.md +53 -8
- package/skills/configure-requests/references/plugins.md +54 -6
- package/src/index.ts +57 -0
- package/src/lib/adapters/fetch-helpers.ts +167 -0
- package/src/lib/adapters/fetch.ts +871 -0
- package/src/lib/cancel/CanceledError.ts +23 -0
- package/src/lib/cancel/isCancel.ts +10 -0
- package/src/lib/core/Faxios.ts +517 -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 +213 -0
- package/src/lib/core/prepareRequest.ts +155 -0
- package/src/lib/core/route.ts +65 -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 +22 -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 +23 -0
- package/src/lib/helpers/throttle.ts +45 -0
- package/src/lib/helpers/toFormData.ts +298 -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 +129 -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 +941 -0
package/src/lib/utils.ts
ADDED
|
@@ -0,0 +1,941 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
// utils is a library of generic helper functions non-specific to faxios
|
|
4
|
+
|
|
5
|
+
const { toString } = Object.prototype;
|
|
6
|
+
const { getPrototypeOf } = Object;
|
|
7
|
+
const { iterator, toStringTag } = Symbol;
|
|
8
|
+
|
|
9
|
+
const hasOwnProperty = (obj: unknown, prop: PropertyKey) => Object.hasOwn(obj as object, prop);
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* The one dangerous-key check: `__proto__`, `constructor` and `prototype` are skipped wherever
|
|
13
|
+
* config, route or form data keys are materialized into objects, to block prototype-pollution writes.
|
|
14
|
+
*/
|
|
15
|
+
const isDangerousKey = (key: PropertyKey): boolean =>
|
|
16
|
+
key === "__proto__" || key === "constructor" || key === "prototype";
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Walk the prototype chain (excluding the shared Object.prototype) looking for
|
|
20
|
+
* an own `prop`. This distinguishes genuine own/inherited members — including
|
|
21
|
+
* class accessors and template prototypes — from members injected via
|
|
22
|
+
* Object.prototype pollution (e.g. `Object.prototype.username = '...'`), which
|
|
23
|
+
* live on Object.prototype itself and are therefore never matched.
|
|
24
|
+
*
|
|
25
|
+
* @param {*} thing The value whose chain to inspect
|
|
26
|
+
* @param {string|symbol} prop The property key to look for
|
|
27
|
+
*
|
|
28
|
+
* @returns {boolean} True when `prop` is owned below Object.prototype
|
|
29
|
+
*/
|
|
30
|
+
const hasOwnInPrototypeChain = (thing: unknown, prop: PropertyKey): boolean => {
|
|
31
|
+
let obj: null | object = thing != null && typeof thing === "object" ? thing : null;
|
|
32
|
+
if (obj === null) return false;
|
|
33
|
+
const seen: Array<object> = [];
|
|
34
|
+
|
|
35
|
+
while (obj != null && obj !== Object.prototype) {
|
|
36
|
+
if (seen.indexOf(obj) !== -1) {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
seen.push(obj);
|
|
40
|
+
|
|
41
|
+
if (hasOwnProperty(obj, prop)) {
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
obj = getPrototypeOf(obj) as null | object;
|
|
45
|
+
}
|
|
46
|
+
return false;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Read `obj[prop]` only when it is safe from Object.prototype pollution. Own
|
|
51
|
+
* properties and members inherited from a non-Object.prototype source (a class
|
|
52
|
+
* instance or template object) are honored; a value reachable only through a
|
|
53
|
+
* polluted Object.prototype is ignored and `undefined` is returned.
|
|
54
|
+
*
|
|
55
|
+
* @param {*} obj The source object
|
|
56
|
+
* @param {string|symbol} prop The property key to read
|
|
57
|
+
*
|
|
58
|
+
* @returns {*} The resolved value, or undefined when unsafe/absent
|
|
59
|
+
*/
|
|
60
|
+
const getSafeProp = (obj: unknown, prop: PropertyKey): unknown =>
|
|
61
|
+
obj != null && hasOwnInPrototypeChain(obj, prop) ? (obj as Record<PropertyKey, unknown>)[prop] : undefined;
|
|
62
|
+
|
|
63
|
+
const kindOf = (cache => (thing: unknown) => {
|
|
64
|
+
const str = toString.call(thing);
|
|
65
|
+
return (cache as Record<string, string>)[str] || ((cache as Record<string, string>)[str] = str.slice(8, -1).toLowerCase());
|
|
66
|
+
})(Object.create(null) as object);
|
|
67
|
+
|
|
68
|
+
const kindOfTest = (type: string) => {
|
|
69
|
+
type = type.toLowerCase();
|
|
70
|
+
return (thing: unknown) => kindOf(thing) === type;
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
const typeOfTest = (type: string) => (thing: unknown) => typeof thing === type;
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Determine if a value is a non-null object
|
|
77
|
+
*
|
|
78
|
+
* @param {Object} val The value to test
|
|
79
|
+
*
|
|
80
|
+
* @returns {boolean} True if value is an Array, otherwise false
|
|
81
|
+
*/
|
|
82
|
+
const { isArray } = Array;
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Determine if a value is undefined
|
|
86
|
+
*
|
|
87
|
+
* @param {*} val The value to test
|
|
88
|
+
*
|
|
89
|
+
* @returns {boolean} True if the value is undefined, otherwise false
|
|
90
|
+
*/
|
|
91
|
+
const isUndefined = typeOfTest("undefined");
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Determine if a value is a Buffer
|
|
95
|
+
*
|
|
96
|
+
* @param {*} val The value to test
|
|
97
|
+
*
|
|
98
|
+
* @returns {boolean} True if value is a Buffer, otherwise false
|
|
99
|
+
*/
|
|
100
|
+
function isBuffer(val: unknown): boolean {
|
|
101
|
+
return (
|
|
102
|
+
val !== null &&
|
|
103
|
+
!isUndefined(val) &&
|
|
104
|
+
!isUndefined((val as Record<string, unknown>).constructor) &&
|
|
105
|
+
isFunction((val as { constructor: Record<string, unknown>; }).constructor["isBuffer"]) &&
|
|
106
|
+
(val as { constructor: { isBuffer: (v: unknown) => boolean; }; }).constructor.isBuffer(val)
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Determine if a value is an ArrayBuffer
|
|
112
|
+
*
|
|
113
|
+
* @param {*} val The value to test
|
|
114
|
+
*
|
|
115
|
+
* @returns {boolean} True if value is an ArrayBuffer, otherwise false
|
|
116
|
+
*/
|
|
117
|
+
const isArrayBuffer = kindOfTest("ArrayBuffer");
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Determine if a value is a view on an ArrayBuffer
|
|
121
|
+
*
|
|
122
|
+
* @param {*} val The value to test
|
|
123
|
+
*
|
|
124
|
+
* @returns {boolean} True if value is a view on an ArrayBuffer, otherwise false
|
|
125
|
+
*/
|
|
126
|
+
function isArrayBufferView(val: unknown): boolean {
|
|
127
|
+
let result;
|
|
128
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
129
|
+
if (typeof ArrayBuffer !== "undefined" && ArrayBuffer.isView) {
|
|
130
|
+
result = ArrayBuffer.isView(val);
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
result = val && (val as Record<string, unknown>).buffer && isArrayBuffer((val as Record<string, unknown>).buffer);
|
|
134
|
+
}
|
|
135
|
+
return !!result;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Determine if a value is a String
|
|
140
|
+
*
|
|
141
|
+
* @param {*} val The value to test
|
|
142
|
+
*
|
|
143
|
+
* @returns {boolean} True if value is a String, otherwise false
|
|
144
|
+
*/
|
|
145
|
+
const isString = typeOfTest("string");
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Determine if a value is a Function
|
|
149
|
+
*
|
|
150
|
+
* @param {*} val The value to test
|
|
151
|
+
* @returns {boolean} True if value is a Function, otherwise false
|
|
152
|
+
*/
|
|
153
|
+
const isFunction = typeOfTest("function");
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Determine if a value is a Number
|
|
157
|
+
*
|
|
158
|
+
* @param {*} val The value to test
|
|
159
|
+
*
|
|
160
|
+
* @returns {boolean} True if value is a Number, otherwise false
|
|
161
|
+
*/
|
|
162
|
+
const isNumber = typeOfTest("number");
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Determine if a value is an Object
|
|
166
|
+
*
|
|
167
|
+
* @param {*} thing The value to test
|
|
168
|
+
*
|
|
169
|
+
* @returns {boolean} True if value is an Object, otherwise false
|
|
170
|
+
*/
|
|
171
|
+
const isObject = (thing: unknown): thing is object => thing !== null && typeof thing === "object";
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Determine if a value is a Boolean
|
|
175
|
+
*
|
|
176
|
+
* @param {*} thing The value to test
|
|
177
|
+
* @returns {boolean} True if value is a Boolean, otherwise false
|
|
178
|
+
*/
|
|
179
|
+
const isBoolean = (thing: unknown) => thing === true || thing === false;
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Determine if a value is a plain Object
|
|
183
|
+
*
|
|
184
|
+
* @param {*} val The value to test
|
|
185
|
+
*
|
|
186
|
+
* @returns {boolean} True if value is a plain Object, otherwise false
|
|
187
|
+
*/
|
|
188
|
+
const isPlainObject = (val: unknown): boolean => {
|
|
189
|
+
if (!isObject(val)) {
|
|
190
|
+
return false;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
const prototype = getPrototypeOf(val);
|
|
194
|
+
return (
|
|
195
|
+
(prototype === null ||
|
|
196
|
+
prototype === Object.prototype ||
|
|
197
|
+
getPrototypeOf(prototype) === null) &&
|
|
198
|
+
// Treat any genuine (non-Object.prototype-polluted) Symbol.toStringTag or
|
|
199
|
+
// Symbol.iterator as evidence the value is a tagged/iterable type rather
|
|
200
|
+
// than a plain object, while ignoring keys injected onto Object.prototype.
|
|
201
|
+
!hasOwnInPrototypeChain(val, toStringTag) &&
|
|
202
|
+
!hasOwnInPrototypeChain(val, iterator)
|
|
203
|
+
);
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Determine if a value is an empty object (safely handles Buffers)
|
|
208
|
+
*
|
|
209
|
+
* @param {*} val The value to test
|
|
210
|
+
*
|
|
211
|
+
* @returns {boolean} True if value is an empty object, otherwise false
|
|
212
|
+
*/
|
|
213
|
+
const isEmptyObject = (val: unknown): boolean => {
|
|
214
|
+
// Early return for non-objects or Buffers to prevent RangeError
|
|
215
|
+
if (!isObject(val) || isBuffer(val)) {
|
|
216
|
+
return false;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
try {
|
|
220
|
+
return Object.keys(val).length === 0 && Object.getPrototypeOf(val) === Object.prototype;
|
|
221
|
+
}
|
|
222
|
+
catch {
|
|
223
|
+
// Fallback for any other objects that might cause RangeError with Object.keys()
|
|
224
|
+
return false;
|
|
225
|
+
}
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Determine if a value is a Date
|
|
230
|
+
*
|
|
231
|
+
* @param {*} val The value to test
|
|
232
|
+
*
|
|
233
|
+
* @returns {boolean} True if value is a Date, otherwise false
|
|
234
|
+
*/
|
|
235
|
+
const isDate = kindOfTest("Date");
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Determine if a value is a File
|
|
239
|
+
*
|
|
240
|
+
* @param {*} val The value to test
|
|
241
|
+
*
|
|
242
|
+
* @returns {boolean} True if value is a File, otherwise false
|
|
243
|
+
*/
|
|
244
|
+
const isFile = kindOfTest("File");
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Determine if a value is a React Native Blob
|
|
248
|
+
* React Native "blob": an object with a `uri` attribute. Optionally, it can
|
|
249
|
+
* also have a `name` and `type` attribute to specify filename and content type
|
|
250
|
+
*
|
|
251
|
+
* @see https://github.com/facebook/react-native/blob/26684cf3adf4094eb6c405d345a75bf8c7c0bf88/Libraries/Network/FormData.js#L68-L71
|
|
252
|
+
*
|
|
253
|
+
* @param {*} value The value to test
|
|
254
|
+
*
|
|
255
|
+
* @returns {boolean} True if value is a React Native Blob, otherwise false
|
|
256
|
+
*/
|
|
257
|
+
const isReactNativeBlob = (value: unknown) => !!(value && typeof (value as Record<string, unknown>).uri !== "undefined");
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Determine if environment is React Native
|
|
261
|
+
* ReactNative `FormData` has a non-standard `getParts()` method
|
|
262
|
+
*
|
|
263
|
+
* @param {*} formData The formData to test
|
|
264
|
+
*
|
|
265
|
+
* @returns {boolean} True if environment is React Native, otherwise false
|
|
266
|
+
*/
|
|
267
|
+
const isReactNative = (formData: unknown) => formData && typeof (formData as Record<string, unknown>).getParts !== "undefined";
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* Determine if a value is a Blob
|
|
271
|
+
*
|
|
272
|
+
* @param {*} val The value to test
|
|
273
|
+
*
|
|
274
|
+
* @returns {boolean} True if value is a Blob, otherwise false
|
|
275
|
+
*/
|
|
276
|
+
const isBlob = kindOfTest("Blob");
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Determine if a value is a FileList
|
|
280
|
+
*
|
|
281
|
+
* @param {*} val The value to test
|
|
282
|
+
*
|
|
283
|
+
* @returns {boolean} True if value is a FileList, otherwise false
|
|
284
|
+
*/
|
|
285
|
+
const isFileList = kindOfTest("FileList");
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Determine if a value is a Stream
|
|
289
|
+
*
|
|
290
|
+
* @param {*} val The value to test
|
|
291
|
+
*
|
|
292
|
+
* @returns {boolean} True if value is a Stream, otherwise false
|
|
293
|
+
*/
|
|
294
|
+
const isStream = (val: unknown) => isObject(val) && isFunction((val as Record<string, unknown>).pipe);
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* Determine if a value is a FormData
|
|
298
|
+
*
|
|
299
|
+
* @param {*} thing The value to test
|
|
300
|
+
*
|
|
301
|
+
* @returns {boolean} True if value is an FormData, otherwise false
|
|
302
|
+
*/
|
|
303
|
+
const G: Record<string, unknown> = globalThis;
|
|
304
|
+
const FormDataCtor = typeof G["FormData"] !== "undefined" ? G["FormData"] as new () => object : undefined;
|
|
305
|
+
|
|
306
|
+
const isFormData = (thing: unknown): boolean => {
|
|
307
|
+
if (!thing) return false;
|
|
308
|
+
if (FormDataCtor && thing instanceof FormDataCtor) return true;
|
|
309
|
+
// Reject plain objects inheriting directly from Object.prototype so prototype-pollution gadgets can't spoof FormData.
|
|
310
|
+
const proto = getPrototypeOf(thing);
|
|
311
|
+
if (!proto || proto === Object.prototype) return false;
|
|
312
|
+
if (!isFunction((thing as Record<string, unknown>).append)) return false;
|
|
313
|
+
const kind = kindOf(thing);
|
|
314
|
+
return (
|
|
315
|
+
kind === "formdata" ||
|
|
316
|
+
// detect form-data instance
|
|
317
|
+
(kind === "object" && isFunction((thing as Record<string, unknown>).toString) && (thing as { toString: () => string; }).toString() === "[object FormData]")
|
|
318
|
+
);
|
|
319
|
+
};
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* Determine if a value is a URLSearchParams object
|
|
323
|
+
*
|
|
324
|
+
* @param {*} val The value to test
|
|
325
|
+
*
|
|
326
|
+
* @returns {boolean} True if value is a URLSearchParams object, otherwise false
|
|
327
|
+
*/
|
|
328
|
+
const isURLSearchParams = kindOfTest("URLSearchParams");
|
|
329
|
+
|
|
330
|
+
const [ isReadableStream, isRequest, isResponse, isHeaders ] = [
|
|
331
|
+
"ReadableStream",
|
|
332
|
+
"Request",
|
|
333
|
+
"Response",
|
|
334
|
+
"Headers",
|
|
335
|
+
].map(kindOfTest);
|
|
336
|
+
|
|
337
|
+
/**
|
|
338
|
+
* Iterate over an Array or an Object invoking a function for each item.
|
|
339
|
+
*
|
|
340
|
+
* If `obj` is an Array callback will be called passing
|
|
341
|
+
* the value, index, and complete array for each item.
|
|
342
|
+
*
|
|
343
|
+
* If 'obj' is an Object callback will be called passing
|
|
344
|
+
* the value, key, and complete object for each property.
|
|
345
|
+
*
|
|
346
|
+
* @param {Object|Array<unknown>} obj The object to iterate
|
|
347
|
+
* @param {Function} fn The callback to invoke for each item
|
|
348
|
+
*
|
|
349
|
+
* @param {Object} [options]
|
|
350
|
+
* @param {Boolean} [options.allOwnKeys = false]
|
|
351
|
+
* @returns {any}
|
|
352
|
+
*/
|
|
353
|
+
function forEach(obj: unknown, fn: (value: unknown, key: unknown, obj: unknown) => void, { allOwnKeys = false } = {}): void {
|
|
354
|
+
// Don't bother if no value provided
|
|
355
|
+
if (obj === null || typeof obj === "undefined") {
|
|
356
|
+
return;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
let i: number;
|
|
360
|
+
let l: number;
|
|
361
|
+
|
|
362
|
+
// Force an array if not already something iterable
|
|
363
|
+
if (typeof obj !== "object") {
|
|
364
|
+
/*eslint no-param-reassign:0*/
|
|
365
|
+
obj = [ obj ];
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
if (isArray(obj)) {
|
|
369
|
+
// Iterate over array values
|
|
370
|
+
for (i = 0, l = obj.length; i < l; i++) {
|
|
371
|
+
fn.call(null, obj[i], i, obj);
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
else {
|
|
375
|
+
// Buffer check
|
|
376
|
+
if (isBuffer(obj)) {
|
|
377
|
+
return;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
// Iterate over object keys
|
|
381
|
+
const keys = allOwnKeys ? Object.getOwnPropertyNames(obj) : Object.keys(obj as object);
|
|
382
|
+
const len = keys.length;
|
|
383
|
+
let key: string | undefined;
|
|
384
|
+
|
|
385
|
+
for (i = 0; i < len; i++) {
|
|
386
|
+
key = keys[i]!;
|
|
387
|
+
fn.call(null, (obj as Record<string, unknown>)[key], key, obj);
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
/**
|
|
393
|
+
* Finds a key in an object, case-insensitive, returning the actual key name.
|
|
394
|
+
* Returns null if the object is a Buffer or if no match is found.
|
|
395
|
+
*
|
|
396
|
+
* @param {Object} obj - The object to search.
|
|
397
|
+
* @param {string} key - The key to find (case-insensitive).
|
|
398
|
+
* @returns {?string} The actual key name if found, otherwise null.
|
|
399
|
+
*/
|
|
400
|
+
function findKey(obj: unknown, key: string): null | string {
|
|
401
|
+
if (isBuffer(obj)) {
|
|
402
|
+
return null;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
key = key.toLowerCase();
|
|
406
|
+
const keys = Object.keys(obj as object);
|
|
407
|
+
let i = keys.length;
|
|
408
|
+
let _key: string | undefined;
|
|
409
|
+
while (i-- > 0) {
|
|
410
|
+
_key = keys[i]!;
|
|
411
|
+
if (key === _key.toLowerCase()) {
|
|
412
|
+
return _key;
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
return null;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
type GlobalWithEvents = typeof globalThis & {
|
|
419
|
+
addEventListener?: (type: string, listener: (event: Record<string, unknown>) => void, capture?: boolean) => void;
|
|
420
|
+
postMessage?: (message: unknown, targetOrigin: string) => void;
|
|
421
|
+
process?: { nextTick?: (cb: () => void) => void; };
|
|
422
|
+
setImmediate?: (cb: () => void) => void;
|
|
423
|
+
};
|
|
424
|
+
const _global = globalThis as GlobalWithEvents;
|
|
425
|
+
|
|
426
|
+
const isContextDefined = (context: unknown) => !isUndefined(context) && context !== _global;
|
|
427
|
+
|
|
428
|
+
/**
|
|
429
|
+
* Accepts varargs expecting each argument to be an object, then
|
|
430
|
+
* immutably merges the properties of each object and returns result.
|
|
431
|
+
*
|
|
432
|
+
* When multiple objects contain the same key the later object in
|
|
433
|
+
* the arguments list will take precedence.
|
|
434
|
+
*
|
|
435
|
+
* Example:
|
|
436
|
+
*
|
|
437
|
+
* ```js
|
|
438
|
+
* const result = merge({foo: 123}, {foo: 456});
|
|
439
|
+
* console.log(result.foo); // outputs 456
|
|
440
|
+
* ```
|
|
441
|
+
*
|
|
442
|
+
* @param {Object} obj1 Object to merge
|
|
443
|
+
*
|
|
444
|
+
* @returns {Object} Result of all merge properties
|
|
445
|
+
*/
|
|
446
|
+
function merge(this: unknown, ...objs: Array<unknown>): Record<string, unknown> {
|
|
447
|
+
const ctx = (isContextDefined(this) && this) as false | { caseless?: unknown; skipUndefined?: unknown; };
|
|
448
|
+
const caseless = ctx && ctx.caseless;
|
|
449
|
+
const skipUndefined = ctx && ctx.skipUndefined;
|
|
450
|
+
const result: Record<string | symbol, unknown> = {};
|
|
451
|
+
const assignValue = (val: unknown, key: unknown) => {
|
|
452
|
+
const keyStr = key as string | symbol;
|
|
453
|
+
// Skip dangerous property names to prevent prototype pollution
|
|
454
|
+
if (isDangerousKey(keyStr)) {
|
|
455
|
+
return;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
// findKey lowercases the key, so caseless lookup only applies to strings —
|
|
459
|
+
// symbol keys are identity-matched.
|
|
460
|
+
const targetKey: string | symbol = (caseless && typeof keyStr === "string" ? (findKey(result, keyStr) ?? (keyStr)) : (keyStr));
|
|
461
|
+
// Read via own-prop only — a bare `result[targetKey]` walks the prototype
|
|
462
|
+
// chain, so a polluted Object.prototype value could surface here and get
|
|
463
|
+
// copied into the merged result.
|
|
464
|
+
const existing = hasOwnProperty(result, targetKey) ? result[targetKey] : undefined;
|
|
465
|
+
if (isPlainObject(existing) && isPlainObject(val)) {
|
|
466
|
+
result[targetKey] = merge(existing, val);
|
|
467
|
+
}
|
|
468
|
+
else if (isPlainObject(val)) {
|
|
469
|
+
result[targetKey] = merge({}, val);
|
|
470
|
+
}
|
|
471
|
+
else if (isArray(val)) {
|
|
472
|
+
result[targetKey] = val.slice();
|
|
473
|
+
}
|
|
474
|
+
else if (!skipUndefined || !isUndefined(val)) {
|
|
475
|
+
result[targetKey] = val;
|
|
476
|
+
}
|
|
477
|
+
};
|
|
478
|
+
|
|
479
|
+
for (let i = 0, l = objs.length; i < l; i++) {
|
|
480
|
+
const source = objs[i];
|
|
481
|
+
if (!source || isBuffer(source)) {
|
|
482
|
+
continue;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
forEach(source, assignValue);
|
|
486
|
+
|
|
487
|
+
if (typeof source !== "object" || isArray(source)) {
|
|
488
|
+
continue;
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
const symbols = Object.getOwnPropertySymbols(source);
|
|
492
|
+
for (let j = 0; j < symbols.length; j++) {
|
|
493
|
+
const symbol = symbols[j]!;
|
|
494
|
+
if (propertyIsEnumerable.call(source, symbol)) {
|
|
495
|
+
assignValue((source as Record<symbol, unknown>)[symbol], symbol);
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
return result;
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
/**
|
|
503
|
+
* Extends object a by mutably adding to it the properties of object b.
|
|
504
|
+
*
|
|
505
|
+
* @param {Object} a The object to be extended
|
|
506
|
+
* @param {Object} b The object to copy properties from
|
|
507
|
+
* @param {Object} thisArg The object to bind function to
|
|
508
|
+
*
|
|
509
|
+
* @param {Object} [options]
|
|
510
|
+
* @param {Boolean} [options.allOwnKeys]
|
|
511
|
+
* @returns {Object} The resulting value of object a
|
|
512
|
+
*/
|
|
513
|
+
const extend = (a: Record<string, unknown>, b: unknown, thisArg: unknown, { allOwnKeys }: { allOwnKeys?: boolean; } = {}) => {
|
|
514
|
+
forEach(
|
|
515
|
+
b,
|
|
516
|
+
(val, key) => {
|
|
517
|
+
if (thisArg && isFunction(val)) {
|
|
518
|
+
Object.defineProperty(a, key as PropertyKey, Object.assign(Object.create(null) as PropertyDescriptor, {
|
|
519
|
+
value: (val as (...args: Array<unknown>) => unknown).bind(thisArg),
|
|
520
|
+
writable: true,
|
|
521
|
+
enumerable: true,
|
|
522
|
+
configurable: true,
|
|
523
|
+
}));
|
|
524
|
+
}
|
|
525
|
+
else {
|
|
526
|
+
Object.defineProperty(a, key as PropertyKey, Object.assign(Object.create(null) as PropertyDescriptor, {
|
|
527
|
+
value: val,
|
|
528
|
+
writable: true,
|
|
529
|
+
enumerable: true,
|
|
530
|
+
configurable: true,
|
|
531
|
+
}));
|
|
532
|
+
}
|
|
533
|
+
},
|
|
534
|
+
{ allOwnKeys }
|
|
535
|
+
);
|
|
536
|
+
return a;
|
|
537
|
+
};
|
|
538
|
+
|
|
539
|
+
/**
|
|
540
|
+
* Remove byte order marker. This catches EF BB BF (the UTF-8 BOM)
|
|
541
|
+
*
|
|
542
|
+
* @param {string} content with BOM
|
|
543
|
+
*
|
|
544
|
+
* @returns {string} content value without BOM
|
|
545
|
+
*/
|
|
546
|
+
const stripBOM = (content: string) => {
|
|
547
|
+
if (content.charCodeAt(0) === 0xfeff) {
|
|
548
|
+
content = content.slice(1);
|
|
549
|
+
}
|
|
550
|
+
return content;
|
|
551
|
+
};
|
|
552
|
+
|
|
553
|
+
/**
|
|
554
|
+
* Resolve object with deep prototype chain to a flat object
|
|
555
|
+
* @param {Object} sourceObj source object
|
|
556
|
+
* @param {Object} [destObj]
|
|
557
|
+
* @param {Function|Boolean} [filter]
|
|
558
|
+
* @param {Function} [propFilter]
|
|
559
|
+
*
|
|
560
|
+
* @returns {Object}
|
|
561
|
+
*/
|
|
562
|
+
const toFlatObject = (sourceObj: unknown, destObj?: Record<string, unknown>, filter?: ((src: object, dest: Record<string, unknown>) => boolean) | false, propFilter?: (prop: string, src: unknown, dest: Record<string, unknown>) => boolean): Record<string, unknown> => {
|
|
563
|
+
let props: Array<string>;
|
|
564
|
+
let i: number;
|
|
565
|
+
let prop: string | undefined;
|
|
566
|
+
// Null prototype: a polluted Object.prototype[prop] must not mark an own prop as already copied.
|
|
567
|
+
const merged: Record<string, boolean> = Object.create(null);
|
|
568
|
+
|
|
569
|
+
const dest: Record<string, unknown> = destObj ?? {};
|
|
570
|
+
|
|
571
|
+
if (sourceObj == null) return dest;
|
|
572
|
+
|
|
573
|
+
let src: unknown = sourceObj;
|
|
574
|
+
|
|
575
|
+
do {
|
|
576
|
+
props = Object.getOwnPropertyNames(src);
|
|
577
|
+
i = props.length;
|
|
578
|
+
while (i-- > 0) {
|
|
579
|
+
prop = props[i]!;
|
|
580
|
+
if ((!propFilter || propFilter(prop, src, dest)) && !merged[prop]) {
|
|
581
|
+
dest[prop] = (src as Record<string, unknown>)[prop];
|
|
582
|
+
merged[prop] = true;
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
src = filter !== false && getPrototypeOf(src);
|
|
586
|
+
} while (src && (!filter || filter(src, dest)) && src !== Object.prototype);
|
|
587
|
+
|
|
588
|
+
return dest;
|
|
589
|
+
};
|
|
590
|
+
|
|
591
|
+
const toArray = (thing?: unknown): Array<unknown> | null => {
|
|
592
|
+
if (!thing) return null;
|
|
593
|
+
if (isArray(thing)) return thing;
|
|
594
|
+
if (!isNumber((thing as { length?: unknown; }).length)) return null;
|
|
595
|
+
return Array.from(thing as ArrayLike<unknown>);
|
|
596
|
+
};
|
|
597
|
+
|
|
598
|
+
/**
|
|
599
|
+
* Checking if the Uint8Array exists and if it does, it returns a function that checks if the
|
|
600
|
+
* thing passed in is an instance of Uint8Array
|
|
601
|
+
*
|
|
602
|
+
* @param {TypedArray}
|
|
603
|
+
*
|
|
604
|
+
* @returns {Array}
|
|
605
|
+
*/
|
|
606
|
+
|
|
607
|
+
const isTypedArray = ((TypedArray: (abstract new (...args: Array<unknown>) => unknown) | false) =>
|
|
608
|
+
|
|
609
|
+
(thing: unknown) => TypedArray && thing instanceof TypedArray
|
|
610
|
+
)(typeof Uint8Array !== "undefined" && getPrototypeOf(Uint8Array) as abstract new (...args: Array<unknown>) => unknown);
|
|
611
|
+
|
|
612
|
+
const forEachEntry = (obj: unknown, fn: (key: unknown, value: unknown) => void) => {
|
|
613
|
+
for (const [ key, value ] of obj as Iterable<[unknown, unknown]>) {
|
|
614
|
+
fn.call(obj, key, value);
|
|
615
|
+
}
|
|
616
|
+
};
|
|
617
|
+
|
|
618
|
+
/**
|
|
619
|
+
* It takes a regular expression and a string, and returns an array of all the matches
|
|
620
|
+
*
|
|
621
|
+
* @param {string} regExp - The regular expression to match against.
|
|
622
|
+
* @param {string} str - The string to search.
|
|
623
|
+
*
|
|
624
|
+
* @returns {Array<boolean>}
|
|
625
|
+
*/
|
|
626
|
+
const matchAll = (regExp: RegExp, str: string) => {
|
|
627
|
+
let matches: null | RegExpExecArray;
|
|
628
|
+
const arr: Array<RegExpExecArray> = [];
|
|
629
|
+
|
|
630
|
+
while ((matches = regExp.exec(str)) !== null) {
|
|
631
|
+
arr.push(matches);
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
return arr;
|
|
635
|
+
};
|
|
636
|
+
|
|
637
|
+
/* Checking if the kindOfTest function returns true when passed an HTMLFormElement. */
|
|
638
|
+
const isHTMLForm = kindOfTest("HTMLFormElement");
|
|
639
|
+
|
|
640
|
+
const toCamelCase = (str: string) => str.toLowerCase().replace(/[-_\s]([a-z\d])(\w*)/g, function replacer(_m: string, p1: string, p2: string) {
|
|
641
|
+
return p1.toUpperCase() + p2;
|
|
642
|
+
});
|
|
643
|
+
|
|
644
|
+
const { propertyIsEnumerable } = Object.prototype;
|
|
645
|
+
|
|
646
|
+
/**
|
|
647
|
+
* Determine if a value is a RegExp object
|
|
648
|
+
*
|
|
649
|
+
* @param {*} val The value to test
|
|
650
|
+
*
|
|
651
|
+
* @returns {boolean} True if value is a RegExp object, otherwise false
|
|
652
|
+
*/
|
|
653
|
+
const isRegExp = kindOfTest("RegExp");
|
|
654
|
+
|
|
655
|
+
const reduceDescriptors = (obj: object, reducer: (descriptor: PropertyDescriptor, name: string, obj: object) => false | PropertyDescriptor | undefined) => {
|
|
656
|
+
const descriptors = Object.getOwnPropertyDescriptors(obj);
|
|
657
|
+
const reducedDescriptors: PropertyDescriptorMap = {};
|
|
658
|
+
|
|
659
|
+
forEach(descriptors, (descriptor, name) => {
|
|
660
|
+
let ret;
|
|
661
|
+
if ((ret = reducer(descriptor as PropertyDescriptor, name as string, obj)) !== false) {
|
|
662
|
+
reducedDescriptors[name as string] = ret ?? (descriptor as PropertyDescriptor);
|
|
663
|
+
}
|
|
664
|
+
});
|
|
665
|
+
|
|
666
|
+
Object.defineProperties(obj, reducedDescriptors);
|
|
667
|
+
};
|
|
668
|
+
|
|
669
|
+
/**
|
|
670
|
+
* Makes all methods read-only
|
|
671
|
+
* @param {Object} obj
|
|
672
|
+
*/
|
|
673
|
+
|
|
674
|
+
const freezeMethods = (obj: object) => {
|
|
675
|
+
// eslint-disable-next-line sonarjs/function-return-type
|
|
676
|
+
reduceDescriptors(obj, (descriptor, name): false | PropertyDescriptor => {
|
|
677
|
+
// skip restricted props in strict mode
|
|
678
|
+
if (isFunction(obj) && [ "arguments", "caller", "callee" ].includes(name)) {
|
|
679
|
+
return false;
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
const value = (obj as Record<string, unknown>)[name];
|
|
683
|
+
|
|
684
|
+
if (!isFunction(value)) return false;
|
|
685
|
+
|
|
686
|
+
descriptor.enumerable = false;
|
|
687
|
+
|
|
688
|
+
if ("writable" in descriptor) {
|
|
689
|
+
descriptor.writable = false;
|
|
690
|
+
return descriptor;
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
if (!descriptor.set) {
|
|
694
|
+
descriptor.set = () => {
|
|
695
|
+
throw Error("Can not rewrite read-only method '" + name + "'");
|
|
696
|
+
};
|
|
697
|
+
}
|
|
698
|
+
return descriptor;
|
|
699
|
+
});
|
|
700
|
+
};
|
|
701
|
+
|
|
702
|
+
/**
|
|
703
|
+
* Converts an array or a delimited string into an object set with values as keys and true as values.
|
|
704
|
+
* Useful for fast membership checks.
|
|
705
|
+
*
|
|
706
|
+
* @param {Array|string} arrayOrString - The array or string to convert.
|
|
707
|
+
* @param {string} delimiter - The delimiter to use if input is a string.
|
|
708
|
+
* @returns {Object} An object with keys from the array or string, values set to true.
|
|
709
|
+
*/
|
|
710
|
+
const toObjectSet = (arrayOrString: Array<unknown> | string, delimiter: string) => {
|
|
711
|
+
const obj: Record<string, boolean> = {};
|
|
712
|
+
|
|
713
|
+
const define = (arr: Array<unknown>) => {
|
|
714
|
+
arr.forEach(value => {
|
|
715
|
+
obj[value as string] = true;
|
|
716
|
+
});
|
|
717
|
+
};
|
|
718
|
+
|
|
719
|
+
isArray(arrayOrString) ? define(arrayOrString) : define(String(arrayOrString).split(delimiter));
|
|
720
|
+
|
|
721
|
+
return obj;
|
|
722
|
+
};
|
|
723
|
+
|
|
724
|
+
const noop = () => {};
|
|
725
|
+
|
|
726
|
+
const toFiniteNumber = (value: unknown, defaultValue?: number) => {
|
|
727
|
+
const num = +(value as number);
|
|
728
|
+
return value != null && Number.isFinite(num) ? num : defaultValue;
|
|
729
|
+
};
|
|
730
|
+
|
|
731
|
+
/**
|
|
732
|
+
* If the thing is a FormData object, return true, otherwise return false.
|
|
733
|
+
*
|
|
734
|
+
* @param {unknown} thing - The thing to check.
|
|
735
|
+
*
|
|
736
|
+
* @returns {boolean}
|
|
737
|
+
*/
|
|
738
|
+
function isSpecCompliantForm(thing: unknown): boolean {
|
|
739
|
+
return !!(
|
|
740
|
+
thing &&
|
|
741
|
+
isFunction((thing as Record<string | symbol, unknown>).append) &&
|
|
742
|
+
(thing as Record<string | symbol, unknown>)[toStringTag] === "FormData" &&
|
|
743
|
+
(thing as Record<string | symbol, unknown>)[iterator]
|
|
744
|
+
);
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
/**
|
|
748
|
+
* Recursively converts an object to a JSON-compatible object, handling circular references and Buffers.
|
|
749
|
+
*
|
|
750
|
+
* @param {Object} obj - The object to convert.
|
|
751
|
+
* @returns {Object} The JSON-compatible object.
|
|
752
|
+
*/
|
|
753
|
+
const toJSONObject = (obj: unknown): unknown => {
|
|
754
|
+
const visited = new WeakSet<object>();
|
|
755
|
+
|
|
756
|
+
const visit = (source: unknown): unknown => {
|
|
757
|
+
if (isObject(source)) {
|
|
758
|
+
if (visited.has(source)) {
|
|
759
|
+
return;
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
//Buffer check
|
|
763
|
+
if (isBuffer(source)) {
|
|
764
|
+
return source;
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
if (!("toJSON" in source)) {
|
|
768
|
+
// add-on descent / delete-on-ascent: preserves path semantics, so DAG nodes serialise at every occurrence (see #7230).
|
|
769
|
+
visited.add(source);
|
|
770
|
+
const target: Record<number | string, unknown> = isArray(source) ? ([] as Record<number, unknown>) : {};
|
|
771
|
+
|
|
772
|
+
forEach(source, (value, key) => {
|
|
773
|
+
const reducedValue = visit(value);
|
|
774
|
+
!isUndefined(reducedValue) && (target[key as string] = reducedValue);
|
|
775
|
+
});
|
|
776
|
+
|
|
777
|
+
visited.delete(source);
|
|
778
|
+
|
|
779
|
+
return target;
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
return source;
|
|
784
|
+
};
|
|
785
|
+
|
|
786
|
+
return visit(obj);
|
|
787
|
+
};
|
|
788
|
+
|
|
789
|
+
/**
|
|
790
|
+
* Determines if a value is an async function.
|
|
791
|
+
*
|
|
792
|
+
* @param {*} thing - The value to test.
|
|
793
|
+
* @returns {boolean} True if value is an async function, otherwise false.
|
|
794
|
+
*/
|
|
795
|
+
const isAsyncFn = kindOfTest("AsyncFunction");
|
|
796
|
+
|
|
797
|
+
/**
|
|
798
|
+
* Determines if a value is thenable (has then and catch methods).
|
|
799
|
+
*
|
|
800
|
+
* @param {*} thing - The value to test.
|
|
801
|
+
* @returns {boolean} True if value is thenable, otherwise false.
|
|
802
|
+
*/
|
|
803
|
+
const isThenable = (thing: unknown) =>
|
|
804
|
+
thing &&
|
|
805
|
+
(isObject(thing) || isFunction(thing)) &&
|
|
806
|
+
isFunction((thing as Record<string, unknown>).then) &&
|
|
807
|
+
isFunction((thing as Record<string, unknown>).catch);
|
|
808
|
+
|
|
809
|
+
// original code
|
|
810
|
+
// https://github.com/DigitalBrainJS/FaxiosPromise/blob/16deab13710ec09779922131f3fa5954320f83ab/lib/utils.js#L11-L34
|
|
811
|
+
|
|
812
|
+
/**
|
|
813
|
+
* Provides a cross-platform setImmediate implementation.
|
|
814
|
+
* Uses native setImmediate if available, otherwise falls back to postMessage or setTimeout.
|
|
815
|
+
*
|
|
816
|
+
* @param {boolean} setImmediateSupported - Whether setImmediate is supported.
|
|
817
|
+
* @param {boolean} postMessageSupported - Whether postMessage is supported.
|
|
818
|
+
* @returns {Function} A function to schedule a callback asynchronously.
|
|
819
|
+
*/
|
|
820
|
+
const _setImmediate = ((setImmediateSupported: boolean, postMessageSupported: boolean) => {
|
|
821
|
+
if (setImmediateSupported) {
|
|
822
|
+
return (_global["setImmediate"] as (cb: () => void) => unknown);
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
return postMessageSupported
|
|
826
|
+
? ((token: string, callbacks: Array<() => void>) => {
|
|
827
|
+
const _addEventListener = _global.addEventListener as NonNullable<GlobalWithEvents["addEventListener"]>;
|
|
828
|
+
_addEventListener(
|
|
829
|
+
"message",
|
|
830
|
+
(evt: Record<string, unknown>) => {
|
|
831
|
+
if (evt["source"] === _global && evt["data"] === token) {
|
|
832
|
+
callbacks.length && callbacks.shift()!();
|
|
833
|
+
}
|
|
834
|
+
},
|
|
835
|
+
false
|
|
836
|
+
);
|
|
837
|
+
|
|
838
|
+
const _postMessage = _global.postMessage as NonNullable<GlobalWithEvents["postMessage"]>;
|
|
839
|
+
|
|
840
|
+
return (cb: () => void) => {
|
|
841
|
+
callbacks.push(cb);
|
|
842
|
+
_postMessage(token, "*");
|
|
843
|
+
};
|
|
844
|
+
// eslint-disable-next-line sonarjs/pseudo-random
|
|
845
|
+
})(`faxios@${Math.random()}`, [])
|
|
846
|
+
: (cb: () => void) => setTimeout(cb);
|
|
847
|
+
})(isFunction(_global["setImmediate"]), isFunction(_global["postMessage"]));
|
|
848
|
+
|
|
849
|
+
/**
|
|
850
|
+
* Schedules a microtask or asynchronous callback as soon as possible.
|
|
851
|
+
* Uses queueMicrotask if available, otherwise falls back to process.nextTick or _setImmediate.
|
|
852
|
+
*
|
|
853
|
+
* @type {Function}
|
|
854
|
+
*/
|
|
855
|
+
|
|
856
|
+
const _process = _global["process"];
|
|
857
|
+
const asap =
|
|
858
|
+
typeof queueMicrotask !== "undefined"
|
|
859
|
+
? queueMicrotask.bind(globalThis)
|
|
860
|
+
: (_process && _process.nextTick) || _setImmediate;
|
|
861
|
+
|
|
862
|
+
// *********************
|
|
863
|
+
|
|
864
|
+
const isIterable = (thing: unknown) => thing != null && isFunction((thing as Record<symbol, unknown>)[iterator]);
|
|
865
|
+
|
|
866
|
+
/**
|
|
867
|
+
* Determine if a value is iterable via an iterator that is NOT sourced solely
|
|
868
|
+
* from a polluted Object.prototype. Use this instead of `isIterable` whenever
|
|
869
|
+
* the iterable comes from untrusted input (e.g. user-supplied header sources),
|
|
870
|
+
* so `Object.prototype[Symbol.iterator] = ...` cannot turn an ordinary object
|
|
871
|
+
* into an attacker-controlled entries iterator.
|
|
872
|
+
*
|
|
873
|
+
* @param {*} thing The value to test
|
|
874
|
+
*
|
|
875
|
+
* @returns {boolean} True if value has a non-polluted iterator
|
|
876
|
+
*/
|
|
877
|
+
const isSafeIterable = (thing: unknown) =>
|
|
878
|
+
thing != null && hasOwnInPrototypeChain(thing, iterator) && isIterable(thing);
|
|
879
|
+
|
|
880
|
+
export default {
|
|
881
|
+
isArray,
|
|
882
|
+
isArrayBuffer,
|
|
883
|
+
isBuffer,
|
|
884
|
+
isFormData,
|
|
885
|
+
isArrayBufferView,
|
|
886
|
+
isString,
|
|
887
|
+
isNumber,
|
|
888
|
+
isBoolean,
|
|
889
|
+
isObject,
|
|
890
|
+
isPlainObject,
|
|
891
|
+
isEmptyObject,
|
|
892
|
+
isReadableStream,
|
|
893
|
+
isRequest,
|
|
894
|
+
isResponse,
|
|
895
|
+
isHeaders,
|
|
896
|
+
isUndefined,
|
|
897
|
+
isDate,
|
|
898
|
+
isFile,
|
|
899
|
+
isReactNativeBlob,
|
|
900
|
+
isReactNative,
|
|
901
|
+
isBlob,
|
|
902
|
+
isRegExp,
|
|
903
|
+
isFunction,
|
|
904
|
+
isStream,
|
|
905
|
+
isURLSearchParams,
|
|
906
|
+
isTypedArray,
|
|
907
|
+
isFileList,
|
|
908
|
+
forEach,
|
|
909
|
+
merge,
|
|
910
|
+
extend,
|
|
911
|
+
stripBOM,
|
|
912
|
+
toFlatObject,
|
|
913
|
+
kindOf,
|
|
914
|
+
kindOfTest,
|
|
915
|
+
toArray,
|
|
916
|
+
forEachEntry,
|
|
917
|
+
matchAll,
|
|
918
|
+
isHTMLForm,
|
|
919
|
+
hasOwnProperty,
|
|
920
|
+
hasOwnProp: hasOwnProperty, // an alias to avoid ESLint no-prototype-builtins detection
|
|
921
|
+
isDangerousKey,
|
|
922
|
+
hasOwnInPrototypeChain,
|
|
923
|
+
getSafeProp,
|
|
924
|
+
reduceDescriptors,
|
|
925
|
+
freezeMethods,
|
|
926
|
+
toObjectSet,
|
|
927
|
+
toCamelCase,
|
|
928
|
+
noop,
|
|
929
|
+
toFiniteNumber,
|
|
930
|
+
findKey,
|
|
931
|
+
global: _global,
|
|
932
|
+
isContextDefined,
|
|
933
|
+
isSpecCompliantForm,
|
|
934
|
+
toJSONObject,
|
|
935
|
+
isAsyncFn,
|
|
936
|
+
isThenable,
|
|
937
|
+
setImmediate: _setImmediate,
|
|
938
|
+
asap,
|
|
939
|
+
isIterable,
|
|
940
|
+
isSafeIterable,
|
|
941
|
+
};
|