@zayne-labs/callapi 1.6.17 → 1.6.20

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.
@@ -102,7 +102,7 @@ interface CallApiSchemas {
102
102
  */
103
103
  query?: StandardSchemaV1<Query>;
104
104
  }
105
- interface CallApiValidators<TData = never, TErrorData = never> {
105
+ interface CallApiValidators<TData = unknown, TErrorData = unknown> {
106
106
  /**
107
107
  * Custom function to validate the response data.
108
108
  */
@@ -133,7 +133,7 @@ interface UrlOptions<TSchemas extends CallApiSchemas> {
133
133
  query?: InferSchemaResult<TSchemas["query"], Query>;
134
134
  }
135
135
 
136
- type RetryCondition<TErrorData> = (context: ErrorContext<TErrorData>) => boolean | Promise<boolean>;
136
+ type RetryCondition<TErrorData> = (context: ErrorContext<TErrorData>) => Awaitable<boolean>;
137
137
  interface RetryOptions<TErrorData> {
138
138
  /**
139
139
  * Keeps track of the number of times the request has already been retried
@@ -244,8 +244,25 @@ declare const definePlugin: <TPlugin extends CallApiPlugin | AnyFunction<CallApi
244
244
  type Plugins<TPluginArray extends CallApiPlugin[]> = TPluginArray;
245
245
 
246
246
  declare const fetchSpecificKeys: ("body" | "cache" | "credentials" | "headers" | "integrity" | "keepalive" | "method" | "mode" | "priority" | "redirect" | "referrer" | "referrerPolicy" | "signal" | "window")[];
247
- declare const defaultRetryMethods: ("GET" | "POST")[];
248
- declare const defaultRetryStatusCodes: Required<BaseCallApiExtraOptions>["retryStatusCodes"];
247
+ declare const getDefaultOptions: () => {
248
+ baseURL: string;
249
+ bodySerializer: {
250
+ (value: any, replacer?: (this: any, key: string, value: any) => any, space?: string | number): string;
251
+ (value: any, replacer?: (number | string)[] | null, space?: string | number): string;
252
+ };
253
+ dedupeStrategy: "cancel";
254
+ defaultErrorMessage: string;
255
+ mergedHooksExecutionMode: "parallel";
256
+ mergedHooksExecutionOrder: "mainHooksAfterPlugins";
257
+ responseType: "json";
258
+ resultMode: "all";
259
+ retryAttempts: number;
260
+ retryDelay: number;
261
+ retryMaxDelay: number;
262
+ retryMethods: ("GET" | "POST")[];
263
+ retryStatusCodes: (AnyNumber | 409 | 425 | 429 | 500 | 502 | 503 | 504)[];
264
+ retryStrategy: "linear";
265
+ };
249
266
 
250
267
  /**
251
268
  * @description Makes a type required if TSchema type is undefined or if the output type of TSchema contains undefined, otherwise keeps it as is
@@ -576,4 +593,4 @@ declare class HTTPError<TErrorResponse = Record<string, unknown>> extends Error
576
593
  constructor(errorDetails: ErrorDetails<TErrorResponse>, errorOptions?: ErrorOptions);
577
594
  }
578
595
 
579
- export { defaultRetryMethods as A, type BaseCallApiConfig as B, type CallApiPlugin as C, type DefaultPluginArray as D, type ErrorContext as E, defaultRetryStatusCodes as F, 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 BaseCallApiExtraOptions as j, type CallApiExtraOptions as k, type PossibleJavaScriptError as l, type PossibleHTTPError as m, type CallApiRequestOptions as n, type CallApiRequestOptionsForHooks as o, type CallApiResultErrorVariant as p, type CallApiResultSuccessVariant as q, type CombinedCallApiExtraOptions as r, type Interceptors as s, type InterceptorsOrInterceptorArray as t, type PossibleJavascriptErrorNames as u, type Register as v, type RequestContext as w, type RequestErrorContext as x, type ResponseContext as y, type ResponseErrorContext as z };
596
+ export { type ResponseContext as A, type BaseCallApiConfig as B, type CallApiPlugin as C, type DefaultPluginArray as D, type ErrorContext as E, type ResponseErrorContext as F, 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, getDefaultOptions as j, type RetryOptions as k, type BaseCallApiExtraOptions as l, type CallApiExtraOptions as m, type PossibleJavaScriptError as n, type PossibleHTTPError as o, type CallApiRequestOptions as p, type CallApiRequestOptionsForHooks as q, type CallApiResultErrorVariant as r, type CallApiResultSuccessVariant as s, type CombinedCallApiExtraOptions as t, type Interceptors as u, type InterceptorsOrInterceptorArray as v, type PossibleJavascriptErrorNames as w, type Register as x, type RequestContext as y, type RequestErrorContext as z };
@@ -24,7 +24,8 @@ __export(index_exports, {
24
24
  callApi: () => callApi,
25
25
  createFetchClient: () => createFetchClient,
26
26
  defineParameters: () => defineParameters,
27
- definePlugin: () => definePlugin
27
+ definePlugin: () => definePlugin,
28
+ getDefaultOptions: () => getDefaultOptions
28
29
  });
29
30
  module.exports = __toCommonJS(index_exports);
30
31
 
@@ -205,6 +206,23 @@ var retryStatusCodesLookup = defineEnum({
205
206
  });
206
207
  var defaultRetryMethods = ["GET", "POST"];
207
208
  var defaultRetryStatusCodes = Object.keys(retryStatusCodesLookup).map(Number);
209
+ var defaultExtraOptions = {
210
+ baseURL: "",
211
+ bodySerializer: JSON.stringify,
212
+ dedupeStrategy: "cancel",
213
+ defaultErrorMessage: "Failed to fetch data from server!",
214
+ mergedHooksExecutionMode: "parallel",
215
+ mergedHooksExecutionOrder: "mainHooksAfterPlugins",
216
+ responseType: "json",
217
+ resultMode: "all",
218
+ retryAttempts: 0,
219
+ retryDelay: 1e3,
220
+ retryMaxDelay: 1e4,
221
+ retryMethods: defaultRetryMethods,
222
+ retryStatusCodes: defaultRetryStatusCodes,
223
+ retryStrategy: "linear"
224
+ };
225
+ var getDefaultOptions = () => defaultExtraOptions;
208
226
 
209
227
  // src/utils/common.ts
210
228
  var omitKeys = (initialObject, keysToOmit) => {
@@ -490,28 +508,28 @@ var getExponentialDelay = (currentAttemptCount, options) => {
490
508
  const exponentialDelay = (options.retryDelay ?? 1e3) * 2 ** currentAttemptCount;
491
509
  return Math.min(exponentialDelay, maxDelay);
492
510
  };
493
- var createRetryStrategy = (options, ctx) => {
494
- const currentRetryCount = options["~retryCount"] ?? 0;
511
+ var createRetryStrategy = (ctx) => {
512
+ const currentRetryCount = ctx.options["~retryCount"] ?? 0;
495
513
  const getDelay = () => {
496
- if (options.retryStrategy === "exponential") {
497
- return getExponentialDelay(currentRetryCount, options);
514
+ if (ctx.options.retryStrategy === "exponential") {
515
+ return getExponentialDelay(currentRetryCount, ctx.options);
498
516
  }
499
- return getLinearDelay(options);
517
+ return getLinearDelay(ctx.options);
500
518
  };
501
519
  const shouldAttemptRetry = async () => {
502
- const customRetryCondition = await options.retryCondition?.(ctx) ?? true;
503
- const maxRetryAttempts = options.retryAttempts ?? 0;
520
+ const customRetryCondition = await ctx.options.retryCondition?.(ctx) ?? true;
521
+ const maxRetryAttempts = ctx.options.retryAttempts ?? 0;
504
522
  const baseRetryCondition = maxRetryAttempts > currentRetryCount && customRetryCondition;
505
523
  if (ctx.error.name !== "HTTPError") {
506
524
  return baseRetryCondition;
507
525
  }
508
526
  const includesMethod = (
509
527
  // eslint-disable-next-line no-implicit-coercion -- Boolean doesn't narrow
510
- !!ctx.request.method && options.retryMethods?.includes(ctx.request.method)
528
+ !!ctx.request.method && ctx.options.retryMethods?.includes(ctx.request.method)
511
529
  );
512
530
  const includesCodes = (
513
531
  // eslint-disable-next-line no-implicit-coercion -- Boolean doesn't narrow
514
- !!ctx.response?.status && options.retryStatusCodes?.includes(ctx.response.status)
532
+ !!ctx.response?.status && ctx.options.retryStatusCodes?.includes(ctx.response.status)
515
533
  );
516
534
  return includesCodes && includesMethod && baseRetryCondition;
517
535
  };
@@ -595,7 +613,11 @@ var createFetchClient = (baseConfig = {}) => {
595
613
  const callApi2 = async (...parameters) => {
596
614
  const [initURL, config = {}] = parameters;
597
615
  const [fetchOptions, extraOptions] = splitConfig(config);
598
- const resolvedBaseConfig = isFunction(baseConfig) ? baseConfig({ initURL: initURL.toString(), options: extraOptions, request: fetchOptions }) : baseConfig;
616
+ const resolvedBaseConfig = isFunction(baseConfig) ? baseConfig({
617
+ initURL: initURL.toString(),
618
+ options: extraOptions,
619
+ request: fetchOptions
620
+ }) : baseConfig;
599
621
  const [baseFetchOptions, baseExtraOptions] = splitBaseConfig(resolvedBaseConfig);
600
622
  const initCombinedHooks = {};
601
623
  for (const key of Object.keys(hooksEnum)) {
@@ -605,26 +627,12 @@ var createFetchClient = (baseConfig = {}) => {
605
627
  );
606
628
  initCombinedHooks[key] = combinedHook;
607
629
  }
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",
630
+ const mergedExtraOptions = {
631
+ ...defaultExtraOptions,
623
632
  ...baseExtraOptions,
624
- ...extraOptions,
625
- ...initCombinedHooks
633
+ ...extraOptions
626
634
  };
627
- const defaultRequestOptions = {
635
+ const mergedRequestOptions = {
628
636
  ...baseFetchOptions,
629
637
  ...fetchOptions
630
638
  };
@@ -632,8 +640,8 @@ var createFetchClient = (baseConfig = {}) => {
632
640
  baseConfig: resolvedBaseConfig,
633
641
  config,
634
642
  initURL,
635
- options: defaultExtraOptions,
636
- request: defaultRequestOptions
643
+ options: mergedExtraOptions,
644
+ request: mergedRequestOptions
637
645
  });
638
646
  const fullURL = `${resolvedOptions.baseURL}${mergeUrlWithParamsAndQuery(url, resolvedOptions.params, resolvedOptions.query)}`;
639
647
  const options = {
@@ -694,11 +702,7 @@ var createFetchClient = (baseConfig = {}) => {
694
702
  options.responseType,
695
703
  options.responseParser
696
704
  );
697
- const validSuccessData = await handleValidation(
698
- successData,
699
- schemas?.data,
700
- validators?.data
701
- );
705
+ const validSuccessData = await handleValidation(successData, schemas?.data, validators?.data);
702
706
  const successContext = {
703
707
  data: validSuccessData,
704
708
  options,
@@ -727,9 +731,11 @@ var createFetchClient = (baseConfig = {}) => {
727
731
  request,
728
732
  response: apiDetails.response
729
733
  };
730
- const { getDelay, shouldAttemptRetry } = createRetryStrategy(options, errorContext);
731
- const shouldRetry = !combinedSignal.aborted && await shouldAttemptRetry();
732
- if (shouldRetry) {
734
+ const shouldThrowOnError = isFunction(options.throwOnError) ? options.throwOnError(errorContext) : options.throwOnError;
735
+ const handleRetry = async () => {
736
+ const { getDelay, shouldAttemptRetry } = createRetryStrategy(errorContext);
737
+ const shouldRetry = !combinedSignal.aborted && await shouldAttemptRetry();
738
+ if (!shouldRetry) return;
733
739
  await executeHooks(options.onRetry(errorContext));
734
740
  const delay = getDelay();
735
741
  await waitUntil(delay);
@@ -737,9 +743,8 @@ var createFetchClient = (baseConfig = {}) => {
737
743
  ...config,
738
744
  "~retryCount": (options["~retryCount"] ?? 0) + 1
739
745
  };
740
- return await callApi2(initURL, updatedOptions);
741
- }
742
- const shouldThrowOnError = isFunction(options.throwOnError) ? options.throwOnError(errorContext) : options.throwOnError;
746
+ return callApi2(initURL, updatedOptions);
747
+ };
743
748
  const handleThrowOnError = () => {
744
749
  if (!shouldThrowOnError) return;
745
750
  throw apiDetails.error;
@@ -750,18 +755,21 @@ var createFetchClient = (baseConfig = {}) => {
750
755
  options.onError(errorContext),
751
756
  options.onResponse({ ...errorContext, data: null })
752
757
  );
758
+ await handleRetry();
753
759
  handleThrowOnError();
754
760
  return getErrorResult();
755
761
  }
756
762
  if (error instanceof DOMException && error.name === "AbortError") {
757
763
  const { message, name } = error;
758
764
  console.error(`${name}:`, message);
765
+ await handleRetry();
759
766
  handleThrowOnError();
760
767
  return getErrorResult();
761
768
  }
762
769
  if (error instanceof DOMException && error.name === "TimeoutError") {
763
770
  const message = `Request timed out after ${options.timeout}ms`;
764
771
  console.error(`${error.name}:`, message);
772
+ await handleRetry();
765
773
  handleThrowOnError();
766
774
  return getErrorResult({ message });
767
775
  }
@@ -771,6 +779,7 @@ var createFetchClient = (baseConfig = {}) => {
771
779
  // == Also call the onError interceptor
772
780
  options.onError(errorContext)
773
781
  );
782
+ await handleRetry();
774
783
  handleThrowOnError();
775
784
  return getErrorResult();
776
785
  } finally {
@@ -791,6 +800,7 @@ var defineParameters = (...parameters) => {
791
800
  callApi,
792
801
  createFetchClient,
793
802
  defineParameters,
794
- definePlugin
803
+ definePlugin,
804
+ getDefaultOptions
795
805
  });
796
806
  //# sourceMappingURL=index.cjs.map