@zayne-labs/callapi 1.7.8 → 1.7.12
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/{chunk-DLKKYMSL.js → chunk-SJZKYDA4.js} +89 -53
- package/dist/esm/chunk-SJZKYDA4.js.map +1 -0
- package/dist/esm/{common-8-vDWsfT.d.ts → common-CUR8HxVd.d.ts} +120 -136
- package/dist/esm/index.d.ts +2 -2
- package/dist/esm/index.js +84 -102
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/utils/index.d.ts +1 -1
- package/dist/esm/utils/index.js +1 -1
- package/package.json +1 -1
- package/dist/esm/chunk-DLKKYMSL.js.map +0 -1
package/dist/esm/index.js
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
import { splitConfig, isFunction, splitBaseConfig, createTimeoutSignal, createCombinedSignal, commonDefaults,
|
2
|
-
export { HTTPError } from './chunk-
|
1
|
+
import { splitConfig, isFunction, splitBaseConfig, createTimeoutSignal, createCombinedSignal, commonDefaults, getHeaders, isSerializable, resolveResponseData, HTTPError, resolveSuccessResult, resolveErrorResult, isHTTPErrorInstance, getCustomizedErrorResult, waitUntil, hookDefaults, dedupeDefaults, retryDefaults, isArray, isPlainObject, isString, toQueryString, getFetchImpl, isReadableStream, isHTTPError, requestOptionDefaults, isObject } from './chunk-SJZKYDA4.js';
|
2
|
+
export { HTTPError } from './chunk-SJZKYDA4.js';
|
3
3
|
|
4
4
|
// src/hooks.ts
|
5
5
|
var hookRegistries = {
|
@@ -29,7 +29,25 @@ var composeTwoHooks = (hooks, mergedHooksExecutionMode) => {
|
|
29
29
|
};
|
30
30
|
return mergedHook;
|
31
31
|
};
|
32
|
-
var
|
32
|
+
var executeHooksInTryBlock = async (...hookResults) => {
|
33
|
+
await Promise.all(hookResults);
|
34
|
+
};
|
35
|
+
var createExecuteHooksFn = (info) => {
|
36
|
+
const { errorInfo, shouldThrowOnError } = info;
|
37
|
+
const executeHooksInCatchBlock = async (...hookResults) => {
|
38
|
+
try {
|
39
|
+
await Promise.all(hookResults);
|
40
|
+
return null;
|
41
|
+
} catch (hookError) {
|
42
|
+
const hookErrorResult = resolveErrorResult(hookError, errorInfo);
|
43
|
+
if (shouldThrowOnError) {
|
44
|
+
throw hookError;
|
45
|
+
}
|
46
|
+
return hookErrorResult;
|
47
|
+
}
|
48
|
+
};
|
49
|
+
return executeHooksInCatchBlock;
|
50
|
+
};
|
33
51
|
|
34
52
|
// src/stream.ts
|
35
53
|
var createProgressEvent = (options) => {
|
@@ -61,7 +79,7 @@ var toStreamableRequest = async (context) => {
|
|
61
79
|
totalBytes = await calculateTotalBytesFromBody(requestInstance.clone().body, totalBytes);
|
62
80
|
}
|
63
81
|
let transferredBytes = 0;
|
64
|
-
await
|
82
|
+
await executeHooksInTryBlock(
|
65
83
|
options.onRequestStream({
|
66
84
|
baseConfig,
|
67
85
|
config,
|
@@ -78,7 +96,7 @@ var toStreamableRequest = async (context) => {
|
|
78
96
|
for await (const chunk of body) {
|
79
97
|
transferredBytes += chunk.byteLength;
|
80
98
|
totalBytes = Math.max(totalBytes, transferredBytes);
|
81
|
-
await
|
99
|
+
await executeHooksInTryBlock(
|
82
100
|
options.onRequestStream?.({
|
83
101
|
baseConfig,
|
84
102
|
config,
|
@@ -106,7 +124,7 @@ var toStreamableResponse = async (context) => {
|
|
106
124
|
totalBytes = await calculateTotalBytesFromBody(response.clone().body, totalBytes);
|
107
125
|
}
|
108
126
|
let transferredBytes = 0;
|
109
|
-
await
|
127
|
+
await executeHooksInTryBlock(
|
110
128
|
options.onResponseStream({
|
111
129
|
baseConfig,
|
112
130
|
config,
|
@@ -123,7 +141,7 @@ var toStreamableResponse = async (context) => {
|
|
123
141
|
for await (const chunk of body) {
|
124
142
|
transferredBytes += chunk.byteLength;
|
125
143
|
totalBytes = Math.max(totalBytes, transferredBytes);
|
126
|
-
await
|
144
|
+
await executeHooksInTryBlock(
|
127
145
|
options.onResponseStream?.({
|
128
146
|
baseConfig,
|
129
147
|
config,
|
@@ -284,7 +302,7 @@ var initializePlugins = async (context) => {
|
|
284
302
|
const flattenedHookArray = [...hookRegistry].flat();
|
285
303
|
const mergedHooksExecutionMode = options.mergedHooksExecutionMode ?? hookDefaults.mergedHooksExecutionMode;
|
286
304
|
const composedHook = composeTwoHooks(flattenedHookArray, mergedHooksExecutionMode);
|
287
|
-
resolvedHooks[key] = composedHook;
|
305
|
+
composedHook && (resolvedHooks[key] = composedHook);
|
288
306
|
}
|
289
307
|
return {
|
290
308
|
resolvedHooks,
|
@@ -294,46 +312,6 @@ var initializePlugins = async (context) => {
|
|
294
312
|
};
|
295
313
|
};
|
296
314
|
|
297
|
-
// src/response.ts
|
298
|
-
var getResponseType = (response, parser) => ({
|
299
|
-
arrayBuffer: () => response.arrayBuffer(),
|
300
|
-
blob: () => response.blob(),
|
301
|
-
formData: () => response.formData(),
|
302
|
-
json: async () => {
|
303
|
-
const text = await response.text();
|
304
|
-
return parser(text);
|
305
|
-
},
|
306
|
-
stream: () => response.body,
|
307
|
-
text: () => response.text()
|
308
|
-
});
|
309
|
-
var resolveResponseData = (response, responseType, parser) => {
|
310
|
-
const selectedParser = parser ?? responseDefaults.responseParser;
|
311
|
-
const selectedResponseType = responseType ?? responseDefaults.responseType;
|
312
|
-
const RESPONSE_TYPE_LOOKUP = getResponseType(response, selectedParser);
|
313
|
-
if (!Object.hasOwn(RESPONSE_TYPE_LOOKUP, selectedResponseType)) {
|
314
|
-
throw new Error(`Invalid response type: ${responseType}`);
|
315
|
-
}
|
316
|
-
return RESPONSE_TYPE_LOOKUP[selectedResponseType]();
|
317
|
-
};
|
318
|
-
var resolveSuccessResult = (info) => {
|
319
|
-
const { data, response, resultMode } = info;
|
320
|
-
const apiDetails = { data, error: null, response };
|
321
|
-
if (!resultMode) {
|
322
|
-
return apiDetails;
|
323
|
-
}
|
324
|
-
const resultModeMap = {
|
325
|
-
all: apiDetails,
|
326
|
-
allWithException: apiDetails,
|
327
|
-
allWithoutResponse: omitKeys(apiDetails, ["response"]),
|
328
|
-
onlyError: apiDetails.error,
|
329
|
-
onlyResponse: apiDetails.response,
|
330
|
-
onlyResponseWithException: apiDetails.response,
|
331
|
-
onlySuccess: apiDetails.data,
|
332
|
-
onlySuccessWithException: apiDetails.data
|
333
|
-
};
|
334
|
-
return resultModeMap[resultMode];
|
335
|
-
};
|
336
|
-
|
337
315
|
// src/retry.ts
|
338
316
|
var getLinearDelay = (currentAttemptCount, options) => {
|
339
317
|
const retryDelay = options.retryDelay ?? options.retry?.delay;
|
@@ -342,14 +320,16 @@ var getLinearDelay = (currentAttemptCount, options) => {
|
|
342
320
|
};
|
343
321
|
var getExponentialDelay = (currentAttemptCount, options) => {
|
344
322
|
const retryDelay = options.retryDelay ?? options.retry?.delay ?? retryDefaults.delay;
|
345
|
-
const
|
323
|
+
const resolvedRetryDelay = Number(
|
324
|
+
isFunction(retryDelay) ? retryDelay(currentAttemptCount) : retryDelay
|
325
|
+
);
|
346
326
|
const maxDelay = Number(options.retryMaxDelay ?? options.retry?.maxDelay ?? retryDefaults.maxDelay);
|
347
|
-
const exponentialDelay =
|
327
|
+
const exponentialDelay = resolvedRetryDelay * 2 ** currentAttemptCount;
|
348
328
|
return Math.min(exponentialDelay, maxDelay);
|
349
329
|
};
|
350
330
|
var createRetryStrategy = (ctx) => {
|
351
331
|
const { options } = ctx;
|
352
|
-
const currentAttemptCount = options["~retryAttemptCount"] ??
|
332
|
+
const currentAttemptCount = options["~retryAttemptCount"] ?? 1;
|
353
333
|
const retryStrategy = options.retryStrategy ?? options.retry?.strategy ?? retryDefaults.strategy;
|
354
334
|
const getDelay = () => {
|
355
335
|
switch (retryStrategy) {
|
@@ -360,46 +340,33 @@ var createRetryStrategy = (ctx) => {
|
|
360
340
|
return getLinearDelay(currentAttemptCount, options);
|
361
341
|
}
|
362
342
|
default: {
|
363
|
-
throw new Error(`Invalid retry strategy: ${retryStrategy}`);
|
343
|
+
throw new Error(`Invalid retry strategy: ${String(retryStrategy)}`);
|
364
344
|
}
|
365
345
|
}
|
366
346
|
};
|
367
347
|
const shouldAttemptRetry = async () => {
|
368
348
|
const retryCondition = options.retryCondition ?? options.retry?.condition ?? retryDefaults.condition;
|
369
|
-
const
|
349
|
+
const maximumRetryAttempts = options.retryAttempts ?? options.retry?.attempts ?? retryDefaults.attempts;
|
370
350
|
const customRetryCondition = await retryCondition(ctx);
|
371
|
-
const baseShouldRetry =
|
372
|
-
if (
|
373
|
-
return
|
351
|
+
const baseShouldRetry = maximumRetryAttempts >= currentAttemptCount && customRetryCondition;
|
352
|
+
if (!baseShouldRetry) {
|
353
|
+
return false;
|
374
354
|
}
|
375
|
-
|
376
|
-
|
377
|
-
|
355
|
+
if (!isHTTPError(ctx.error)) {
|
356
|
+
return true;
|
357
|
+
}
|
358
|
+
const selectedMethodArray = options.retryMethods ?? options.retry?.methods ?? retryDefaults.methods;
|
359
|
+
const retryMethods = new Set(selectedMethodArray);
|
360
|
+
const method = ctx.request.method ?? requestOptionDefaults.method;
|
361
|
+
const includesMethod = Boolean(method) && retryMethods.has(method);
|
378
362
|
const selectedStatusCodeArray = options.retryStatusCodes ?? options.retry?.statusCodes;
|
379
363
|
const retryStatusCodes = selectedStatusCodeArray ? new Set(selectedStatusCodeArray) : null;
|
380
|
-
const includesMethod = Boolean(ctx.request.method) && retryMethods.has(ctx.request.method);
|
381
364
|
const includesStatusCodes = Boolean(ctx.response?.status) && (retryStatusCodes?.has(ctx.response.status) ?? true);
|
382
|
-
const shouldRetry =
|
365
|
+
const shouldRetry = includesMethod && includesStatusCodes;
|
383
366
|
return shouldRetry;
|
384
367
|
};
|
385
|
-
const executeRetryHook = async (shouldThrowOnError) => {
|
386
|
-
try {
|
387
|
-
return await executeHooks(options.onRetry?.(ctx));
|
388
|
-
} catch (error) {
|
389
|
-
const { apiDetails } = resolveErrorResult({
|
390
|
-
cloneResponse: options.cloneResponse,
|
391
|
-
defaultErrorMessage: options.defaultErrorMessage,
|
392
|
-
error,
|
393
|
-
resultMode: options.resultMode
|
394
|
-
});
|
395
|
-
if (shouldThrowOnError) {
|
396
|
-
throw error;
|
397
|
-
}
|
398
|
-
return apiDetails;
|
399
|
-
}
|
400
|
-
};
|
401
368
|
return {
|
402
|
-
|
369
|
+
currentAttemptCount,
|
403
370
|
getDelay,
|
404
371
|
shouldAttemptRetry
|
405
372
|
};
|
@@ -507,7 +474,7 @@ var createFetchClient = (initBaseConfig = {}) => {
|
|
507
474
|
const request = {
|
508
475
|
...resolvedRequestOptions,
|
509
476
|
body: isSerializable(resolvedRequestOptions.body) ? bodySerializer(resolvedRequestOptions.body) : resolvedRequestOptions.body,
|
510
|
-
headers:
|
477
|
+
headers: await getHeaders({
|
511
478
|
auth: options.auth,
|
512
479
|
baseHeaders: baseFetchOptions.headers,
|
513
480
|
body: resolvedRequestOptions.body,
|
@@ -530,16 +497,16 @@ var createFetchClient = (initBaseConfig = {}) => {
|
|
530
497
|
});
|
531
498
|
await handleRequestCancelStrategy();
|
532
499
|
try {
|
533
|
-
await
|
534
|
-
request.headers =
|
500
|
+
await executeHooksInTryBlock(options.onRequest?.({ baseConfig, config, options, request }));
|
501
|
+
request.headers = await getHeaders({
|
535
502
|
auth: options.auth,
|
536
503
|
body: request.body,
|
537
504
|
headers: request.headers
|
538
505
|
});
|
539
506
|
const response = await handleRequestDeferStrategy();
|
540
507
|
const shouldCloneResponse = dedupeStrategy === "defer" || options.cloneResponse;
|
541
|
-
const schemas = isFunction(options.schemas) ? options.schemas({ baseSchemas: baseExtraOptions.schemas
|
542
|
-
const validators = isFunction(options.validators) ? options.validators({ baseValidators: baseExtraOptions.validators
|
508
|
+
const schemas = isFunction(options.schemas) ? options.schemas({ baseSchemas: baseExtraOptions.schemas }) : options.schemas;
|
509
|
+
const validators = isFunction(options.validators) ? options.validators({ baseValidators: baseExtraOptions.validators }) : options.validators;
|
543
510
|
if (!response.ok) {
|
544
511
|
const errorData = await resolveResponseData(
|
545
512
|
shouldCloneResponse ? response.clone() : response,
|
@@ -571,74 +538,89 @@ var createFetchClient = (initBaseConfig = {}) => {
|
|
571
538
|
request,
|
572
539
|
response
|
573
540
|
};
|
574
|
-
await
|
541
|
+
await executeHooksInTryBlock(
|
575
542
|
options.onSuccess?.(successContext),
|
576
543
|
options.onResponse?.({ ...successContext, error: null })
|
577
544
|
);
|
578
|
-
|
579
|
-
data: successContext.data,
|
545
|
+
const successResult = await resolveSuccessResult(successContext.data, {
|
580
546
|
response: successContext.response,
|
581
547
|
resultMode: options.resultMode
|
582
548
|
});
|
549
|
+
return successResult;
|
583
550
|
} catch (error) {
|
584
|
-
const
|
551
|
+
const errorInfo = {
|
585
552
|
cloneResponse: options.cloneResponse,
|
586
553
|
defaultErrorMessage: options.defaultErrorMessage,
|
587
|
-
error,
|
588
554
|
resultMode: options.resultMode
|
589
|
-
}
|
555
|
+
};
|
556
|
+
const generalErrorResult = resolveErrorResult(error, errorInfo);
|
590
557
|
const errorContext = {
|
591
558
|
baseConfig,
|
592
559
|
config,
|
593
|
-
error:
|
560
|
+
error: generalErrorResult?.error,
|
594
561
|
options,
|
595
562
|
request,
|
596
|
-
response:
|
563
|
+
response: generalErrorResult?.response
|
597
564
|
};
|
598
565
|
const shouldThrowOnError = isFunction(options.throwOnError) ? options.throwOnError(errorContext) : options.throwOnError;
|
599
|
-
const
|
600
|
-
|
566
|
+
const executeHooksInCatchBlock = createExecuteHooksFn({ errorInfo, shouldThrowOnError });
|
567
|
+
const handleRetryOrGetErrorResult = async () => {
|
568
|
+
const { currentAttemptCount, getDelay, shouldAttemptRetry } = createRetryStrategy(errorContext);
|
601
569
|
const shouldRetry = !combinedSignal.aborted && await shouldAttemptRetry();
|
602
570
|
if (shouldRetry) {
|
603
|
-
|
571
|
+
const retryContext = {
|
572
|
+
...errorContext,
|
573
|
+
retryAttemptCount: currentAttemptCount
|
574
|
+
};
|
575
|
+
const hookError2 = await executeHooksInCatchBlock(options.onRetry?.(retryContext));
|
576
|
+
if (hookError2) {
|
577
|
+
return hookError2;
|
578
|
+
}
|
604
579
|
const delay = getDelay();
|
605
580
|
await waitUntil(delay);
|
606
581
|
const updatedOptions = {
|
607
582
|
...config,
|
608
|
-
"~retryAttemptCount":
|
583
|
+
"~retryAttemptCount": currentAttemptCount + 1
|
609
584
|
};
|
610
585
|
return callApi2(initURL, updatedOptions);
|
611
586
|
}
|
612
587
|
if (shouldThrowOnError) {
|
613
588
|
throw error;
|
614
589
|
}
|
615
|
-
return
|
590
|
+
return generalErrorResult;
|
616
591
|
};
|
617
592
|
if (isHTTPErrorInstance(error)) {
|
618
|
-
await
|
593
|
+
const hookError2 = await executeHooksInCatchBlock(
|
619
594
|
options.onResponseError?.(errorContext),
|
620
595
|
options.onError?.(errorContext),
|
621
596
|
options.onResponse?.({ ...errorContext, data: null })
|
622
597
|
);
|
623
|
-
|
598
|
+
if (hookError2) {
|
599
|
+
return hookError2;
|
600
|
+
}
|
601
|
+
return await handleRetryOrGetErrorResult();
|
624
602
|
}
|
625
603
|
if (error instanceof DOMException && error.name === "AbortError") {
|
626
604
|
const { message, name } = error;
|
627
605
|
!shouldThrowOnError && console.error(`${name}:`, message);
|
628
|
-
return await
|
606
|
+
return await handleRetryOrGetErrorResult();
|
629
607
|
}
|
630
608
|
if (error instanceof DOMException && error.name === "TimeoutError") {
|
631
609
|
const message = `Request timed out after ${options.timeout}ms`;
|
632
610
|
!shouldThrowOnError && console.error(`${error.name}:`, message);
|
633
|
-
|
611
|
+
const errorResult = await handleRetryOrGetErrorResult();
|
612
|
+
return getCustomizedErrorResult(errorResult, { message });
|
634
613
|
}
|
635
|
-
await
|
614
|
+
const hookError = await executeHooksInCatchBlock(
|
636
615
|
// == At this point only the request errors exist, so the request error hook is called
|
637
616
|
options.onRequestError?.(errorContext),
|
638
617
|
// == Also call the onError hook
|
639
618
|
options.onError?.(errorContext)
|
640
619
|
);
|
641
|
-
|
620
|
+
if (hookError) {
|
621
|
+
return hookError;
|
622
|
+
}
|
623
|
+
return await handleRetryOrGetErrorResult();
|
642
624
|
} finally {
|
643
625
|
removeDedupeKeyFromCache();
|
644
626
|
}
|