@zayne-labs/callapi 1.10.6 → 1.11.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.
package/dist/esm/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { HTTPError, ValidationError, createCombinedSignal, createTimeoutSignal, deterministicHashFn, extraOptionDefaults, fallBackRouteSchemaKey, getBody, getCurrentRouteSchemaKeyAndMainInitURL, getFetchImpl, getFullAndNormalizedURL, getHeaders, getMethod, handleConfigValidation, handleSchemaValidation, isArray, isBoolean, isFunction, isHTTPErrorInstance, isObject, isPlainObject, isReadableStream, isString, isValidationErrorInstance, splitBaseConfig, splitConfig, waitFor } from "./common-BFea9qeg.js";
1
+ import { HTTPError, ValidationError, createCombinedSignal, createTimeoutSignal, deterministicHashFn, extraOptionDefaults, fallBackRouteSchemaKey, getBody, getCurrentRouteSchemaKeyAndMainInitURL, getFetchImpl, getFullAndNormalizedURL, getHeaders, getMethod, handleConfigValidation, handleSchemaValidation, isArray, isBoolean, isFunction, isHTTPErrorInstance, isObject, isPlainObject, isReadableStream, isString, isValidationErrorInstance, splitBaseConfig, splitConfig, waitFor } from "./common-CEcqiR7c.js";
2
2
 
3
3
  //#region src/result.ts
