@plyaz/api 1.6.7 → 1.6.8

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.cjs CHANGED
@@ -21623,7 +21623,7 @@ function createOnErrorHandler(handlers, clearTemporaryOverrides2, clearOnComplet
21623
21623
  const apiError = new ApiPackageError(
21624
21624
  "request.failed",
21625
21625
  api.PACKAGE_STATUS_CODES.REQUEST_FAILED,
21626
- error.status ? `HTTP_${error.status}` : api.API_ERROR_CODES.NETWORK_ERROR,
21626
+ error.status ? errors$1.getErrorCodeByStatus(error.status) ?? api.API_ERROR_CODES.CLIENT_ERROR : api.API_ERROR_CODES.NETWORK_ERROR,
21627
21627
  {
21628
21628
  cause: error,
21629
21629
  context: {
@@ -22249,6 +22249,546 @@ function applyQualityBasedConfiguration(resolvedConfig, quality, networkAware, n
22249
22249
  }
22250
22250
  }
22251
22251
  __name(applyQualityBasedConfiguration, "applyQualityBasedConfiguration");
22252
+ var PROGRESS_CHUNK_SIZE_MULTIPLIER = 64;
22253
+ var UPLOAD_CONSTANTS = {
22254
+ DEFAULT_CHUNK_SIZE: PROGRESS_CHUNK_SIZE_MULTIPLIER * config.NUMBER_SYSTEM.BYTES_PER_KB,
22255
+ DEFAULT_THROTTLE_MS: config.TIME_CONSTANTS.HUNDRED_MS,
22256
+ DEFAULT_CONTENT_TYPE: "application/octet-stream",
22257
+ DEFAULT_TIMEOUT: config.TIME_CONSTANTS.TWO_MINUTES,
22258
+ DEFAULT_RETRY_DELAY: config.RETRY_DELAYS.SHORT,
22259
+ DEFAULT_RETRY_BACKOFF: config.RETRY_BACKOFF.MEDIUM,
22260
+ DEFAULT_RETRY_MAX_DELAY: config.RETRY_DELAYS.MAX,
22261
+ PROGRESS_PERCENTAGE_THRESHOLD: config.NUMERIC_CONSTANTS.FIVE,
22262
+ FULL_PERCENTAGE: config.MATH_CONSTANTS.PERCENTAGE_MAX,
22263
+ HTTPS_DEFAULT_PORT: config.TIME_CONSTANTS.HTTPS_PORT,
22264
+ HTTP_DEFAULT_PORT: config.TIME_CONSTANTS.HTTP_PORT,
22265
+ /** Max server error status code (exclusive boundary for 5xx range) */
22266
+ MAX_SERVER_ERROR_STATUS: 600
22267
+ };
22268
+ var RETRYABLE_ERROR_CODES = [
22269
+ "ETIMEDOUT",
22270
+ "ECONNRESET",
22271
+ "ECONNREFUSED",
22272
+ "ENOTFOUND",
22273
+ "ENETUNREACH",
22274
+ "EAI_AGAIN"
22275
+ ];
22276
+ var RETRYABLE_MESSAGE_PATTERNS = [
22277
+ "timeout",
22278
+ "timed out",
22279
+ "network",
22280
+ "econnreset",
22281
+ "econnrefused",
22282
+ "etimedout",
22283
+ "service unavailable",
22284
+ "rate limit",
22285
+ "too many requests"
22286
+ ];
22287
+
22288
+ // src/api/upload/config.ts
22289
+ function extractGlobalHeaders(globalConfig) {
22290
+ const globalHeaders = {};
22291
+ if (!globalConfig.headers || typeof globalConfig.headers !== "object") {
22292
+ return globalHeaders;
22293
+ }
22294
+ if (!("presets" in globalConfig.headers) && !("static" in globalConfig.headers)) {
22295
+ Object.entries(globalConfig.headers).forEach(([key, value]) => {
22296
+ if (typeof value === "string") {
22297
+ globalHeaders[key] = value;
22298
+ }
22299
+ });
22300
+ return globalHeaders;
22301
+ }
22302
+ if ("static" in globalConfig.headers) {
22303
+ const staticHeaders = globalConfig.headers.static;
22304
+ if (staticHeaders) {
22305
+ Object.entries(staticHeaders).forEach(([key, value]) => {
22306
+ if (typeof value === "string") {
22307
+ globalHeaders[key] = value;
22308
+ }
22309
+ });
22310
+ }
22311
+ }
22312
+ return globalHeaders;
22313
+ }
22314
+ __name(extractGlobalHeaders, "extractGlobalHeaders");
22315
+ function mergeRetryConfig(optionRetry, globalRetry) {
22316
+ if (optionRetry !== void 0) return optionRetry;
22317
+ if (globalRetry !== void 0) return globalRetry;
22318
+ return false;
22319
+ }
22320
+ __name(mergeRetryConfig, "mergeRetryConfig");
22321
+ function buildLocalConfig(options) {
22322
+ return {
22323
+ headers: options.headers ?? {},
22324
+ timeout: options.timeout ?? UPLOAD_CONSTANTS.DEFAULT_TIMEOUT,
22325
+ baseURL: options.baseURL,
22326
+ retry: options.retry ?? false,
22327
+ onError: options.onError,
22328
+ withCredentials: options.withCredentials ?? false
22329
+ };
22330
+ }
22331
+ __name(buildLocalConfig, "buildLocalConfig");
22332
+ function getMergedConfig(options) {
22333
+ if (options.useGlobalConfig === false) {
22334
+ return buildLocalConfig(options);
22335
+ }
22336
+ const globalConfig = getGlobalConfig();
22337
+ const globalHeaders = extractGlobalHeaders(globalConfig);
22338
+ return {
22339
+ headers: { ...globalHeaders, ...options.headers ?? {} },
22340
+ timeout: options.timeout ?? globalConfig.timeout ?? UPLOAD_CONSTANTS.DEFAULT_TIMEOUT,
22341
+ baseURL: options.baseURL ?? globalConfig.baseURL,
22342
+ retry: mergeRetryConfig(options.retry, globalConfig.retry),
22343
+ onError: options.onError,
22344
+ withCredentials: options.withCredentials ?? globalConfig.withCredentials ?? false
22345
+ };
22346
+ }
22347
+ __name(getMergedConfig, "getMergedConfig");
22348
+ function checkRetryableFlag(error) {
22349
+ if (typeof error.isRetryable === "function") return error.isRetryable();
22350
+ if (typeof error.isRetryable === "boolean") return error.isRetryable;
22351
+ if (typeof error.retryable === "boolean") return error.retryable;
22352
+ return void 0;
22353
+ }
22354
+ __name(checkRetryableFlag, "checkRetryableFlag");
22355
+ function isRetryableStatus(status) {
22356
+ if (status === void 0) return false;
22357
+ if (status === config.HTTP_STATUS.TOO_MANY_REQUESTS) return true;
22358
+ return status >= config.HTTP_STATUS.INTERNAL_SERVER_ERROR && status < UPLOAD_CONSTANTS.MAX_SERVER_ERROR_STATUS;
22359
+ }
22360
+ __name(isRetryableStatus, "isRetryableStatus");
22361
+ function hasRetryableErrorCode(error) {
22362
+ return Boolean(
22363
+ error.code && RETRYABLE_ERROR_CODES.includes(error.code)
22364
+ );
22365
+ }
22366
+ __name(hasRetryableErrorCode, "hasRetryableErrorCode");
22367
+ function hasRetryableMessage(error) {
22368
+ const message = error.message?.toLowerCase() ?? "";
22369
+ return RETRYABLE_MESSAGE_PATTERNS.some((pattern) => message.includes(pattern));
22370
+ }
22371
+ __name(hasRetryableMessage, "hasRetryableMessage");
22372
+ function isRetryableError(error, status) {
22373
+ if (!error) return false;
22374
+ const errorWithRetryable = error;
22375
+ const flagResult = checkRetryableFlag(errorWithRetryable);
22376
+ if (flagResult !== void 0) return flagResult;
22377
+ if (hasRetryableErrorCode(errorWithRetryable)) return true;
22378
+ if (hasRetryableMessage(error)) return true;
22379
+ const httpStatus = status ?? errorWithRetryable.statusCode;
22380
+ return isRetryableStatus(httpStatus);
22381
+ }
22382
+ __name(isRetryableError, "isRetryableError");
22383
+ function calculateRetryDelay(attempt, config) {
22384
+ const delay = config.delay ?? UPLOAD_CONSTANTS.DEFAULT_RETRY_DELAY;
22385
+ const backoff = config.backoff ?? UPLOAD_CONSTANTS.DEFAULT_RETRY_BACKOFF;
22386
+ const maxDelay = config.maxDelay ?? UPLOAD_CONSTANTS.DEFAULT_RETRY_MAX_DELAY;
22387
+ const calculatedDelay = delay * Math.pow(backoff, attempt);
22388
+ return Math.min(calculatedDelay, maxDelay);
22389
+ }
22390
+ __name(calculateRetryDelay, "calculateRetryDelay");
22391
+ function notifyRetryError(params) {
22392
+ const { ctx, message, status, statusText, cause } = params;
22393
+ if (!ctx.config.onError) return;
22394
+ ctx.config.onError({
22395
+ message,
22396
+ status,
22397
+ statusText,
22398
+ cause,
22399
+ retryable: true,
22400
+ attempt: ctx.attempt,
22401
+ maxAttempts: ctx.maxAttempts
22402
+ });
22403
+ }
22404
+ __name(notifyRetryError, "notifyRetryError");
22405
+ function notifyFinalError(ctx, error) {
22406
+ if (!ctx.config.onError) return;
22407
+ ctx.config.onError({
22408
+ message: error.message,
22409
+ cause: error,
22410
+ retryable: false,
22411
+ attempt: ctx.attempt,
22412
+ maxAttempts: ctx.maxAttempts
22413
+ });
22414
+ }
22415
+ __name(notifyFinalError, "notifyFinalError");
22416
+ function shouldRetryResult(result, config, attempt, maxAttempts) {
22417
+ if (result.success) return false;
22418
+ if (!config.retry) return false;
22419
+ if (attempt >= maxAttempts - 1) return false;
22420
+ return isRetryableError(new Error(result.statusText ?? "Upload failed"), result.status);
22421
+ }
22422
+ __name(shouldRetryResult, "shouldRetryResult");
22423
+ function shouldRetryError(error, config, attempt, maxAttempts) {
22424
+ if (!config.retry) return false;
22425
+ if (attempt >= maxAttempts - 1) return false;
22426
+ return isRetryableError(error);
22427
+ }
22428
+ __name(shouldRetryError, "shouldRetryError");
22429
+ async function handleRetryDelay(attempt, config) {
22430
+ await sleep(calculateRetryDelay(attempt, config));
22431
+ }
22432
+ __name(handleRetryDelay, "handleRetryDelay");
22433
+ function resolveUrl(url, baseURL) {
22434
+ if (url.startsWith("http://") || url.startsWith("https://")) {
22435
+ return url;
22436
+ }
22437
+ if (!baseURL) {
22438
+ return url;
22439
+ }
22440
+ const base = baseURL.replace(/\/$/, "");
22441
+ const path = url.startsWith("/") ? url : `/${url}`;
22442
+ return `${base}${path}`;
22443
+ }
22444
+ __name(resolveUrl, "resolveUrl");
22445
+ function normalizeData(data) {
22446
+ if (Buffer.isBuffer(data)) return data;
22447
+ if (data instanceof Uint8Array) return data;
22448
+ if (data instanceof ArrayBuffer) return new Uint8Array(data);
22449
+ throw new ApiPackageError(
22450
+ "Blob data type is only supported in browser environment",
22451
+ void 0,
22452
+ errors.API_ERROR_CODES.VALIDATION_ERROR
22453
+ );
22454
+ }
22455
+ __name(normalizeData, "normalizeData");
22456
+ function createUploadState(totalSize) {
22457
+ const now2 = Date.now();
22458
+ return {
22459
+ status: "uploading",
22460
+ startTime: now2,
22461
+ bytesUploaded: 0,
22462
+ totalBytes: totalSize,
22463
+ lastProgressTime: now2,
22464
+ lastBytesUploaded: 0
22465
+ };
22466
+ }
22467
+ __name(createUploadState, "createUploadState");
22468
+ function calculateProgress(state) {
22469
+ const now2 = Date.now();
22470
+ const timeDelta = (now2 - state.lastProgressTime) / config.TIME_CONSTANTS.SECOND;
22471
+ const bytesDelta = state.bytesUploaded - state.lastBytesUploaded;
22472
+ const speed = timeDelta > 0 ? bytesDelta / timeDelta : 0;
22473
+ const percentage2 = Math.round(
22474
+ state.bytesUploaded / state.totalBytes * UPLOAD_CONSTANTS.FULL_PERCENTAGE
22475
+ );
22476
+ const remainingBytes = state.totalBytes - state.bytesUploaded;
22477
+ return {
22478
+ loaded: state.bytesUploaded,
22479
+ total: state.totalBytes,
22480
+ percentage: percentage2,
22481
+ speed: speed > 0 ? speed : void 0,
22482
+ estimatedTimeRemaining: speed > 0 ? remainingBytes / speed : void 0
22483
+ };
22484
+ }
22485
+ __name(calculateProgress, "calculateProgress");
22486
+ function emitFinalProgress(onProgress, totalSize, startTime) {
22487
+ if (!onProgress) return;
22488
+ const elapsed = (Date.now() - startTime) / config.TIME_CONSTANTS.SECOND;
22489
+ onProgress({
22490
+ loaded: totalSize,
22491
+ total: totalSize,
22492
+ percentage: UPLOAD_CONSTANTS.FULL_PERCENTAGE,
22493
+ speed: elapsed > 0 ? totalSize / elapsed : void 0,
22494
+ estimatedTimeRemaining: 0
22495
+ });
22496
+ }
22497
+ __name(emitFinalProgress, "emitFinalProgress");
22498
+ function shouldEmitProgress(state, totalSize, throttleMs) {
22499
+ const now2 = Date.now();
22500
+ const timeSinceLastProgress = now2 - state.lastProgressTime;
22501
+ const currentPct = Math.round(
22502
+ state.bytesUploaded / totalSize * UPLOAD_CONSTANTS.FULL_PERCENTAGE
22503
+ );
22504
+ const lastPct = Math.round(
22505
+ state.lastBytesUploaded / totalSize * UPLOAD_CONSTANTS.FULL_PERCENTAGE
22506
+ );
22507
+ return timeSinceLastProgress >= throttleMs || currentPct - lastPct >= UPLOAD_CONSTANTS.PROGRESS_PERCENTAGE_THRESHOLD;
22508
+ }
22509
+ __name(shouldEmitProgress, "shouldEmitProgress");
22510
+ function parseNodeHeaders(headers2) {
22511
+ const result = {};
22512
+ for (const [key, value] of Object.entries(headers2)) {
22513
+ if (value !== void 0) {
22514
+ result[key] = Array.isArray(value) ? value.join(", ") : value;
22515
+ }
22516
+ }
22517
+ return result;
22518
+ }
22519
+ __name(parseNodeHeaders, "parseNodeHeaders");
22520
+
22521
+ // src/api/upload/node.ts
22522
+ var createTimeoutError = /* @__PURE__ */ __name((url) => new ApiPackageError("Upload timed out", void 0, errors.API_ERROR_CODES.REQUEST_TIMEOUT, {
22523
+ context: { url }
22524
+ }), "createTimeoutError");
22525
+ var createAbortError = /* @__PURE__ */ __name((url) => new ApiPackageError("Upload aborted", void 0, errors.API_ERROR_CODES.REQUEST_ABORTED, {
22526
+ context: { url }
22527
+ }), "createAbortError");
22528
+ var normalizeError = /* @__PURE__ */ __name((error) => error instanceof Error ? error : new ApiPackageError(String(error), void 0, errors.API_ERROR_CODES.UNKNOWN_ERROR), "normalizeError");
22529
+ async function uploadOnce(options, config$1, resolvedUrl) {
22530
+ const {
22531
+ data,
22532
+ method = "PUT",
22533
+ contentType = UPLOAD_CONSTANTS.DEFAULT_CONTENT_TYPE,
22534
+ onProgress,
22535
+ abortSignal
22536
+ } = options;
22537
+ const chunkSize = options.chunkSize ?? UPLOAD_CONSTANTS.DEFAULT_CHUNK_SIZE;
22538
+ const throttleMs = options.throttleMs ?? UPLOAD_CONSTANTS.DEFAULT_THROTTLE_MS;
22539
+ const { headers: mergedHeaders, timeout } = config$1;
22540
+ const buffer = normalizeData(data);
22541
+ const totalSize = buffer.length;
22542
+ const parsedUrl = new URL(resolvedUrl);
22543
+ const isHttps = parsedUrl.protocol === "https:";
22544
+ const httpModule = await (isHttps ? import('https') : import('http'));
22545
+ const state = createUploadState(totalSize);
22546
+ return new Promise((resolve, reject) => {
22547
+ let timeoutId;
22548
+ if (timeout > 0) timeoutId = setTimeout(() => reject(createTimeoutError(resolvedUrl)), timeout);
22549
+ const clearUploadTimeout = /* @__PURE__ */ __name(() => {
22550
+ if (timeoutId) {
22551
+ clearTimeout(timeoutId);
22552
+ timeoutId = void 0;
22553
+ }
22554
+ }, "clearUploadTimeout");
22555
+ onProgress?.({ loaded: 0, total: totalSize, percentage: 0 });
22556
+ const requestOptions = {
22557
+ hostname: parsedUrl.hostname,
22558
+ port: parsedUrl.port || (isHttps ? UPLOAD_CONSTANTS.HTTPS_DEFAULT_PORT : UPLOAD_CONSTANTS.HTTP_DEFAULT_PORT),
22559
+ path: parsedUrl.pathname + parsedUrl.search,
22560
+ method,
22561
+ headers: {
22562
+ "Content-Type": contentType,
22563
+ "Content-Length": totalSize.toString(),
22564
+ ...mergedHeaders
22565
+ }
22566
+ };
22567
+ const req = httpModule.request(requestOptions, (res) => {
22568
+ let responseData = "";
22569
+ res.on("data", (chunk) => {
22570
+ responseData += chunk;
22571
+ });
22572
+ res.on("end", () => {
22573
+ clearUploadTimeout();
22574
+ const success = res.statusCode !== void 0 && res.statusCode >= config.HTTP_STATUS.OK && res.statusCode < config.HTTP_STATUS.MULTIPLE_CHOICES;
22575
+ if (success) emitFinalProgress(onProgress, totalSize, state.startTime);
22576
+ resolve({
22577
+ status: res.statusCode ?? 0,
22578
+ statusText: res.statusMessage ?? "",
22579
+ data: responseData || void 0,
22580
+ headers: parseNodeHeaders(res.headers),
22581
+ success
22582
+ });
22583
+ });
22584
+ });
22585
+ if (abortSignal)
22586
+ abortSignal.addEventListener("abort", () => {
22587
+ clearUploadTimeout();
22588
+ req.destroy();
22589
+ state.status = "aborted";
22590
+ reject(createAbortError(resolvedUrl));
22591
+ });
22592
+ req.on("error", (error) => {
22593
+ clearUploadTimeout();
22594
+ state.status = "failed";
22595
+ state.error = error;
22596
+ reject(error);
22597
+ });
22598
+ let offset = 0;
22599
+ const writeNextChunk = /* @__PURE__ */ __name(() => {
22600
+ while (offset < totalSize) {
22601
+ const end = Math.min(offset + chunkSize, totalSize);
22602
+ const canContinue = req.write(buffer.subarray(offset, end));
22603
+ state.bytesUploaded = end;
22604
+ offset = end;
22605
+ if (onProgress && shouldEmitProgress(state, totalSize, throttleMs)) {
22606
+ onProgress(calculateProgress(state));
22607
+ state.lastProgressTime = Date.now();
22608
+ state.lastBytesUploaded = state.bytesUploaded;
22609
+ }
22610
+ if (!canContinue) {
22611
+ req.once("drain", writeNextChunk);
22612
+ return;
22613
+ }
22614
+ }
22615
+ state.status = "completed";
22616
+ req.end();
22617
+ }, "writeNextChunk");
22618
+ writeNextChunk();
22619
+ });
22620
+ }
22621
+ __name(uploadOnce, "uploadOnce");
22622
+ async function uploadWithProgressNode(options) {
22623
+ const config = getMergedConfig(options);
22624
+ const resolvedUrl = resolveUrl(options.url, config.baseURL);
22625
+ const maxAttempts = config.retry ? (config.retry.attempts ?? 0) + 1 : 1;
22626
+ let lastError;
22627
+ for (let attempt = 0; attempt < maxAttempts; attempt++) {
22628
+ const ctx = { config, maxAttempts, attempt };
22629
+ try {
22630
+ const result = await uploadOnce(options, config, resolvedUrl);
22631
+ if (shouldRetryResult(result, config, attempt, maxAttempts)) {
22632
+ notifyRetryError({
22633
+ ctx,
22634
+ message: `Upload failed: ${result.status}`,
22635
+ status: result.status,
22636
+ statusText: result.statusText
22637
+ });
22638
+ await handleRetryDelay(attempt, config.retry);
22639
+ continue;
22640
+ }
22641
+ return { ...result, attempts: attempt };
22642
+ } catch (error) {
22643
+ lastError = normalizeError(error);
22644
+ if (shouldRetryError(lastError, config, attempt, maxAttempts)) {
22645
+ notifyRetryError({ ctx, message: lastError.message, cause: lastError });
22646
+ await handleRetryDelay(attempt, config.retry);
22647
+ continue;
22648
+ }
22649
+ notifyFinalError(ctx, lastError);
22650
+ throw lastError;
22651
+ }
22652
+ }
22653
+ throw lastError ?? new ApiPackageError(
22654
+ "Upload failed after all retry attempts",
22655
+ void 0,
22656
+ errors.API_ERROR_CODES.NETWORK_ERROR
22657
+ );
22658
+ }
22659
+ __name(uploadWithProgressNode, "uploadWithProgressNode");
22660
+ var normalizeError2 = /* @__PURE__ */ __name((error) => error instanceof Error ? error : new ApiPackageError(String(error), void 0, errors.API_ERROR_CODES.UNKNOWN_ERROR), "normalizeError");
22661
+ async function uploadOnce2(options, config$1, resolvedUrl) {
22662
+ const {
22663
+ data,
22664
+ method = "PUT",
22665
+ contentType = UPLOAD_CONSTANTS.DEFAULT_CONTENT_TYPE,
22666
+ onProgress,
22667
+ abortSignal
22668
+ } = options;
22669
+ const { headers: mergedHeaders, timeout, withCredentials } = config$1;
22670
+ return new Promise((resolve, reject) => {
22671
+ const xhr = new XMLHttpRequest();
22672
+ const startTime = Date.now();
22673
+ if (timeout > 0) xhr.timeout = timeout;
22674
+ xhr.addEventListener(
22675
+ "timeout",
22676
+ () => reject(
22677
+ new ApiPackageError("Upload timed out", void 0, errors.API_ERROR_CODES.REQUEST_TIMEOUT, {
22678
+ context: { url: resolvedUrl }
22679
+ })
22680
+ )
22681
+ );
22682
+ xhr.upload.addEventListener("progress", (event) => {
22683
+ if (!event.lengthComputable || !onProgress) return;
22684
+ const elapsed = (Date.now() - startTime) / config.TIME_CONSTANTS.SECOND;
22685
+ const speed = elapsed > 0 ? event.loaded / elapsed : 0;
22686
+ const remaining = event.total - event.loaded;
22687
+ onProgress({
22688
+ loaded: event.loaded,
22689
+ total: event.total,
22690
+ percentage: Math.round(event.loaded / event.total * UPLOAD_CONSTANTS.FULL_PERCENTAGE),
22691
+ speed,
22692
+ estimatedTimeRemaining: speed > 0 ? remaining / speed : void 0
22693
+ });
22694
+ });
22695
+ xhr.addEventListener("load", () => {
22696
+ const success = xhr.status >= config.HTTP_STATUS.OK && xhr.status < config.HTTP_STATUS.MULTIPLE_CHOICES;
22697
+ const responseHeaders = {};
22698
+ const headerLines = xhr.getAllResponseHeaders().trim().split("\n");
22699
+ for (const line of headerLines) {
22700
+ const [key, ...valueParts] = line.split(":");
22701
+ if (key) responseHeaders[key.trim().toLowerCase()] = valueParts.join(":").trim();
22702
+ }
22703
+ resolve({
22704
+ status: xhr.status,
22705
+ statusText: xhr.statusText,
22706
+ data: xhr.responseText || void 0,
22707
+ headers: responseHeaders,
22708
+ success
22709
+ });
22710
+ });
22711
+ xhr.addEventListener(
22712
+ "error",
22713
+ () => reject(
22714
+ new ApiPackageError(
22715
+ `Upload failed: ${xhr.statusText || "Network error"}`,
22716
+ void 0,
22717
+ errors.API_ERROR_CODES.NETWORK_ERROR,
22718
+ { context: { url: resolvedUrl, statusText: xhr.statusText } }
22719
+ )
22720
+ )
22721
+ );
22722
+ xhr.addEventListener(
22723
+ "abort",
22724
+ () => reject(
22725
+ new ApiPackageError("Upload aborted", void 0, errors.API_ERROR_CODES.REQUEST_ABORTED, {
22726
+ context: { url: resolvedUrl }
22727
+ })
22728
+ )
22729
+ );
22730
+ if (abortSignal) abortSignal.addEventListener("abort", () => xhr.abort());
22731
+ xhr.open(method, resolvedUrl);
22732
+ if (withCredentials) xhr.withCredentials = true;
22733
+ xhr.setRequestHeader("Content-Type", contentType);
22734
+ for (const [key, value] of Object.entries(mergedHeaders)) xhr.setRequestHeader(key, value);
22735
+ if (data instanceof Blob || data instanceof ArrayBuffer) {
22736
+ xhr.send(data);
22737
+ } else if (data instanceof Uint8Array) {
22738
+ xhr.send(new Uint8Array(data));
22739
+ } else {
22740
+ xhr.send(data);
22741
+ }
22742
+ });
22743
+ }
22744
+ __name(uploadOnce2, "uploadOnce");
22745
+ async function uploadWithProgressBrowser(options) {
22746
+ const config = getMergedConfig(options);
22747
+ const resolvedUrl = resolveUrl(options.url, config.baseURL);
22748
+ const maxAttempts = config.retry ? (config.retry.attempts ?? 0) + 1 : 1;
22749
+ let lastError;
22750
+ for (let attempt = 0; attempt < maxAttempts; attempt++) {
22751
+ const ctx = { config, maxAttempts, attempt };
22752
+ try {
22753
+ const result = await uploadOnce2(options, config, resolvedUrl);
22754
+ if (shouldRetryResult(result, config, attempt, maxAttempts)) {
22755
+ notifyRetryError({
22756
+ ctx,
22757
+ message: `Upload failed: ${result.status}`,
22758
+ status: result.status,
22759
+ statusText: result.statusText
22760
+ });
22761
+ await handleRetryDelay(attempt, config.retry);
22762
+ continue;
22763
+ }
22764
+ return { ...result, attempts: attempt };
22765
+ } catch (error) {
22766
+ lastError = normalizeError2(error);
22767
+ if (shouldRetryError(lastError, config, attempt, maxAttempts)) {
22768
+ notifyRetryError({ ctx, message: lastError.message, cause: lastError });
22769
+ await handleRetryDelay(attempt, config.retry);
22770
+ continue;
22771
+ }
22772
+ notifyFinalError(ctx, lastError);
22773
+ throw lastError;
22774
+ }
22775
+ }
22776
+ throw lastError ?? new ApiPackageError(
22777
+ "Upload failed after all retry attempts",
22778
+ void 0,
22779
+ errors.API_ERROR_CODES.NETWORK_ERROR
22780
+ );
22781
+ }
22782
+ __name(uploadWithProgressBrowser, "uploadWithProgressBrowser");
22783
+
22784
+ // src/api/upload/uploadWithProgress.ts
22785
+ async function uploadWithProgress(options) {
22786
+ if (isNode()) {
22787
+ return uploadWithProgressNode(options);
22788
+ }
22789
+ return uploadWithProgressBrowser(options);
22790
+ }
22791
+ __name(uploadWithProgress, "uploadWithProgress");
22252
22792
 
22253
22793
  // src/api/hooks/factories/defaults.ts
22254
22794
  var DEFAULT_QUERY_OPTIONS = {};
@@ -24396,13 +24936,13 @@ function isAbortError(error) {
24396
24936
  return message.includes("abort") || message.includes("cancel");
24397
24937
  }
24398
24938
  __name(isAbortError, "isAbortError");
24399
- function createAbortError(message = "Request aborted") {
24939
+ function createAbortError2(message = "Request aborted") {
24400
24940
  if (message === null || message === void 0) {
24401
24941
  return "Request aborted";
24402
24942
  }
24403
24943
  return message;
24404
24944
  }
24405
- __name(createAbortError, "createAbortError");
24945
+ __name(createAbortError2, "createAbortError");
24406
24946
 
24407
24947
  // src/api/request/tracker.ts
24408
24948
  var RequestTracker = class {
@@ -24452,7 +24992,7 @@ var RequestTracker = class {
24452
24992
  controller.abort(reason);
24453
24993
  this.unregister(key);
24454
24994
  }
24455
- void abortRequest(key, createAbortError(reason ?? "Request aborted"));
24995
+ void abortRequest(key, createAbortError2(reason ?? "Request aborted"));
24456
24996
  }
24457
24997
  /**
24458
24998
  * Abort all requests in a group
@@ -24478,7 +25018,7 @@ var RequestTracker = class {
24478
25018
  });
24479
25019
  this.activeRequests.clear();
24480
25020
  this.requestGroups.clear();
24481
- void abortRequest("*", createAbortError(reason ?? "All requests aborted"));
25021
+ void abortRequest("*", createAbortError2(reason ?? "All requests aborted"));
24482
25022
  }
24483
25023
  /**
24484
25024
  * Get active request count
@@ -24535,14 +25075,14 @@ function useRequestCleanup() {
24535
25075
  }, "untrackRequest");
24536
25076
  const abortTracked = /* @__PURE__ */ __name((reason) => {
24537
25077
  requestKeys.current.forEach((key) => {
24538
- void abortRequest(key, createAbortError(reason ?? "Manual abort"));
25078
+ void abortRequest(key, createAbortError2(reason ?? "Manual abort"));
24539
25079
  });
24540
25080
  requestKeys.current.clear();
24541
25081
  }, "abortTracked");
24542
25082
  react.useEffect(() => {
24543
25083
  return () => {
24544
25084
  requestKeys.current.forEach((key) => {
24545
- void abortRequest(key, createAbortError("Component unmounted"));
25085
+ void abortRequest(key, createAbortError2("Component unmounted"));
24546
25086
  });
24547
25087
  requestKeys.current.clear();
24548
25088
  };
@@ -24563,14 +25103,14 @@ function useAbortableRequest(key) {
24563
25103
  controllerRef.current.abort("Component unmounted or dependency changed");
24564
25104
  requestTracker.unregister(key);
24565
25105
  }
24566
- void abortRequest(key, createAbortError("Request cancelled"));
25106
+ void abortRequest(key, createAbortError2("Request cancelled"));
24567
25107
  };
24568
25108
  }, [key]);
24569
25109
  const abort = /* @__PURE__ */ __name((reason) => {
24570
25110
  if (controllerRef.current) {
24571
25111
  controllerRef.current.abort(reason);
24572
25112
  }
24573
- void abortRequest(key, createAbortError(reason ?? "Request aborted by user"));
25113
+ void abortRequest(key, createAbortError2(reason ?? "Request aborted by user"));
24574
25114
  }, "abort");
24575
25115
  return {
24576
25116
  signal,
@@ -24632,9 +25172,9 @@ function setupRouteChangeCleanup(router, options = {}) {
24632
25172
  }
24633
25173
  const pattern = options.abortPattern ?? "*";
24634
25174
  if (options.preservePatterns && options.preservePatterns.length > 0) {
24635
- void abortRequest(pattern, createAbortError(`Route changed to ${url}`));
25175
+ void abortRequest(pattern, createAbortError2(`Route changed to ${url}`));
24636
25176
  } else {
24637
- void abortRequest(pattern, createAbortError(`Route changed to ${url}`));
25177
+ void abortRequest(pattern, createAbortError2(`Route changed to ${url}`));
24638
25178
  }
24639
25179
  }, "executeAbort");
24640
25180
  if (options.delay && options.delay > 0) {
@@ -24681,7 +25221,7 @@ function createRouteGuard(pattern = "*") {
24681
25221
  }, "enter"),
24682
25222
  leave: /* @__PURE__ */ __name((reason) => {
24683
25223
  if (isActive) {
24684
- void abortRequest(pattern, createAbortError(reason ?? "Leaving route"));
25224
+ void abortRequest(pattern, createAbortError2(reason ?? "Leaving route"));
24685
25225
  isActive = false;
24686
25226
  }
24687
25227
  }, "leave"),
@@ -24713,7 +25253,7 @@ __name(createRouteScope, "createRouteScope");
24713
25253
 
24714
25254
  // src/api/request/utils.ts
24715
25255
  function abortByPattern(pattern, reason) {
24716
- void abortRequest(pattern, createAbortError(reason ?? `Requests matching ${pattern} aborted`));
25256
+ void abortRequest(pattern, createAbortError2(reason ?? `Requests matching ${pattern} aborted`));
24717
25257
  }
24718
25258
  __name(abortByPattern, "abortByPattern");
24719
25259
  function abortSearchRequests(reason) {
@@ -24731,25 +25271,25 @@ __name(abortAllRequests, "abortAllRequests");
24731
25271
  function createScopedAbort(scope) {
24732
25272
  return (key, reason) => {
24733
25273
  const fullKey = key.startsWith("/") ? `${scope}${key}` : `${scope}/${key}`;
24734
- void abortRequest(fullKey, createAbortError(reason ?? "Scoped request aborted"));
25274
+ void abortRequest(fullKey, createAbortError2(reason ?? "Scoped request aborted"));
24735
25275
  };
24736
25276
  }
24737
25277
  __name(createScopedAbort, "createScopedAbort");
24738
25278
  function createDebouncedAbort(delay = 300) {
24739
25279
  return debounce((key, reason) => {
24740
- void abortRequest(key, createAbortError(reason ?? "Debounced abort"));
25280
+ void abortRequest(key, createAbortError2(reason ?? "Debounced abort"));
24741
25281
  }, delay);
24742
25282
  }
24743
25283
  __name(createDebouncedAbort, "createDebouncedAbort");
24744
25284
  function createThrottledAbort(limit = 1e3) {
24745
25285
  return throttle((key, reason) => {
24746
- void abortRequest(key, createAbortError(reason ?? "Throttled abort"));
25286
+ void abortRequest(key, createAbortError2(reason ?? "Throttled abort"));
24747
25287
  }, limit);
24748
25288
  }
24749
25289
  __name(createThrottledAbort, "createThrottledAbort");
24750
25290
  async function requestWithTimeout(key, fetcher, timeoutMs) {
24751
25291
  const timeoutId = setTimeout(() => {
24752
- void abortRequest(key, createAbortError(`Request timeout after ${timeoutMs}ms`));
25292
+ void abortRequest(key, createAbortError2(`Request timeout after ${timeoutMs}ms`));
24753
25293
  }, timeoutMs);
24754
25294
  try {
24755
25295
  return await fetcher();
@@ -24762,7 +25302,7 @@ async function raceRequests(requests) {
24762
25302
  const abortLosers = /* @__PURE__ */ __name((winnerKey) => {
24763
25303
  requests.forEach((req) => {
24764
25304
  if (req.key !== winnerKey) {
24765
- void abortRequest(req.key, createAbortError("Lost race"));
25305
+ void abortRequest(req.key, createAbortError2("Lost race"));
24766
25306
  }
24767
25307
  });
24768
25308
  }, "abortLosers");
@@ -24783,7 +25323,7 @@ async function sequentialRequests(requests) {
24783
25323
  results.push(result);
24784
25324
  } catch (error) {
24785
25325
  for (let j = i + 1; j < requests.length; j++) {
24786
- void abortRequest(requests[j].key, createAbortError("Previous request in chain failed"));
25326
+ void abortRequest(requests[j].key, createAbortError2("Previous request in chain failed"));
24787
25327
  }
24788
25328
  throw error;
24789
25329
  }
@@ -27039,7 +27579,7 @@ exports.configConflictDetector = configConflictDetector;
27039
27579
  exports.configureForEnvironment = configureForEnvironment;
27040
27580
  exports.containsAny = containsAny;
27041
27581
  exports.convertEndpointsToFetchff = convertEndpointsToFetchff;
27042
- exports.createAbortError = createAbortError;
27582
+ exports.createAbortError = createAbortError2;
27043
27583
  exports.createAdaptiveResponse = createAdaptiveResponse;
27044
27584
  exports.createApiClient = createApiClient;
27045
27585
  exports.createCachePattern = createCachePattern;
@@ -27490,6 +28030,7 @@ exports.updateInfobipScheduledEmailStatuses = updateInfobipScheduledEmailStatuse
27490
28030
  exports.uploadFile = uploadFile;
27491
28031
  exports.uploadFileForScanning = uploadFileForScanning;
27492
28032
  exports.uploadFiles = uploadFiles;
28033
+ exports.uploadWithProgress = uploadWithProgress;
27493
28034
  exports.useAbortableRequest = useAbortableRequest;
27494
28035
  exports.useApiConfigConflicts = useApiConfigConflicts;
27495
28036
  exports.useApiDebugInfo = useApiDebugInfo;