@zayne-labs/callapi 1.12.3 → 1.12.5

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/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { A as getCurrentRouteSchemaKeyAndMainInitURL, B as isReadableStream, L as isArray, M as handleSchemaValidation, N as HTTPError, R as isBoolean, V as isString, a as getBody, c as getMethod, d as splitConfig, f as waitFor, h as isHTTPErrorInstance, i as createTimeoutSignal, j as handleConfigValidation, k as getFullAndNormalizedURL, l as getResolvedHeaders, o as getFetchImpl, r as createCombinedSignal, s as getHeaders, t as extraOptionDefaults, u as omitKeys, v as isValidationErrorInstance, z as isFunction } from "./defaults-S9x_Ra9q.js";
1
+ import { A as getCurrentRouteSchemaKeyAndMainInitURL, B as isString, L as isArray, M as handleSchemaValidation, N as HTTPError, R as isBoolean, a as getBody, c as getMethod, d as splitConfig, f as waitFor, h as isHTTPErrorInstance, i as createTimeoutSignal, j as handleConfigValidation, k as getFullAndNormalizedURL, l as getResolvedHeaders, o as getFetchImpl, r as createCombinedSignal, s as getHeaders, t as extraOptionDefaults, u as omitKeys, v as isValidationErrorInstance, z as isFunction } from "./defaults-D0QJmGE5.js";
2
2
  //#region src/result.ts