4
4
  const getResponseType = (response, parser) => ({
@@ -6,8 +6,7 @@ const getResponseType = (response, parser) => ({
6
6
  blob: () => response.blob(),
7
7
  formData: () => response.formData(),
8
8
  json: async () => {
9
- const text = await response.text();
10
- return parser(text);
9
+ return parser(await response.text());
11
10
  },
12
11
  stream: () => response.body,
13
12
  text: () => response.text()
@@ -107,8 +106,8 @@ const getCustomizedErrorResult = (errorResult, customErrorInfo) => {
107
106
 
108
107
  //#endregion
109
108
  //#region src/hooks.ts
110
- const getHookRegistries = () => {
111
- return {
109
+ const getHookRegistriesAndKeys = () => {
110
+ const hookRegistries = {
112
111
  onError: /* @__PURE__ */ new Set(),
113
112
  onRequest: /* @__PURE__ */ new Set(),
114
113
  onRequestError: /* @__PURE__ */ new Set(),
@@ -121,9 +120,13 @@ const getHookRegistries = () => {
121
120
  onSuccess: /* @__PURE__ */ new Set(),
122
121
  onValidationError: /* @__PURE__ */ new Set()
123
122
  };
123
+ return {
124
+ hookRegistries,
125
+ hookRegistryKeys: Object.keys(hookRegistries)
126
+ };
124
127
  };
125
128
  const composeAllHooks = (hooksArray, hooksExecutionMode) => {
126
- const mergedHook = async (ctx) => {
129
+ const composedHook = async (ctx) => {
127
130
  switch (hooksExecutionMode) {
128
131
  case "parallel":
129
132
  await Promise.all(hooksArray.map((uniqueHook) => uniqueHook?.(ctx)));
@@ -134,9 +137,9 @@ const composeAllHooks = (hooksArray, hooksExecutionMode) => {
134
137
  default:
135
138
  }
136
139
  };
137
- return mergedHook;
140
+ return composedHook;
138
141
  };
139
- const executeHooksInTryBlock = async (...hookResultsOrPromise) => {
142
+ const executeHooks = async (...hookResultsOrPromise) => {
140
143
  await Promise.all(hookResultsOrPromise);
141
144
  };
142
145
  const executeHooksInCatchBlock = async (hookResultsOrPromise, hookInfo) => {
@@ -195,11 +198,11 @@ const toStreamableRequest = async (context) => {
195
198
  request,
196
199
  requestInstance
197
200
  };
198
- await executeHooksInTryBlock(options.onRequestStream?.(requestStreamContext));
201
+ await executeHooks(options.onRequestStream?.(requestStreamContext));
199
202
  for await (const chunk of body) {
200
203
  transferredBytes += chunk.byteLength;
201
204
  totalBytes = Math.max(totalBytes, transferredBytes);
202
- await executeHooksInTryBlock(options.onRequestStream?.({
205
+ await executeHooks(options.onRequestStream?.({
203
206
  ...requestStreamContext,
204
207
  event: createProgressEvent({
205
208
  chunk,
@@ -239,11 +242,11 @@ const toStreamableResponse = async (context) => {
239
242
  request,
240
243
  response
241
244
  };
242
- await executeHooksInTryBlock(options.onResponseStream?.(responseStreamContext));
245
+ await executeHooks(options.onResponseStream?.(responseStreamContext));
243
246
  for await (const chunk of body) {
244
247
  transferredBytes += chunk.byteLength;
245
248
  totalBytes = Math.max(totalBytes, transferredBytes);
246
- await executeHooksInTryBlock(options.onResponseStream?.({
249
+ await executeHooks(options.onResponseStream?.({
247
250
  ...responseStreamContext,
248
251
  event: createProgressEvent({
249
252
  chunk,
@@ -296,8 +299,7 @@ const createDedupeStrategy = async (context) => {
296
299
  return Promise.resolve();
297
300
  };
298
301
  const handleRequestDeferStrategy = async (deferContext) => {
299
- const { options: localOptions, request: localRequest } = deferContext;
300
- const fetchApi = getFetchImpl(localOptions.customFetchImpl);
302
+ const { fetchApi, options: localOptions, request: localRequest } = deferContext;
301
303
  const shouldUsePromiseFromCache = prevRequestInfo && resolvedDedupeStrategy === "defer";
302
304
  const streamableContext = {
303
305
  baseConfig,
@@ -328,6 +330,25 @@ const createDedupeStrategy = async (context) => {
328
330
  };
329
331
  };
330
332
 
333
+ //#endregion
334
+ //#region src/middlewares.ts
335
+ const getMiddlewareRegistriesAndKeys = () => {
336
+ const middlewareRegistries = { fetchMiddleware: /* @__PURE__ */ new Set() };
337
+ return {
338
+ middlewareRegistries,
339
+ middlewareRegistryKeys: Object.keys(middlewareRegistries)
340
+ };
341
+ };
342
+ const composeAllMiddlewares = (middlewareArray) => {
343
+ let composedMiddleware;
344
+ for (const currentMiddleware of middlewareArray) {
345
+ if (!currentMiddleware) continue;
346
+ const previousMiddleware = composedMiddleware;
347
+ composedMiddleware = previousMiddleware ? (fetchImpl) => currentMiddleware(previousMiddleware(fetchImpl)) : currentMiddleware;
348
+ }
349
+ return composedMiddleware;
350
+ };
351
+
331
352
  //#endregion
332
353
  //#region src/plugins.ts
333
354
  const getResolvedPlugins = (context) => {
@@ -336,27 +357,11 @@ const getResolvedPlugins = (context) => {
336
357
  };
337
358
  const initializePlugins = async (context) => {
338
359
  const { baseConfig, config, initURL, options, request } = context;
339
- const hookRegistries = getHookRegistries();
340
- const hookRegistryKeyArray = Object.keys(hookRegistries);
341
- const addMainHooks = () => {
342
- for (const key of hookRegistryKeyArray) {
343
- const overriddenHook = options[key];
344
- const baseHook = baseConfig[key];
345
- const instanceHook = config[key];
346
- const mainHook = isArray(baseHook) && Boolean(instanceHook) ? [baseHook, instanceHook].flat() : overriddenHook;
347
- if (!mainHook) continue;
348
- hookRegistries[key].add(mainHook);
349
- }
350
- };
351
- const addPluginHooks = (pluginHooks) => {
352
- for (const key of hookRegistryKeyArray) {
353
- const pluginHook = pluginHooks[key];
354
- if (!pluginHook) continue;
355
- hookRegistries[key].add(pluginHook);
356
- }
357
- };
358
- const hookRegistrationOrder = options.hooksRegistrationOrder ?? extraOptionDefaults().hooksRegistrationOrder;
359
- if (hookRegistrationOrder === "mainFirst") addMainHooks();
360
+ const { addMainHooks, addMainMiddlewares, addPluginHooks, addPluginMiddlewares, getResolvedHooks, getResolvedMiddlewares } = setupHooksAndMiddlewares({
361
+ baseConfig,
362
+ config,
363
+ options
364
+ });
360
365
  const { currentRouteSchemaKey, mainInitURL } = getCurrentRouteSchemaKeyAndMainInitURL({
361
366
  baseExtraOptions: baseConfig,
362
367
  extraOptions: config,
@@ -366,15 +371,9 @@ const initializePlugins = async (context) => {
366
371
  let resolvedInitURL = mainInitURL;
367
372
  let resolvedOptions = options;
368
373
  let resolvedRequestOptions = request;
369
- const executePluginSetupFn = async (pluginSetupFn) => {
370
- if (!pluginSetupFn) return;
371
- const initResult = await pluginSetupFn({
372
- baseConfig,
373
- config,
374
- initURL,
375
- options,
376
- request
377
- });
374
+ const executePluginSetupFn = async (pluginSetup) => {
375
+ if (!pluginSetup) return;
376
+ const initResult = await pluginSetup(context);
378
377
  if (!isPlainObject(initResult)) return;
379
378
  const urlString = initResult.initURL?.toString();
380
379
  if (isString(urlString)) {
@@ -386,35 +385,104 @@ const initializePlugins = async (context) => {
386
385
  resolvedCurrentRouteSchemaKey = newResult.currentRouteSchemaKey;
387
386
  resolvedInitURL = newResult.mainInitURL;
388
387
  }
389
- if (isPlainObject(initResult.request)) resolvedRequestOptions = initResult.request;
390
- if (isPlainObject(initResult.options)) resolvedOptions = initResult.options;
388
+ if (isPlainObject(initResult.request)) resolvedRequestOptions = {
389
+ ...resolvedRequestOptions,
390
+ ...initResult.request
391
+ };
392
+ if (isPlainObject(initResult.options)) resolvedOptions = {
393
+ ...resolvedOptions,
394
+ ...initResult.options
395
+ };
391
396
  };
392
397
  const resolvedPlugins = getResolvedPlugins({
393
398
  baseConfig,
394
399
  options
395
400
  });
396
401
  for (const plugin of resolvedPlugins) {
397
- await executePluginSetupFn(plugin.setup);
398
- if (!plugin.hooks) continue;
399
- addPluginHooks(plugin.hooks);
400
- }
401
- if (hookRegistrationOrder === "pluginsFirst") addMainHooks();
402
- const resolvedHooks = {};
403
- for (const [key, hookRegistry] of Object.entries(hookRegistries)) {
404
- if (hookRegistry.size === 0) continue;
405
- const flattenedHookArray = [...hookRegistry].flat();
406
- if (flattenedHookArray.length === 0) continue;
407
- const hooksExecutionMode = options.hooksExecutionMode ?? extraOptionDefaults().hooksExecutionMode;
408
- resolvedHooks[key] = composeAllHooks(flattenedHookArray, hooksExecutionMode);
402
+ const [, pluginHooks, pluginMiddlewares] = await Promise.all([
403
+ executePluginSetupFn(plugin.setup),
404
+ isFunction(plugin.hooks) ? plugin.hooks(context) : plugin.hooks,
405
+ isFunction(plugin.middlewares) ? plugin.middlewares(context) : plugin.middlewares
406
+ ]);
407
+ pluginHooks && addPluginHooks(pluginHooks);
408
+ pluginMiddlewares && addPluginMiddlewares(pluginMiddlewares);
409
409
  }
410
+ addMainHooks();
411
+ addMainMiddlewares();
412
+ const resolvedHooks = getResolvedHooks();
413
+ const resolvedMiddlewares = getResolvedMiddlewares();
410
414
  return {
411
415
  resolvedCurrentRouteSchemaKey,
412
416
  resolvedHooks,
413
417
  resolvedInitURL,
418
+ resolvedMiddlewares,
414
419
  resolvedOptions,
415
420
  resolvedRequestOptions
416
421
  };
417
422
  };
423
+ const setupHooksAndMiddlewares = (context) => {
424
+ const { baseConfig, config, options } = context;
425
+ const { hookRegistries, hookRegistryKeys } = getHookRegistriesAndKeys();
426
+ const { middlewareRegistries, middlewareRegistryKeys } = getMiddlewareRegistriesAndKeys();
427
+ const addMainHooks = () => {
428
+ for (const hookName of hookRegistryKeys) {
429
+ const overriddenHook = options[hookName];
430
+ const baseHook = baseConfig[hookName];
431
+ const instanceHook = config[hookName];
432
+ const mainHook = isArray(baseHook) && instanceHook ? [baseHook, instanceHook].flat() : overriddenHook;
433
+ mainHook && hookRegistries[hookName].add(mainHook);
434
+ }
435
+ };
436
+ const addPluginHooks = (pluginHooks) => {
437
+ for (const hookName of hookRegistryKeys) {
438
+ const pluginHook = pluginHooks[hookName];
439
+ pluginHook && hookRegistries[hookName].add(pluginHook);
440
+ }
441
+ };
442
+ const addMainMiddlewares = () => {
443
+ for (const middlewareName of middlewareRegistryKeys) {
444
+ const baseMiddleware = baseConfig[middlewareName];
445
+ const instanceMiddleware = config[middlewareName];
446
+ baseMiddleware && middlewareRegistries[middlewareName].add(baseMiddleware);
447
+ instanceMiddleware && middlewareRegistries[middlewareName].add(instanceMiddleware);
448
+ }
449
+ };
450
+ const addPluginMiddlewares = (pluginMiddlewares) => {
451
+ for (const middlewareName of middlewareRegistryKeys) {
452
+ const pluginMiddleware = pluginMiddlewares[middlewareName];
453
+ if (!pluginMiddleware) continue;
454
+ middlewareRegistries[middlewareName].add(pluginMiddleware);
455
+ }
456
+ };
457
+ const getResolvedHooks = () => {
458
+ const resolvedHooks = {};
459
+ for (const [hookName, hookRegistry] of Object.entries(hookRegistries)) {
460
+ if (hookRegistry.size === 0) continue;
461
+ const flattenedHookArray = [...hookRegistry].flat();
462
+ if (flattenedHookArray.length === 0) continue;
463
+ resolvedHooks[hookName] = composeAllHooks(flattenedHookArray, options.hooksExecutionMode ?? extraOptionDefaults().hooksExecutionMode);
464
+ }
465
+ return resolvedHooks;
466
+ };
467
+ const getResolvedMiddlewares = () => {
468
+ const resolvedMiddlewares = {};
469
+ for (const [middlewareName, middlewareRegistry] of Object.entries(middlewareRegistries)) {
470
+ if (middlewareRegistry.size === 0) continue;
471
+ const middlewareArray = [...middlewareRegistry];
472
+ if (middlewareArray.length === 0) continue;
473
+ resolvedMiddlewares[middlewareName] = composeAllMiddlewares(middlewareArray);
474
+ }
475
+ return resolvedMiddlewares;
476
+ };
477
+ return {
478
+ addMainHooks,
479
+ addMainMiddlewares,
480
+ addPluginHooks,
481
+ addPluginMiddlewares,
482
+ getResolvedHooks,
483
+ getResolvedMiddlewares
484
+ };
485
+ };
418
486
 
419
487
  //#endregion
420
488
  //#region src/retry.ts
@@ -485,7 +553,7 @@ const createFetchClient = (initBaseConfig = {}) => {
485
553
  ...baseFetchOptions,
486
554
  ...!shouldSkipAutoMergeForRequest && fetchOptions
487
555
  };
488
- const { resolvedCurrentRouteSchemaKey, resolvedHooks, resolvedInitURL, resolvedOptions, resolvedRequestOptions } = await initializePlugins({
556
+ const { resolvedCurrentRouteSchemaKey, resolvedHooks, resolvedInitURL, resolvedMiddlewares, resolvedOptions, resolvedRequestOptions } = await initializePlugins({
489
557
  baseConfig,
490
558
  config,
491
559
  initURL: initURLOrURLObject.toString(),
@@ -501,6 +569,7 @@ const createFetchClient = (initBaseConfig = {}) => {
501
569
  let options = {
502
570
  ...resolvedOptions,
503
571
  ...resolvedHooks,
572
+ ...resolvedMiddlewares,
504
573
  fullURL,
505
574
  initURL: resolvedInitURL,
506
575
  initURLNormalized: normalizedInitURL
@@ -528,7 +597,7 @@ const createFetchClient = (initBaseConfig = {}) => {
528
597
  });
529
598
  try {
530
599
  await handleRequestCancelStrategy();
531
- await executeHooksInTryBlock(options.onRequest?.({
600
+ await executeHooks(options.onRequest?.({
532
601
  baseConfig,
533
602
  config,
534
603
  options,
@@ -565,21 +634,21 @@ const createFetchClient = (initBaseConfig = {}) => {
565
634
  ...Boolean(validHeaders) && { headers: validHeaders },
566
635
  ...Boolean(validMethod) && { method: validMethod }
567
636
  };
568
- await executeHooksInTryBlock(options.onRequestReady?.({
637
+ await executeHooks(options.onRequestReady?.({
569
638
  baseConfig,
570
639
  config,
571
640
  options,
572
641
  request
573
642
  }));
574
643
  const response = await handleRequestDeferStrategy({
644
+ fetchApi: getFetchImpl(options.customFetchImpl, options.fetchMiddleware),
575
645
  options,
576
646
  request
577
647
  });
578
648
  const shouldCloneResponse = resolvedDedupeStrategy === "defer" || options.cloneResponse;
579
649
  if (!response.ok) {
580
- const errorData = await resolveResponseData(shouldCloneResponse ? response.clone() : response, options.responseType, options.responseParser);
581
650
  const validErrorData = await handleSchemaValidation(resolvedSchema, "errorData", {
582
- inputValue: errorData,
651
+ inputValue: await resolveResponseData(shouldCloneResponse ? response.clone() : response, options.responseType, options.responseParser),
583
652
  response,
584
653
  schemaConfig: resolvedSchemaConfig
585
654
  });
@@ -589,21 +658,19 @@ const createFetchClient = (initBaseConfig = {}) => {
589
658
  response
590
659
  }, { cause: validErrorData });
591
660
  }
592
- const successData = await resolveResponseData(shouldCloneResponse ? response.clone() : response, options.responseType, options.responseParser);
593
- const validSuccessData = await handleSchemaValidation(resolvedSchema, "data", {
594
- inputValue: successData,
595
- response,
596
- schemaConfig: resolvedSchemaConfig
597
- });
598
661
  const successContext = {
599
662
  baseConfig,
600
663
  config,
601
- data: validSuccessData,
664
+ data: await handleSchemaValidation(resolvedSchema, "data", {
665
+ inputValue: await resolveResponseData(shouldCloneResponse ? response.clone() : response, options.responseType, options.responseParser),
666
+ response,
667
+ schemaConfig: resolvedSchemaConfig
668
+ }),
602
669
  options,
603
670
  request,
604
671
  response
605
672
  };
606
- await executeHooksInTryBlock(options.onSuccess?.(successContext), options.onResponse?.({
673
+ await executeHooks(options.onSuccess?.(successContext), options.onResponse?.({
607
674
  ...successContext,
608
675
  error: null
609
676
  }));
@@ -639,13 +706,11 @@ const createFetchClient = (initBaseConfig = {}) => {
639
706
  };
640
707
  const hookError = await executeHooksInCatchBlock([options.onRetry?.(retryContext)], hookInfo);
641
708
  if (hookError) return hookError;
642
- const delay = getDelay();
643
- await waitFor(delay);
644
- const updatedOptions = {
709
+ await waitFor(getDelay());
710
+ return callApi$1(initURLOrURLObject, {
645
711
  ...config,
646
712
  "~retryAttemptCount": currentAttemptCount + 1
647
- };
648
- return callApi$1(initURLOrURLObject, updatedOptions);
713
+ });
649
714
  }
650
715
  if (shouldThrowOnError) throw error;
651
716
  return generalErrorResult;