@zayne-labs/callapi 1.6.16 → 1.6.18

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.
@@ -115,77 +115,25 @@ interface CallApiValidators<TData = unknown, TErrorData = unknown> {
115
115
  }
116
116
  type InferSchemaResult<TSchema, TData> = TSchema extends StandardSchemaV1 ? StandardSchemaV1.InferOutput<TSchema> : TData;
117
117
 
118
- /**
119
- * @description Makes a type required if TSchema type is undefined or if the output type of TSchema contains undefined, otherwise keeps it as is
120
- */
121
- type MakeSchemaOptionRequired<TSchema extends StandardSchemaV1 | undefined, TObject> = undefined extends TSchema ? TObject : undefined extends InferSchemaResult<TSchema, NonNullable<unknown>> ? TObject : Required<TObject>;
122
- type JsonPrimitive = boolean | number | string | null | undefined;
123
- type SerializableObject = Record<keyof object, unknown>;
124
- type SerializableArray = Array<JsonPrimitive | SerializableArray | SerializableObject> | ReadonlyArray<JsonPrimitive | SerializableArray | SerializableObject>;
125
- type Body = UnmaskType<RequestInit["body"] | SerializableArray | SerializableObject>;
126
- type BodyOption<TSchemas extends CallApiSchemas> = MakeSchemaOptionRequired<TSchemas["body"], {
118
+ type Params = UnmaskType<Record<string, boolean | number | string> | Array<boolean | number | string>>;
119
+ type Query = UnmaskType<Record<string, boolean | number | string>>;
120
+ type InitURL = UnmaskType<string | URL>;
121
+ interface UrlOptions<TSchemas extends CallApiSchemas> {
127
122
  /**
128
- * Body of the request, can be a object or any other supported body type.
123
+ * URL to be used in the request.
129
124
  */
130
- body?: InferSchemaResult<TSchemas["body"], Body>;
131
- }>;
132
- type Method = UnmaskType<"CONNECT" | "DELETE" | "GET" | "HEAD" | "OPTIONS" | "PATCH" | "POST" | "PUT" | "TRACE" | AnyString>;
133
- type MethodOption<TSchemas extends CallApiSchemas> = MakeSchemaOptionRequired<TSchemas["method"], {
125
+ readonly initURL?: string;
134
126
  /**
135
- * HTTP method for the request.
136
- * @default "GET"
127
+ * Parameters to be appended to the URL (i.e: /:id)
137
128
  */
138
- method?: InferSchemaResult<TSchemas["method"], Method>;
139
- }>;
140
- type Headers = UnmaskType<Record<"Authorization", CommonAuthorizationHeaders> | Record<"Content-Type", CommonContentTypes> | Record<CommonRequestHeaders, string | undefined> | Record<string, string | undefined> | RequestInit["headers"]>;
141
- type HeadersOption<TSchemas extends CallApiSchemas> = MakeSchemaOptionRequired<TSchemas["headers"], {
129
+ params?: InferSchemaResult<TSchemas["params"], Params>;
142
130
  /**
143
- * Headers to be used in the request.
131
+ * Query parameters to append to the URL.
144
132
  */
145
- headers?: InferSchemaResult<TSchemas["headers"], Headers>;
146
- }>;
147
- interface Register {
133
+ query?: InferSchemaResult<TSchemas["query"], Query>;
148
134
  }
149
- type GlobalMeta = Register extends {
150
- meta?: infer TMeta extends Record<string, unknown>;
151
- } ? TMeta : never;
152
- type MetaOption<TSchemas extends CallApiSchemas> = {
153
- /**
154
- * - An optional field you can fill with additional information,
155
- * to associate with the request, typically used for logging or tracing.
156
- *
157
- * - A good use case for this, would be to use the info to handle specific cases in any of the shared interceptors.
158
- *
159
- * @example
160
- * ```ts
161
- * const callMainApi = callApi.create({
162
- * baseURL: "https://main-api.com",
163
- * onResponseError: ({ response, options }) => {
164
- * if (options.meta?.userId) {
165
- * console.error(`User ${options.meta.userId} made an error`);
166
- * }
167
- * },
168
- * });
169
- *
170
- * const response = await callMainApi({
171
- * url: "https://example.com/api/data",
172
- * meta: { userId: "123" },
173
- * });
174
- * ```
175
- */
176
- meta?: InferSchemaResult<TSchemas["meta"], GlobalMeta>;
177
- };
178
- type ResultModeOption<TErrorData, TResultMode extends ResultModeUnion> = TErrorData extends false ? {
179
- resultMode: "onlySuccessWithException";
180
- } : TErrorData extends false | undefined ? {
181
- resultMode?: "onlySuccessWithException";
182
- } : undefined extends TResultMode ? {
183
- resultMode?: TResultMode;
184
- } : {
185
- resultMode: TResultMode;
186
- };
187
135
 
188
- type RetryCondition<TErrorData> = (context: ErrorContext<TErrorData>) => boolean | Promise<boolean>;
136
+ type RetryCondition<TErrorData> = (context: ErrorContext<TErrorData>) => Awaitable<boolean>;
189
137
  interface RetryOptions<TErrorData> {
190
138
  /**
191
139
  * Keeps track of the number of times the request has already been retried
@@ -215,12 +163,12 @@ interface RetryOptions<TErrorData> {
215
163
  * HTTP methods that are allowed to retry
216
164
  * @default ["GET", "POST"]
217
165
  */
218
- retryMethods?: Method[];
166
+ retryMethods?: Method[] | ((context: ErrorContext<TErrorData>) => Method[]);
219
167
  /**
220
168
  * HTTP status codes that trigger a retry
221
169
  * @default [409, 425, 429, 500, 502, 503, 504]
222
170
  */
223
- retryStatusCodes?: Array<409 | 425 | 429 | 500 | 502 | 503 | 504 | AnyNumber>;
171
+ retryStatusCodes?: Array<409 | 425 | 429 | 500 | 502 | 503 | 504 | AnyNumber> | ((context: ErrorContext<TErrorData>) => Array<409 | 425 | 429 | 500 | 502 | 503 | 504 | AnyNumber>);
224
172
  /**
225
173
  * Strategy to use when retrying
226
174
  * @default "linear"
@@ -255,6 +203,7 @@ type InferPluginOptions<TPluginArray extends CallApiPlugin[]> = UnionToIntersect
255
203
  type PluginInitContext<TMoreOptions = DefaultMoreOptions> = WithMoreOptions<TMoreOptions> & {
256
204
  baseConfig: BaseCallApiExtraOptions & CallApiRequestOptions;
257
205
  config: CallApiExtraOptions & CallApiRequestOptions;
206
+ defaultOptions: CallApiExtraOptions;
258
207
  initURL: InitURL | undefined;
259
208
  options: CombinedCallApiExtraOptions;
260
209
  request: CallApiRequestOptionsForHooks;
@@ -296,8 +245,76 @@ declare const definePlugin: <TPlugin extends CallApiPlugin | AnyFunction<CallApi
296
245
  type Plugins<TPluginArray extends CallApiPlugin[]> = TPluginArray;
297
246
 
298
247
  declare const fetchSpecificKeys: ("body" | "cache" | "credentials" | "headers" | "integrity" | "keepalive" | "method" | "mode" | "priority" | "redirect" | "referrer" | "referrerPolicy" | "signal" | "window")[];
299
- declare const defaultRetryMethods: ("GET" | "POST")[];
300
- declare const defaultRetryStatusCodes: Required<BaseCallApiExtraOptions>["retryStatusCodes"];
248
+
249
+ /**
250
+ * @description Makes a type required if TSchema type is undefined or if the output type of TSchema contains undefined, otherwise keeps it as is
251
+ */
252
+ type MakeSchemaOptionRequired<TSchema extends StandardSchemaV1 | undefined, TObject> = undefined extends TSchema ? TObject : undefined extends InferSchemaResult<TSchema, NonNullable<unknown>> ? TObject : Required<TObject>;
253
+ type JsonPrimitive = boolean | number | string | null | undefined;
254
+ type SerializableObject = Record<keyof object, unknown>;
255
+ type SerializableArray = Array<JsonPrimitive | SerializableArray | SerializableObject> | ReadonlyArray<JsonPrimitive | SerializableArray | SerializableObject>;
256
+ type Body = UnmaskType<RequestInit["body"] | SerializableArray | SerializableObject>;
257
+ type BodyOption<TSchemas extends CallApiSchemas> = MakeSchemaOptionRequired<TSchemas["body"], {
258
+ /**
259
+ * Body of the request, can be a object or any other supported body type.
260
+ */
261
+ body?: InferSchemaResult<TSchemas["body"], Body>;
262
+ }>;
263
+ type Method = UnmaskType<"CONNECT" | "DELETE" | "GET" | "HEAD" | "OPTIONS" | "PATCH" | "POST" | "PUT" | "TRACE" | AnyString>;
264
+ type MethodOption<TSchemas extends CallApiSchemas> = MakeSchemaOptionRequired<TSchemas["method"], {
265
+ /**
266
+ * HTTP method for the request.
267
+ * @default "GET"
268
+ */
269
+ method?: InferSchemaResult<TSchemas["method"], Method>;
270
+ }>;
271
+ type Headers = UnmaskType<Record<"Authorization", CommonAuthorizationHeaders> | Record<"Content-Type", CommonContentTypes> | Record<CommonRequestHeaders, string | undefined> | Record<string, string | undefined> | RequestInit["headers"]>;
272
+ type HeadersOption<TSchemas extends CallApiSchemas> = MakeSchemaOptionRequired<TSchemas["headers"], {
273
+ /**
274
+ * Headers to be used in the request.
275
+ */
276
+ headers?: InferSchemaResult<TSchemas["headers"], Headers>;
277
+ }>;
278
+ interface Register {
279
+ }
280
+ type GlobalMeta = Register extends {
281
+ meta?: infer TMeta extends Record<string, unknown>;
282
+ } ? TMeta : never;
283
+ type MetaOption<TSchemas extends CallApiSchemas> = {
284
+ /**
285
+ * - An optional field you can fill with additional information,
286
+ * to associate with the request, typically used for logging or tracing.
287
+ *
288
+ * - A good use case for this, would be to use the info to handle specific cases in any of the shared interceptors.
289
+ *
290
+ * @example
291
+ * ```ts
292
+ * const callMainApi = callApi.create({
293
+ * baseURL: "https://main-api.com",
294
+ * onResponseError: ({ response, options }) => {
295
+ * if (options.meta?.userId) {
296
+ * console.error(`User ${options.meta.userId} made an error`);
297
+ * }
298
+ * },
299
+ * });
300
+ *
301
+ * const response = await callMainApi({
302
+ * url: "https://example.com/api/data",
303
+ * meta: { userId: "123" },
304
+ * });
305
+ * ```
306
+ */
307
+ meta?: InferSchemaResult<TSchemas["meta"], GlobalMeta>;
308
+ };
309
+ type ResultModeOption<TErrorData, TResultMode extends ResultModeUnion> = TErrorData extends false ? {
310
+ resultMode: "onlySuccessWithException";
311
+ } : TErrorData extends false | undefined ? {
312
+ resultMode?: "onlySuccessWithException";
313
+ } : undefined extends TResultMode ? {
314
+ resultMode?: TResultMode;
315
+ } : {
316
+ resultMode: TResultMode;
317
+ };
301
318
 
302
319
  type FetchSpecificKeysUnion = Exclude<(typeof fetchSpecificKeys)[number], "body" | "headers" | "method">;
303
320
  type CallApiRequestOptions<TSchemas extends CallApiSchemas = DefaultMoreOptions> = BodyOption<TSchemas> & HeadersOption<TSchemas> & MethodOption<TSchemas> & Pick<RequestInit, FetchSpecificKeysUnion>;
@@ -448,13 +465,15 @@ declare const optionsEnumToOmitFromBase: ("dedupeKey" | "extend")[];
448
465
  type BaseCallApiExtraOptions<TBaseData = DefaultDataType, TBaseErrorData = DefaultDataType, TBaseResultMode extends ResultModeUnion = ResultModeUnion, TBaseThrowOnError extends boolean = DefaultThrowOnError, TBaseResponseType extends ResponseTypeUnion = ResponseTypeUnion, TBasePluginArray extends CallApiPlugin[] = DefaultPluginArray, TBaseSchemas extends CallApiSchemas = DefaultMoreOptions> = Omit<Partial<CallApiExtraOptions<TBaseData, TBaseErrorData, TBaseResultMode, TBaseThrowOnError, TBaseResponseType, TBasePluginArray, TBaseSchemas>>, (typeof optionsEnumToOmitFromBase)[number]>;
449
466
  type CombinedCallApiExtraOptions = BaseCallApiExtraOptions & CallApiExtraOptions;
450
467
  type BaseCallApiConfig<TBaseData = DefaultDataType, TBaseErrorData = DefaultDataType, TBaseResultMode extends ResultModeUnion = ResultModeUnion, TBaseThrowOnError extends boolean = DefaultThrowOnError, TBaseResponseType extends ResponseTypeUnion = ResponseTypeUnion, TBasePluginArray extends CallApiPlugin[] = DefaultPluginArray, TBaseSchemas extends CallApiSchemas = DefaultMoreOptions> = (CallApiRequestOptions<TBaseSchemas> & BaseCallApiExtraOptions<TBaseData, TBaseErrorData, TBaseResultMode, TBaseThrowOnError, TBaseResponseType, TBasePluginArray, TBaseSchemas>) | ((context: {
468
+ defaultOptions: CallApiExtraOptions;
451
469
  initURL: string;
452
470
  options: CallApiExtraOptions;
453
471
  request: CallApiRequestOptions;
454
472
  }) => CallApiRequestOptions<TBaseSchemas> & BaseCallApiExtraOptions<TBaseData, TBaseErrorData, TBaseResultMode, TBaseThrowOnError, TBaseResponseType, TBasePluginArray, TBaseSchemas>);
473
+ type CallApiConfig<TData = DefaultDataType, TErrorData = DefaultDataType, TResultMode extends ResultModeUnion = ResultModeUnion, TThrowOnError extends boolean = DefaultThrowOnError, TResponseType extends ResponseTypeUnion = ResponseTypeUnion, TPluginArray extends CallApiPlugin[] = DefaultPluginArray, TSchemas extends CallApiSchemas = DefaultMoreOptions> = CallApiRequestOptions<TSchemas> & CallApiExtraOptions<TData, TErrorData, TResultMode, TThrowOnError, TResponseType, TPluginArray, TSchemas>;
455
474
  type CallApiParameters<TData = DefaultDataType, TErrorData = DefaultDataType, TResultMode extends ResultModeUnion = ResultModeUnion, TThrowOnError extends boolean = DefaultThrowOnError, TResponseType extends ResponseTypeUnion = ResponseTypeUnion, TPluginArray extends CallApiPlugin[] = DefaultPluginArray, TSchemas extends CallApiSchemas = DefaultMoreOptions> = [
456
475
  initURL: InferSchemaResult<TSchemas["initURL"], InitURL>,
457
- config?: CallApiRequestOptions<TSchemas> & CallApiExtraOptions<TData, TErrorData, TResultMode, TThrowOnError, TResponseType, TPluginArray, TSchemas>
476
+ config?: CallApiConfig<TData, TErrorData, TResultMode, TThrowOnError, TResponseType, TPluginArray, TSchemas>
458
477
  ];
459
478
  type RequestContext = UnmaskType<{
460
479
  options: CombinedCallApiExtraOptions;
@@ -539,24 +558,7 @@ type ResultModeMap<TData = DefaultDataType, TErrorData = DefaultDataType, TRespo
539
558
  }>;
540
559
  type ResultModeUnion = keyof ResultModeMap | undefined;
541
560
  type GetCallApiResult<TData, TErrorData, TResultMode extends ResultModeUnion, TThrowOnError extends boolean, TResponseType extends ResponseTypeUnion> = TErrorData extends false | undefined ? ResultModeMap<TData, TErrorData, TResponseType>["onlySuccessWithException"] : ResultModeUnion | undefined extends TResultMode ? TThrowOnError extends true ? ResultModeMap<TData, TErrorData, TResponseType>["allWithException"] : ResultModeMap<TData, TErrorData, TResponseType>["all"] : TResultMode extends NonNullable<ResultModeUnion> ? TResultMode extends "onlySuccess" ? ResultModeMap<TData, TErrorData, TResponseType>["onlySuccessWithException"] : TResultMode extends "onlyResponse" ? ResultModeMap<TData, TErrorData, TResponseType>["onlyResponseWithException"] : ResultModeMap<TData, TErrorData, TResponseType>[TResultMode] : never;
542
-
543
- type Params = UnmaskType<Record<string, boolean | number | string> | Array<boolean | number | string>>;
544
- type Query = UnmaskType<Record<string, boolean | number | string>>;
545
- type InitURL = UnmaskType<string | URL>;
546
- interface UrlOptions<TSchemas extends CallApiSchemas> {
547
- /**
548
- * URL to be used in the request.
549
- */
550
- readonly initURL?: string;
551
- /**
552
- * Parameters to be appended to the URL (i.e: /:id)
553
- */
554
- params?: InferSchemaResult<TSchemas["params"], Params>;
555
- /**
556
- * Query parameters to append to the URL.
557
- */
558
- query?: InferSchemaResult<TSchemas["query"], Query>;
559
- }
561
+ type CallApiResult<TData, TErrorData, TResultMode extends ResultModeUnion, TThrowOnError extends boolean, TResponseType extends ResponseTypeUnion> = Promise<GetCallApiResult<TData, TErrorData, TResultMode, TThrowOnError, TResponseType>>;
560
562
 
561
563
  type ErrorDetails<TErrorResponse> = {
562
564
  defaultErrorMessage: string;
@@ -574,4 +576,4 @@ declare class HTTPError<TErrorResponse = Record<string, unknown>> extends Error
574
576
  constructor(errorDetails: ErrorDetails<TErrorResponse>, errorOptions?: ErrorOptions);
575
577
  }
576
578
 
577
- export { type AnyString as A, type BaseCallApiConfig as B, type CallApiPlugin as C, type DefaultPluginArray as D, type ExtraOptions as E, type Interceptors as F, type GetCallApiResult as G, HTTPError as H, type InferSchemaResult as I, type PossibleJavascriptErrorNames as J, type Register as K, type RequestContext as L, type MetaOption as M, type RequestErrorContext as N, type ResponseContext as O, type PossibleJavaScriptError as P, type ResponseErrorContext as Q, type ResultModeUnion as R, type SerializableArray as S, type SuccessContext as T, type UrlOptions as U, defaultRetryMethods as V, defaultRetryStatusCodes as W, type ResponseTypeUnion as a, type CallApiSchemas as b, type SerializableObject as c, type CommonContentTypes as d, type CommonRequestHeaders as e, type Auth as f, type Awaitable as g, type CombinedCallApiExtraOptions as h, type CallApiRequestOptionsForHooks as i, type CallApiValidators as j, type InterceptorsOrInterceptorArray as k, type RetryOptions as l, type ResultModeOption as m, type DefaultDataType as n, type DefaultThrowOnError as o, type DefaultMoreOptions as p, type CallApiParameters as q, definePlugin as r, type PluginInitContext as s, type BaseCallApiExtraOptions as t, type CallApiExtraOptions as u, type PossibleHTTPError as v, type CallApiRequestOptions as w, type CallApiResultErrorVariant as x, type CallApiResultSuccessVariant as y, type ErrorContext as z };
579
+ export { type ResponseErrorContext as A, type BaseCallApiConfig as B, type CallApiPlugin as C, type DefaultPluginArray as D, type ErrorContext as E, HTTPError as H, type InferSchemaResult as I, type PluginInitContext as P, type ResultModeUnion as R, type SuccessContext as S, type ResponseTypeUnion as a, type CallApiSchemas as b, type CallApiConfig as c, type CallApiResult as d, type DefaultDataType as e, type DefaultThrowOnError as f, type DefaultMoreOptions as g, type CallApiParameters as h, definePlugin as i, type RetryOptions as j, type BaseCallApiExtraOptions as k, type CallApiExtraOptions as l, type PossibleJavaScriptError as m, type PossibleHTTPError as n, type CallApiRequestOptions as o, type CallApiRequestOptionsForHooks as p, type CallApiResultErrorVariant as q, type CallApiResultSuccessVariant as r, type CombinedCallApiExtraOptions as s, type Interceptors as t, type InterceptorsOrInterceptorArray as u, type PossibleJavascriptErrorNames as v, type Register as w, type RequestContext as x, type RequestErrorContext as y, type ResponseContext as z };
@@ -205,6 +205,22 @@ var retryStatusCodesLookup = defineEnum({
205
205
  });
206
206
  var defaultRetryMethods = ["GET", "POST"];
207
207
  var defaultRetryStatusCodes = Object.keys(retryStatusCodesLookup).map(Number);
208
+ var defaultExtraOptions = {
209
+ baseURL: "",
210
+ bodySerializer: JSON.stringify,
211
+ dedupeStrategy: "cancel",
212
+ defaultErrorMessage: "Failed to fetch data from server!",
213
+ mergedHooksExecutionMode: "parallel",
214
+ mergedHooksExecutionOrder: "mainHooksAfterPlugins",
215
+ responseType: "json",
216
+ resultMode: "all",
217
+ retryAttempts: 0,
218
+ retryDelay: 1e3,
219
+ retryMaxDelay: 1e4,
220
+ retryMethods: defaultRetryMethods,
221
+ retryStatusCodes: defaultRetryStatusCodes,
222
+ retryStrategy: "linear"
223
+ };
208
224
 
209
225
  // src/utils/common.ts
210
226
  var omitKeys = (initialObject, keysToOmit) => {
@@ -375,7 +391,7 @@ var getPluginArray = (plugins) => {
375
391
  return plugins;
376
392
  };
377
393
  var initializePlugins = async (context) => {
378
- const { baseConfig, config, initURL, options, request } = context;
394
+ const { baseConfig, config, defaultOptions, initURL, options, request } = context;
379
395
  const hookRegistries = structuredClone(hooksEnum);
380
396
  const addMainHooks = () => {
381
397
  for (const key of Object.keys(hooksEnum)) {
@@ -404,6 +420,7 @@ var initializePlugins = async (context) => {
404
420
  const initResult = await pluginInit({
405
421
  baseConfig,
406
422
  config,
423
+ defaultOptions,
407
424
  initURL,
408
425
  options,
409
426
  request
@@ -490,28 +507,30 @@ var getExponentialDelay = (currentAttemptCount, options) => {
490
507
  const exponentialDelay = (options.retryDelay ?? 1e3) * 2 ** currentAttemptCount;
491
508
  return Math.min(exponentialDelay, maxDelay);
492
509
  };
493
- var createRetryStrategy = (options, ctx) => {
494
- const currentRetryCount = options["~retryCount"] ?? 0;
510
+ var createRetryStrategy = (ctx) => {
511
+ const currentRetryCount = ctx.options["~retryCount"] ?? 0;
495
512
  const getDelay = () => {
496
- if (options.retryStrategy === "exponential") {
497
- return getExponentialDelay(currentRetryCount, options);
513
+ if (ctx.options.retryStrategy === "exponential") {
514
+ return getExponentialDelay(currentRetryCount, ctx.options);
498
515
  }
499
- return getLinearDelay(options);
516
+ return getLinearDelay(ctx.options);
500
517
  };
501
518
  const shouldAttemptRetry = async () => {
502
- const customRetryCondition = await options.retryCondition?.(ctx) ?? true;
503
- const maxRetryAttempts = options.retryAttempts ?? 0;
519
+ const customRetryCondition = await ctx.options.retryCondition?.(ctx) ?? true;
520
+ const maxRetryAttempts = ctx.options.retryAttempts ?? 0;
504
521
  const baseRetryCondition = maxRetryAttempts > currentRetryCount && customRetryCondition;
505
522
  if (ctx.error.name !== "HTTPError") {
506
523
  return baseRetryCondition;
507
524
  }
525
+ const resolvedRetryMethods = isFunction(ctx.options.retryMethods) ? ctx.options.retryMethods(ctx) : ctx.options.retryMethods;
526
+ const resolvedRetryStatusCodes = isFunction(ctx.options.retryStatusCodes) ? ctx.options.retryStatusCodes(ctx) : ctx.options.retryStatusCodes;
508
527
  const includesMethod = (
509
528
  // eslint-disable-next-line no-implicit-coercion -- Boolean doesn't narrow
510
- !!ctx.request.method && options.retryMethods?.includes(ctx.request.method)
529
+ !!ctx.request.method && resolvedRetryMethods?.includes(ctx.request.method)
511
530
  );
512
531
  const includesCodes = (
513
532
  // eslint-disable-next-line no-implicit-coercion -- Boolean doesn't narrow
514
- !!ctx.response?.status && options.retryStatusCodes?.includes(ctx.response.status)
533
+ !!ctx.response?.status && resolvedRetryStatusCodes?.includes(ctx.response.status)
515
534
  );
516
535
  return includesCodes && includesMethod && baseRetryCondition;
517
536
  };
@@ -595,7 +614,12 @@ var createFetchClient = (baseConfig = {}) => {
595
614
  const callApi2 = async (...parameters) => {
596
615
  const [initURL, config = {}] = parameters;
597
616
  const [fetchOptions, extraOptions] = splitConfig(config);
598
- const resolvedBaseConfig = isFunction(baseConfig) ? baseConfig({ initURL: initURL.toString(), options: extraOptions, request: fetchOptions }) : baseConfig;
617
+ const resolvedBaseConfig = isFunction(baseConfig) ? baseConfig({
618
+ defaultOptions: defaultExtraOptions,
619
+ initURL: initURL.toString(),
620
+ options: extraOptions,
621
+ request: fetchOptions
622
+ }) : baseConfig;
599
623
  const [baseFetchOptions, baseExtraOptions] = splitBaseConfig(resolvedBaseConfig);
600
624
  const initCombinedHooks = {};
601
625
  for (const key of Object.keys(hooksEnum)) {
@@ -605,35 +629,22 @@ var createFetchClient = (baseConfig = {}) => {
605
629
  );
606
630
  initCombinedHooks[key] = combinedHook;
607
631
  }
608
- const defaultExtraOptions = {
609
- baseURL: "",
610
- bodySerializer: JSON.stringify,
611
- dedupeStrategy: "cancel",
612
- defaultErrorMessage: "Failed to fetch data from server!",
613
- mergedHooksExecutionMode: "parallel",
614
- mergedHooksExecutionOrder: "mainHooksAfterPlugins",
615
- responseType: "json",
616
- resultMode: "all",
617
- retryAttempts: 0,
618
- retryDelay: 1e3,
619
- retryMaxDelay: 1e4,
620
- retryMethods: defaultRetryMethods,
621
- retryStatusCodes: defaultRetryStatusCodes,
622
- retryStrategy: "linear",
632
+ const mergedExtraOptions = {
633
+ ...defaultExtraOptions,
623
634
  ...baseExtraOptions,
624
- ...extraOptions,
625
- ...initCombinedHooks
635
+ ...extraOptions
626
636
  };
627
- const defaultRequestOptions = {
637
+ const mergedRequestOptions = {
628
638
  ...baseFetchOptions,
629
639
  ...fetchOptions
630
640
  };
631
641
  const { resolvedHooks, resolvedOptions, resolvedRequestOptions, url } = await initializePlugins({
632
642
  baseConfig: resolvedBaseConfig,
633
643
  config,
644
+ defaultOptions: defaultExtraOptions,
634
645
  initURL,
635
- options: defaultExtraOptions,
636
- request: defaultRequestOptions
646
+ options: mergedExtraOptions,
647
+ request: mergedRequestOptions
637
648
  });
638
649
  const fullURL = `${resolvedOptions.baseURL}${mergeUrlWithParamsAndQuery(url, resolvedOptions.params, resolvedOptions.query)}`;
639
650
  const options = {
@@ -666,7 +677,6 @@ var createFetchClient = (baseConfig = {}) => {
666
677
  await executeHooks(options.onRequest({ options, request }));
667
678
  request.headers = mergeAndResolveHeaders({
668
679
  auth: options.auth,
669
- baseHeaders: baseFetchOptions.headers,
670
680
  body: request.body,
671
681
  headers: request.headers
672
682
  });
@@ -724,9 +734,11 @@ var createFetchClient = (baseConfig = {}) => {
724
734
  request,
725
735
  response: apiDetails.response
726
736
  };
727
- const { getDelay, shouldAttemptRetry } = createRetryStrategy(options, errorContext);
728
- const shouldRetry = !combinedSignal.aborted && await shouldAttemptRetry();
729
- if (shouldRetry) {
737
+ const shouldThrowOnError = isFunction(options.throwOnError) ? options.throwOnError(errorContext) : options.throwOnError;
738
+ const handleRetry = async () => {
739
+ const { getDelay, shouldAttemptRetry } = createRetryStrategy(errorContext);
740
+ const shouldRetry = !combinedSignal.aborted && await shouldAttemptRetry();
741
+ if (!shouldRetry) return;
730
742
  await executeHooks(options.onRetry(errorContext));
731
743
  const delay = getDelay();
732
744
  await waitUntil(delay);
@@ -734,9 +746,8 @@ var createFetchClient = (baseConfig = {}) => {
734
746
  ...config,
735
747
  "~retryCount": (options["~retryCount"] ?? 0) + 1
736
748
  };
737
- return await callApi2(initURL, updatedOptions);
738
- }
739
- const shouldThrowOnError = isFunction(options.throwOnError) ? options.throwOnError(errorContext) : options.throwOnError;
749
+ return callApi2(initURL, updatedOptions);
750
+ };
740
751
  const handleThrowOnError = () => {
741
752
  if (!shouldThrowOnError) return;
742
753
  throw apiDetails.error;
@@ -747,18 +758,21 @@ var createFetchClient = (baseConfig = {}) => {
747
758
  options.onError(errorContext),
748
759
  options.onResponse({ ...errorContext, data: null })
749
760
  );
761
+ await handleRetry();
750
762
  handleThrowOnError();
751
763
  return getErrorResult();
752
764
  }
753
765
  if (error instanceof DOMException && error.name === "AbortError") {
754
766
  const { message, name } = error;
755
767
  console.error(`${name}:`, message);
768
+ await handleRetry();
756
769
  handleThrowOnError();
757
770
  return getErrorResult();
758
771
  }
759
772
  if (error instanceof DOMException && error.name === "TimeoutError") {
760
773
  const message = `Request timed out after ${options.timeout}ms`;
761
774
  console.error(`${error.name}:`, message);
775
+ await handleRetry();
762
776
  handleThrowOnError();
763
777
  return getErrorResult({ message });
764
778
  }
@@ -768,6 +782,7 @@ var createFetchClient = (baseConfig = {}) => {
768
782
  // == Also call the onError interceptor
769
783
  options.onError(errorContext)
770
784
  );
785
+ await handleRetry();
771
786
  handleThrowOnError();
772
787
  return getErrorResult();
773
788
  } finally {