3
3
  const getResponseType = (response, responseParser) => ({
4
4
  arrayBuffer: () => response.arrayBuffer(),
@@ -159,104 +159,128 @@ const executeHooksInCatchBlock = async (hookResultsOrPromise, hookInfo) => {
159
159
  //#endregion
160
160
  //#region src/stream.ts
161
161
  const createProgressEvent = (options) => {
162
- const { chunk, totalBytes, transferredBytes } = options;
162
+ const { chunk, isDone, totalBytes, transferredBytes } = options;
163
+ let percentage = totalBytes === 0 ? 0 : transferredBytes / totalBytes;
164
+ if (percentage >= 1) percentage = 1 - Number.EPSILON;
163
165
  return {
164
166
  chunk,
165
- progress: Math.round(transferredBytes / totalBytes * 100) || 0,
167
+ progress: (isDone ? 1 : percentage) * 100,
166
168
  totalBytes,
167
169
  transferredBytes
168
170
  };
169
171
  };
170
- const calculateTotalBytesFromBody = async (requestBody, existingTotalBytes) => {
171
- let totalBytes = existingTotalBytes;
172
- if (!requestBody) return totalBytes;
173
- for await (const chunk of requestBody) totalBytes += chunk.byteLength;
174
- return totalBytes;
172
+ const textEncoder = new TextEncoder();
173
+ const estimateBodySize = (body) => {
174
+ if (!body) return 0;
175
+ if (body instanceof ReadableStream) return 0;
176
+ if (body instanceof FormData) {
177
+ let size = 0;
178
+ for (const [key, value] of body) {
179
+ size += 40;
180
+ size += textEncoder.encode(`Content-Disposition: form-data; name="${key}"`).byteLength;
181
+ size += isString(value) ? textEncoder.encode(value).byteLength : value.size;
182
+ }
183
+ return size;
184
+ }
185
+ if (body instanceof Blob) return body.size;
186
+ if (body instanceof ArrayBuffer || ArrayBuffer.isView(body)) return body.byteLength;
187
+ if (isString(body) || body instanceof URLSearchParams) return textEncoder.encode(String(body)).byteLength;
188
+ return 0;
175
189
  };
176
- const toStreamableRequest = async (context) => {
190
+ const createTrackedStream = (streamOptions) => {
191
+ const { initialTotalBytes, onStream, streamBody } = streamOptions;
192
+ let totalBytes = initialTotalBytes;
193
+ let transferredBytes = 0;
194
+ const reportProgress = async (progressOptions) => {
195
+ const { chunk, isDone } = progressOptions;
196
+ if (isDone) {
197
+ await onStream(createProgressEvent({
198
+ chunk: null,
199
+ isDone: true,
200
+ totalBytes,
201
+ transferredBytes
202
+ }));
203
+ return;
204
+ }
205
+ transferredBytes += chunk.byteLength;
206
+ totalBytes = Math.max(totalBytes, transferredBytes);
207
+ await onStream(createProgressEvent({
208
+ chunk,
209
+ totalBytes,
210
+ transferredBytes
211
+ }));
212
+ };
213
+ return streamBody.pipeThrough(new TransformStream({
214
+ flush: async () => {
215
+ await reportProgress({
216
+ chunk: null,
217
+ isDone: true
218
+ });
219
+ },
220
+ start: async () => {
221
+ await reportProgress({ chunk: new Uint8Array() });
222
+ },
223
+ transform: async (chunk, controller) => {
224
+ controller.enqueue(chunk);
225
+ await reportProgress({ chunk });
226
+ }
227
+ }));
228
+ };
229
+ const toStreamableRequest = (context) => {
177
230
  const { baseConfig, config, options, request } = context;
178
- if (!options.onRequestStream || !isReadableStream(request.body)) return request;
231
+ if (!options.onRequestStream || !request.body) return request;
179
232
  const requestInstance = new Request(options.fullURL, {
180
233
  ...request,
181
234
  duplex: "half"
182
235
  });
183
236
  const contentLength = requestInstance.headers.get("content-length");
184
- let totalBytes = Number(contentLength ?? 0);
185
- if (!contentLength && options.forcefullyCalculateRequestStreamSize) totalBytes = await calculateTotalBytesFromBody(requestInstance.clone().body, totalBytes);
186
- let transferredBytes = 0;
187
- const stream = new ReadableStream({ start: async (controller) => {
188
- const body = requestInstance.body;
189
- if (!body) return;
190
- const requestStreamContext = {
191
- baseConfig,
192
- config,
193
- event: createProgressEvent({
194
- chunk: new Uint8Array(),
195
- totalBytes,
196
- transferredBytes
197
- }),
198
- options,
199
- request,
200
- requestInstance
201
- };
202
- await executeHooks(options.onRequestStream?.(requestStreamContext));
203
- for await (const chunk of body) {
204
- transferredBytes += chunk.byteLength;
205
- totalBytes = Math.max(totalBytes, transferredBytes);
237
+ const initialTotalBytes = contentLength ? Math.max(0, Number(contentLength) || 0) : estimateBodySize(config.body ?? request.body);
238
+ const streamBody = requestInstance.body;
239
+ if (!streamBody) return requestInstance;
240
+ const requestStreamContext = {
241
+ baseConfig,
242
+ config,
243
+ options,
244
+ request,
245
+ requestInstance
246
+ };
247
+ const trackedStream = createTrackedStream({
248
+ initialTotalBytes,
249
+ onStream: async (event) => {
206
250
  await executeHooks(options.onRequestStream?.({
207
251
  ...requestStreamContext,
208
- event: createProgressEvent({
209
- chunk,
210
- totalBytes,
211
- transferredBytes
212
- })
252
+ event
213
253
  }));
214
- controller.enqueue(chunk);
215
- }
216
- controller.close();
217
- } });
254
+ },
255
+ streamBody
256
+ });
218
257
  return new Request(requestInstance, {
219
- body: stream,
258
+ body: trackedStream,
220
259
  duplex: "half"
221
260
  });
222
261
  };
223
262
  const toStreamableResponse = (context) => {
224
263
  const { baseConfig, config, options, request, response } = context;
225
- if (!options.onResponseStream || !response.body) return response;
226
- const contentLength = response.headers.get("content-length");
227
- let totalBytes = Number(contentLength ?? 0);
228
- let transferredBytes = 0;
229
- const stream = new ReadableStream({ start: async (controller) => {
230
- const body = response.body;
231
- if (!body) return;
232
- const responseStreamContext = {
233
- baseConfig,
234
- config,
235
- event: createProgressEvent({
236
- chunk: new Uint8Array(),
237
- totalBytes,
238
- transferredBytes
239
- }),
240
- options,
241
- request,
242
- response
243
- };
244
- await executeHooks(options.onResponseStream?.(responseStreamContext));
245
- for await (const chunk of body) {
246
- transferredBytes += chunk.byteLength;
247
- totalBytes = Math.max(totalBytes, transferredBytes);
264
+ if (!options.onResponseStream || !response.body || response.status === 204) return response;
265
+ const initialTotalBytes = Math.max(0, Number(response.headers.get("content-length")) || 0);
266
+ const streamBody = response.body;
267
+ const responseStreamContext = {
268
+ baseConfig,
269
+ config,
270
+ options,
271
+ request,
272
+ response
273
+ };
274
+ const stream = createTrackedStream({
275
+ initialTotalBytes,
276
+ onStream: async (event) => {
248
277
  await executeHooks(options.onResponseStream?.({
249
278
  ...responseStreamContext,
250
- event: createProgressEvent({
251
- chunk,
252
- totalBytes,
253
- transferredBytes
254
- })
279
+ event
255
280
  }));
256
- controller.enqueue(chunk);
257
- }
258
- controller.close();
259
- } });
281
+ },
282
+ streamBody
283
+ });
260
284
  return new Response(stream, response);
261
285
  };
262
286
  //#endregion
@@ -326,20 +350,19 @@ const createDedupeStrategy = async (context) => {
326
350
  const handleRequestDeferStrategy = async (deferContext) => {
327
351
  const { fetchApi, options: localOptions, request: localRequest } = deferContext;
328
352
  const shouldUsePromiseFromCache = prevRequestInfo && resolvedDedupeStrategy === "defer";
329
- const streamableContext = {
353
+ const streamContext = {
330
354
  baseConfig,
331
355
  config,
332
356
  options: localOptions,
333
357
  request: localRequest
334
358
  };
335
- const streamableRequest = await toStreamableRequest(streamableContext);
336
- const responsePromise = shouldUsePromiseFromCache ? prevRequestInfo.responsePromise : fetchApi(localOptions.fullURL, streamableRequest);
359
+ const responsePromise = shouldUsePromiseFromCache ? prevRequestInfo.responsePromise : fetchApi(localOptions.fullURL, toStreamableRequest(streamContext));
337
360
  $RequestInfoCache?.set({
338
361
  controller: newFetchController,
339
362
  responsePromise
340
363
  });
341
364
  return toStreamableResponse({
342
- ...streamableContext,
365
+ ...streamContext,
343
366
  response: await responsePromise
344
367
  });
345
368
  };
@@ -586,16 +609,15 @@ const createRetryManager = (ctx) => {
586
609
  };
587
610
  //#endregion
588
611
  //#region src/createFetchClient.ts
589
- const getTimeoutSignal = "timeout" in AbortSignal ? createTimeoutSignal : import("./timeoutSignal-B9V7QESI.js").then((module) => module.createTimeoutSignal);
590
- const getCombinedSignal = "any" in AbortSignal ? createCombinedSignal : import("./combinedSignal-ChYtee_L.js").then((module) => module.createCombinedSignal);
591
612
  const $GlobalRequestInfoCache = /* @__PURE__ */ new Map();
592
613
  const createFetchClientWithContext = () => {
593
614
  const createFetchClient = (initBaseConfig = {}) => {
594
615
  const $LocalRequestInfoCache = /* @__PURE__ */ new Map();
595
616
  const callApi = async (initURL, initConfig = {}) => {
596
617
  const [fetchOptions, extraOptions] = splitConfig(initConfig);
618
+ const initURLString = initURL.toString();
597
619
  const baseConfig = isFunction(initBaseConfig) ? initBaseConfig({
598
- initURL: initURL.toString(),
620
+ initURL: initURLString,
599
621
  options: extraOptions,
600
622
  request: fetchOptions
601
623
  }) : initBaseConfig;
@@ -616,7 +638,7 @@ const createFetchClientWithContext = () => {
616
638
  const initURLResult = getCurrentRouteSchemaKeyAndMainInitURL({
617
639
  baseExtraOptions: baseConfig,
618
640
  extraOptions: config,
619
- initURL: initURL.toString()
641
+ initURL: initURLString
620
642
  });
621
643
  const { resolvedCurrentRouteSchemaKey, resolvedHooks, resolvedInitURL, resolvedMiddlewares, resolvedOptions, resolvedRequest } = await initializePlugins({
622
644
  baseConfig,
@@ -659,8 +681,7 @@ const createFetchClientWithContext = () => {
659
681
  });
660
682
  Object.assign(options, refetchFnResult);
661
683
  const newFetchController = new AbortController();
662
- const timeoutSignal = (await getTimeoutSignal)(options.timeout);
663
- const combinedSignal = (await getCombinedSignal)(timeoutSignal, resolvedRequest.signal, newFetchController.signal);
684
+ const combinedSignal = createCombinedSignal(createTimeoutSignal(options.timeout), resolvedRequest.signal, newFetchController.signal);
664
685
  const request = {
665
686
  ...resolvedRequest,
666
687
  signal: combinedSignal