@zayne-labs/callapi 1.14.1 → 1.15.0

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.
@@ -125,7 +125,8 @@ type AllowedQueryParamValues = UnmaskType<boolean | number | string>;
125
125
  type RecordStyleParams = UnmaskType<Record<string, AllowedQueryParamValues>>;
126
126
  type TupleStyleParams = UnmaskType<AllowedQueryParamValues[]>;
127
127
  type Params = UnmaskType<RecordStyleParams | TupleStyleParams>;
128
- type Query = UnmaskType<Record<string, AllowedQueryParamValues> | URLSearchParams>;
128
+ type StructuredQueryValues = Record<string, unknown> | unknown[] | null | undefined;
129
+ type Query = UnmaskType<Record<string, AllowedQueryParamValues | StructuredQueryValues> | URLSearchParams>;
129
130
  type InitURLOrURLObject = AnyString | RouteKeyMethodsURLUnion | URL;
130
131
  interface URLOptions {
131
132
  /**
@@ -617,8 +618,8 @@ declare const toFormData: <TSchema extends CallApiSchemaType<BodyType>>(data: In
617
618
  //#endregion
618
619
  //#region src/utils/external/define.d.ts
619
620
  declare const defineSchema: <const TBaseSchemaRoutes extends BaseCallApiSchemaRoutes, const TSchemaConfig extends CallApiSchemaConfig>(routes: TBaseSchemaRoutes, config?: Satisfies<TSchemaConfig, CallApiSchemaConfig>) => {
620
- config: Writeable<Satisfies<TSchemaConfig, CallApiSchemaConfig>, "deep">;
621
621
  routes: Writeable<TBaseSchemaRoutes, "deep">;
622
+ config: Writeable<Satisfies<TSchemaConfig, CallApiSchemaConfig>, "deep">;
622
623
  };
623
624
  declare const defineSchemaRoutes: <const TSchemaRoutes extends BaseCallApiSchemaRoutes>(routes: TSchemaRoutes) => Writeable<typeof routes, "deep">;
624
625
  declare const defineMainSchema: <const TSchema extends CallApiSchema>(mainSchema: Satisfies<TSchema, CallApiSchema>) => Writeable<typeof mainSchema, "deep">;
@@ -632,6 +633,9 @@ type DefineBaseConfig = {
632
633
  };
633
634
  declare const defineBaseConfig: DefineBaseConfig;
634
635
  declare const defineInstanceConfig: <const TInstanceConfig extends CallApiConfig>(config: TInstanceConfig) => Writeable<typeof config, "deep">;
636
+ declare const defineFallbackRouteSchema: <const TSchema extends CallApiSchema>(schema: TSchema) => {
637
+ "@default": NonNullable<TSchema> extends Record<string | number | symbol, unknown> | unknown[] | readonly unknown[] ? Writeable<TSchema, "deep"> : TSchema;
638
+ };
635
639
  //#endregion
636
640
  //#region src/utils/external/guards.d.ts
637
641
  declare const isHTTPError: <TErrorData>(error: CallApiResultErrorVariant<TErrorData>["error"] | null) => error is PossibleHTTPError<TErrorData>;
@@ -666,6 +670,11 @@ interface RetryOptions<TErrorData> {
666
670
  * @deprecated **WARNING**: This property is used internally to track retries. Please abstain from reading or modifying it.
667
671
  */
668
672
  readonly ["~retryAttemptCount"]?: number;
673
+ /**
674
+ * Use a valid `Retry-After` response header instead of the configured retry delay
675
+ * @default false
676
+ */
677
+ respectRetryAfter?: boolean;
669
678
  /**
670
679
  * Number of allowed retry attempts on HTTP errors
671
680
  * @default 0
@@ -1911,5 +1920,5 @@ type ThrowOnErrorOption<TErrorData, TThrowOnError extends ThrowOnErrorBoolean> =
1911
1920
  throwOnError?: ThrowOnErrorType<TErrorData, TThrowOnError>;
1912
1921
  };
1913
1922
  //#endregion
1914
- export { defineMainSchema as $, Register as A, BaseCallApiSchemaAndConfig as At, ResponseErrorContext as B, fallBackRouteSchemaKey as Bt, CallApiResultLoose as C, PossibleJavaScriptError as Ct, GetCallApiContextRequired as D, ResultModeType as Dt, GetCallApiContext as E, ResponseTypeType as Et, Hooks as F, InferSchemaInput as Ft, objectifyHeaders as G, NoInferUnMasked as Gt, SuccessContext as H, CommonContentTypes as Ht, HooksOrHooksArray as I, InferSchemaOutput as It, isJavascriptError as J, isHTTPError as K, Writeable as Kt, RequestContext as L, InferSchemaResult as Lt, CallApiExtraOptionsForHooks as M, BaseSchemaRouteKeyPrefixes as Mt, CallApiRequestOptionsForHooks as N, CallApiSchema as Nt, GlobalMeta as O, HTTPError as Ot, ErrorContext as P, CallApiSchemaConfig as Pt, defineInstanceConfig as Q, RequestStreamContext as R, URLOptions as Rt, CallApiResult as S, PossibleHTTPError as St, GetBaseSchemaRoutes as T, ResponseTypeMap as Tt, RefetchOptions as U, CommonRequestHeaders as Ut, ResponseStreamContext as V, AnyString as Vt, RetryOptions as W, DistributiveOmit as Wt, isValidationErrorInstance as X, isValidationError as Y, defineBaseConfig as Z, CallApiConfig as _, CallApiResultErrorVariant as _t, GetCurrentRouteSchemaKey as a, toQueryString as at, CallApiParameters as b, GetResponseType as bt, InferAllMainRoutes as c, DefaultDataType as ct, SerializableArray as d, PluginHooks as dt, definePlugin as et, SerializableObject as f, PluginMiddlewares as ft, BaseCallApiExtraOptions as g, Middlewares as gt, BaseCallApiConfig as h, FetchMiddlewareContext as ht, GetCurrentRouteSchema as i, toFormData as it, DedupeOptions as j, BaseCallApiSchemaRoutes as jt, InstanceContext as k, ValidationError as kt, InferInitURL as l, DefaultPluginArray as lt, AuthOption as m, FetchImpl as mt, ApplyURLBasedConfig as n, defineSchemaConfig as nt, HeadersOption as o, toSearchParams as ot, ThrowOnErrorBoolean as p, PluginSetupContext as pt, isHTTPErrorInstance as q, fetchSpecificKeys as qt, Body as r, defineSchemaRoutes as rt, InferAllMainRouteKeys as s, DefaultCallApiContext as st, ApplyStrictConfig as t, defineSchema as tt, InferParamsFromRoute as u, CallApiPlugin as ut, CallApiContext as v, CallApiResultSuccessOrErrorVariant as vt, GetBaseSchemaConfig as w, PossibleValidationError as wt, CallApiRequestOptions as x, InferCallApiResult as xt, CallApiExtraOptions as y, CallApiResultSuccessVariant as yt, ResponseContext as z, FallBackRouteSchemaKey as zt };
1915
- //# sourceMappingURL=conditional-types-BFeM4YSg.d.ts.map
1923
+ export { defineInstanceConfig as $, Register as A, ValidationError as At, ResponseErrorContext as B, FallBackRouteSchemaKey as Bt, CallApiResultLoose as C, PossibleHTTPError as Ct, GetCallApiContextRequired as D, ResponseTypeType as Dt, GetCallApiContext as E, ResponseTypeMap as Et, Hooks as F, CallApiSchemaConfig as Ft, objectifyHeaders as G, DistributiveOmit as Gt, SuccessContext as H, AnyString as Ht, HooksOrHooksArray as I, InferSchemaInput as It, isJavascriptError as J, fetchSpecificKeys as Jt, isHTTPError as K, NoInferUnMasked as Kt, RequestContext as L, InferSchemaOutput as Lt, CallApiExtraOptionsForHooks as M, BaseCallApiSchemaRoutes as Mt, CallApiRequestOptionsForHooks as N, BaseSchemaRouteKeyPrefixes as Nt, GlobalMeta as O, ResultModeType as Ot, ErrorContext as P, CallApiSchema as Pt, defineFallbackRouteSchema as Q, RequestStreamContext as R, InferSchemaResult as Rt, CallApiResult as S, InferCallApiResult as St, GetBaseSchemaRoutes as T, PossibleValidationError as Tt, RefetchOptions as U, CommonContentTypes as Ut, ResponseStreamContext as V, fallBackRouteSchemaKey as Vt, RetryOptions as W, CommonRequestHeaders as Wt, isValidationErrorInstance as X, isValidationError as Y, defineBaseConfig as Z, CallApiConfig as _, Middlewares as _t, GetCurrentRouteSchemaKey as a, toFormData as at, CallApiParameters as b, CallApiResultSuccessVariant as bt, InferAllMainRoutes as c, DefaultCallApiContext as ct, SerializableArray as d, CallApiPlugin as dt, defineMainSchema as et, SerializableObject as f, PluginHooks as ft, BaseCallApiExtraOptions as g, FetchMiddlewareContext as gt, BaseCallApiConfig as h, FetchImpl as ht, GetCurrentRouteSchema as i, defineSchemaRoutes as it, DedupeOptions as j, BaseCallApiSchemaAndConfig as jt, InstanceContext as k, HTTPError as kt, InferInitURL as l, DefaultDataType as lt, AuthOption as m, PluginSetupContext as mt, ApplyURLBasedConfig as n, defineSchema as nt, HeadersOption as o, toQueryString as ot, ThrowOnErrorBoolean as p, PluginMiddlewares as pt, isHTTPErrorInstance as q, Writeable as qt, Body as r, defineSchemaConfig as rt, InferAllMainRouteKeys as s, toSearchParams as st, ApplyStrictConfig as t, definePlugin as tt, InferParamsFromRoute as u, DefaultPluginArray as ut, CallApiContext as v, CallApiResultErrorVariant as vt, GetBaseSchemaConfig as w, PossibleJavaScriptError as wt, CallApiRequestOptions as x, GetResponseType as xt, CallApiExtraOptions as y, CallApiResultSuccessOrErrorVariant as yt, ResponseContext as z, URLOptions as zt };
1924
+ //# sourceMappingURL=conditional-types-DaKFU9_F.d.ts.map
@@ -1,17 +1,18 @@
1
- import { Bt as fallBackRouteSchemaKey, L as RequestContext, qt as fetchSpecificKeys, zt as FallBackRouteSchemaKey } from "../conditional-types-BFeM4YSg.js";
1
+ import { Bt as FallBackRouteSchemaKey, Jt as fetchSpecificKeys, L as RequestContext, Vt as fallBackRouteSchemaKey } from "../conditional-types-DaKFU9_F.js";
2
2
  //#region src/constants/defaults.d.ts
3
- declare const extraOptionDefaults: Readonly<Readonly<{
3
+ export declare const extraOptionDefaults: Readonly<Readonly<{
4
4
  bodySerializer: {
5
5
  (value: any, replacer?: (this: any, key: string, value: any) => any, space?: string | number): string;
6
6
  (value: any, replacer?: (number | string)[] | null, space?: string | number): string;
7
7
  };
8
8
  debugMode: true;
9
- defaultHTTPErrorMessage: "Request failed unexpectedly";
10
9
  dedupeCacheScope: "local";
11
- dedupeKey: (ctx: RequestContext) => string;
12
10
  dedupeCacheScopeKey: "default";
11
+ dedupeKey: (ctx: RequestContext) => string;
13
12
  dedupeStrategy: "cancel";
13
+ defaultHTTPErrorMessage: "Request failed unexpectedly";
14
14
  hooksExecutionMode: "parallel";
15
+ respectRetryAfter: false;
15
16
  responseParser: (text: string, reviver?: (this: any, key: string, value: any) => any) => any;
16
17
  responseType: "json";
17
18
  resultMode: "all";
@@ -23,9 +24,9 @@ declare const extraOptionDefaults: Readonly<Readonly<{
23
24
  retryStatusCodes: [];
24
25
  retryStrategy: "linear";
25
26
  }>>;
26
- declare const requestOptionDefaults: Readonly<Readonly<{
27
+ export declare const requestOptionDefaults: Readonly<Readonly<{
27
28
  method: "GET";
28
29
  }>>;
29
30
  //#endregion
30
- export { FallBackRouteSchemaKey, extraOptionDefaults, fallBackRouteSchemaKey, fetchSpecificKeys, requestOptionDefaults };
31
+ export { FallBackRouteSchemaKey, fallBackRouteSchemaKey, fetchSpecificKeys };
31
32
  //# sourceMappingURL=index.d.ts.map
@@ -1,2 +1,2 @@
1
- import { F as fallBackRouteSchemaKey, n as requestOptionDefaults, t as extraOptionDefaults, z as fetchSpecificKeys } from "../constants-DB6Z7gFB.js";
1
+ import { B as fetchSpecificKeys, I as fallBackRouteSchemaKey, n as requestOptionDefaults, t as extraOptionDefaults } from "../constants-Cm0RTgJ0.js";
2
2
  export { extraOptionDefaults, fallBackRouteSchemaKey, fetchSpecificKeys, requestOptionDefaults };
@@ -65,32 +65,33 @@ const isPromise = (value) => value instanceof Promise;
65
65
  //#endregion
66
66
  //#region src/auth.ts
67
67
  const resolveAuthValue = (value) => isFunction(value) ? value() : value;
68
+ const isMissingAuthValue = (value) => value == null;
68
69
  const getAuthHeader = async (auth) => {
69
70
  if (auth === void 0) return;
70
71
  if (isPromise(auth) || isFunction(auth) || !isObject(auth)) {
71
72
  const authValue = await resolveAuthValue(auth);
72
- if (authValue === void 0) return;
73
+ if (isMissingAuthValue(authValue)) return;
73
74
  return { Authorization: `Bearer ${authValue}` };
74
75
  }
75
76
  switch (auth.type) {
76
77
  case "Basic": {
77
78
  const [username, password] = await Promise.all([resolveAuthValue(auth.username), resolveAuthValue(auth.password)]);
78
- if (username === void 0 || password === void 0) return;
79
+ if (isMissingAuthValue(username) || isMissingAuthValue(password)) return;
79
80
  return { Authorization: `Basic ${globalThis.btoa(`${username}:${password}`)}` };
80
81
  }
81
82
  case "Bearer": {
82
83
  const value = await resolveAuthValue(auth.value);
83
- if (value === void 0) return;
84
+ if (isMissingAuthValue(value)) return;
84
85
  return { Authorization: `Bearer ${value}` };
85
86
  }
86
87
  case "Custom": {
87
88
  const [prefix, value] = await Promise.all([resolveAuthValue(auth.prefix), resolveAuthValue(auth.value)]);
88
- if (value === void 0) return;
89
+ if (isMissingAuthValue(prefix) || isMissingAuthValue(value)) return;
89
90
  return { Authorization: `${prefix} ${value}` };
90
91
  }
91
92
  case "Token": {
92
93
  const value = await resolveAuthValue(auth.value);
93
- if (value === void 0) return;
94
+ if (isMissingAuthValue(value)) return;
94
95
  return { Authorization: `Token ${value}` };
95
96
  }
96
97
  default: return;
@@ -348,90 +349,6 @@ const getCurrentRouteSchemaKeyAndMainInitURL = (context) => {
348
349
  };
349
350
  };
350
351
  //#endregion
351
- //#region src/url.ts
352
- const handleArrayParams = (url, params) => {
353
- let newUrl = url;
354
- const urlParts = newUrl.split("/");
355
- const matchedParamsArray = [];
356
- for (const part of urlParts) {
357
- if (!(part.startsWith(":") || part.startsWith("{") && part.endsWith("}"))) continue;
358
- matchedParamsArray.push(part);
359
- }
360
- for (const [paramIndex, matchedParam] of matchedParamsArray.entries()) {
361
- const stringParamValue = String(params[paramIndex]);
362
- newUrl = newUrl.replace(matchedParam, stringParamValue);
363
- }
364
- return newUrl;
365
- };
366
- const handleObjectParams = (url, params) => {
367
- let newUrl = url;
368
- for (const [paramKey, paramValue] of Object.entries(params)) {
369
- const colonPattern = `:${paramKey}`;
370
- const bracePattern = `{${paramKey}}`;
371
- const stringValue = String(paramValue);
372
- newUrl = newUrl.replace(colonPattern, stringValue);
373
- newUrl = newUrl.replace(bracePattern, stringValue);
374
- }
375
- return newUrl;
376
- };
377
- const mergeUrlWithParams = (url, params) => {
378
- if (!params) return url;
379
- return isArray(params) ? handleArrayParams(url, params) : handleObjectParams(url, params);
380
- };
381
- const mergeUrlWithQuery = (url, query) => {
382
- if (!query) return url;
383
- const queryString = new URLSearchParams(query).toString();
384
- if (queryString.length === 0) return url;
385
- if (url.endsWith("?")) return `${url}${queryString}`;
386
- if (url.includes("?")) return `${url}&${queryString}`;
387
- return `${url}?${queryString}`;
388
- };
389
- /**
390
- * @description Extracts the HTTP method from method-prefixed route patterns.
391
- *
392
- * Analyzes URLs that start with method modifiers (e.g., "@get/", "@post/") and extracts
393
- * the HTTP method for use in API requests. This enables method specification directly
394
- * in route definitions.
395
- *
396
- * @param initURL - The URL string to analyze for method modifiers
397
- * @returns The extracted HTTP method (lowercase) if found, otherwise undefined
398
- *
399
- * @example
400
- * ```typescript
401
- * extractMethodFromURL("@get/users"); // Returns: "get"
402
- * extractMethodFromURL("@post/users"); // Returns: "post"
403
- * ```
404
- */
405
- const extractMethodFromURL = (initURL) => {
406
- if (!initURL?.startsWith("@")) return;
407
- const methodFromURL = routeKeyMethods.find((method) => initURL.startsWith(`@${method}/`));
408
- if (!methodFromURL) return;
409
- return methodFromURL;
410
- };
411
- const normalizeURL = (initURL, options = {}) => {
412
- const { retainLeadingSlashForRelativeURLs = true } = options;
413
- const methodFromURL = extractMethodFromURL(initURL);
414
- if (!methodFromURL) return initURL;
415
- return retainLeadingSlashForRelativeURLs && !initURL.includes("http") ? initURL.replace(`@${methodFromURL}`, "") : initURL.replace(`@${methodFromURL}/`, "");
416
- };
417
- const getFullURL = (initURL, baseURL) => {
418
- if (!baseURL || initURL.startsWith("http")) return initURL;
419
- return initURL.length > 0 && !initURL.startsWith("/") && !baseURL.endsWith("/") ? `${baseURL}/${initURL}` : `${baseURL}${initURL}`;
420
- };
421
- const getFullAndNormalizedURL = (options) => {
422
- const { baseURL, debugMode, initURL, params, query } = options;
423
- const normalizedInitURL = normalizeURL(initURL);
424
- const fullURL = getFullURL(mergeUrlWithQuery(mergeUrlWithParams(normalizedInitURL, params), query), baseURL);
425
- if ((debugMode ?? extraOptionDefaults.debugMode) && !URL.canParse(fullURL)) {
426
- const errorMessage = !baseURL ? `Invalid URL '${initURL}'. Are you passing a relative url to CallApi without setting the 'baseURL' option?` : `Invalid URL '${fullURL}'. Please validate that you are passing the correct url.`;
427
- console.error(errorMessage);
428
- }
429
- return {
430
- fullURL,
431
- normalizedInitURL
432
- };
433
- };
434
- //#endregion
435
352
  //#region src/utils/external/body.ts
436
353
  const toStringOrStringify = (value) => {
437
354
  return isString(value) ? value : JSON.stringify(value);
@@ -443,6 +360,7 @@ const toSearchParams = (data, schema) => {
443
360
  issues: result.issues,
444
361
  response: null
445
362
  });
363
+ if (result.value instanceof URLSearchParams) return new URLSearchParams(result.value);
446
364
  const searchParams = new URLSearchParams();
447
365
  for (const [key, value] of Object.entries(result.value)) {
448
366
  if (value == null) continue;
@@ -521,8 +439,8 @@ const toFormData = (data, schema) => {
521
439
  //#region src/utils/external/define.ts
522
440
  const defineSchema = (routes, config) => {
523
441
  return {
524
- config: defineSchemaConfig(config),
525
- routes: defineSchemaRoutes(routes)
442
+ routes: defineSchemaRoutes(routes),
443
+ config: defineSchemaConfig(config)
526
444
  };
527
445
  };
528
446
  const defineSchemaRoutes = (routes) => {
@@ -543,6 +461,9 @@ const defineBaseConfig = (baseConfig) => {
543
461
  const defineInstanceConfig = (config) => {
544
462
  return config;
545
463
  };
464
+ const defineFallbackRouteSchema = (schema) => {
465
+ return defineSchemaRoutes({ [fallBackRouteSchemaKey]: schema });
466
+ };
546
467
  //#endregion
547
468
  //#region src/utils/external/guards.ts
548
469
  const isHTTPError = (error) => {
@@ -568,6 +489,121 @@ const objectifyHeaders = (headers) => {
568
489
  return Object.fromEntries(headers);
569
490
  };
570
491
  //#endregion
492
+ //#region src/url.ts
493
+ const isReservedPathSegment = (value) => value === "." || value === "..";
494
+ const encodeParamValue = (value) => {
495
+ const stringValue = String(value);
496
+ if (isReservedPathSegment(stringValue)) throw new TypeError("Path parameters cannot be reserved path segments");
497
+ return encodeURIComponent(stringValue);
498
+ };
499
+ const isColonPathParam = (segment) => Boolean(segment?.startsWith(":"));
500
+ const isBracePathParam = (segment) => {
501
+ return Boolean(segment?.startsWith("{") && segment.endsWith("}"));
502
+ };
503
+ const handleArrayParams = (url, params) => {
504
+ const placeholders = [];
505
+ const urlSegments = url.split("/");
506
+ for (const segment of urlSegments) {
507
+ if (!isColonPathParam(segment) && !isBracePathParam(segment)) continue;
508
+ placeholders.push(segment);
509
+ }
510
+ let resolvedURL = url;
511
+ for (const index of placeholders.keys()) {
512
+ const placeholder = placeholders[index];
513
+ if (placeholder === void 0) continue;
514
+ const paramValue = params[index];
515
+ resolvedURL = resolvedURL.replace(placeholder, encodeParamValue(paramValue));
516
+ }
517
+ return resolvedURL;
518
+ };
519
+ const getPathParamKey = (segment) => {
520
+ if (isColonPathParam(segment)) return segment.slice(1);
521
+ if (isBracePathParam(segment)) return segment.slice(1, -1);
522
+ return null;
523
+ };
524
+ const handleObjectParams = (url, params) => {
525
+ const urlSegments = url.split("/");
526
+ for (const segmentIndex of urlSegments.keys()) {
527
+ const segment = urlSegments[segmentIndex];
528
+ if (segment === void 0) continue;
529
+ const paramKey = getPathParamKey(segment);
530
+ if (paramKey === null || !Object.hasOwn(params, paramKey)) continue;
531
+ const paramValue = params[paramKey];
532
+ urlSegments[segmentIndex] = encodeParamValue(paramValue);
533
+ }
534
+ return urlSegments.join("/");
535
+ };
536
+ const mergeUrlWithParams = (url, params) => {
537
+ if (!params) return url;
538
+ return isArray(params) ? handleArrayParams(url, params) : handleObjectParams(url, params);
539
+ };
540
+ const splitURLFragment = (url) => {
541
+ const fragmentIndex = url.indexOf("#");
542
+ if (fragmentIndex === -1) return [url, ""];
543
+ return [url.slice(0, fragmentIndex), url.slice(fragmentIndex)];
544
+ };
545
+ const mergeUrlWithQuery = (url, query) => {
546
+ if (!query) return url;
547
+ const incomingSearchParams = toSearchParams(query);
548
+ if (incomingSearchParams.size === 0) return url;
549
+ const [urlWithoutFragment, fragment] = splitURLFragment(url);
550
+ if (!urlWithoutFragment.includes("?")) return `${urlWithoutFragment}?${incomingSearchParams}${fragment}`;
551
+ if (urlWithoutFragment.endsWith("?")) return `${urlWithoutFragment}${incomingSearchParams}${fragment}`;
552
+ const [mainUrl, existingQueryString] = urlWithoutFragment.split("?");
553
+ const searchParams = new URLSearchParams(existingQueryString);
554
+ for (const key of incomingSearchParams.keys()) searchParams.delete(key);
555
+ for (const entry of incomingSearchParams) searchParams.append(...entry);
556
+ return `${mainUrl}?${searchParams}${fragment}`;
557
+ };
558
+ /**
559
+ * @description Extracts the HTTP method from method-prefixed route patterns.
560
+ *
561
+ * Analyzes URLs that start with method modifiers (e.g., "@get/", "@post/") and extracts
562
+ * the HTTP method for use in API requests. This enables method specification directly
563
+ * in route definitions.
564
+ *
565
+ * @param initURL - The URL string to analyze for method modifiers
566
+ * @returns The extracted HTTP method (lowercase) if found, otherwise undefined
567
+ *
568
+ * @example
569
+ * ```typescript
570
+ * extractMethodFromURL("@get/users"); // Returns: "get"
571
+ * extractMethodFromURL("@post/users"); // Returns: "post"
572
+ * ```
573
+ */
574
+ const extractMethodFromURL = (initURL) => {
575
+ if (!initURL?.startsWith("@")) return;
576
+ const methodFromURL = routeKeyMethods.find((method) => initURL.startsWith(`@${method}/`));
577
+ if (!methodFromURL) return;
578
+ return methodFromURL;
579
+ };
580
+ const isAbsoluteHTTPURL = (value) => {
581
+ return value.startsWith("http://") || value.startsWith("https://");
582
+ };
583
+ const normalizeURL = (initURL, options = {}) => {
584
+ const { retainLeadingSlashForRelativeURLs = true } = options;
585
+ const methodFromURL = extractMethodFromURL(initURL);
586
+ if (!methodFromURL) return initURL;
587
+ const initURLWithoutMethod = initURL.replace(`@${methodFromURL}/`, "");
588
+ return retainLeadingSlashForRelativeURLs && !isAbsoluteHTTPURL(initURLWithoutMethod) ? `/${initURLWithoutMethod}` : initURLWithoutMethod;
589
+ };
590
+ const getFullURL = (initURL, baseURL) => {
591
+ if (!baseURL || isAbsoluteHTTPURL(initURL)) return initURL;
592
+ const normalizedBaseURL = baseURL.replace(/\/+$/, "");
593
+ const normalizedInitURL = initURL.replace(/^\/+/, "");
594
+ return normalizedInitURL ? `${normalizedBaseURL}/${normalizedInitURL}` : normalizedBaseURL;
595
+ };
596
+ const getFullAndNormalizedURL = (options) => {
597
+ const { baseURL, debugMode, initURL, params, query } = options;
598
+ const normalizedInitURL = normalizeURL(initURL);
599
+ const fullURL = getFullURL(mergeUrlWithQuery(mergeUrlWithParams(normalizedInitURL, params), query), baseURL);
600
+ if ((debugMode ?? extraOptionDefaults.debugMode) && !isAbsoluteHTTPURL(fullURL) && !URL.canParse(fullURL)) console.error(`Relative URL '${fullURL}' may fail during SSR. Set an absolute 'baseURL' for server-side requests.`);
601
+ return {
602
+ fullURL,
603
+ normalizedInitURL
604
+ };
605
+ };
606
+ //#endregion
571
607
  //#region src/utils/common.ts
572
608
  const omitKeys = (initialObject, keysToOmit) => {
573
609
  const updatedObject = {};
@@ -582,7 +618,8 @@ const pickKeys = (initialObject, keysToPick) => {
582
618
  const splitConfig = (config) => [pickKeys(config, fetchSpecificKeys), omitKeys(config, fetchSpecificKeys)];
583
619
  const getResolvedHeaders = (options) => {
584
620
  const { baseHeaders, headers } = options;
585
- return objectifyHeaders(isFunction(headers) ? headers({ baseHeaders: objectifyHeaders(baseHeaders) }) : headers ?? baseHeaders);
621
+ const resolvedHeaders = isFunction(headers) ? headers({ baseHeaders: objectifyHeaders(baseHeaders) }) : headers ?? baseHeaders;
622
+ return objectifyHeaders(resolvedHeaders);
586
623
  };
587
624
  const detectContentTypeHeader = (body) => {
588
625
  if (isQueryString(body)) return { "Content-Type": "application/x-www-form-urlencoded" };
@@ -594,21 +631,24 @@ const detectContentTypeHeader = (body) => {
594
631
  };
595
632
  const getHeaders = async (options) => {
596
633
  const { auth, body, resolvedHeaders } = options;
597
- const authHeaderObject = await getAuthHeader(auth);
598
634
  const resolvedHeadersObject = objectifyHeaders(resolvedHeaders);
599
- if (!(Object.hasOwn(resolvedHeadersObject, "Content-Type") || Object.hasOwn(resolvedHeadersObject, "content-type"))) {
600
- const contentTypeHeader = detectContentTypeHeader(body);
601
- contentTypeHeader && Object.assign(resolvedHeadersObject, contentTypeHeader);
602
- }
603
- return {
604
- ...authHeaderObject,
635
+ const headersObject = {
636
+ ...await getAuthHeader(auth),
605
637
  ...resolvedHeadersObject
606
638
  };
639
+ if (!new Headers(headersObject).has("Content-Type")) {
640
+ const contentTypeHeader = detectContentTypeHeader(body);
641
+ contentTypeHeader && Object.assign(headersObject, contentTypeHeader);
642
+ }
643
+ return headersObject;
607
644
  };
608
645
  const getMethod = (ctx) => {
609
646
  const { initURL, method } = ctx;
610
647
  return method?.toUpperCase() ?? extractMethodFromURL(initURL)?.toUpperCase() ?? requestOptionDefaults.method;
611
648
  };
649
+ const getMediaType = (contentType) => {
650
+ return contentType.split(";", 1)[0]?.trim().toLowerCase();
651
+ };
612
652
  const getBody = (options) => {
613
653
  const { body, bodySerializer, bodyTransformer, resolvedHeaders } = options;
614
654
  const headers = new Headers(resolvedHeaders);
@@ -616,9 +656,10 @@ const getBody = (options) => {
616
656
  body,
617
657
  headers
618
658
  });
619
- const existingContentType = headers.get("content-type");
620
- if (!existingContentType && isSerializableObject(body)) return (bodySerializer ?? extraOptionDefaults.bodySerializer)(body);
621
- if (existingContentType === "application/x-www-form-urlencoded" && isSerializableObject(body)) return new URLSearchParams(body).toString();
659
+ const contentTypeHeader = headers.get("content-type");
660
+ const existingMediaType = contentTypeHeader ? getMediaType(contentTypeHeader) : null;
661
+ if ((!existingMediaType || existingMediaType === "application/json") && isSerializableObject(body)) return (bodySerializer ?? extraOptionDefaults.bodySerializer)(body);
662
+ if (existingMediaType === "application/x-www-form-urlencoded" && isSerializableObject(body)) return new URLSearchParams(body).toString();
622
663
  return body;
623
664
  };
624
665
  const getInitFetchImpl = (customFetchImpl) => {
@@ -662,15 +703,16 @@ const deterministicHashFn = (value) => {
662
703
  const extraOptionDefaults = Object.freeze(defineEnum({
663
704
  bodySerializer: JSON.stringify,
664
705
  debugMode: true,
665
- defaultHTTPErrorMessage: "Request failed unexpectedly",
666
706
  dedupeCacheScope: "local",
707
+ dedupeCacheScopeKey: "default",
667
708
  dedupeKey: (ctx) => `${ctx.options.fullURL}-${deterministicHashFn({
668
709
  options: ctx.options,
669
710
  request: ctx.request
670
711
  })}`,
671
- dedupeCacheScopeKey: "default",
672
712
  dedupeStrategy: "cancel",
713
+ defaultHTTPErrorMessage: "Request failed unexpectedly",
673
714
  hooksExecutionMode: "parallel",
715
+ respectRetryAfter: false,
674
716
  responseParser: JSON.parse,
675
717
  responseType: "json",
676
718
  resultMode: "all",
@@ -684,6 +726,6 @@ const extraOptionDefaults = Object.freeze(defineEnum({
684
726
  }));
685
727
  const requestOptionDefaults = Object.freeze(defineEnum({ method: "GET" }));
686
728
  //#endregion
687
- export { getCurrentRouteSchemaKeyAndMainInitURL as A, defineSchema as C, toQueryString as D, toFormData as E, fallBackRouteSchemaKey as F, isArray as I, isFunction as L, handleSchemaValidation as M, HTTPError as N, toSearchParams as O, ValidationError as P, isString as R, definePlugin as S, defineSchemaRoutes as T, isValidationError as _, getBody as a, defineInstanceConfig as b, getMethod as c, splitConfig as d, waitFor as f, isJavascriptError as g, isHTTPErrorInstance as h, createTimeoutSignal as i, handleConfigValidation as j, getFullAndNormalizedURL as k, getResolvedHeaders as l, isHTTPError as m, requestOptionDefaults as n, getFetchImpl as o, objectifyHeaders as p, createCombinedSignal as r, getHeaders as s, extraOptionDefaults as t, omitKeys as u, isValidationErrorInstance as v, defineSchemaConfig as w, defineMainSchema as x, defineBaseConfig as y, fetchSpecificKeys as z };
729
+ export { toSearchParams as A, fetchSpecificKeys as B, defineMainSchema as C, defineSchemaRoutes as D, defineSchemaConfig as E, ValidationError as F, fallBackRouteSchemaKey as I, isArray as L, handleConfigValidation as M, handleSchemaValidation as N, toFormData as O, HTTPError as P, isFunction as R, defineInstanceConfig as S, defineSchema as T, isJavascriptError as _, getBody as a, defineBaseConfig as b, getMethod as c, splitConfig as d, waitFor as f, isHTTPErrorInstance as g, isHTTPError as h, createTimeoutSignal as i, getCurrentRouteSchemaKeyAndMainInitURL as j, toQueryString as k, getResolvedHeaders as l, objectifyHeaders as m, requestOptionDefaults as n, getFetchImpl as o, getFullAndNormalizedURL as p, createCombinedSignal as r, getHeaders as s, extraOptionDefaults as t, omitKeys as u, isValidationError as v, definePlugin as w, defineFallbackRouteSchema as x, isValidationErrorInstance as y, isString as z };
688
730
 
689
- //# sourceMappingURL=constants-DB6Z7gFB.js.map
731
+ //# sourceMappingURL=constants-Cm0RTgJ0.js.map