@zayne-labs/callapi 1.10.5 → 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,12 +106,12 @@ const getCustomizedErrorResult = (errorResult, customErrorInfo) => {
107
106
 
108
107
  //#endregion
109
108
  //#region src/hooks.ts
110
- const getHookRegistries = () => {
111
- return {
112
- onBeforeRequest: /* @__PURE__ */ new Set(),
109
+ const getHookRegistriesAndKeys = () => {
110
+ const hookRegistries = {
113
111
  onError: /* @__PURE__ */ new Set(),
114
112
  onRequest: /* @__PURE__ */ new Set(),
115
113
  onRequestError: /* @__PURE__ */ new Set(),
114
+ onRequestReady: /* @__PURE__ */ new Set(),
116
115
  onRequestStream: /* @__PURE__ */ new Set(),
117
116
  onResponse: /* @__PURE__ */ new Set(),
118
117
  onResponseError: /* @__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
@@ -508,8 +577,13 @@ const createFetchClient = (initBaseConfig = {}) => {
508
577
  const newFetchController = new AbortController();
509
578
  const timeoutSignal = options.timeout != null ? createTimeoutSignal(options.timeout) : null;
510
579
  const combinedSignal = createCombinedSignal(resolvedRequestOptions.signal, timeoutSignal, newFetchController.signal);
580
+ const initMethod = getMethod({
581
+ initURL: resolvedInitURL,
582
+ method: resolvedRequestOptions.method
583
+ });
511
584
  let request = {
512
585
  ...resolvedRequestOptions,
586
+ method: initMethod,
513
587
  signal: combinedSignal
514
588
  };
515
589
  const { getAbortErrorMessage, handleRequestCancelStrategy, handleRequestDeferStrategy, removeDedupeKeyFromCache, resolvedDedupeStrategy } = await createDedupeStrategy({
@@ -523,7 +597,7 @@ const createFetchClient = (initBaseConfig = {}) => {
523
597
  });
524
598
  try {
525
599
  await handleRequestCancelStrategy();
526
- await executeHooksInTryBlock(options.onBeforeRequest?.({
600
+ await executeHooks(options.onRequest?.({
527
601
  baseConfig,
528
602
  config,
529
603
  options,
@@ -540,43 +614,41 @@ const createFetchClient = (initBaseConfig = {}) => {
540
614
  ...options,
541
615
  ...extraOptionsValidationResult
542
616
  };
543
- const rawBody = shouldApplySchemaOutput ? requestOptionsValidationResult?.body : request.body;
617
+ const validMethod = getMethod({
618
+ initURL: resolvedInitURL,
619
+ method: shouldApplySchemaOutput ? requestOptionsValidationResult?.method : request.method
620
+ });
544
621
  const validBody = getBody({
545
- body: rawBody,
622
+ body: shouldApplySchemaOutput ? requestOptionsValidationResult?.body : request.body,
546
623
  bodySerializer: options.bodySerializer
547
624
  });
548
625
  const resolvedHeaders = isFunction(fetchOptions.headers) ? fetchOptions.headers({ baseHeaders: baseFetchOptions.headers ?? {} }) : fetchOptions.headers ?? baseFetchOptions.headers;
549
626
  const validHeaders = await getHeaders({
550
627
  auth: options.auth,
551
- body: rawBody,
628
+ body: validBody,
552
629
  headers: shouldApplySchemaOutput ? requestOptionsValidationResult?.headers : resolvedHeaders
553
630
  });
554
- const validMethod = getMethod({
555
- initURL: resolvedInitURL,
556
- method: shouldApplySchemaOutput ? requestOptionsValidationResult?.method : request.method,
557
- schemaConfig: resolvedSchemaConfig
558
- });
559
631
  request = {
560
632
  ...request,
561
633
  ...Boolean(validBody) && { body: validBody },
562
634
  ...Boolean(validHeaders) && { headers: validHeaders },
563
635
  ...Boolean(validMethod) && { method: validMethod }
564
636
  };
565
- await executeHooksInTryBlock(options.onRequest?.({
637
+ await executeHooks(options.onRequestReady?.({
566
638
  baseConfig,
567
639
  config,
568
640
  options,
569
641
  request
570
642
  }));
571
643
  const response = await handleRequestDeferStrategy({
644
+ fetchApi: getFetchImpl(options.customFetchImpl, options.fetchMiddleware),
572
645
  options,
573
646
  request
574
647
  });
575
648
  const shouldCloneResponse = resolvedDedupeStrategy === "defer" || options.cloneResponse;
576
649
  if (!response.ok) {
577
- const errorData = await resolveResponseData(shouldCloneResponse ? response.clone() : response, options.responseType, options.responseParser);
578
650
  const validErrorData = await handleSchemaValidation(resolvedSchema, "errorData", {
579
- inputValue: errorData,
651
+ inputValue: await resolveResponseData(shouldCloneResponse ? response.clone() : response, options.responseType, options.responseParser),
580
652
  response,
581
653
  schemaConfig: resolvedSchemaConfig
582
654
  });
@@ -586,21 +658,19 @@ const createFetchClient = (initBaseConfig = {}) => {
586
658
  response
587
659
  }, { cause: validErrorData });
588
660
  }
589
- const successData = await resolveResponseData(shouldCloneResponse ? response.clone() : response, options.responseType, options.responseParser);
590
- const validSuccessData = await handleSchemaValidation(resolvedSchema, "data", {
591
- inputValue: successData,
592
- response,
593
- schemaConfig: resolvedSchemaConfig
594
- });
595
661
  const successContext = {
596
662
  baseConfig,
597
663
  config,
598
- 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
+ }),
599
669
  options,
600
670
  request,
601
671
  response
602
672
  };
603
- await executeHooksInTryBlock(options.onSuccess?.(successContext), options.onResponse?.({
673
+ await executeHooks(options.onSuccess?.(successContext), options.onResponse?.({
604
674
  ...successContext,
605
675
  error: null
606
676
  }));
@@ -636,13 +706,11 @@ const createFetchClient = (initBaseConfig = {}) => {
636
706
  };
637
707
  const hookError = await executeHooksInCatchBlock([options.onRetry?.(retryContext)], hookInfo);
638
708
  if (hookError) return hookError;
639
- const delay = getDelay();
640
- await waitFor(delay);
641
- const updatedOptions = {
709
+ await waitFor(getDelay());
710
+ return callApi$1(initURLOrURLObject, {
642
711
  ...config,
643
712
  "~retryAttemptCount": currentAttemptCount + 1
644
- };
645
- return callApi$1(initURLOrURLObject, updatedOptions);
713
+ });
646
714
  }
647
715
  if (shouldThrowOnError) throw error;
648
716
  return generalErrorResult;