@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
|
@@ -13,7 +13,7 @@ class CanceledError extends FaxiosError {
|
|
|
13
13
|
*
|
|
14
14
|
* @returns {CanceledError} The created error.
|
|
15
15
|
*/
|
|
16
|
-
constructor(message?:
|
|
16
|
+
constructor(message?: null | string, config?: FaxiosRequestConfig, request?: unknown) {
|
|
17
17
|
super(message == null ? "canceled" : message, FaxiosError.ERR_CANCELED, config as InternalFaxiosRequestConfig, request);
|
|
18
18
|
this.name = "CanceledError";
|
|
19
19
|
(this as unknown as Record<string, unknown>)["__CANCEL__"] = true;
|
package/src/lib/core/Faxios.ts
CHANGED
|
@@ -2,10 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
import CanceledError from "../cancel/CanceledError.js";
|
|
4
4
|
import buildURL from "../helpers/buildURL.js";
|
|
5
|
-
import cloneConfig
|
|
5
|
+
import cloneConfig from "../helpers/cloneConfig.js";
|
|
6
6
|
import validator from "../helpers/validator.js";
|
|
7
7
|
import type { ValidatorFn } from "../helpers/validator.js";
|
|
8
|
-
import type { StandardSchemaV1 } from "../types/standard-schema.js";
|
|
9
8
|
import type {
|
|
10
9
|
FaxiosContext,
|
|
11
10
|
FaxiosMiddleware,
|
|
@@ -21,6 +20,7 @@ import type {
|
|
|
21
20
|
SchemaConfig,
|
|
22
21
|
StringLiteralsOrString
|
|
23
22
|
} from "../types.js";
|
|
23
|
+
import type { StandardSchemaV1 } from "../types/standard-schema.js";
|
|
24
24
|
import utils from "../utils.js";
|
|
25
25
|
import buildFullPath from "./buildFullPath.js";
|
|
26
26
|
import { createDefinedEndpoint } from "./define.js";
|
|
@@ -29,21 +29,21 @@ import dispatchRequest from "./dispatchRequest.js";
|
|
|
29
29
|
import FaxiosError from "./FaxiosError.js";
|
|
30
30
|
import FaxiosHeaders from "./FaxiosHeaders.js";
|
|
31
31
|
import mergeConfig from "./mergeConfig.js";
|
|
32
|
-
import type {
|
|
32
|
+
import type { RouteBuilder, RouteConfig } from "./route.js";
|
|
33
33
|
import { createRouteBuilder } from "./route.js";
|
|
34
34
|
|
|
35
35
|
type TransitionalFn = (
|
|
36
|
-
validator:
|
|
36
|
+
validator: false | undefined | ValidatorFn,
|
|
37
37
|
version?: string,
|
|
38
38
|
message?: string
|
|
39
39
|
) => ValidatorFn;
|
|
40
40
|
type SpellingFn = (correctSpelling: string) => ValidatorFn;
|
|
41
41
|
const validators = validator.validators as Record<
|
|
42
42
|
string,
|
|
43
|
-
|
|
43
|
+
undefined | ValidatorFn
|
|
44
44
|
> & {
|
|
45
|
-
transitional?: TransitionalFn;
|
|
46
45
|
spelling?: SpellingFn;
|
|
46
|
+
transitional?: TransitionalFn;
|
|
47
47
|
};
|
|
48
48
|
|
|
49
49
|
// Every method header group declared on HeadersDefaults. `satisfies` keeps this
|
|
@@ -133,7 +133,10 @@ function resolveAllowAbsoluteUrls(
|
|
|
133
133
|
defaults: FaxiosRequestConfig
|
|
134
134
|
): void {
|
|
135
135
|
if (config.allowAbsoluteUrls === undefined) {
|
|
136
|
-
|
|
136
|
+
// Own reads only: instance defaults may be a plain object (the default instance's are).
|
|
137
|
+
const allowAbsoluteUrls = utils.hasOwnProp(defaults, "allowAbsoluteUrls") ? defaults.allowAbsoluteUrls : undefined;
|
|
138
|
+
const baseURL = utils.hasOwnProp(defaults, "baseURL") ? defaults.baseURL : undefined;
|
|
139
|
+
config.allowAbsoluteUrls = allowAbsoluteUrls ?? !baseURL;
|
|
137
140
|
}
|
|
138
141
|
}
|
|
139
142
|
|
|
@@ -143,10 +146,10 @@ type AnyContextMiddleware = FaxiosMiddleware<unknown, unknown>;
|
|
|
143
146
|
type AnyContextNext = FaxiosNext<unknown, unknown>;
|
|
144
147
|
|
|
145
148
|
type MiddlewareEntry = {
|
|
149
|
+
provided: Array<string>;
|
|
146
150
|
// The value passed to use(), kept only for eject()'s identity check.
|
|
147
151
|
ref: unknown;
|
|
148
152
|
run: AnyContextMiddleware;
|
|
149
|
-
provided: Array<string>;
|
|
150
153
|
};
|
|
151
154
|
|
|
152
155
|
function composeMiddleware(entries: ReadonlyArray<MiddlewareEntry>, dispatch: AnyContextNext): AnyContextNext {
|
|
@@ -272,7 +275,7 @@ class Faxios {
|
|
|
272
275
|
|
|
273
276
|
#addCapabilities(pluginName: string, provides: unknown): Array<string> {
|
|
274
277
|
const source = provides as Record<string, unknown>;
|
|
275
|
-
const keys = Object.keys(source).filter(key => !
|
|
278
|
+
const keys = Object.keys(source).filter(key => !utils.isDangerousKey(key));
|
|
276
279
|
for (const key of keys) {
|
|
277
280
|
if (utils.hasOwnProp(this.#capabilities, key)) {
|
|
278
281
|
throw new FaxiosError(`Plugin "${pluginName}" provides capability "${key}", which another plugin already provides`, FaxiosError.ERR_BAD_OPTION);
|
|
@@ -295,9 +298,9 @@ class Faxios {
|
|
|
295
298
|
*/
|
|
296
299
|
|
|
297
300
|
async request<O, D = unknown>(config: SchemaConfig<O, D>): Promise<FaxiosResponse<O, D>>;
|
|
298
|
-
async request<T = unknown, R = FaxiosResponse<T>, D = unknown>(configOrUrl:
|
|
301
|
+
async request<T = unknown, R = FaxiosResponse<T>, D = unknown>(configOrUrl: FaxiosRequestConfig<D> | string, config?: FaxiosRequestConfig<D>): Promise<R>;
|
|
299
302
|
async request(
|
|
300
|
-
configOrUrl:
|
|
303
|
+
configOrUrl: FaxiosRequestConfig | string,
|
|
301
304
|
config?: FaxiosRequestConfig
|
|
302
305
|
) {
|
|
303
306
|
try {
|
|
@@ -313,7 +316,7 @@ class Faxios {
|
|
|
313
316
|
}
|
|
314
317
|
|
|
315
318
|
async #request(
|
|
316
|
-
configOrUrl:
|
|
319
|
+
configOrUrl: FaxiosRequestConfig | string,
|
|
317
320
|
config?: FaxiosRequestConfig
|
|
318
321
|
): Promise<unknown> {
|
|
319
322
|
/*eslint no-param-reassign:0*/
|
|
@@ -361,8 +364,9 @@ class Faxios {
|
|
|
361
364
|
);
|
|
362
365
|
|
|
363
366
|
// Set config.method
|
|
367
|
+
const defaultMethod = utils.hasOwnProp(this.defaults, "method") ? this.defaults.method : undefined;
|
|
364
368
|
config.method = (
|
|
365
|
-
(config.method ||
|
|
369
|
+
(config.method || defaultMethod || "get") as string
|
|
366
370
|
).toLowerCase();
|
|
367
371
|
|
|
368
372
|
// Flatten headers
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// @ts-self-types="./FaxiosError.d.ts" — required for Deno: index.d.ts re-exports SchemaValidationError from here
|
|
2
2
|
"use strict";
|
|
3
3
|
|
|
4
|
+
import type { FaxiosResponse, InternalFaxiosRequestConfig } from "../types.js";
|
|
4
5
|
import type { StandardSchemaV1 } from "../types/standard-schema.js";
|
|
5
|
-
import type { InternalFaxiosRequestConfig, FaxiosResponse } from "../types.js";
|
|
6
6
|
import utils from "../utils.js";
|
|
7
7
|
import FaxiosHeaders from "./FaxiosHeaders.js";
|
|
8
8
|
|
|
@@ -247,9 +247,9 @@ export type SchemaValidationError =
|
|
|
247
247
|
}
|
|
248
248
|
| FaxiosError & {
|
|
249
249
|
code:
|
|
250
|
-
| typeof FaxiosError.ERR_BAD_REQUEST_SCHEMA
|
|
251
250
|
| typeof FaxiosError.ERR_BAD_PARAMS_SCHEMA
|
|
252
|
-
| typeof FaxiosError.ERR_BAD_PATH_PARAMS_SCHEMA
|
|
251
|
+
| typeof FaxiosError.ERR_BAD_PATH_PARAMS_SCHEMA
|
|
252
|
+
| typeof FaxiosError.ERR_BAD_REQUEST_SCHEMA;
|
|
253
253
|
issues: SchemaIssues;
|
|
254
254
|
};
|
|
255
255
|
|
|
@@ -9,16 +9,16 @@ import utils from "../utils.js";
|
|
|
9
9
|
const $internals = Symbol("internals");
|
|
10
10
|
|
|
11
11
|
type HeaderMatcher =
|
|
12
|
-
| string
|
|
12
|
+
| ((this: FaxiosHeaders, value: string, name: string) => boolean)
|
|
13
13
|
| RegExp
|
|
14
|
-
|
|
|
14
|
+
| string;
|
|
15
15
|
|
|
16
16
|
type HeaderInput =
|
|
17
|
-
| Record<string, unknown>
|
|
18
17
|
| FaxiosHeaders
|
|
18
|
+
| null
|
|
19
|
+
| Record<string, unknown>
|
|
19
20
|
| string
|
|
20
|
-
| undefined
|
|
21
|
-
| null;
|
|
21
|
+
| undefined;
|
|
22
22
|
|
|
23
23
|
/** Matches a `FaxiosHeaders` instance by its type-only brand. */
|
|
24
24
|
export type FaxiosHeadersInstance = Pick<FaxiosHeaders, typeof faxiosHeadersBrand>;
|
|
@@ -28,10 +28,29 @@ function normalizeHeader(header: string): string {
|
|
|
28
28
|
.toLowerCase();
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
// Per instance: lowercased own key -> own key. Callers may also write and delete headers as plain
|
|
32
|
+
// properties, so an entry is only trusted while its key is still own, and a miss rebuilds the index.
|
|
33
|
+
const keyIndexes = new WeakMap<object, Map<string, string>>();
|
|
34
|
+
|
|
35
|
+
function indexKeys(headers: object): Map<string, string> {
|
|
36
|
+
const index = new Map<string, string>();
|
|
37
|
+
// Later keys overwrite earlier ones, matching utils.findKey, which scans from the end.
|
|
38
|
+
for (const key of Object.keys(headers)) {
|
|
39
|
+
index.set(key.toLowerCase(), key);
|
|
40
|
+
}
|
|
41
|
+
keyIndexes.set(headers, index);
|
|
42
|
+
return index;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function findHeaderKey(headers: object, lHeader: string): string | undefined {
|
|
46
|
+
const key = keyIndexes.get(headers)?.get(lHeader);
|
|
47
|
+
return key !== undefined && utils.hasOwnProp(headers, key) ? key : indexKeys(headers).get(lHeader);
|
|
48
|
+
}
|
|
49
|
+
|
|
31
50
|
// eslint-disable-next-line sonarjs/function-return-type
|
|
32
51
|
function normalizeValue(
|
|
33
52
|
value: FaxiosHeaderValue | undefined
|
|
34
|
-
):
|
|
53
|
+
): Array<string> | false | null | string | undefined {
|
|
35
54
|
if (value == null) {
|
|
36
55
|
return value;
|
|
37
56
|
}
|
|
@@ -64,9 +83,9 @@ function matchHeaderValue(
|
|
|
64
83
|
value: unknown,
|
|
65
84
|
header: string,
|
|
66
85
|
filter:
|
|
67
|
-
| string
|
|
68
|
-
| RegExp
|
|
69
86
|
| ((this: FaxiosHeaders, value: string, name: string) => boolean)
|
|
87
|
+
| RegExp
|
|
88
|
+
| string
|
|
70
89
|
| undefined,
|
|
71
90
|
isHeaderNameFilter?: boolean
|
|
72
91
|
): boolean | undefined {
|
|
@@ -176,7 +195,7 @@ class FaxiosHeaders {
|
|
|
176
195
|
declare hasAuthorization: (matcher?: HeaderMatcher) => boolean;
|
|
177
196
|
|
|
178
197
|
constructor(
|
|
179
|
-
headers?: Record<string, unknown> |
|
|
198
|
+
headers?: FaxiosHeaders | null | Record<string, unknown> | string
|
|
180
199
|
) {
|
|
181
200
|
headers && this.set(headers);
|
|
182
201
|
}
|
|
@@ -187,6 +206,9 @@ class FaxiosHeaders {
|
|
|
187
206
|
rewrite?: boolean
|
|
188
207
|
): this {
|
|
189
208
|
const self = this;
|
|
209
|
+
// Set once a lookup misses, which rebuilds the index from the own keys. Only setHeader writes
|
|
210
|
+
// to self until this call returns, so from then on the index is complete and a miss is final.
|
|
211
|
+
let index: Map<string, string> | undefined;
|
|
190
212
|
|
|
191
213
|
function setHeader(
|
|
192
214
|
_value: unknown,
|
|
@@ -199,7 +221,11 @@ class FaxiosHeaders {
|
|
|
199
221
|
return;
|
|
200
222
|
}
|
|
201
223
|
|
|
202
|
-
const key =
|
|
224
|
+
const key = index ? index.get(lHeader) : findHeaderKey(self, lHeader);
|
|
225
|
+
if (key === undefined) {
|
|
226
|
+
index ??= keyIndexes.get(self)!;
|
|
227
|
+
index.set(String(_header).toLowerCase(), _header);
|
|
228
|
+
}
|
|
203
229
|
|
|
204
230
|
if (
|
|
205
231
|
!key ||
|
|
@@ -244,23 +270,23 @@ class FaxiosHeaders {
|
|
|
244
270
|
|
|
245
271
|
get(header: string): FaxiosHeaderValue | undefined;
|
|
246
272
|
get(header: string, parser: true): Record<string, string> | undefined;
|
|
247
|
-
get(header: string, parser: RegExp):
|
|
273
|
+
get(header: string, parser: RegExp): null | RegExpExecArray | undefined;
|
|
248
274
|
get<R>(header: string, parser: (this: FaxiosHeaders, value: FaxiosHeaderValue, header: string) => R): R | undefined;
|
|
249
275
|
get(
|
|
250
276
|
header: string,
|
|
251
277
|
parser?:
|
|
252
|
-
| RegExp
|
|
253
278
|
| ((
|
|
254
279
|
this: FaxiosHeaders,
|
|
255
280
|
value: FaxiosHeaderValue,
|
|
256
281
|
header: string
|
|
257
282
|
) => unknown)
|
|
283
|
+
| RegExp
|
|
258
284
|
| true
|
|
259
285
|
): unknown {
|
|
260
286
|
header = normalizeHeader(header);
|
|
261
287
|
|
|
262
288
|
if (header) {
|
|
263
|
-
const key =
|
|
289
|
+
const key = findHeaderKey(this, header);
|
|
264
290
|
|
|
265
291
|
if (key) {
|
|
266
292
|
const value = (this as Record<string, unknown>)[
|
|
@@ -299,7 +325,7 @@ class FaxiosHeaders {
|
|
|
299
325
|
header = normalizeHeader(header);
|
|
300
326
|
|
|
301
327
|
if (header) {
|
|
302
|
-
const key =
|
|
328
|
+
const key = findHeaderKey(this, header);
|
|
303
329
|
|
|
304
330
|
return !!(
|
|
305
331
|
key &&
|
|
@@ -317,7 +343,7 @@ class FaxiosHeaders {
|
|
|
317
343
|
return false;
|
|
318
344
|
}
|
|
319
345
|
|
|
320
|
-
delete(header: string |
|
|
346
|
+
delete(header: Array<string> | string, matcher?: HeaderMatcher): boolean {
|
|
321
347
|
const self = this;
|
|
322
348
|
let deleted = false;
|
|
323
349
|
|
|
@@ -325,7 +351,7 @@ class FaxiosHeaders {
|
|
|
325
351
|
_header = normalizeHeader(_header);
|
|
326
352
|
|
|
327
353
|
if (_header) {
|
|
328
|
-
const key =
|
|
354
|
+
const key = findHeaderKey(self, _header);
|
|
329
355
|
|
|
330
356
|
if (
|
|
331
357
|
key &&
|
|
@@ -381,11 +407,12 @@ class FaxiosHeaders {
|
|
|
381
407
|
|
|
382
408
|
normalize(format: boolean = false): this {
|
|
383
409
|
const self = this;
|
|
384
|
-
|
|
410
|
+
// Lowercased normalized name -> normalized name, for names already kept.
|
|
411
|
+
const kept = new Map<string, string>();
|
|
385
412
|
|
|
386
413
|
utils.forEach(this, (value: unknown, _header: unknown) => {
|
|
387
414
|
const header = _header as string;
|
|
388
|
-
const key =
|
|
415
|
+
const key = kept.get(header.toLowerCase());
|
|
389
416
|
|
|
390
417
|
if (key) {
|
|
391
418
|
(self as Record<string, unknown>)[key] = normalizeValue(
|
|
@@ -405,7 +432,7 @@ class FaxiosHeaders {
|
|
|
405
432
|
value as FaxiosHeaderValue
|
|
406
433
|
);
|
|
407
434
|
|
|
408
|
-
|
|
435
|
+
kept.set(normalized.toLowerCase(), normalized);
|
|
409
436
|
});
|
|
410
437
|
|
|
411
438
|
return this;
|
|
@@ -450,15 +477,15 @@ class FaxiosHeaders {
|
|
|
450
477
|
}
|
|
451
478
|
|
|
452
479
|
static from(
|
|
453
|
-
thing?: Record<string, unknown> |
|
|
480
|
+
thing?: FaxiosHeaders | null | Record<string, unknown> | string
|
|
454
481
|
): FaxiosHeaders {
|
|
455
482
|
return thing instanceof this ? thing : new this(thing);
|
|
456
483
|
}
|
|
457
484
|
|
|
458
485
|
static concat(
|
|
459
|
-
first: Record<string, unknown> |
|
|
486
|
+
first: FaxiosHeaders | null | Record<string, unknown> | string | undefined,
|
|
460
487
|
...targets: Array<
|
|
461
|
-
Record<string, unknown> |
|
|
488
|
+
FaxiosHeaders | null | Record<string, unknown> | string | undefined
|
|
462
489
|
>
|
|
463
490
|
): FaxiosHeaders {
|
|
464
491
|
const computed = new this(first);
|
|
@@ -468,7 +495,7 @@ class FaxiosHeaders {
|
|
|
468
495
|
return computed;
|
|
469
496
|
}
|
|
470
497
|
|
|
471
|
-
static accessor(header: string |
|
|
498
|
+
static accessor(header: Array<string> | string): typeof FaxiosHeaders {
|
|
472
499
|
const self = this as unknown as Record<
|
|
473
500
|
symbol,
|
|
474
501
|
{ accessors: Record<string, boolean>; }
|
package/src/lib/core/define.ts
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
// @ts-self-types="./define.d.ts" — required for Deno: maps built .js to adjacent .d.ts in dist/
|
|
2
2
|
|
|
3
|
+
import type { FaxiosRequestConfig, FaxiosResponse, Method, StringLiteralsOrString } from "../types.js";
|
|
3
4
|
import type { StandardSchemaV1 } from "../types/standard-schema.js";
|
|
4
|
-
import type { FaxiosRequestConfig, FaxiosResponse, StringLiteralsOrString, Method } from "../types.js";
|
|
5
5
|
import mergeConfig from "./mergeConfig.js";
|
|
6
6
|
|
|
7
7
|
type StrippedFields =
|
|
8
|
-
| "
|
|
8
|
+
| "data"
|
|
9
9
|
| "method"
|
|
10
|
-
| "pathParams"
|
|
11
10
|
| "params"
|
|
12
|
-
| "data"
|
|
13
|
-
| "pathParamsSchema"
|
|
14
11
|
| "paramsSchema"
|
|
12
|
+
| "pathParams"
|
|
13
|
+
| "pathParamsSchema"
|
|
15
14
|
| "requestSchema"
|
|
16
|
-
| "responseSchema"
|
|
15
|
+
| "responseSchema"
|
|
16
|
+
| "url";
|
|
17
17
|
|
|
18
18
|
/** Request config accepted by a defined endpoint call: everything except `url`, `method`, `pathParams`, `params`, `data` and the schemas. */
|
|
19
19
|
export type BasePerCallConfig = Omit<FaxiosRequestConfig, StrippedFields>;
|
|
@@ -47,12 +47,12 @@ export type DefineConfig<
|
|
|
47
47
|
D extends StandardSchemaV1 | undefined = undefined,
|
|
48
48
|
R extends StandardSchemaV1 | undefined = undefined
|
|
49
49
|
> = BasePerCallConfig & {
|
|
50
|
+
paramsSchema?: P;
|
|
50
51
|
/**
|
|
51
52
|
* Standard Schema that validates `pathParams` on every call; its output fills the `{key}`
|
|
52
53
|
* placeholders. Makes `pathParams` required per call. A failure rejects with `ERR_BAD_PATH_PARAMS_SCHEMA`.
|
|
53
54
|
*/
|
|
54
55
|
pathParamsSchema?: PP;
|
|
55
|
-
paramsSchema?: P;
|
|
56
56
|
requestSchema?: D;
|
|
57
57
|
responseSchema?: R;
|
|
58
58
|
};
|
|
@@ -7,7 +7,7 @@ import FaxiosError from "../core/FaxiosError.js";
|
|
|
7
7
|
import FaxiosHeaders from "../core/FaxiosHeaders.js";
|
|
8
8
|
import { validateSchema } from "../core/validateSchema.js";
|
|
9
9
|
import { substitutePathParams } from "../helpers/substitutePathParams.js";
|
|
10
|
-
import type {
|
|
10
|
+
import type { FaxiosResponse, InternalFaxiosRequestConfig } from "../types.js";
|
|
11
11
|
import utils from "../utils.js";
|
|
12
12
|
import transformData from "./transformData.js";
|
|
13
13
|
|
|
@@ -104,7 +104,12 @@ export default async function dispatchRequest(this: unknown, config: InternalFax
|
|
|
104
104
|
|
|
105
105
|
config.data = transformData.call(config, config.transformRequest);
|
|
106
106
|
|
|
107
|
-
|
|
107
|
+
const data: unknown = config.data;
|
|
108
|
+
// Binary and stream bodies keep their own type: fetch uses `Blob.type` or sends none.
|
|
109
|
+
const isBinaryOrStream = utils.isBlob(data) || utils.isFile(data) || utils.isArrayBuffer(data) || utils.isArrayBufferView(data) ||
|
|
110
|
+
utils.isReadableStream?.(data) || utils.isStream(data) ||
|
|
111
|
+
(typeof data === "object" && data !== null && Symbol.asyncIterator in data);
|
|
112
|
+
if (data != null && !utils.isFormData(data) && !isBinaryOrStream && [ "post", "put", "patch" ].indexOf(config.method as string) !== -1) {
|
|
108
113
|
(config.headers as unknown as { setContentType: (v: string, r: boolean) => void; }).setContentType("application/x-www-form-urlencoded", false);
|
|
109
114
|
}
|
|
110
115
|
|
|
@@ -151,7 +156,7 @@ export default async function dispatchRequest(this: unknown, config: InternalFax
|
|
|
151
156
|
if (!isCancel(reason)) {
|
|
152
157
|
throwIfCancellationRequested(config);
|
|
153
158
|
|
|
154
|
-
const r = reason as { response?: { data?: unknown; headers?: unknown; status?: number;
|
|
159
|
+
const r = reason as null | { response?: { [k: string]: unknown; data?: unknown; headers?: unknown; status?: number; }; };
|
|
155
160
|
if (r?.response) {
|
|
156
161
|
(config as unknown as Record<string, unknown>)["response"] = r.response;
|
|
157
162
|
try {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
import type {
|
|
3
|
+
import type { FaxiosDefaults, FaxiosRequestConfig } from "../types.js";
|
|
4
4
|
import utils from "../utils.js";
|
|
5
5
|
import FaxiosHeaders from "./FaxiosHeaders.js";
|
|
6
6
|
|
|
@@ -15,7 +15,7 @@ const headersToObject = (thing: unknown) => (thing instanceof FaxiosHeaders ? {
|
|
|
15
15
|
*
|
|
16
16
|
* @returns {Object} New object resulting from merging config2 to config1
|
|
17
17
|
*/
|
|
18
|
-
export default function mergeConfig(config1:
|
|
18
|
+
export default function mergeConfig(config1: FaxiosDefaults | FaxiosRequestConfig | Record<string, unknown>, config2?: FaxiosDefaults | FaxiosRequestConfig | Record<string, unknown>): FaxiosRequestConfig & Record<string, unknown> {
|
|
19
19
|
|
|
20
20
|
config2 = config2 || {};
|
|
21
21
|
|
|
@@ -79,6 +79,40 @@ export default function mergeConfig(config1: FaxiosRequestConfig | FaxiosDefault
|
|
|
79
79
|
return undefined;
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
+
// Shallow own-key copy into a null-prototype object, later sources winning. Every own key is
|
|
83
|
+
// kept, including `constructor`, `prototype` and `__proto__`: `params` are caller data that
|
|
84
|
+
// reach the query string, and defineProperty stores them as plain data slots.
|
|
85
|
+
function ownCopy(...sources: Array<unknown>): Record<string, unknown> {
|
|
86
|
+
const out: Record<string, unknown> = Object.create(null);
|
|
87
|
+
for (const source of sources) {
|
|
88
|
+
if (!utils.isPlainObject(source)) continue;
|
|
89
|
+
const record = source as Record<string, unknown>;
|
|
90
|
+
for (const key of Object.keys(record)) {
|
|
91
|
+
Object.defineProperty(out, key, Object.assign(Object.create(null) as PropertyDescriptor, {
|
|
92
|
+
value: record[key],
|
|
93
|
+
enumerable: true,
|
|
94
|
+
writable: true,
|
|
95
|
+
configurable: true,
|
|
96
|
+
}));
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return out;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// `params`: a plain object is copied with every own key; anything else (URLSearchParams,
|
|
103
|
+
// a custom serializer's input) passes through as given.
|
|
104
|
+
function mergeParams(a: unknown, b: unknown): unknown {
|
|
105
|
+
const source = utils.isUndefined(b) ? a : b;
|
|
106
|
+
if (!utils.isPlainObject(source)) return source;
|
|
107
|
+
return utils.isUndefined(b) ? ownCopy(a) : ownCopy(a, b);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// `env`: shallow, null-prototype, so `fetch`, `Request` and `Response` can only be own values.
|
|
111
|
+
function mergeEnv(a: unknown, b: unknown): unknown {
|
|
112
|
+
if (utils.isUndefined(a) && utils.isUndefined(b)) return undefined;
|
|
113
|
+
return ownCopy(a, b);
|
|
114
|
+
}
|
|
115
|
+
|
|
82
116
|
function getMergedTransitionalOption(prop: string): unknown {
|
|
83
117
|
const c2 = config2 as Record<string, unknown>;
|
|
84
118
|
const c1 = config1 as Record<string, unknown>;
|
|
@@ -117,7 +151,11 @@ export default function mergeConfig(config1: FaxiosRequestConfig | FaxiosDefault
|
|
|
117
151
|
const mergeMap = {
|
|
118
152
|
url: valueFromConfig2,
|
|
119
153
|
method: valueFromConfig2,
|
|
120
|
-
|
|
154
|
+
// The body is passed by reference: faxios never mutates it, and copying would drop keys such
|
|
155
|
+
// as `constructor` and cost a deep clone per request.
|
|
156
|
+
data: (_a: unknown, b: unknown) => b,
|
|
157
|
+
params: mergeParams,
|
|
158
|
+
env: mergeEnv,
|
|
121
159
|
baseURL: defaultToConfig2,
|
|
122
160
|
transformRequest: defaultToConfig2,
|
|
123
161
|
transformResponse: defaultToConfig2,
|
|
@@ -150,7 +188,7 @@ export default function mergeConfig(config1: FaxiosRequestConfig | FaxiosDefault
|
|
|
150
188
|
|
|
151
189
|
utils.forEach(Object.keys({ ...config1, ...config2 }), function computeConfigValue(_value: unknown, _prop: unknown) {
|
|
152
190
|
const key = _value as string;
|
|
153
|
-
if (key
|
|
191
|
+
if (utils.isDangerousKey(key)) return;
|
|
154
192
|
const mergeFn = (utils.hasOwnProp(mergeMap, key) ? (mergeMap as Record<string, typeof mergeDeepProperties>)[key] : mergeDeepProperties)!;
|
|
155
193
|
const a = utils.hasOwnProp(config1, key) ? c1[key] : undefined;
|
|
156
194
|
const b = utils.hasOwnProp(config2, key) ? c2[key] : undefined;
|
|
@@ -96,7 +96,7 @@ function prepareRequest(config: FaxiosRequestConfig): FaxiosRequestConfig {
|
|
|
96
96
|
const url = own("url");
|
|
97
97
|
|
|
98
98
|
const headers: FaxiosHeaders = FaxiosHeaders.from(
|
|
99
|
-
own("headers") as Record<string, unknown> |
|
|
99
|
+
own("headers") as null | Record<string, unknown> | undefined
|
|
100
100
|
);
|
|
101
101
|
newConfig.headers = headers;
|
|
102
102
|
|
package/src/lib/core/route.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// @ts-self-types="./route.d.ts" — required for Deno: maps built .js to adjacent .d.ts in dist/
|
|
2
2
|
|
|
3
|
+
import cloneConfig from "../helpers/cloneConfig.js";
|
|
3
4
|
import type { StandardSchemaV1 } from "../types/standard-schema.js";
|
|
4
5
|
import type { BasePerCallConfig, DefineConfig, DefinedEndpoint, FaxiosLike } from "./define.js";
|
|
5
6
|
import { createDefinedEndpoint } from "./define.js";
|
|
@@ -28,7 +29,7 @@ export type RouteMethodConfig<
|
|
|
28
29
|
|
|
29
30
|
/** The object `route()` returns: one endpoint factory per HTTP method (no `query`). */
|
|
30
31
|
export type RouteBuilder<PP extends StandardSchemaV1<unknown, Record<string, unknown>> | undefined, TOpts = unknown> = {
|
|
31
|
-
[M in "
|
|
32
|
+
[M in "delete" | "get" | "head" | "options" | "patch" | "post" | "put"]: <
|
|
32
33
|
P extends StandardSchemaV1 | undefined = undefined,
|
|
33
34
|
D extends StandardSchemaV1 | undefined = undefined,
|
|
34
35
|
R extends StandardSchemaV1 | undefined = undefined
|
|
@@ -43,11 +44,7 @@ export function createRouteBuilder<PP extends StandardSchemaV1<unknown, Record<s
|
|
|
43
44
|
url: string,
|
|
44
45
|
routeConfig?: RouteConfig<PP>
|
|
45
46
|
): RouteBuilder<PP> {
|
|
46
|
-
const
|
|
47
|
-
delete raw.__proto__;
|
|
48
|
-
delete raw.constructor;
|
|
49
|
-
delete raw.prototype;
|
|
50
|
-
const { pathParamsSchema, ...routeDefaults } = raw;
|
|
47
|
+
const { pathParamsSchema, ...routeDefaults } = cloneConfig(routeConfig ?? {});
|
|
51
48
|
|
|
52
49
|
const builder = {} as RouteBuilder<PP>;
|
|
53
50
|
for (const method of methods) {
|
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
import FaxiosHeaders from "../core/FaxiosHeaders.js";
|
|
4
4
|
import defaults from "../defaults/index.js";
|
|
5
|
-
import type {
|
|
5
|
+
import type { FaxiosRequestHeaders, FaxiosRequestTransformer, FaxiosResponseTransformer, InternalFaxiosRequestConfig } from "../types.js";
|
|
6
6
|
import utils from "../utils.js";
|
|
7
7
|
|
|
8
8
|
type TransformFn = FaxiosRequestTransformer | FaxiosResponseTransformer;
|
|
9
9
|
|
|
10
|
-
export default function transformData(this: unknown, fns: TransformFn |
|
|
10
|
+
export default function transformData(this: unknown, fns: Array<TransformFn> | TransformFn | undefined, response?: null | { data?: unknown; headers?: unknown; status?: number; }): unknown {
|
|
11
11
|
const config = (this || defaults) as InternalFaxiosRequestConfig;
|
|
12
12
|
const context = response || config;
|
|
13
13
|
const headers = FaxiosHeaders.from(context.headers as Record<string, unknown> | undefined);
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import isCancel from "../cancel/isCancel.js";
|
|
2
|
+
import type { FaxiosResponse, InternalFaxiosRequestConfig } from "../types.js";
|
|
2
3
|
import type { StandardSchemaV1 } from "../types/standard-schema.js";
|
|
3
|
-
import type { InternalFaxiosRequestConfig, FaxiosResponse } from "../types.js";
|
|
4
4
|
import FaxiosError from "./FaxiosError.js";
|
|
5
5
|
|
|
6
6
|
type SchemaErrorCode =
|
|
7
|
-
| typeof FaxiosError.ERR_BAD_RESPONSE_SCHEMA
|
|
8
|
-
| typeof FaxiosError.ERR_BAD_REQUEST_SCHEMA
|
|
9
7
|
| typeof FaxiosError.ERR_BAD_PARAMS_SCHEMA
|
|
10
|
-
| typeof FaxiosError.ERR_BAD_PATH_PARAMS_SCHEMA
|
|
8
|
+
| typeof FaxiosError.ERR_BAD_PATH_PARAMS_SCHEMA
|
|
9
|
+
| typeof FaxiosError.ERR_BAD_REQUEST_SCHEMA
|
|
10
|
+
| typeof FaxiosError.ERR_BAD_RESPONSE_SCHEMA;
|
|
11
11
|
|
|
12
12
|
export async function validateSchema<S extends StandardSchemaV1>(
|
|
13
13
|
schema: S,
|
|
@@ -96,7 +96,7 @@ const defaults: FaxiosDefaults = {
|
|
|
96
96
|
headers: FaxiosRequestHeaders
|
|
97
97
|
) {
|
|
98
98
|
const contentType =
|
|
99
|
-
(headers.getContentType() as
|
|
99
|
+
(headers.getContentType() as null | string | undefined) || "";
|
|
100
100
|
const hasJSONContentType = contentType.indexOf("application/json") > -1;
|
|
101
101
|
const isObjectPayload = utils.isObject(data);
|
|
102
102
|
|
package/src/lib/env/data.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const VERSION = "0.2.
|
|
1
|
+
export const VERSION = "0.2.3";
|