@zayne-labs/callapi 1.7.4 → 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-FE6ZVVZS.js → chunk-UVFIGKZS.js} +44 -44
- package/dist/esm/chunk-UVFIGKZS.js.map +1 -0
- package/dist/{cjs/common-DiBiESb2.d.cts → esm/common-BwOrtpui.d.ts} +103 -102
- package/dist/esm/index.d.ts +3 -3
- package/dist/esm/index.js +82 -54
- 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 -964
- 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-FE6ZVVZS.js.map +0 -1
- package/dist/esm/common-DiBiESb2.d.ts +0 -774
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,22 +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
|
-
|
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)) {
|
304
314
|
throw new Error(`Invalid response type: ${responseType}`);
|
305
315
|
}
|
306
|
-
|
307
|
-
return responseData;
|
316
|
+
return RESPONSE_TYPE_LOOKUP[selectedResponseType]();
|
308
317
|
};
|
309
318
|
var resolveSuccessResult = (info) => {
|
310
319
|
const { data, response, resultMode } = info;
|
@@ -326,37 +335,52 @@ var resolveSuccessResult = (info) => {
|
|
326
335
|
};
|
327
336
|
|
328
337
|
// src/retry.ts
|
329
|
-
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
|
+
};
|
330
343
|
var getExponentialDelay = (currentAttemptCount, options) => {
|
331
|
-
const
|
332
|
-
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;
|
333
348
|
return Math.min(exponentialDelay, maxDelay);
|
334
349
|
};
|
335
350
|
var createRetryStrategy = (ctx) => {
|
336
351
|
const { options } = ctx;
|
337
|
-
const
|
352
|
+
const currentAttemptCount = options["~retryAttemptCount"] ?? 0;
|
353
|
+
const retryStrategy = options.retryStrategy ?? options.retry?.strategy ?? retryDefaults.strategy;
|
338
354
|
const getDelay = () => {
|
339
|
-
|
340
|
-
|
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
|
+
}
|
341
365
|
}
|
342
|
-
return getLinearDelay(options);
|
343
366
|
};
|
344
367
|
const shouldAttemptRetry = async () => {
|
345
|
-
const
|
346
|
-
const maxRetryAttempts = options.retryAttempts ??
|
347
|
-
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;
|
348
372
|
if (ctx.error.name !== "HTTPError") {
|
349
|
-
return
|
373
|
+
return baseShouldRetry;
|
350
374
|
}
|
351
|
-
const
|
352
|
-
|
353
|
-
!!ctx.request.method && options.retryMethods?.includes(ctx.request.method)
|
354
|
-
);
|
355
|
-
const includesCodes = (
|
356
|
-
// eslint-disable-next-line no-implicit-coercion -- Boolean doesn't narrow
|
357
|
-
!!ctx.response?.status && options.retryStatusCodes?.includes(ctx.response.status)
|
375
|
+
const retryMethods = new Set(
|
376
|
+
options.retryMethods ?? options.retry?.methods ?? retryDefaults.methods
|
358
377
|
);
|
359
|
-
|
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;
|
360
384
|
};
|
361
385
|
const executeRetryHook = async (shouldThrowOnError) => {
|
362
386
|
try {
|
@@ -449,12 +473,10 @@ var createFetchClient = (initBaseConfig = {}) => {
|
|
449
473
|
const resolvedBaseConfig = isFunction(initBaseConfig) ? initBaseConfig({ initURL: initURL.toString(), options: extraOptions, request: fetchOptions }) : initBaseConfig;
|
450
474
|
const [baseFetchOptions, baseExtraOptions] = splitBaseConfig(resolvedBaseConfig);
|
451
475
|
const mergedExtraOptions = {
|
452
|
-
...defaultExtraOptions,
|
453
476
|
...baseExtraOptions,
|
454
477
|
...baseExtraOptions.skipAutoMergeFor !== "all" && baseExtraOptions.skipAutoMergeFor !== "options" && extraOptions
|
455
478
|
};
|
456
479
|
const mergedRequestOptions = {
|
457
|
-
...defaultRequestOptions,
|
458
480
|
...baseFetchOptions,
|
459
481
|
...baseExtraOptions.skipAutoMergeFor !== "all" && baseExtraOptions.skipAutoMergeFor !== "request" && fetchOptions
|
460
482
|
};
|
@@ -467,7 +489,7 @@ var createFetchClient = (initBaseConfig = {}) => {
|
|
467
489
|
options: mergedExtraOptions,
|
468
490
|
request: mergedRequestOptions
|
469
491
|
});
|
470
|
-
const fullURL = `${resolvedOptions.baseURL}${mergeUrlWithParamsAndQuery(url, resolvedOptions.params, resolvedOptions.query)}`;
|
492
|
+
const fullURL = `${resolvedOptions.baseURL ?? ""}${mergeUrlWithParamsAndQuery(url, resolvedOptions.params, resolvedOptions.query)}`;
|
471
493
|
const options = {
|
472
494
|
...resolvedOptions,
|
473
495
|
...resolvedHooks,
|
@@ -481,9 +503,10 @@ var createFetchClient = (initBaseConfig = {}) => {
|
|
481
503
|
timeoutSignal,
|
482
504
|
newFetchController.signal
|
483
505
|
);
|
506
|
+
const bodySerializer = options.bodySerializer ?? commonDefaults.bodySerializer;
|
484
507
|
const request = {
|
485
508
|
...resolvedRequestOptions,
|
486
|
-
body: isSerializable(resolvedRequestOptions.body) ?
|
509
|
+
body: isSerializable(resolvedRequestOptions.body) ? bodySerializer(resolvedRequestOptions.body) : resolvedRequestOptions.body,
|
487
510
|
headers: mergeAndResolveHeaders({
|
488
511
|
auth: options.auth,
|
489
512
|
baseHeaders: baseFetchOptions.headers,
|
@@ -492,7 +515,12 @@ var createFetchClient = (initBaseConfig = {}) => {
|
|
492
515
|
}),
|
493
516
|
signal: combinedSignal
|
494
517
|
};
|
495
|
-
const {
|
518
|
+
const {
|
519
|
+
dedupeStrategy,
|
520
|
+
handleRequestCancelStrategy,
|
521
|
+
handleRequestDeferStrategy,
|
522
|
+
removeDedupeKeyFromCache
|
523
|
+
} = await createDedupeStrategy({
|
496
524
|
$RequestInfoCache,
|
497
525
|
baseConfig,
|
498
526
|
config,
|
@@ -509,7 +537,7 @@ var createFetchClient = (initBaseConfig = {}) => {
|
|
509
537
|
headers: request.headers
|
510
538
|
});
|
511
539
|
const response = await handleRequestDeferStrategy();
|
512
|
-
const shouldCloneResponse =
|
540
|
+
const shouldCloneResponse = dedupeStrategy === "defer" || options.cloneResponse;
|
513
541
|
const schemas = isFunction(options.schemas) ? options.schemas({ baseSchemas: baseExtraOptions.schemas ?? {} }) : options.schemas;
|
514
542
|
const validators = isFunction(options.validators) ? options.validators({ baseValidators: baseExtraOptions.validators ?? {} }) : options.validators;
|
515
543
|
if (!response.ok) {
|
@@ -577,7 +605,7 @@ var createFetchClient = (initBaseConfig = {}) => {
|
|
577
605
|
await waitUntil(delay);
|
578
606
|
const updatedOptions = {
|
579
607
|
...config,
|
580
|
-
"~
|
608
|
+
"~retryAttemptCount": (options["~retryAttemptCount"] ?? 0) + 1
|
581
609
|
};
|
582
610
|
return callApi2(initURL, updatedOptions);
|
583
611
|
}
|