@zayne-labs/callapi 1.11.9 → 1.11.11

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.
@@ -0,0 +1,649 @@
1
+ //#region src/types/type-helpers.ts
2
+ const defineEnum = (value) => Object.freeze(value);
3
+
4
+ //#endregion
5
+ //#region src/constants/defaults.ts
6
+ const extraOptionDefaults = Object.freeze(defineEnum({
7
+ bodySerializer: JSON.stringify,
8
+ defaultHTTPErrorMessage: "HTTP request failed unexpectedly",
9
+ dedupeCacheScope: "local",
10
+ dedupeCacheScopeKey: "default",
11
+ dedupeStrategy: "cancel",
12
+ hooksExecutionMode: "parallel",
13
+ responseParser: JSON.parse,
14
+ responseType: "json",
15
+ resultMode: "all",
16
+ retryAttempts: 0,
17
+ retryCondition: () => true,
18
+ retryDelay: 1e3,
19
+ retryMaxDelay: 1e4,
20
+ retryMethods: ["GET", "POST"],
21
+ retryStatusCodes: [],
22
+ retryStrategy: "linear"
23
+ }));
24
+ const requestOptionDefaults = defineEnum({ method: "GET" });
25
+
26
+ //#endregion
27
+ //#region src/utils/guards.ts
28
+ const isArray = (value) => Array.isArray(value);
29
+ const isBoolean = (value) => typeof value === "boolean";
30
+ const isBlob = (value) => value instanceof Blob;
31
+ const isObject = (value) => {
32
+ return typeof value === "object" && value !== null;
33
+ };
34
+ const hasObjectPrototype = (value) => {
35
+ return Object.prototype.toString.call(value) === "[object Object]";
36
+ };
37
+ /**
38
+ * @description Copied from TanStack Query's isPlainObject
39
+ * @see https://github.com/TanStack/query/blob/main/packages/query-core/src/utils.ts#L321
40
+ */
41
+ const isPlainObject = (value) => {
42
+ if (!hasObjectPrototype(value)) return false;
43
+ const constructor = value?.constructor;
44
+ if (constructor === void 0) return true;
45
+ const prototype = constructor.prototype;
46
+ if (!hasObjectPrototype(prototype)) return false;
47
+ if (!Object.hasOwn(prototype, "isPrototypeOf")) return false;
48
+ if (Object.getPrototypeOf(value) !== Object.prototype) return false;
49
+ return true;
50
+ };
51
+ const isValidJsonString = (value) => {
52
+ if (!isString(value)) return false;
53
+ try {
54
+ JSON.parse(value);
55
+ return true;
56
+ } catch {
57
+ return false;
58
+ }
59
+ };
60
+ const isSerializable = (value) => {
61
+ return isPlainObject(value) || isArray(value) || typeof value?.toJSON === "function";
62
+ };
63
+ const isFunction = (value) => typeof value === "function";
64
+ const isQueryString = (value) => isString(value) && value.includes("=");
65
+ const isString = (value) => typeof value === "string";
66
+ const isPromise = (value) => value instanceof Promise;
67
+ const isReadableStream = (value) => {
68
+ return value instanceof ReadableStream;
69
+ };
70
+
71
+ //#endregion
72
+ //#region src/utils/external/error.ts
73
+ const httpErrorSymbol = Symbol("HTTPError");
74
+ var HTTPError = class HTTPError extends Error {
75
+ errorData;
76
+ httpErrorSymbol = httpErrorSymbol;
77
+ name = "HTTPError";
78
+ response;
79
+ constructor(errorDetails, errorOptions) {
80
+ const { defaultHTTPErrorMessage, errorData, response } = errorDetails;
81
+ const selectedDefaultErrorMessage = (isString(defaultHTTPErrorMessage) ? defaultHTTPErrorMessage : defaultHTTPErrorMessage?.({
82
+ errorData,
83
+ response
84
+ })) ?? (response.statusText || extraOptionDefaults.defaultHTTPErrorMessage);
85
+ const message = errorData?.message ?? selectedDefaultErrorMessage;
86
+ super(message, errorOptions);
87
+ this.errorData = errorData;
88
+ this.response = response;
89
+ }
90
+ /**
91
+ * @description Checks if the given error is an instance of HTTPError
92
+ * @param error - The error to check
93
+ * @returns true if the error is an instance of HTTPError, false otherwise
94
+ */
95
+ static isError(error) {
96
+ if (!isObject(error)) return false;
97
+ if (error instanceof HTTPError) return true;
98
+ const actualError = error;
99
+ return actualError.httpErrorSymbol === httpErrorSymbol && actualError.name === "HTTPError";
100
+ }
101
+ };
102
+ const prettifyPath = (path) => {
103
+ if (!path || path.length === 0) return "";
104
+ return ` → at ${path.map((segment) => isObject(segment) ? segment.key : segment).join(".")}`;
105
+ };
106
+ const prettifyValidationIssues = (issues) => {
107
+ return issues.map((issue) => `✖ ${issue.message}${prettifyPath(issue.path)}`).join(" | ");
108
+ };
109
+ const validationErrorSymbol = Symbol("ValidationErrorSymbol");
110
+ var ValidationError = class ValidationError extends Error {
111
+ errorData;
112
+ issueCause;
113
+ name = "ValidationError";
114
+ response;
115
+ validationErrorSymbol = validationErrorSymbol;
116
+ constructor(details, errorOptions) {
117
+ const { issueCause, issues, response } = details;
118
+ const message = prettifyValidationIssues(issues);
119
+ super(message, errorOptions);
120
+ this.errorData = issues;
121
+ this.response = response;
122
+ this.issueCause = issueCause;
123
+ }
124
+ /**
125
+ * @description Checks if the given error is an instance of ValidationError
126
+ * @param error - The error to check
127
+ * @returns true if the error is an instance of ValidationError, false otherwise
128
+ */
129
+ static isError(error) {
130
+ if (!isObject(error)) return false;
131
+ if (error instanceof ValidationError) return true;
132
+ const actualError = error;
133
+ return actualError.validationErrorSymbol === validationErrorSymbol && actualError.name === "ValidationError";
134
+ }
135
+ };
136
+
137
+ //#endregion
138
+ //#region src/utils/external/guards.ts
139
+ const isHTTPError = (error) => {
140
+ return isObject(error) && error.name === "HTTPError";
141
+ };
142
+ const isHTTPErrorInstance = (error) => {
143
+ return HTTPError.isError(error);
144
+ };
145
+ const isValidationError = (error) => {
146
+ return isObject(error) && error.name === "ValidationError";
147
+ };
148
+ const isValidationErrorInstance = (error) => {
149
+ return ValidationError.isError(error);
150
+ };
151
+ const isJavascriptError = (error) => {
152
+ return isObject(error) && !isHTTPError(error) && !isValidationError(error);
153
+ };
154
+
155
+ //#endregion
156
+ //#region src/auth.ts
157
+ const resolveAuthValue = (value) => isFunction(value) ? value() : value;
158
+ const getAuthHeader = async (auth) => {
159
+ if (auth === void 0) return;
160
+ if (isPromise(auth) || isFunction(auth) || !isObject(auth)) {
161
+ const authValue = await resolveAuthValue(auth);
162
+ if (authValue === void 0) return;
163
+ return { Authorization: `Bearer ${authValue}` };
164
+ }
165
+ switch (auth.type) {
166
+ case "Basic": {
167
+ const [username, password] = await Promise.all([resolveAuthValue(auth.username), resolveAuthValue(auth.password)]);
168
+ if (username === void 0 || password === void 0) return;
169
+ return { Authorization: `Basic ${globalThis.btoa(`${username}:${password}`)}` };
170
+ }
171
+ case "Custom": {
172
+ const [prefix, value] = await Promise.all([resolveAuthValue(auth.prefix), resolveAuthValue(auth.value)]);
173
+ if (value === void 0) return;
174
+ return { Authorization: `${prefix} ${value}` };
175
+ }
176
+ default: {
177
+ const [bearer, token] = await Promise.all([resolveAuthValue(auth.bearer), resolveAuthValue(auth.token)]);
178
+ if (bearer !== void 0) return { Authorization: `Bearer ${bearer}` };
179
+ if (token === void 0) return;
180
+ return { Authorization: `Token ${token}` };
181
+ }
182
+ }
183
+ };
184
+
185
+ //#endregion
186
+ //#region src/constants/common.ts
187
+ const fetchSpecificKeys = defineEnum([
188
+ "body",
189
+ "integrity",
190
+ "duplex",
191
+ "method",
192
+ "headers",
193
+ "signal",
194
+ "cache",
195
+ "redirect",
196
+ "window",
197
+ "credentials",
198
+ "keepalive",
199
+ "referrer",
200
+ "priority",
201
+ "mode",
202
+ "referrerPolicy"
203
+ ]);
204
+
205
+ //#endregion
206
+ //#region src/utils/external/body.ts
207
+ const toQueryString = (query) => {
208
+ if (!query) {
209
+ console.error("toQueryString:", "No query params provided!");
210
+ return null;
211
+ }
212
+ return new URLSearchParams(query).toString();
213
+ };
214
+ const toBlobOrString = (value) => {
215
+ return isBlob(value) ? value : String(value);
216
+ };
217
+ /**
218
+ * @description Converts a plain object to FormData.
219
+ *
220
+ * Handles various data types:
221
+ * - **Primitives** (string, number, boolean): Converted to strings
222
+ * - **Blobs/Files**: Added directly to FormData
223
+ * - **Arrays**: Each item is appended (allows multiple values for same key)
224
+ * - **Objects**: JSON stringified before adding to FormData
225
+ *
226
+ * @example
227
+ * ```ts
228
+ * // Basic usage
229
+ * const formData = toFormData({
230
+ * name: "John",
231
+ * age: 30,
232
+ * active: true
233
+ * });
234
+ *
235
+ * // With arrays
236
+ * const formData = toFormData({
237
+ * tags: ["javascript", "typescript"],
238
+ * name: "John"
239
+ * });
240
+ *
241
+ * // With files
242
+ * const formData = toFormData({
243
+ * avatar: fileBlob,
244
+ * name: "John"
245
+ * });
246
+ *
247
+ * // With nested objects (one level only)
248
+ * const formData = toFormData({
249
+ * user: { name: "John", age: 30 },
250
+ * settings: { theme: "dark" }
251
+ * });
252
+ *
253
+ * // Type-preserving usage with Zod
254
+ * const schema = z.object({ name: z.string(), file: z.instanceof(Blob) });
255
+ * const data = schema.parse({ name: "John", file: blob });
256
+ * const typedFormData = toFormData(data, { returnType: "inputType" });
257
+ * // Type is { name: string; file: Blob }, runtime is FormData
258
+ * ```
259
+ */
260
+ const toFormData = (data) => {
261
+ const formData = new FormData();
262
+ for (const [key, value] of Object.entries(data)) {
263
+ if (isArray(value)) {
264
+ value.forEach((innerValue) => formData.append(key, toBlobOrString(innerValue)));
265
+ continue;
266
+ }
267
+ if (isObject(value) && !isBlob(value)) {
268
+ formData.set(key, JSON.stringify(value));
269
+ continue;
270
+ }
271
+ formData.set(key, toBlobOrString(value));
272
+ }
273
+ return formData;
274
+ };
275
+
276
+ //#endregion
277
+ //#region src/validation.ts
278
+ const handleValidatorFunction = async (validator, inputData) => {
279
+ try {
280
+ return {
281
+ issues: void 0,
282
+ value: await validator(inputData)
283
+ };
284
+ } catch (error) {
285
+ return {
286
+ issues: toArray(error),
287
+ value: void 0
288
+ };
289
+ }
290
+ };
291
+ const standardSchemaParser = async (fullSchema, schemaName, inputData, response) => {
292
+ const schema = fullSchema?.[schemaName];
293
+ if (!schema) return inputData;
294
+ const result = isFunction(schema) ? await handleValidatorFunction(schema, inputData) : await schema["~standard"].validate(inputData);
295
+ if (result.issues) throw new ValidationError({
296
+ issueCause: schemaName,
297
+ issues: result.issues,
298
+ response: response ?? null
299
+ });
300
+ return result.value;
301
+ };
302
+ const routeKeyMethods = defineEnum([
303
+ "delete",
304
+ "get",
305
+ "patch",
306
+ "post",
307
+ "put"
308
+ ]);
309
+ const handleSchemaValidation = async (fullSchema, schemaName, validationOptions) => {
310
+ const { inputValue, response, schemaConfig } = validationOptions;
311
+ if (schemaConfig?.disableRuntimeValidation) return inputValue;
312
+ return await standardSchemaParser(fullSchema, schemaName, inputValue, response);
313
+ };
314
+ const extraOptionsToBeValidated = [
315
+ "meta",
316
+ "params",
317
+ "query"
318
+ ];
319
+ const handleExtraOptionsValidation = async (validationOptions) => {
320
+ const { options, schema, schemaConfig } = validationOptions;
321
+ const validationResultArray = await Promise.all(extraOptionsToBeValidated.map((schemaName) => handleSchemaValidation(schema, schemaName, {
322
+ inputValue: options[schemaName],
323
+ schemaConfig
324
+ })));
325
+ const validatedResultObject = {};
326
+ for (const [index, schemaName] of extraOptionsToBeValidated.entries()) {
327
+ const validationResult = validationResultArray[index];
328
+ if (validationResult === void 0) continue;
329
+ validatedResultObject[schemaName] = validationResult;
330
+ }
331
+ return validatedResultObject;
332
+ };
333
+ const requestOptionsToBeValidated = [
334
+ "body",
335
+ "headers",
336
+ "method"
337
+ ];
338
+ const handleRequestOptionsValidation = async (validationOptions) => {
339
+ const { requestOptions, schema, schemaConfig } = validationOptions;
340
+ const validationResultArray = await Promise.all(requestOptionsToBeValidated.map((schemaName) => handleSchemaValidation(schema, schemaName, {
341
+ inputValue: requestOptions[schemaName],
342
+ schemaConfig
343
+ })));
344
+ const validatedResultObject = {};
345
+ for (const [index, propertyKey] of requestOptionsToBeValidated.entries()) {
346
+ const validationResult = validationResultArray[index];
347
+ if (validationResult === void 0) continue;
348
+ validatedResultObject[propertyKey] = validationResult;
349
+ }
350
+ return validatedResultObject;
351
+ };
352
+ const handleConfigValidation = async (validationOptions) => {
353
+ const { baseExtraOptions, currentRouteSchemaKey, extraOptions, options, requestOptions } = validationOptions;
354
+ const { currentRouteSchema, resolvedSchema } = getResolvedSchema({
355
+ baseExtraOptions,
356
+ currentRouteSchemaKey,
357
+ extraOptions
358
+ });
359
+ const resolvedSchemaConfig = getResolvedSchemaConfig({
360
+ baseExtraOptions,
361
+ extraOptions
362
+ });
363
+ if (resolvedSchemaConfig?.strict === true && !currentRouteSchema) throw new ValidationError({
364
+ issueCause: "schemaConfig-(strict)",
365
+ issues: [{ message: `Strict Mode - No schema found for route '${currentRouteSchemaKey}' ` }],
366
+ response: null
367
+ });
368
+ if (resolvedSchemaConfig?.disableRuntimeValidation) return {
369
+ extraOptionsValidationResult: null,
370
+ requestOptionsValidationResult: null,
371
+ resolvedSchema,
372
+ resolvedSchemaConfig,
373
+ shouldApplySchemaOutput: false
374
+ };
375
+ const [extraOptionsValidationResult, requestOptionsValidationResult] = await Promise.all([handleExtraOptionsValidation({
376
+ options,
377
+ schema: resolvedSchema,
378
+ schemaConfig: resolvedSchemaConfig
379
+ }), handleRequestOptionsValidation({
380
+ requestOptions,
381
+ schema: resolvedSchema,
382
+ schemaConfig: resolvedSchemaConfig
383
+ })]);
384
+ return {
385
+ extraOptionsValidationResult,
386
+ requestOptionsValidationResult,
387
+ resolvedSchema,
388
+ resolvedSchemaConfig,
389
+ shouldApplySchemaOutput: (Boolean(extraOptionsValidationResult) || Boolean(requestOptionsValidationResult)) && !resolvedSchemaConfig?.disableValidationOutputApplication
390
+ };
391
+ };
392
+ const fallBackRouteSchemaKey = ".";
393
+ const getResolvedSchema = (context) => {
394
+ const { baseExtraOptions, currentRouteSchemaKey, extraOptions } = context;
395
+ const fallbackRouteSchema = baseExtraOptions.schema?.routes[fallBackRouteSchemaKey];
396
+ const currentRouteSchema = baseExtraOptions.schema?.routes[currentRouteSchemaKey];
397
+ const resolvedRouteSchema = {
398
+ ...fallbackRouteSchema,
399
+ ...currentRouteSchema
400
+ };
401
+ return {
402
+ currentRouteSchema,
403
+ resolvedSchema: isFunction(extraOptions.schema) ? extraOptions.schema({
404
+ baseSchemaRoutes: baseExtraOptions.schema?.routes ?? {},
405
+ currentRouteSchema: resolvedRouteSchema ?? {}
406
+ }) : extraOptions.schema ?? resolvedRouteSchema
407
+ };
408
+ };
409
+ const getResolvedSchemaConfig = (context) => {
410
+ const { baseExtraOptions, extraOptions } = context;
411
+ return isFunction(extraOptions.schemaConfig) ? extraOptions.schemaConfig({ baseSchemaConfig: baseExtraOptions.schema?.config ?? {} }) : extraOptions.schemaConfig ?? baseExtraOptions.schema?.config;
412
+ };
413
+ const getCurrentRouteSchemaKeyAndMainInitURL = (context) => {
414
+ const { baseExtraOptions, extraOptions, initURL } = context;
415
+ const schemaConfig = getResolvedSchemaConfig({
416
+ baseExtraOptions,
417
+ extraOptions
418
+ });
419
+ let currentRouteSchemaKey = initURL;
420
+ let mainInitURL = initURL;
421
+ if (schemaConfig?.prefix && currentRouteSchemaKey.startsWith(schemaConfig.prefix)) {
422
+ currentRouteSchemaKey = currentRouteSchemaKey.replace(schemaConfig.prefix, "");
423
+ mainInitURL = mainInitURL.replace(schemaConfig.prefix, schemaConfig.baseURL ?? "");
424
+ }
425
+ if (schemaConfig?.baseURL && currentRouteSchemaKey.startsWith(schemaConfig.baseURL)) currentRouteSchemaKey = currentRouteSchemaKey.replace(schemaConfig.baseURL, "");
426
+ return {
427
+ currentRouteSchemaKey,
428
+ mainInitURL
429
+ };
430
+ };
431
+
432
+ //#endregion
433
+ //#region src/url.ts
434
+ const slash = "/";
435
+ const colon = ":";
436
+ const openBrace = "{";
437
+ const closeBrace = "}";
438
+ const mergeUrlWithParams = (url, params) => {
439
+ if (!params) return url;
440
+ let newUrl = url;
441
+ if (isArray(params)) {
442
+ const matchedParamsArray = newUrl.split(slash).filter((part) => part.startsWith(colon) || part.startsWith(openBrace) && part.endsWith(closeBrace));
443
+ for (const [paramIndex, matchedParam] of matchedParamsArray.entries()) {
444
+ const stringParamValue = String(params[paramIndex]);
445
+ newUrl = newUrl.replace(matchedParam, stringParamValue);
446
+ }
447
+ return newUrl;
448
+ }
449
+ for (const [paramKey, paramValue] of Object.entries(params)) {
450
+ const colonPattern = `${colon}${paramKey}`;
451
+ const bracePattern = `${openBrace}${paramKey}${closeBrace}`;
452
+ const stringValue = String(paramValue);
453
+ newUrl = newUrl.replace(colonPattern, stringValue);
454
+ newUrl = newUrl.replace(bracePattern, stringValue);
455
+ }
456
+ return newUrl;
457
+ };
458
+ const questionMark = "?";
459
+ const ampersand = "&";
460
+ const mergeUrlWithQuery = (url, query) => {
461
+ if (!query) return url;
462
+ const queryString = toQueryString(query);
463
+ if (queryString?.length === 0) return url;
464
+ if (url.endsWith(questionMark)) return `${url}${queryString}`;
465
+ if (url.includes(questionMark)) return `${url}${ampersand}${queryString}`;
466
+ return `${url}${questionMark}${queryString}`;
467
+ };
468
+ /**
469
+ * @description Extracts the HTTP method from method-prefixed route patterns.
470
+ *
471
+ * Analyzes URLs that start with method modifiers (e.g., "@get/", "@post/") and extracts
472
+ * the HTTP method for use in API requests. This enables method specification directly
473
+ * in route definitions.
474
+ *
475
+ * @param initURL - The URL string to analyze for method modifiers
476
+ * @returns The extracted HTTP method (lowercase) if found, otherwise undefined
477
+ *
478
+ * @example
479
+ * ```typescript
480
+ * // Method extraction from prefixed routes
481
+ * extractMethodFromURL("@get/users"); // Returns: "get"
482
+ * extractMethodFromURL("@post/users"); // Returns: "post"
483
+ * extractMethodFromURL("@put/users/:id"); // Returns: "put"
484
+ * extractMethodFromURL("@delete/users/:id"); // Returns: "delete"
485
+ * extractMethodFromURL("@patch/users/:id"); // Returns: "patch"
486
+ *
487
+ * // No method modifier
488
+ * extractMethodFromURL("/users"); // Returns: undefined
489
+ * extractMethodFromURL("users"); // Returns: undefined
490
+ *
491
+ * // Invalid or unsupported methods
492
+ * extractMethodFromURL("@invalid/users"); // Returns: undefined
493
+ * extractMethodFromURL("@/users"); // Returns: undefined
494
+ *
495
+ * // Edge cases
496
+ * extractMethodFromURL(undefined); // Returns: undefined
497
+ * extractMethodFromURL(""); // Returns: undefined
498
+ * ```
499
+ */
500
+ const extractMethodFromURL = (initURL) => {
501
+ if (!initURL?.startsWith("@")) return;
502
+ const method = initURL.split("@")[1]?.split("/")[0];
503
+ if (!method || !routeKeyMethods.includes(method)) return;
504
+ return method;
505
+ };
506
+ const normalizeURL = (initURL) => {
507
+ const methodFromURL = extractMethodFromURL(initURL);
508
+ if (!methodFromURL) return initURL;
509
+ return initURL.replace(`@${methodFromURL}/`, "/");
510
+ };
511
+ const getFullAndNormalizedURL = (options) => {
512
+ const { baseURL, initURL, params, query } = options;
513
+ const normalizedInitURL = normalizeURL(initURL);
514
+ const urlWithMergedQueryAndParams = mergeUrlWithQuery(mergeUrlWithParams(normalizedInitURL, params), query);
515
+ return {
516
+ fullURL: !urlWithMergedQueryAndParams.startsWith("http") && baseURL ? `${baseURL}${urlWithMergedQueryAndParams}` : urlWithMergedQueryAndParams,
517
+ normalizedInitURL
518
+ };
519
+ };
520
+
521
+ //#endregion
522
+ //#region src/utils/polyfills/combinedSignal.ts
523
+ const createCombinedSignalPolyfill = (signals) => {
524
+ const controller = new AbortController();
525
+ const handleAbort = (actualSignal) => {
526
+ if (controller.signal.aborted) return;
527
+ controller.abort(actualSignal.reason);
528
+ };
529
+ for (const actualSignal of signals) {
530
+ if (actualSignal.aborted) {
531
+ handleAbort(actualSignal);
532
+ break;
533
+ }
534
+ actualSignal.addEventListener("abort", () => handleAbort(actualSignal), { signal: controller.signal });
535
+ }
536
+ return controller.signal;
537
+ };
538
+
539
+ //#endregion
540
+ //#region src/utils/polyfills/timeoutSignal.ts
541
+ const createTimeoutSignalPolyfill = (milliseconds) => {
542
+ const controller = new AbortController();
543
+ const reason = new DOMException("Request timed out", "TimeoutError");
544
+ const timeout = setTimeout(() => controller.abort(reason), milliseconds);
545
+ controller.signal.addEventListener("abort", () => clearTimeout(timeout));
546
+ return controller.signal;
547
+ };
548
+
549
+ //#endregion
550
+ //#region src/utils/common.ts
551
+ const omitKeys = (initialObject, keysToOmit) => {
552
+ const updatedObject = {};
553
+ const keysToOmitSet = new Set(keysToOmit);
554
+ for (const [key, value] of Object.entries(initialObject)) if (!keysToOmitSet.has(key)) updatedObject[key] = value;
555
+ return updatedObject;
556
+ };
557
+ const pickKeys = (initialObject, keysToPick) => {
558
+ const updatedObject = {};
559
+ const keysToPickSet = new Set(keysToPick);
560
+ for (const [key, value] of Object.entries(initialObject)) if (keysToPickSet.has(key)) updatedObject[key] = value;
561
+ return updatedObject;
562
+ };
563
+ const splitBaseConfig = (baseConfig) => [pickKeys(baseConfig, fetchSpecificKeys), omitKeys(baseConfig, fetchSpecificKeys)];
564
+ const splitConfig = (config) => [pickKeys(config, fetchSpecificKeys), omitKeys(config, fetchSpecificKeys)];
565
+ const objectifyHeaders = (headers) => {
566
+ if (!headers || isPlainObject(headers)) return headers;
567
+ return Object.fromEntries(headers);
568
+ };
569
+ const getHeaders = async (options) => {
570
+ const { auth, body, headers } = options;
571
+ if (!(Boolean(headers) || Boolean(body) || Boolean(auth))) return;
572
+ const headersObject = {
573
+ ...await getAuthHeader(auth),
574
+ ...objectifyHeaders(headers)
575
+ };
576
+ if (isQueryString(body)) {
577
+ headersObject["Content-Type"] = "application/x-www-form-urlencoded";
578
+ return headersObject;
579
+ }
580
+ if (isSerializable(body) || isValidJsonString(body)) {
581
+ headersObject["Content-Type"] = "application/json";
582
+ headersObject.Accept = "application/json";
583
+ }
584
+ return headersObject;
585
+ };
586
+ const getMethod = (ctx) => {
587
+ const { initURL, method } = ctx;
588
+ return method?.toUpperCase() ?? extractMethodFromURL(initURL)?.toUpperCase() ?? requestOptionDefaults.method;
589
+ };
590
+ const getBody = (options) => {
591
+ const { body, bodySerializer } = options;
592
+ if (isSerializable(body)) return (bodySerializer ?? extraOptionDefaults.bodySerializer)(body);
593
+ return body;
594
+ };
595
+ const getInitFetchImpl = (customFetchImpl) => {
596
+ if (customFetchImpl) return customFetchImpl;
597
+ if (typeof globalThis !== "undefined" && isFunction(globalThis.fetch)) return globalThis.fetch;
598
+ throw new Error("No fetch implementation found");
599
+ };
600
+ const getFetchImpl = (context) => {
601
+ const { customFetchImpl, fetchMiddleware, requestContext } = context;
602
+ const initFetchImpl = getInitFetchImpl(customFetchImpl);
603
+ return fetchMiddleware ? fetchMiddleware({
604
+ ...requestContext,
605
+ fetchImpl: initFetchImpl
606
+ }) : initFetchImpl;
607
+ };
608
+ const PromiseWithResolvers = () => {
609
+ let reject;
610
+ let resolve;
611
+ return {
612
+ promise: new Promise((res, rej) => {
613
+ resolve = res;
614
+ reject = rej;
615
+ }),
616
+ reject,
617
+ resolve
618
+ };
619
+ };
620
+ const waitFor = (delay) => {
621
+ if (delay === 0) return;
622
+ const { promise, resolve } = PromiseWithResolvers();
623
+ setTimeout(resolve, delay);
624
+ return promise;
625
+ };
626
+ const createCombinedSignal = (...signals) => {
627
+ const cleanedSignals = signals.filter((signal) => signal != null);
628
+ if (!("any" in AbortSignal)) return createCombinedSignalPolyfill(cleanedSignals);
629
+ return AbortSignal.any(cleanedSignals);
630
+ };
631
+ const createTimeoutSignal = (milliseconds) => {
632
+ if (milliseconds == null) return null;
633
+ if (!("timeout" in AbortSignal)) return createTimeoutSignalPolyfill(milliseconds);
634
+ return AbortSignal.timeout(milliseconds);
635
+ };
636
+ const deterministicHashFn = (value) => {
637
+ return JSON.stringify(value, (_, val) => {
638
+ if (!isPlainObject(val)) return val;
639
+ const sortedKeys = Object.keys(val).toSorted();
640
+ const result = {};
641
+ for (const key of sortedKeys) result[key] = val[key];
642
+ return result;
643
+ });
644
+ };
645
+ const toArray = (value) => isArray(value) ? value : [value];
646
+
647
+ //#endregion
648
+ export { isReadableStream as A, HTTPError as C, isFunction as D, isBoolean as E, extraOptionDefaults as M, isObject as O, isValidationErrorInstance as S, isArray as T, toQueryString as _, getFetchImpl as a, isJavascriptError as b, splitBaseConfig as c, getFullAndNormalizedURL as d, fallBackRouteSchemaKey as f, toFormData as g, handleSchemaValidation as h, getBody as i, isString as j, isPlainObject as k, splitConfig as l, handleConfigValidation as m, createTimeoutSignal as n, getHeaders as o, getCurrentRouteSchemaKeyAndMainInitURL as p, deterministicHashFn as r, getMethod as s, createCombinedSignal as t, waitFor as u, isHTTPError as v, ValidationError as w, isValidationError as x, isHTTPErrorInstance as y };
649
+ //# sourceMappingURL=common-CXyKVpND.js.map