@zayne-labs/callapi 1.7.5 → 1.7.6
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-G4FFGADM.js → chunk-UVFIGKZS.js} +44 -44
- package/dist/esm/chunk-UVFIGKZS.js.map +1 -0
- package/dist/{cjs/common-BUhBcx_C.d.cts → esm/common-BwOrtpui.d.ts} +42 -43
- package/dist/esm/index.d.ts +3 -3
- package/dist/esm/index.js +82 -57
- 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 +5 -6
- package/dist/cjs/index.cjs +0 -967
- package/dist/cjs/index.cjs.map +0 -1
- package/dist/cjs/index.d.cts +0 -9
- package/dist/cjs/utils/index.cjs +0 -95
- package/dist/cjs/utils/index.cjs.map +0 -1
- package/dist/cjs/utils/index.d.cts +0 -12
- package/dist/esm/chunk-G4FFGADM.js.map +0 -1
- package/dist/esm/common-BUhBcx_C.d.ts +0 -776
package/dist/esm/index.js
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
import { splitConfig, isFunction, splitBaseConfig,
|
2
|
-
export { HTTPError
|
1
|
+
import { splitConfig, isFunction, splitBaseConfig, createTimeoutSignal, createCombinedSignal, commonDefaults, mergeAndResolveHeaders, isSerializable, HTTPError, resolveErrorResult, isHTTPErrorInstance, waitUntil, hookDefaults, dedupeDefaults, responseDefaults, omitKeys, retryDefaults, isArray, isPlainObject, isString, toQueryString, getFetchImpl, isReadableStream, isObject, requestOptionDefaults } from './chunk-UVFIGKZS.js';
|
2
|
+
export { HTTPError } from './chunk-UVFIGKZS.js';
|
3
3
|
|
4
4
|
// src/hooks.ts
|
5
5
|
var hookRegistries = {
|
@@ -142,23 +142,24 @@ var toStreamableResponse = async (context) => {
|
|
142
142
|
};
|
143
143
|
|
144
144
|
// src/dedupe.ts
|
145
|
-
var generateDedupeKey = (options, request) => {
|
146
|
-
const shouldHaveDedupeKey = options.dedupeStrategy === "cancel" || options.dedupeStrategy === "defer";
|
147
|
-
if (!shouldHaveDedupeKey) {
|
148
|
-
return null;
|
149
|
-
}
|
150
|
-
return `${options.fullURL}-${JSON.stringify({ options, request })}`;
|
151
|
-
};
|
152
145
|
var createDedupeStrategy = async (context) => {
|
153
146
|
const { $RequestInfoCache, baseConfig, config, newFetchController, options, request } = context;
|
154
|
-
const
|
147
|
+
const dedupeStrategy = options.dedupeStrategy ?? dedupeDefaults.dedupeStrategy;
|
148
|
+
const generateDedupeKey = () => {
|
149
|
+
const shouldHaveDedupeKey = dedupeStrategy === "cancel" || dedupeStrategy === "defer";
|
150
|
+
if (!shouldHaveDedupeKey) {
|
151
|
+
return null;
|
152
|
+
}
|
153
|
+
return `${options.fullURL}-${JSON.stringify({ options, request })}`;
|
154
|
+
};
|
155
|
+
const dedupeKey = options.dedupeKey ?? generateDedupeKey();
|
155
156
|
const $RequestInfoCacheOrNull = dedupeKey !== null ? $RequestInfoCache : null;
|
156
157
|
if (dedupeKey !== null) {
|
157
158
|
await waitUntil(0.1);
|
158
159
|
}
|
159
160
|
const prevRequestInfo = $RequestInfoCacheOrNull?.get(dedupeKey);
|
160
161
|
const handleRequestCancelStrategy = () => {
|
161
|
-
const shouldCancelRequest = prevRequestInfo &&
|
162
|
+
const shouldCancelRequest = prevRequestInfo && dedupeStrategy === "cancel";
|
162
163
|
if (!shouldCancelRequest) return;
|
163
164
|
const message = options.dedupeKey ? `Duplicate request detected - Aborting previous request with key '${options.dedupeKey}' as a new request was initiated` : `Duplicate request detected - Aborting previous request to '${options.fullURL}' as a new request with identical options was initiated`;
|
164
165
|
const reason = new DOMException(message, "AbortError");
|
@@ -167,7 +168,7 @@ var createDedupeStrategy = async (context) => {
|
|
167
168
|
};
|
168
169
|
const handleRequestDeferStrategy = async () => {
|
169
170
|
const fetchApi = getFetchImpl(options.customFetchImpl);
|
170
|
-
const shouldUsePromiseFromCache = prevRequestInfo &&
|
171
|
+
const shouldUsePromiseFromCache = prevRequestInfo && dedupeStrategy === "defer";
|
171
172
|
const requestInstance = new Request(
|
172
173
|
options.fullURL,
|
173
174
|
isReadableStream(request.body) && !request.duplex ? { ...request, duplex: "half" } : request
|
@@ -183,7 +184,9 @@ var createDedupeStrategy = async (context) => {
|
|
183
184
|
if (isReadableStream(request.body)) {
|
184
185
|
return fetchApi(requestInstance.clone());
|
185
186
|
}
|
186
|
-
|
187
|
+
const method = request.method ?? requestOptionDefaults.method;
|
188
|
+
const modifiedRequest = { ...request, method };
|
189
|
+
return fetchApi(options.fullURL, modifiedRequest);
|
187
190
|
};
|
188
191
|
const responsePromise = shouldUsePromiseFromCache ? prevRequestInfo.responsePromise : getFetchApiPromise();
|
189
192
|
$RequestInfoCacheOrNull?.set(dedupeKey, { controller: newFetchController, responsePromise });
|
@@ -200,6 +203,7 @@ var createDedupeStrategy = async (context) => {
|
|
200
203
|
$RequestInfoCacheOrNull?.delete(dedupeKey);
|
201
204
|
};
|
202
205
|
return {
|
206
|
+
dedupeStrategy,
|
203
207
|
handleRequestCancelStrategy,
|
204
208
|
handleRequestDeferStrategy,
|
205
209
|
removeDedupeKeyFromCache
|
@@ -224,17 +228,23 @@ var initializePlugins = async (context) => {
|
|
224
228
|
const clonedHookRegistries = structuredClone(hookRegistries);
|
225
229
|
const addMainHooks = () => {
|
226
230
|
for (const key of Object.keys(clonedHookRegistries)) {
|
227
|
-
const
|
231
|
+
const baseHook = baseConfig[key];
|
232
|
+
const instanceHook = config[key];
|
233
|
+
const overriddenHook = options[key];
|
234
|
+
const mainHook = isArray(baseHook) && Boolean(instanceHook) ? [baseHook, instanceHook].flat() : overriddenHook;
|
235
|
+
if (!mainHook) continue;
|
228
236
|
clonedHookRegistries[key].add(mainHook);
|
229
237
|
}
|
230
238
|
};
|
231
239
|
const addPluginHooks = (pluginHooks) => {
|
232
240
|
for (const key of Object.keys(clonedHookRegistries)) {
|
233
241
|
const pluginHook = pluginHooks[key];
|
242
|
+
if (!pluginHook) continue;
|
234
243
|
clonedHookRegistries[key].add(pluginHook);
|
235
244
|
}
|
236
245
|
};
|
237
|
-
|
246
|
+
const mergedHooksExecutionOrder = options.mergedHooksExecutionOrder ?? hookDefaults.mergedHooksExecutionOrder;
|
247
|
+
if (mergedHooksExecutionOrder === "mainHooksBeforePlugins") {
|
238
248
|
addMainHooks();
|
239
249
|
}
|
240
250
|
const resolvedPlugins = resolvePluginArray(options.plugins, baseConfig.plugins);
|
@@ -266,13 +276,14 @@ var initializePlugins = async (context) => {
|
|
266
276
|
if (!plugin.hooks) continue;
|
267
277
|
addPluginHooks(plugin.hooks);
|
268
278
|
}
|
269
|
-
if (
|
279
|
+
if (mergedHooksExecutionOrder === "mainHooksAfterPlugins") {
|
270
280
|
addMainHooks();
|
271
281
|
}
|
272
282
|
const resolvedHooks = {};
|
273
283
|
for (const [key, hookRegistry] of Object.entries(clonedHookRegistries)) {
|
274
|
-
const flattenedHookArray = [...hookRegistry].flat()
|
275
|
-
const
|
284
|
+
const flattenedHookArray = [...hookRegistry].flat();
|
285
|
+
const mergedHooksExecutionMode = options.mergedHooksExecutionMode ?? hookDefaults.mergedHooksExecutionMode;
|
286
|
+
const composedHook = composeTwoHooks(flattenedHookArray, mergedHooksExecutionMode);
|
276
287
|
resolvedHooks[key] = composedHook;
|
277
288
|
}
|
278
289
|
return {
|
@@ -289,25 +300,20 @@ var getResponseType = (response, parser) => ({
|
|
289
300
|
blob: () => response.blob(),
|
290
301
|
formData: () => response.formData(),
|
291
302
|
json: async () => {
|
292
|
-
|
293
|
-
|
294
|
-
return parser(text);
|
295
|
-
}
|
296
|
-
return response.json();
|
303
|
+
const text = await response.text();
|
304
|
+
return parser(text);
|
297
305
|
},
|
298
306
|
stream: () => response.body,
|
299
307
|
text: () => response.text()
|
300
308
|
});
|
301
|
-
var resolveResponseData =
|
302
|
-
const
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
if (!Object.hasOwn(RESPONSE_TYPE_LOOKUP, responseType)) {
|
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)) {
|
307
314
|
throw new Error(`Invalid response type: ${responseType}`);
|
308
315
|
}
|
309
|
-
|
310
|
-
return responseData;
|
316
|
+
return RESPONSE_TYPE_LOOKUP[selectedResponseType]();
|
311
317
|
};
|
312
318
|
var resolveSuccessResult = (info) => {
|
313
319
|
const { data, response, resultMode } = info;
|
@@ -329,37 +335,52 @@ var resolveSuccessResult = (info) => {
|
|
329
335
|
};
|
330
336
|
|
331
337
|
// src/retry.ts
|
332
|
-
var getLinearDelay = (options) =>
|
338
|
+
var getLinearDelay = (currentAttemptCount, options) => {
|
339
|
+
const retryDelay = options.retryDelay ?? options.retry?.delay;
|
340
|
+
const resolveRetryDelay = (isFunction(retryDelay) ? retryDelay(currentAttemptCount) : retryDelay) ?? retryDefaults.delay;
|
341
|
+
return resolveRetryDelay;
|
342
|
+
};
|
333
343
|
var getExponentialDelay = (currentAttemptCount, options) => {
|
334
|
-
const
|
335
|
-
const
|
344
|
+
const retryDelay = options.retryDelay ?? options.retry?.delay ?? retryDefaults.delay;
|
345
|
+
const resolveRetryDelay = Number(isFunction(retryDelay) ? retryDelay(currentAttemptCount) : retryDelay);
|
346
|
+
const maxDelay = Number(options.retryMaxDelay ?? options.retry?.maxDelay ?? retryDefaults.maxDelay);
|
347
|
+
const exponentialDelay = resolveRetryDelay * 2 ** currentAttemptCount;
|
336
348
|
return Math.min(exponentialDelay, maxDelay);
|
337
349
|
};
|
338
350
|
var createRetryStrategy = (ctx) => {
|
339
351
|
const { options } = ctx;
|
340
|
-
const
|
352
|
+
const currentAttemptCount = options["~retryAttemptCount"] ?? 0;
|
353
|
+
const retryStrategy = options.retryStrategy ?? options.retry?.strategy ?? retryDefaults.strategy;
|
341
354
|
const getDelay = () => {
|
342
|
-
|
343
|
-
|
355
|
+
switch (retryStrategy) {
|
356
|
+
case "exponential": {
|
357
|
+
return getExponentialDelay(currentAttemptCount, options);
|
358
|
+
}
|
359
|
+
case "linear": {
|
360
|
+
return getLinearDelay(currentAttemptCount, options);
|
361
|
+
}
|
362
|
+
default: {
|
363
|
+
throw new Error(`Invalid retry strategy: ${retryStrategy}`);
|
364
|
+
}
|
344
365
|
}
|
345
|
-
return getLinearDelay(options);
|
346
366
|
};
|
347
367
|
const shouldAttemptRetry = async () => {
|
348
|
-
const
|
349
|
-
const maxRetryAttempts = options.retryAttempts ??
|
350
|
-
const
|
368
|
+
const retryCondition = options.retryCondition ?? options.retry?.condition ?? retryDefaults.condition;
|
369
|
+
const maxRetryAttempts = options.retryAttempts ?? options.retry?.attempts ?? retryDefaults.attempts;
|
370
|
+
const customRetryCondition = await retryCondition(ctx);
|
371
|
+
const baseShouldRetry = maxRetryAttempts > currentAttemptCount && customRetryCondition;
|
351
372
|
if (ctx.error.name !== "HTTPError") {
|
352
|
-
return
|
373
|
+
return baseShouldRetry;
|
353
374
|
}
|
354
|
-
const
|
355
|
-
|
356
|
-
!!ctx.request.method && options.retryMethods?.includes(ctx.request.method)
|
357
|
-
);
|
358
|
-
const includesCodes = (
|
359
|
-
// eslint-disable-next-line no-implicit-coercion -- Boolean doesn't narrow
|
360
|
-
!!ctx.response?.status && options.retryStatusCodes?.includes(ctx.response.status)
|
375
|
+
const retryMethods = new Set(
|
376
|
+
options.retryMethods ?? options.retry?.methods ?? retryDefaults.methods
|
361
377
|
);
|
362
|
-
|
378
|
+
const selectedStatusCodeArray = options.retryStatusCodes ?? options.retry?.statusCodes;
|
379
|
+
const retryStatusCodes = selectedStatusCodeArray ? new Set(selectedStatusCodeArray) : null;
|
380
|
+
const includesMethod = Boolean(ctx.request.method) && retryMethods.has(ctx.request.method);
|
381
|
+
const includesStatusCodes = Boolean(ctx.response?.status) && (retryStatusCodes?.has(ctx.response.status) ?? true);
|
382
|
+
const shouldRetry = baseShouldRetry && includesMethod && includesStatusCodes;
|
383
|
+
return shouldRetry;
|
363
384
|
};
|
364
385
|
const executeRetryHook = async (shouldThrowOnError) => {
|
365
386
|
try {
|
@@ -452,12 +473,10 @@ var createFetchClient = (initBaseConfig = {}) => {
|
|
452
473
|
const resolvedBaseConfig = isFunction(initBaseConfig) ? initBaseConfig({ initURL: initURL.toString(), options: extraOptions, request: fetchOptions }) : initBaseConfig;
|
453
474
|
const [baseFetchOptions, baseExtraOptions] = splitBaseConfig(resolvedBaseConfig);
|
454
475
|
const mergedExtraOptions = {
|
455
|
-
...defaultExtraOptions,
|
456
476
|
...baseExtraOptions,
|
457
477
|
...baseExtraOptions.skipAutoMergeFor !== "all" && baseExtraOptions.skipAutoMergeFor !== "options" && extraOptions
|
458
478
|
};
|
459
479
|
const mergedRequestOptions = {
|
460
|
-
...defaultRequestOptions,
|
461
480
|
...baseFetchOptions,
|
462
481
|
...baseExtraOptions.skipAutoMergeFor !== "all" && baseExtraOptions.skipAutoMergeFor !== "request" && fetchOptions
|
463
482
|
};
|
@@ -470,7 +489,7 @@ var createFetchClient = (initBaseConfig = {}) => {
|
|
470
489
|
options: mergedExtraOptions,
|
471
490
|
request: mergedRequestOptions
|
472
491
|
});
|
473
|
-
const fullURL = `${resolvedOptions.baseURL}${mergeUrlWithParamsAndQuery(url, resolvedOptions.params, resolvedOptions.query)}`;
|
492
|
+
const fullURL = `${resolvedOptions.baseURL ?? ""}${mergeUrlWithParamsAndQuery(url, resolvedOptions.params, resolvedOptions.query)}`;
|
474
493
|
const options = {
|
475
494
|
...resolvedOptions,
|
476
495
|
...resolvedHooks,
|
@@ -484,9 +503,10 @@ var createFetchClient = (initBaseConfig = {}) => {
|
|
484
503
|
timeoutSignal,
|
485
504
|
newFetchController.signal
|
486
505
|
);
|
506
|
+
const bodySerializer = options.bodySerializer ?? commonDefaults.bodySerializer;
|
487
507
|
const request = {
|
488
508
|
...resolvedRequestOptions,
|
489
|
-
body: isSerializable(resolvedRequestOptions.body) ?
|
509
|
+
body: isSerializable(resolvedRequestOptions.body) ? bodySerializer(resolvedRequestOptions.body) : resolvedRequestOptions.body,
|
490
510
|
headers: mergeAndResolveHeaders({
|
491
511
|
auth: options.auth,
|
492
512
|
baseHeaders: baseFetchOptions.headers,
|
@@ -495,7 +515,12 @@ var createFetchClient = (initBaseConfig = {}) => {
|
|
495
515
|
}),
|
496
516
|
signal: combinedSignal
|
497
517
|
};
|
498
|
-
const {
|
518
|
+
const {
|
519
|
+
dedupeStrategy,
|
520
|
+
handleRequestCancelStrategy,
|
521
|
+
handleRequestDeferStrategy,
|
522
|
+
removeDedupeKeyFromCache
|
523
|
+
} = await createDedupeStrategy({
|
499
524
|
$RequestInfoCache,
|
500
525
|
baseConfig,
|
501
526
|
config,
|
@@ -512,7 +537,7 @@ var createFetchClient = (initBaseConfig = {}) => {
|
|
512
537
|
headers: request.headers
|
513
538
|
});
|
514
539
|
const response = await handleRequestDeferStrategy();
|
515
|
-
const shouldCloneResponse =
|
540
|
+
const shouldCloneResponse = dedupeStrategy === "defer" || options.cloneResponse;
|
516
541
|
const schemas = isFunction(options.schemas) ? options.schemas({ baseSchemas: baseExtraOptions.schemas ?? {} }) : options.schemas;
|
517
542
|
const validators = isFunction(options.validators) ? options.validators({ baseValidators: baseExtraOptions.validators ?? {} }) : options.validators;
|
518
543
|
if (!response.ok) {
|
@@ -580,7 +605,7 @@ var createFetchClient = (initBaseConfig = {}) => {
|
|
580
605
|
await waitUntil(delay);
|
581
606
|
const updatedOptions = {
|
582
607
|
...config,
|
583
|
-
"~
|
608
|
+
"~retryAttemptCount": (options["~retryAttemptCount"] ?? 0) + 1
|
584
609
|
};
|
585
610
|
return callApi2(initURL, updatedOptions);
|
586
611
|
}
|