lifecycleion 0.0.20 → 0.0.21

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.
Files changed (72) hide show
  1. package/README.md +39 -36
  2. package/dist/lib/event-emitter.cjs +195 -9
  3. package/dist/lib/event-emitter.cjs.map +1 -1
  4. package/dist/lib/event-emitter.js +195 -9
  5. package/dist/lib/event-emitter.js.map +1 -1
  6. package/dist/lib/global-event-target.cjs +217 -0
  7. package/dist/lib/global-event-target.cjs.map +1 -0
  8. package/dist/lib/global-event-target.d.cts +70 -0
  9. package/dist/lib/global-event-target.d.ts +70 -0
  10. package/dist/lib/global-event-target.js +189 -0
  11. package/dist/lib/global-event-target.js.map +1 -0
  12. package/dist/lib/http-client/index.cjs +554 -193
  13. package/dist/lib/http-client/index.cjs.map +1 -1
  14. package/dist/lib/http-client/index.d.cts +9 -3
  15. package/dist/lib/http-client/index.d.ts +9 -3
  16. package/dist/lib/http-client/index.js +554 -193
  17. package/dist/lib/http-client/index.js.map +1 -1
  18. package/dist/lib/http-client-mock/index.cjs +71 -10
  19. package/dist/lib/http-client-mock/index.cjs.map +1 -1
  20. package/dist/lib/http-client-mock/index.d.cts +50 -3
  21. package/dist/lib/http-client-mock/index.d.ts +50 -3
  22. package/dist/lib/http-client-mock/index.js +71 -10
  23. package/dist/lib/http-client-mock/index.js.map +1 -1
  24. package/dist/lib/http-client-node/index.cjs +98 -19
  25. package/dist/lib/http-client-node/index.cjs.map +1 -1
  26. package/dist/lib/http-client-node/index.d.cts +2 -2
  27. package/dist/lib/http-client-node/index.d.ts +2 -2
  28. package/dist/lib/http-client-node/index.js +98 -19
  29. package/dist/lib/http-client-node/index.js.map +1 -1
  30. package/dist/lib/http-client-xhr/index.cjs.map +1 -1
  31. package/dist/lib/http-client-xhr/index.d.cts +2 -2
  32. package/dist/lib/http-client-xhr/index.d.ts +2 -2
  33. package/dist/lib/http-client-xhr/index.js.map +1 -1
  34. package/dist/lib/lifecycle-manager/index.cjs +199 -13
  35. package/dist/lib/lifecycle-manager/index.cjs.map +1 -1
  36. package/dist/lib/lifecycle-manager/index.js +199 -13
  37. package/dist/lib/lifecycle-manager/index.js.map +1 -1
  38. package/dist/lib/logger/index.cjs +203 -21
  39. package/dist/lib/logger/index.cjs.map +1 -1
  40. package/dist/lib/logger/index.d.cts +5 -1
  41. package/dist/lib/logger/index.d.ts +5 -1
  42. package/dist/lib/logger/index.js +203 -21
  43. package/dist/lib/logger/index.js.map +1 -1
  44. package/dist/lib/lru-cache/index.cjs +195 -9
  45. package/dist/lib/lru-cache/index.cjs.map +1 -1
  46. package/dist/lib/lru-cache/index.js +195 -9
  47. package/dist/lib/lru-cache/index.js.map +1 -1
  48. package/dist/lib/process-signal-manager.cjs +199 -13
  49. package/dist/lib/process-signal-manager.cjs.map +1 -1
  50. package/dist/lib/process-signal-manager.js +199 -13
  51. package/dist/lib/process-signal-manager.js.map +1 -1
  52. package/dist/lib/promise-protected-resolver.cjs +195 -9
  53. package/dist/lib/promise-protected-resolver.cjs.map +1 -1
  54. package/dist/lib/promise-protected-resolver.js +195 -9
  55. package/dist/lib/promise-protected-resolver.js.map +1 -1
  56. package/dist/lib/retry-utils/index.cjs +195 -9
  57. package/dist/lib/retry-utils/index.cjs.map +1 -1
  58. package/dist/lib/retry-utils/index.js +195 -9
  59. package/dist/lib/retry-utils/index.js.map +1 -1
  60. package/dist/lib/safe-handle-callback.cjs +196 -18
  61. package/dist/lib/safe-handle-callback.cjs.map +1 -1
  62. package/dist/lib/safe-handle-callback.d.cts +14 -4
  63. package/dist/lib/safe-handle-callback.d.ts +14 -4
  64. package/dist/lib/safe-handle-callback.js +196 -18
  65. package/dist/lib/safe-handle-callback.js.map +1 -1
  66. package/dist/lib/single-event-observer.cjs +195 -9
  67. package/dist/lib/single-event-observer.cjs.map +1 -1
  68. package/dist/lib/single-event-observer.js +195 -9
  69. package/dist/lib/single-event-observer.js.map +1 -1
  70. package/dist/{types-6G59m8U9.d.cts → types-BFvpJPMt.d.cts} +71 -10
  71. package/dist/{types-CG10j6Lc.d.ts → types-BONtIhQ5.d.ts} +71 -10
  72. package/package.json +12 -2
@@ -1227,18 +1227,204 @@ function isFunction(value) {
1227
1227
  return typeof value === "function" || value instanceof Function;
1228
1228
  }
1229
1229
 
1230
+ // src/lib/global-event-target.ts
1231
+ var GLOBAL_KEY = "__lifecycleion_global_event_target__";
1232
+ var METHOD_NAMES = [
1233
+ "addEventListener",
1234
+ "removeEventListener",
1235
+ "dispatchEvent"
1236
+ ];
1237
+ var g = globalThis;
1238
+ function getState() {
1239
+ const value = readGlobal(GLOBAL_KEY);
1240
+ return value === UNREADABLE ? void 0 : asUsableState(value);
1241
+ }
1242
+ function asUsableState(value) {
1243
+ if (typeof value !== "object" || value === null) {
1244
+ return void 0;
1245
+ }
1246
+ return asUsableTarget(readMember(value, "target")) === null ? void 0 : value;
1247
+ }
1248
+ function asUsableTarget(value) {
1249
+ if (typeof value !== "object" || value === null) {
1250
+ return null;
1251
+ }
1252
+ for (const name of METHOD_NAMES) {
1253
+ if (typeof readMember(value, name) !== "function") {
1254
+ return null;
1255
+ }
1256
+ }
1257
+ return value;
1258
+ }
1259
+ function bindTargetMethods(target) {
1260
+ const bound = {};
1261
+ for (const name of METHOD_NAMES) {
1262
+ const method = readMember(target, name);
1263
+ if (typeof method !== "function") {
1264
+ return null;
1265
+ }
1266
+ let boundMethod;
1267
+ try {
1268
+ boundMethod = method.bind(target);
1269
+ } catch {
1270
+ return null;
1271
+ }
1272
+ if (typeof boundMethod !== "function") {
1273
+ return null;
1274
+ }
1275
+ bound[name] = boundMethod;
1276
+ }
1277
+ return bound;
1278
+ }
1279
+ function isStateInstalled(state) {
1280
+ return state !== void 0 && readMember(state, "isInstalled") === true;
1281
+ }
1282
+ function readStateTarget(state) {
1283
+ if (state === void 0) {
1284
+ return null;
1285
+ }
1286
+ return asUsableTarget(readMember(state, "target"));
1287
+ }
1288
+ var UNREADABLE = /* @__PURE__ */ Symbol("lifecycleion.unreadable");
1289
+ function readGlobal(name) {
1290
+ try {
1291
+ return g[name];
1292
+ } catch {
1293
+ return UNREADABLE;
1294
+ }
1295
+ }
1296
+ function readMember(source, key) {
1297
+ try {
1298
+ return source[key];
1299
+ } catch {
1300
+ return UNREADABLE;
1301
+ }
1302
+ }
1303
+ function probeMember(name) {
1304
+ const value = readGlobal(name);
1305
+ if (value === UNREADABLE) {
1306
+ return "hostile";
1307
+ }
1308
+ if (typeof value === "function") {
1309
+ return "usable";
1310
+ }
1311
+ return value === void 0 ? "absent" : "occupied";
1312
+ }
1313
+ function canDefineProperty(key) {
1314
+ const descriptor = Object.getOwnPropertyDescriptor(g, key);
1315
+ if (descriptor === void 0) {
1316
+ return Object.isExtensible(g);
1317
+ }
1318
+ return descriptor.configurable === true;
1319
+ }
1320
+ function installGlobalEventTarget() {
1321
+ const members = METHOD_NAMES.map((name) => probeMember(name));
1322
+ if (members.every((member) => member === "usable")) {
1323
+ return isStateInstalled(getState()) ? "already-installed" : "native";
1324
+ }
1325
+ if (members.some((member) => member !== "absent")) {
1326
+ return "partial";
1327
+ }
1328
+ const eventTargetConstructor = readGlobal("EventTarget");
1329
+ if (typeof eventTargetConstructor !== "function") {
1330
+ return "unsupported";
1331
+ }
1332
+ const isDefinable = [...METHOD_NAMES, GLOBAL_KEY].every(
1333
+ (key) => canDefineProperty(key)
1334
+ );
1335
+ if (!isDefinable) {
1336
+ return "blocked";
1337
+ }
1338
+ const existingState = getState();
1339
+ const defined = [];
1340
+ const priorStateDescriptor = Object.getOwnPropertyDescriptor(g, GLOBAL_KEY);
1341
+ const rollback = () => {
1342
+ for (const key of defined) {
1343
+ if (key === GLOBAL_KEY && priorStateDescriptor !== void 0) {
1344
+ try {
1345
+ Object.defineProperty(g, GLOBAL_KEY, priorStateDescriptor);
1346
+ } catch {
1347
+ }
1348
+ continue;
1349
+ }
1350
+ try {
1351
+ Reflect.deleteProperty(g, key);
1352
+ } catch {
1353
+ }
1354
+ }
1355
+ };
1356
+ const reusableTarget = readStateTarget(existingState);
1357
+ const reusableMethods = reusableTarget === null ? null : bindTargetMethods(reusableTarget);
1358
+ let state;
1359
+ let methods;
1360
+ try {
1361
+ if (existingState === void 0 || reusableMethods === null) {
1362
+ let target;
1363
+ try {
1364
+ target = new eventTargetConstructor();
1365
+ } catch {
1366
+ return "unsupported";
1367
+ }
1368
+ const freshMethods = bindTargetMethods(target);
1369
+ if (freshMethods === null) {
1370
+ return "unsupported";
1371
+ }
1372
+ state = { target, isInstalled: false };
1373
+ methods = freshMethods;
1374
+ Object.defineProperty(g, GLOBAL_KEY, {
1375
+ value: state,
1376
+ enumerable: false,
1377
+ writable: false,
1378
+ configurable: true
1379
+ });
1380
+ defined.push(GLOBAL_KEY);
1381
+ } else {
1382
+ state = existingState;
1383
+ methods = reusableMethods;
1384
+ }
1385
+ for (const name of METHOD_NAMES) {
1386
+ Object.defineProperty(g, name, {
1387
+ value: methods[name],
1388
+ enumerable: false,
1389
+ writable: true,
1390
+ configurable: true
1391
+ });
1392
+ defined.push(name);
1393
+ }
1394
+ if (readMember(state, "isInstalled") !== true) {
1395
+ state.isInstalled = true;
1396
+ }
1397
+ } catch {
1398
+ rollback();
1399
+ return "blocked";
1400
+ }
1401
+ return "installed";
1402
+ }
1403
+ function isGlobalEventTargetAvailable() {
1404
+ return METHOD_NAMES.every((name) => probeMember(name) === "usable") && probeMember("ErrorEvent") === "usable";
1405
+ }
1406
+
1230
1407
  // src/lib/safe-handle-callback.ts
1408
+ installGlobalEventTarget();
1409
+ function reportCallbackError(callbackName, error) {
1410
+ installGlobalEventTarget();
1411
+ if (!isGlobalEventTargetAvailable()) {
1412
+ return;
1413
+ }
1414
+ try {
1415
+ globalThis.dispatchEvent(
1416
+ new ErrorEvent("reportError", {
1417
+ error: new Error(
1418
+ `Error in a callback ${callbackName}: ${DOUBLE_EOL}${errorToString(error)}`
1419
+ )
1420
+ })
1421
+ );
1422
+ } catch {
1423
+ }
1424
+ }
1231
1425
  async function safeHandleCallbackAndWait(callbackName, callback, ...args) {
1232
1426
  const handleError = (error) => {
1233
- if (typeof globalThis.dispatchEvent === "function") {
1234
- globalThis.dispatchEvent(
1235
- new ErrorEvent("reportError", {
1236
- error: new Error(
1237
- `Error in a callback ${callbackName}: ${DOUBLE_EOL}${errorToString(error)}`
1238
- )
1239
- })
1240
- );
1241
- }
1427
+ reportCallbackError(callbackName, error);
1242
1428
  return { success: false, error };
1243
1429
  };
1244
1430
  if (isFunction(callback)) {
@@ -2003,6 +2189,74 @@ function matchesFilter(filter, context, phaseType, kind) {
2003
2189
  return true;
2004
2190
  }
2005
2191
 
2192
+ // src/lib/http-client/internal/tls-error-utils.ts
2193
+ var CERT_ERROR_CODES = /* @__PURE__ */ new Set([
2194
+ "UNABLE_TO_VERIFY_LEAF_SIGNATURE",
2195
+ "CERT_HAS_EXPIRED",
2196
+ "DEPTH_ZERO_SELF_SIGNED_CERT",
2197
+ "ERR_TLS_CERT_ALTNAME_INVALID",
2198
+ "ERR_SSL_TLSV13_ALERT_CERTIFICATE_REQUIRED",
2199
+ "ERR_SSL_PEER_DID_NOT_RETURN_A_CERTIFICATE",
2200
+ "SELF_SIGNED_CERT_IN_CHAIN",
2201
+ "UNABLE_TO_GET_ISSUER_CERT_LOCALLY",
2202
+ "CERT_REVOKED"
2203
+ ]);
2204
+ var CRL_CODE_PATTERN = /(?:^|_)CRLS?(?:_|$)/;
2205
+ var TRANSPORT_ERROR_CODES = /* @__PURE__ */ new Set([
2206
+ "ENOTFOUND",
2207
+ "EAI_AGAIN",
2208
+ "ECONNREFUSED",
2209
+ "ECONNRESET",
2210
+ "ECONNABORTED",
2211
+ "ETIMEDOUT",
2212
+ "EPIPE",
2213
+ "EHOSTUNREACH",
2214
+ "EHOSTDOWN",
2215
+ "ENETUNREACH",
2216
+ "ENETDOWN",
2217
+ "EADDRNOTAVAIL"
2218
+ ]);
2219
+ var UNDICI_TRANSPORT_ERROR_PREFIX = "UND_ERR_";
2220
+ function isTLSCertificateError(error) {
2221
+ if (isTLSCertificateErrorSelf(error)) {
2222
+ return true;
2223
+ }
2224
+ const cause = readMember2(error, "cause");
2225
+ return isErrorValue(cause) ? isTLSCertificateErrorSelf(cause) : false;
2226
+ }
2227
+ function isErrorValue(value) {
2228
+ try {
2229
+ return value instanceof Error;
2230
+ } catch {
2231
+ return false;
2232
+ }
2233
+ }
2234
+ function isTLSCertificateErrorSelf(error) {
2235
+ const rawCode = readMember2(error, "code");
2236
+ const code = typeof rawCode === "string" ? rawCode : "";
2237
+ if (CERT_ERROR_CODES.has(code)) {
2238
+ return true;
2239
+ }
2240
+ if (CRL_CODE_PATTERN.test(code)) {
2241
+ return true;
2242
+ }
2243
+ if ((code.startsWith("ERR_TLS_") || code.startsWith("ERR_SSL_")) && code.includes("CERT")) {
2244
+ return true;
2245
+ }
2246
+ if (TRANSPORT_ERROR_CODES.has(code) || code.startsWith(UNDICI_TRANSPORT_ERROR_PREFIX)) {
2247
+ return false;
2248
+ }
2249
+ const message = readMember2(error, "message");
2250
+ return typeof message === "string" ? /certificate|self signed|unable to verify|altname/i.test(message) : false;
2251
+ }
2252
+ function readMember2(error, key) {
2253
+ try {
2254
+ return error[key];
2255
+ } catch {
2256
+ return void 0;
2257
+ }
2258
+ }
2259
+
2006
2260
  // src/lib/http-client/consts.ts
2007
2261
  var RETRYABLE_STATUS_CODES = /* @__PURE__ */ new Set([
2008
2262
  // 0: Browser/XHR-style "no response" status.
@@ -2038,6 +2292,7 @@ var RETRYABLE_STATUS_CODES = /* @__PURE__ */ new Set([
2038
2292
  // 599 Network Connect Timeout Error (non-standard)
2039
2293
  599
2040
2294
  ]);
2295
+ var NON_IDEMPOTENT_METHODS = /* @__PURE__ */ new Set(["POST", "PATCH"]);
2041
2296
  var DEFAULT_TIMEOUT_MS = 3e4;
2042
2297
  var DEFAULT_REQUEST_ID_HEADER = "x-local-client-request-id";
2043
2298
  var DEFAULT_REQUEST_ATTEMPT_HEADER = "x-local-client-request-attempt";
@@ -2123,12 +2378,23 @@ var FetchAdapter = class {
2123
2378
  if (isAbortError(error) || signal?.aborted) {
2124
2379
  throw error;
2125
2380
  }
2381
+ const normalizedError = normalizeError(error);
2382
+ if (isTLSCertificateError(normalizedError)) {
2383
+ return {
2384
+ status: 495,
2385
+ isTransportError: true,
2386
+ isRetryable: false,
2387
+ headers: {},
2388
+ body: null,
2389
+ errorCause: normalizedError
2390
+ };
2391
+ }
2126
2392
  return {
2127
2393
  status: 0,
2128
2394
  isTransportError: true,
2129
2395
  headers: {},
2130
2396
  body: null,
2131
- errorCause: error instanceof Error ? error : new Error(String(error))
2397
+ errorCause: normalizedError
2132
2398
  };
2133
2399
  }
2134
2400
  if (response.type === "opaqueredirect") {
@@ -2142,13 +2408,43 @@ var FetchAdapter = class {
2142
2408
  };
2143
2409
  }
2144
2410
  request.onUploadProgress?.({ loaded: 1, total: 1, progress: 1 });
2145
- const rawBody = await readResponseBody(method, response);
2411
+ const responseHeadersForBody = extractFetchHeaders(response.headers);
2412
+ let rawBody;
2413
+ try {
2414
+ rawBody = await readResponseBody(method, response);
2415
+ } catch (error) {
2416
+ if (isAbortError(error) || signal?.aborted) {
2417
+ throw markResponseStreamAbort(
2418
+ error,
2419
+ response.status,
2420
+ responseHeadersForBody
2421
+ );
2422
+ }
2423
+ const detectedRedirectURL2 = resolveDetectedRedirectURL(
2424
+ requestURL,
2425
+ response.status,
2426
+ responseHeadersForBody
2427
+ );
2428
+ return {
2429
+ status: response.status,
2430
+ wasRedirectDetected: detectedRedirectURL2 !== void 0 || REDIRECT_STATUS_CODES.has(response.status),
2431
+ ...detectedRedirectURL2 ? { detectedRedirectURL: detectedRedirectURL2 } : {},
2432
+ headers: responseHeadersForBody,
2433
+ body: null,
2434
+ isStreamError: true,
2435
+ // fetch buffers the body for us, so there is no per-chunk delivery to
2436
+ // distinguish a local write failure from an upstream stream failure.
2437
+ // Everything reaching here is an upstream/transfer failure.
2438
+ streamErrorCode: "stream_response_error",
2439
+ errorCause: normalizeError(error)
2440
+ };
2441
+ }
2146
2442
  request.onDownloadProgress?.({
2147
2443
  loaded: rawBody?.length ?? 0,
2148
2444
  total: rawBody?.length ?? 0,
2149
2445
  progress: 1
2150
2446
  });
2151
- const responseHeaders = extractFetchHeaders(response.headers);
2447
+ const responseHeaders = responseHeadersForBody;
2152
2448
  const detectedRedirectURL = resolveDetectedRedirectURL(
2153
2449
  requestURL,
2154
2450
  response.status,
@@ -2173,7 +2469,33 @@ async function readResponseBody(method, response) {
2173
2469
  return new Uint8Array(buffer);
2174
2470
  }
2175
2471
  function isAbortError(error) {
2176
- return error instanceof Error && error.name === "AbortError";
2472
+ const normalized = asError(error);
2473
+ return normalized !== void 0 && readObjectMember(normalized, "name") === "AbortError";
2474
+ }
2475
+ function asError(value) {
2476
+ try {
2477
+ return value instanceof Error ? value : void 0;
2478
+ } catch {
2479
+ return void 0;
2480
+ }
2481
+ }
2482
+ function normalizeError(value) {
2483
+ const existing = asError(value);
2484
+ if (existing !== void 0) {
2485
+ return existing;
2486
+ }
2487
+ try {
2488
+ return new Error(String(value));
2489
+ } catch {
2490
+ return new Error("Unknown error");
2491
+ }
2492
+ }
2493
+ function readObjectMember(source, key) {
2494
+ try {
2495
+ return source[key];
2496
+ } catch {
2497
+ return void 0;
2498
+ }
2177
2499
  }
2178
2500
  function materializeFetchHeaders(headers) {
2179
2501
  let shouldUseHeadersObject = false;
@@ -2202,6 +2524,22 @@ function materializeFetchHeaders(headers) {
2202
2524
  }
2203
2525
  return materialized;
2204
2526
  }
2527
+ function markResponseStreamAbort(error, status, headers) {
2528
+ const original = asError(error);
2529
+ const originalMessage = original === void 0 ? void 0 : readObjectMember(original, "message");
2530
+ const originalName = original === void 0 ? void 0 : readObjectMember(original, "name");
2531
+ const tagged = new Error(
2532
+ typeof originalMessage === "string" ? originalMessage : "Request aborted"
2533
+ );
2534
+ tagged.name = typeof originalName === "string" ? originalName : "AbortError";
2535
+ Object.assign(tagged, {
2536
+ [RESPONSE_STREAM_ABORT_FLAG]: true,
2537
+ streamAbortStatus: status,
2538
+ streamAbortHeaders: headers,
2539
+ cause: error
2540
+ });
2541
+ return tagged;
2542
+ }
2205
2543
 
2206
2544
  // src/lib/http-client/internal/header-utils.ts
2207
2545
  function isBrowserRestrictedHeader(key, value) {
@@ -2361,6 +2699,7 @@ var HTTPRequestBuilder = class {
2361
2699
  _timeout;
2362
2700
  _signal;
2363
2701
  _retryPolicy;
2702
+ _retryNonIdempotentMethods;
2364
2703
  _label;
2365
2704
  _onUploadProgress;
2366
2705
  _onDownloadProgress;
@@ -2445,6 +2784,15 @@ var HTTPRequestBuilder = class {
2445
2784
  this._retryPolicy = options;
2446
2785
  return this;
2447
2786
  }
2787
+ /**
2788
+ * Allow or forbid retrying this request when its method is not idempotent
2789
+ * (`POST`, `PATCH`). Overrides the client config for this request only.
2790
+ */
2791
+ retryNonIdempotentMethods(allow) {
2792
+ this._assertNotSent("retryNonIdempotentMethods");
2793
+ this._retryNonIdempotentMethods = allow;
2794
+ return this;
2795
+ }
2448
2796
  onUploadProgress(fn) {
2449
2797
  this._assertNotSent("onUploadProgress");
2450
2798
  this._onUploadProgress = fn;
@@ -2573,6 +2921,7 @@ var HTTPRequestBuilder = class {
2573
2921
  timeout: this._timeout,
2574
2922
  signal: this._signal,
2575
2923
  retryPolicy: this._retryPolicy,
2924
+ retryNonIdempotentMethods: this._retryNonIdempotentMethods,
2576
2925
  label: this._label,
2577
2926
  onUploadProgress: this._onUploadProgress,
2578
2927
  onDownloadProgress: this._onDownloadProgress,
@@ -2632,6 +2981,9 @@ var HTTPRequestBuilder = class {
2632
2981
  if (opts.retryPolicy !== void 0) {
2633
2982
  this.retryPolicy(opts.retryPolicy);
2634
2983
  }
2984
+ if (opts.retryNonIdempotentMethods !== void 0) {
2985
+ this.retryNonIdempotentMethods(opts.retryNonIdempotentMethods);
2986
+ }
2635
2987
  if (opts.label !== void 0) {
2636
2988
  this.label(opts.label);
2637
2989
  }
@@ -2830,6 +3182,7 @@ var BaseHTTPClient = class {
2830
3182
  timeout: config.timeout ?? DEFAULT_TIMEOUT_MS,
2831
3183
  cookieJar: config.cookieJar,
2832
3184
  retryPolicy: config.retryPolicy,
3185
+ retryNonIdempotentMethods: config.retryNonIdempotentMethods ?? false,
2833
3186
  includeRequestID: config.includeRequestID ?? false,
2834
3187
  includeAttemptHeader: config.includeAttemptHeader ?? false,
2835
3188
  userAgent: config.userAgent,
@@ -3109,7 +3462,7 @@ var BaseHTTPClient = class {
3109
3462
  requestID,
3110
3463
  false,
3111
3464
  "interceptor_error",
3112
- error instanceof Error ? error : new Error(String(error))
3465
+ normalizeError2(error)
3113
3466
  );
3114
3467
  callbacks.setError(normalizedError);
3115
3468
  trackedCallbacks.setState("failed");
@@ -3214,7 +3567,14 @@ var BaseHTTPClient = class {
3214
3567
  body: null
3215
3568
  },
3216
3569
  requestID,
3570
+ // Provably false: a cancel settles with no adapter response, and
3571
+ // this branch is guarded on having one.
3217
3572
  wasCancelled: false,
3573
+ // Hardcoded even when a per-attempt timeout struck mid-body. The
3574
+ // request ends at the redirect either way, so `redirect_disabled`
3575
+ // is the outcome the caller acts on; surfacing the timeout would
3576
+ // reclassify the error code on whether the body happened to
3577
+ // finish. See docs/http-client.md.
3218
3578
  wasTimeout: false,
3219
3579
  adapterType: this._adapter.getType(),
3220
3580
  initialURL: finalRequest.requestURL,
@@ -3225,7 +3585,7 @@ var BaseHTTPClient = class {
3225
3585
  errorCode = "redirect_disabled";
3226
3586
  break;
3227
3587
  }
3228
- if (this._config.followRedirects && adapterResponse && REDIRECT_STATUS_CODES.has(adapterResponse.status)) {
3588
+ if (this._config.followRedirects && adapterResponse && !adapterResponse.isStreamError && REDIRECT_STATUS_CODES.has(adapterResponse.status)) {
3229
3589
  hopCount++;
3230
3590
  if (hopCount > this._config.maxRedirects) {
3231
3591
  response = this._buildResponse({
@@ -3340,7 +3700,7 @@ var BaseHTTPClient = class {
3340
3700
  isNetworkErrorOverride: false
3341
3701
  });
3342
3702
  errorCode = "interceptor_error";
3343
- adapterCause = error instanceof Error ? error : new Error(String(error));
3703
+ adapterCause = normalizeError2(error);
3344
3704
  break;
3345
3705
  }
3346
3706
  if ("cancel" in redirectIntercept) {
@@ -3418,7 +3778,7 @@ var BaseHTTPClient = class {
3418
3778
  requestID,
3419
3779
  false,
3420
3780
  "request_setup_error",
3421
- error instanceof Error ? error : new Error(String(error))
3781
+ normalizeError2(error)
3422
3782
  );
3423
3783
  callbacks.setAttemptCount(completedAttemptCount);
3424
3784
  callbacks.setNextRetryDelayMS(null);
@@ -3555,11 +3915,28 @@ var BaseHTTPClient = class {
3555
3915
  const startAttempt = params.startAttemptNumber ?? 1;
3556
3916
  const redirectHistory = params.redirectHistory ?? [];
3557
3917
  const cookieJar = params.cookieJar ?? null;
3918
+ const isRetryAvailable = () => policy !== null && policy.errors.length < policy.maxRetryAttempts;
3919
+ const allowNonIdempotentRetry = options.retryNonIdempotentMethods ?? this._config.retryNonIdempotentMethods;
3558
3920
  let attemptNumber = startAttempt - 1;
3559
3921
  let isRetriesExhausted = false;
3560
3922
  while (true) {
3561
3923
  attemptNumber++;
3562
3924
  const isRetry = attemptNumber > startAttempt;
3925
+ const emitAttemptEnd = (outcome) => {
3926
+ options.onAttemptEnd?.({
3927
+ attemptNumber,
3928
+ isRetry,
3929
+ nextRetryDelayMS: void 0,
3930
+ nextRetryAt: void 0,
3931
+ ...outcome,
3932
+ requestID,
3933
+ initialURL,
3934
+ ...hopContext ? {
3935
+ hopNumber: hopContext.hopNumber,
3936
+ redirect: hopContext.redirect
3937
+ } : {}
3938
+ });
3939
+ };
3563
3940
  if (attemptNumber === 1) {
3564
3941
  callbacks.setStartedAt(Date.now());
3565
3942
  } else {
@@ -3621,19 +3998,11 @@ var BaseHTTPClient = class {
3621
3998
  }
3622
3999
  } catch (error) {
3623
4000
  clearTimeout(timeoutID);
3624
- options.onAttemptEnd?.({
3625
- attemptNumber,
3626
- isRetry,
4001
+ emitAttemptEnd({
3627
4002
  willRetry: false,
3628
4003
  nextRetryDelayMS: void 0,
3629
4004
  nextRetryAt: void 0,
3630
- status: 0,
3631
- requestID,
3632
- initialURL,
3633
- ...hopContext ? {
3634
- hopNumber: hopContext.hopNumber,
3635
- redirect: hopContext.redirect
3636
- } : {}
4005
+ status: 0
3637
4006
  });
3638
4007
  return {
3639
4008
  adapterResponse: null,
@@ -3647,24 +4016,16 @@ var BaseHTTPClient = class {
3647
4016
  wasTimeout: false,
3648
4017
  isRetriesExhausted: false,
3649
4018
  errorCode: "interceptor_error",
3650
- adapterCause: error instanceof Error ? error : new Error(String(error))
4019
+ adapterCause: normalizeError2(error)
3651
4020
  };
3652
4021
  }
3653
4022
  if ("cancel" in retryIntercept) {
3654
4023
  clearTimeout(timeoutID);
3655
- options.onAttemptEnd?.({
3656
- attemptNumber,
3657
- isRetry,
4024
+ emitAttemptEnd({
3658
4025
  willRetry: false,
3659
4026
  nextRetryDelayMS: void 0,
3660
4027
  nextRetryAt: void 0,
3661
- status: 0,
3662
- requestID,
3663
- initialURL,
3664
- ...hopContext ? {
3665
- hopNumber: hopContext.hopNumber,
3666
- redirect: hopContext.redirect
3667
- } : {}
4028
+ status: 0
3668
4029
  });
3669
4030
  return {
3670
4031
  adapterResponse: null,
@@ -3737,19 +4098,11 @@ var BaseHTTPClient = class {
3737
4098
  );
3738
4099
  }
3739
4100
  if (adapterResponse.wasRedirectDetected && adapterResponse.status === 0 && !this._config.followRedirects) {
3740
- options.onAttemptEnd?.({
3741
- attemptNumber,
3742
- isRetry,
4101
+ emitAttemptEnd({
3743
4102
  willRetry: false,
3744
4103
  nextRetryDelayMS: void 0,
3745
4104
  nextRetryAt: void 0,
3746
- status: 0,
3747
- requestID,
3748
- initialURL,
3749
- ...hopContext ? {
3750
- hopNumber: hopContext.hopNumber,
3751
- redirect: hopContext.redirect
3752
- } : {}
4105
+ status: 0
3753
4106
  });
3754
4107
  return {
3755
4108
  adapterResponse,
@@ -3761,7 +4114,10 @@ var BaseHTTPClient = class {
3761
4114
  errorCode: "redirect_disabled"
3762
4115
  };
3763
4116
  }
3764
- if (policy && adapterResponse.isRetryable !== false && !adapterResponse.isStreamError && RETRYABLE_STATUS_CODES.has(adapterResponse.status) && !cancelSignal.aborted) {
4117
+ const isTransportOutcome = adapterResponse.isTransportError === true;
4118
+ const isMethodReplayable = allowNonIdempotentRetry || !NON_IDEMPOTENT_METHODS.has(sentRequest.method) || isTransportOutcome && adapterResponse.wasDefinitelyNotSent === true;
4119
+ const retrySuppressedReason = isRetryAvailable() && RETRYABLE_STATUS_CODES.has(adapterResponse.status) && !cancelSignal.aborted ? adapterResponse.isRetryable === false ? "adapter_veto" : adapterResponse.isStreamError ? "stream_error" : !isMethodReplayable ? "non_idempotent_method" : void 0 : void 0;
4120
+ if (policy && adapterResponse.isRetryable !== false && !adapterResponse.isStreamError && isMethodReplayable && RETRYABLE_STATUS_CODES.has(adapterResponse.status) && !cancelSignal.aborted) {
3765
4121
  const { shouldRetry, delayMS } = policy.shouldRetry(
3766
4122
  new Error(`HTTP ${adapterResponse.status}`)
3767
4123
  );
@@ -3771,19 +4127,11 @@ var BaseHTTPClient = class {
3771
4127
  callbacks.setNextRetryAt(nextRetryAt ?? null);
3772
4128
  callbacks.setState("waiting_for_retry");
3773
4129
  }
3774
- options.onAttemptEnd?.({
3775
- attemptNumber,
3776
- isRetry,
4130
+ emitAttemptEnd({
3777
4131
  willRetry: shouldRetry,
3778
4132
  nextRetryDelayMS: shouldRetry ? delayMS : void 0,
3779
4133
  nextRetryAt,
3780
- status: adapterResponse.status,
3781
- requestID,
3782
- initialURL,
3783
- ...hopContext ? {
3784
- hopNumber: hopContext.hopNumber,
3785
- redirect: hopContext.redirect
3786
- } : {}
4134
+ status: adapterResponse.status
3787
4135
  });
3788
4136
  if (shouldRetry) {
3789
4137
  const retryHTTPResponse = this._buildResponse({
@@ -3822,22 +4170,18 @@ var BaseHTTPClient = class {
3822
4170
  }
3823
4171
  isRetriesExhausted = true;
3824
4172
  } else {
3825
- options.onAttemptEnd?.({
3826
- attemptNumber,
3827
- isRetry,
4173
+ emitAttemptEnd({
3828
4174
  willRetry: false,
4175
+ ...retrySuppressedReason ? { retrySuppressedReason } : {},
3829
4176
  nextRetryDelayMS: void 0,
3830
4177
  nextRetryAt: void 0,
3831
- status: adapterResponse.status,
3832
- requestID,
3833
- initialURL,
3834
- ...hopContext ? {
3835
- hopNumber: hopContext.hopNumber,
3836
- redirect: hopContext.redirect
3837
- } : {}
4178
+ status: adapterResponse.status
3838
4179
  });
3839
4180
  }
3840
- const responseCause = adapterResponse.errorCause instanceof Error ? adapterResponse.errorCause : void 0;
4181
+ const responseCauseValue = adapterResponse.errorCause;
4182
+ const responseCause = asErrorValue(
4183
+ responseCauseValue
4184
+ ) ? responseCauseValue : void 0;
3841
4185
  const streamErrorCode = adapterResponse.isStreamError ? adapterResponse.streamErrorCode ?? "stream_write_error" : void 0;
3842
4186
  return {
3843
4187
  adapterResponse,
@@ -3851,20 +4195,19 @@ var BaseHTTPClient = class {
3851
4195
  };
3852
4196
  } catch (error) {
3853
4197
  clearTimeout(timeoutID);
4198
+ const abortedResponse = isResponseStreamAbortError(error) ? getResponseStreamAbortInfo(error) : void 0;
4199
+ if (cookieJar && abortedResponse) {
4200
+ cookieJar.processResponseHeaders(
4201
+ abortedResponse.headers,
4202
+ sentRequest.requestURL
4203
+ );
4204
+ }
3854
4205
  if (cancelSignal.aborted && !isAbortError2(error)) {
3855
- options.onAttemptEnd?.({
3856
- attemptNumber,
3857
- isRetry,
4206
+ emitAttemptEnd({
3858
4207
  willRetry: false,
3859
4208
  nextRetryDelayMS: void 0,
3860
4209
  nextRetryAt: void 0,
3861
- status: 0,
3862
- requestID,
3863
- initialURL,
3864
- ...hopContext ? {
3865
- hopNumber: hopContext.hopNumber,
3866
- redirect: hopContext.redirect
3867
- } : {}
4210
+ status: 0
3868
4211
  });
3869
4212
  const signalReason = getSignalCancelReason(cancelSignal);
3870
4213
  return {
@@ -3877,21 +4220,26 @@ var BaseHTTPClient = class {
3877
4220
  ...signalReason !== void 0 ? { cancelReason: signalReason } : {}
3878
4221
  };
3879
4222
  }
3880
- if (isAbortError2(error) && isResponseStreamAbortError(error)) {
4223
+ if (isResponseStreamAbortError(error)) {
4224
+ const streamCause = normalizeError2(error);
4225
+ const streamSuppressionReason = (status) => isRetryAvailable() && RETRYABLE_STATUS_CODES.has(status) && !cancelSignal.aborted ? "stream_error" : void 0;
4226
+ const redirectFieldsFor = (status, headers) => {
4227
+ const detectedRedirectURL = resolveDetectedRedirectURL(
4228
+ sentRequest.requestURL,
4229
+ status,
4230
+ headers
4231
+ );
4232
+ return {
4233
+ wasRedirectDetected: detectedRedirectURL !== void 0 || REDIRECT_STATUS_CODES.has(status),
4234
+ ...detectedRedirectURL ? { detectedRedirectURL } : {}
4235
+ };
4236
+ };
3881
4237
  if (cancelSignal.aborted) {
3882
- options.onAttemptEnd?.({
3883
- attemptNumber,
3884
- isRetry,
4238
+ emitAttemptEnd({
3885
4239
  willRetry: false,
3886
4240
  nextRetryDelayMS: void 0,
3887
4241
  nextRetryAt: void 0,
3888
- status: 0,
3889
- requestID,
3890
- initialURL,
3891
- ...hopContext ? {
3892
- hopNumber: hopContext.hopNumber,
3893
- redirect: hopContext.redirect
3894
- } : {}
4242
+ status: 0
3895
4243
  });
3896
4244
  const signalReason = getSignalCancelReason(cancelSignal);
3897
4245
  return {
@@ -3908,30 +4256,29 @@ var BaseHTTPClient = class {
3908
4256
  ...signalReason !== void 0 ? { cancelReason: signalReason } : {}
3909
4257
  };
3910
4258
  }
3911
- const streamedAbort = getResponseStreamAbortInfo(error);
3912
- if (isTimedOut && streamedAbort) {
3913
- options.onAttemptEnd?.({
3914
- attemptNumber,
3915
- isRetry,
4259
+ if (isTimedOut && abortedResponse) {
4260
+ const suppressedReason = streamSuppressionReason(
4261
+ abortedResponse.status
4262
+ );
4263
+ emitAttemptEnd({
3916
4264
  willRetry: false,
4265
+ ...suppressedReason ? { retrySuppressedReason: suppressedReason } : {},
3917
4266
  nextRetryDelayMS: void 0,
3918
4267
  nextRetryAt: void 0,
3919
- status: streamedAbort.status,
3920
- requestID,
3921
- initialURL,
3922
- ...hopContext ? {
3923
- hopNumber: hopContext.hopNumber,
3924
- redirect: hopContext.redirect
3925
- } : {}
4268
+ status: abortedResponse.status
3926
4269
  });
3927
4270
  return {
3928
4271
  adapterResponse: {
3929
- status: streamedAbort.status,
3930
- headers: streamedAbort.headers,
4272
+ status: abortedResponse.status,
4273
+ ...redirectFieldsFor(
4274
+ abortedResponse.status,
4275
+ abortedResponse.headers
4276
+ ),
4277
+ headers: abortedResponse.headers,
3931
4278
  body: null,
3932
4279
  isStreamError: true,
3933
4280
  streamErrorCode: "stream_response_error",
3934
- errorCause: error,
4281
+ errorCause: streamCause,
3935
4282
  effectiveRequestHeaders: getEffectiveRequestHeadersFromError(error)
3936
4283
  },
3937
4284
  sentRequest: sentRequestForObservedAdapterError(
@@ -3944,31 +4291,30 @@ var BaseHTTPClient = class {
3944
4291
  wasTimeout: true,
3945
4292
  isRetriesExhausted: false,
3946
4293
  errorCode: "stream_response_error",
3947
- adapterCause: error
4294
+ adapterCause: streamCause
3948
4295
  };
3949
4296
  }
3950
- options.onAttemptEnd?.({
3951
- attemptNumber,
3952
- isRetry,
4297
+ const fallbackSuppressedReason = streamSuppressionReason(
4298
+ abortedResponse?.status ?? 0
4299
+ );
4300
+ emitAttemptEnd({
3953
4301
  willRetry: false,
4302
+ ...fallbackSuppressedReason ? { retrySuppressedReason: fallbackSuppressedReason } : {},
3954
4303
  nextRetryDelayMS: void 0,
3955
4304
  nextRetryAt: void 0,
3956
- status: streamedAbort?.status ?? 0,
3957
- requestID,
3958
- initialURL,
3959
- ...hopContext ? {
3960
- hopNumber: hopContext.hopNumber,
3961
- redirect: hopContext.redirect
3962
- } : {}
4305
+ status: abortedResponse?.status ?? 0
3963
4306
  });
4307
+ const fallbackStatus = abortedResponse?.status ?? 0;
4308
+ const fallbackHeaders = abortedResponse?.headers ?? {};
3964
4309
  return {
3965
4310
  adapterResponse: {
3966
- status: streamedAbort?.status ?? 0,
3967
- headers: streamedAbort?.headers ?? {},
4311
+ status: fallbackStatus,
4312
+ ...redirectFieldsFor(fallbackStatus, fallbackHeaders),
4313
+ headers: fallbackHeaders,
3968
4314
  body: null,
3969
4315
  isStreamError: true,
3970
4316
  streamErrorCode: "stream_response_error",
3971
- errorCause: error,
4317
+ errorCause: streamCause,
3972
4318
  effectiveRequestHeaders: getEffectiveRequestHeadersFromError(error)
3973
4319
  },
3974
4320
  sentRequest: sentRequestForObservedAdapterError(
@@ -3981,24 +4327,16 @@ var BaseHTTPClient = class {
3981
4327
  wasTimeout: isTimedOut,
3982
4328
  isRetriesExhausted: false,
3983
4329
  errorCode: "stream_response_error",
3984
- adapterCause: error
4330
+ adapterCause: streamCause
3985
4331
  };
3986
4332
  }
3987
4333
  if (isAbortError2(error)) {
3988
4334
  if (cancelSignal.aborted) {
3989
- options.onAttemptEnd?.({
3990
- attemptNumber,
3991
- isRetry,
4335
+ emitAttemptEnd({
3992
4336
  willRetry: false,
3993
4337
  nextRetryDelayMS: void 0,
3994
4338
  nextRetryAt: void 0,
3995
- status: 0,
3996
- requestID,
3997
- initialURL,
3998
- ...hopContext ? {
3999
- hopNumber: hopContext.hopNumber,
4000
- redirect: hopContext.redirect
4001
- } : {}
4339
+ status: 0
4002
4340
  });
4003
4341
  const signalReason = getSignalCancelReason(cancelSignal);
4004
4342
  return {
@@ -4015,21 +4353,16 @@ var BaseHTTPClient = class {
4015
4353
  if (isXHRBrowserTimeout(error)) {
4016
4354
  isTimedOut = true;
4017
4355
  } else {
4018
- const factoryCancelValue = error !== null && typeof error === "object" && STREAM_FACTORY_CANCEL_KEY in error ? error[STREAM_FACTORY_CANCEL_KEY] : void 0;
4356
+ const factoryCancelValue = readObjectMember2(
4357
+ error,
4358
+ STREAM_FACTORY_CANCEL_KEY
4359
+ );
4019
4360
  const factoryCancelReason = typeof factoryCancelValue === "string" ? factoryCancelValue : void 0;
4020
- options.onAttemptEnd?.({
4021
- attemptNumber,
4022
- isRetry,
4361
+ emitAttemptEnd({
4023
4362
  willRetry: false,
4024
4363
  nextRetryDelayMS: void 0,
4025
4364
  nextRetryAt: void 0,
4026
- status: 0,
4027
- requestID,
4028
- initialURL,
4029
- ...hopContext ? {
4030
- hopNumber: hopContext.hopNumber,
4031
- redirect: hopContext.redirect
4032
- } : {}
4365
+ status: 0
4033
4366
  });
4034
4367
  return {
4035
4368
  adapterResponse: null,
@@ -4046,19 +4379,11 @@ var BaseHTTPClient = class {
4046
4379
  const didTimeoutThisAttempt = isAbortError2(error) && isTimedOut;
4047
4380
  const isNonRetryableClientCallbackFailure = isNonRetryableClientCallbackError(error);
4048
4381
  if (isNonRetryableClientCallbackFailure) {
4049
- options.onAttemptEnd?.({
4050
- attemptNumber,
4051
- isRetry,
4382
+ emitAttemptEnd({
4052
4383
  willRetry: false,
4053
4384
  nextRetryDelayMS: void 0,
4054
4385
  nextRetryAt: void 0,
4055
- status: 0,
4056
- requestID,
4057
- initialURL,
4058
- ...hopContext ? {
4059
- hopNumber: hopContext.hopNumber,
4060
- redirect: hopContext.redirect
4061
- } : {}
4386
+ status: 0
4062
4387
  });
4063
4388
  const isStreamFactoryError = isStreamFactoryClientCallbackError(error);
4064
4389
  return {
@@ -4073,12 +4398,12 @@ var BaseHTTPClient = class {
4073
4398
  wasTimeout: didTimeoutThisAttempt,
4074
4399
  isRetriesExhausted: false,
4075
4400
  errorCode: isStreamFactoryError ? "stream_setup_error" : "interceptor_error",
4076
- adapterCause: error instanceof Error ? error : new Error(String(error))
4401
+ adapterCause: normalizeError2(error)
4077
4402
  };
4078
4403
  }
4079
- if (policy && !cancelSignal.aborted) {
4404
+ if (policy && !cancelSignal.aborted && (allowNonIdempotentRetry || !NON_IDEMPOTENT_METHODS.has(sentRequest.method))) {
4080
4405
  const { shouldRetry, delayMS } = policy.shouldRetry(
4081
- error instanceof Error ? error : new Error(String(error))
4406
+ normalizeError2(error)
4082
4407
  );
4083
4408
  const nextRetryAt = shouldRetry ? Date.now() + delayMS : void 0;
4084
4409
  if (shouldRetry) {
@@ -4086,19 +4411,11 @@ var BaseHTTPClient = class {
4086
4411
  callbacks.setNextRetryAt(nextRetryAt ?? null);
4087
4412
  callbacks.setState("waiting_for_retry");
4088
4413
  }
4089
- options.onAttemptEnd?.({
4090
- attemptNumber,
4091
- isRetry,
4414
+ emitAttemptEnd({
4092
4415
  willRetry: shouldRetry,
4093
4416
  nextRetryDelayMS: shouldRetry ? delayMS : void 0,
4094
4417
  nextRetryAt,
4095
- status: 0,
4096
- requestID,
4097
- initialURL,
4098
- ...hopContext ? {
4099
- hopNumber: hopContext.hopNumber,
4100
- redirect: hopContext.redirect
4101
- } : {}
4418
+ status: 0
4102
4419
  });
4103
4420
  if (shouldRetry) {
4104
4421
  const failedAttemptResponse = this._buildResponse({
@@ -4117,7 +4434,7 @@ var BaseHTTPClient = class {
4117
4434
  requestID,
4118
4435
  false,
4119
4436
  "adapter_error",
4120
- error instanceof Error ? error : new Error(String(error))
4437
+ normalizeError2(error)
4121
4438
  );
4122
4439
  await this._runErrorObservers(
4123
4440
  retryError,
@@ -4145,19 +4462,13 @@ var BaseHTTPClient = class {
4145
4462
  }
4146
4463
  isRetriesExhausted = true;
4147
4464
  } else {
4148
- options.onAttemptEnd?.({
4149
- attemptNumber,
4150
- isRetry,
4465
+ const isSuppressedByMethod = isRetryAvailable() && !cancelSignal.aborted && !allowNonIdempotentRetry && NON_IDEMPOTENT_METHODS.has(sentRequest.method);
4466
+ emitAttemptEnd({
4151
4467
  willRetry: false,
4468
+ ...isSuppressedByMethod ? { retrySuppressedReason: "non_idempotent_method" } : {},
4152
4469
  nextRetryDelayMS: void 0,
4153
4470
  nextRetryAt: void 0,
4154
- status: 0,
4155
- requestID,
4156
- initialURL,
4157
- ...hopContext ? {
4158
- hopNumber: hopContext.hopNumber,
4159
- redirect: hopContext.redirect
4160
- } : {}
4471
+ status: 0
4161
4472
  });
4162
4473
  }
4163
4474
  return {
@@ -4168,7 +4479,7 @@ var BaseHTTPClient = class {
4168
4479
  wasTimeout: didTimeoutThisAttempt,
4169
4480
  isRetriesExhausted,
4170
4481
  errorCode: "adapter_error",
4171
- adapterCause: error instanceof Error ? error : new Error(String(error))
4482
+ adapterCause: normalizeError2(error)
4172
4483
  };
4173
4484
  }
4174
4485
  }
@@ -4538,7 +4849,7 @@ var BaseHTTPClient = class {
4538
4849
  return AbortSignal.any([a, b]);
4539
4850
  }
4540
4851
  const controller = new AbortController();
4541
- const abort = (signal) => controller.abort(signal.reason);
4852
+ const abort = (signal) => controller.abort(readObjectMember2(signal, "reason"));
4542
4853
  if (a.aborted) {
4543
4854
  abort(a);
4544
4855
  } else if (b.aborted) {
@@ -4622,7 +4933,24 @@ function cloneBodyValue(body) {
4622
4933
  return body;
4623
4934
  }
4624
4935
  function isAbortError2(err) {
4625
- return err instanceof Error && err.name === "AbortError";
4936
+ return asErrorValue(err) && readObjectMember2(err, "name") === "AbortError";
4937
+ }
4938
+ function asErrorValue(value) {
4939
+ try {
4940
+ return value instanceof Error;
4941
+ } catch {
4942
+ return false;
4943
+ }
4944
+ }
4945
+ function normalizeError2(value) {
4946
+ if (asErrorValue(value)) {
4947
+ return value;
4948
+ }
4949
+ try {
4950
+ return new Error(String(value));
4951
+ } catch {
4952
+ return new Error("Unknown error");
4953
+ }
4626
4954
  }
4627
4955
  function sentRequestForNonRetryableAdapterCallbackError(sentRequest, error, observedAfterAdapterResolve) {
4628
4956
  return sentRequestForObservedAdapterError(
@@ -4632,12 +4960,10 @@ function sentRequestForNonRetryableAdapterCallbackError(sentRequest, error, obse
4632
4960
  );
4633
4961
  }
4634
4962
  function isNonRetryableClientCallbackError(err) {
4635
- return Boolean(
4636
- err && typeof err === "object" && NON_RETRYABLE_HTTP_CLIENT_CALLBACK_ERROR_FLAG in err && err[NON_RETRYABLE_HTTP_CLIENT_CALLBACK_ERROR_FLAG] === true
4637
- );
4963
+ return readObjectMember2(err, NON_RETRYABLE_HTTP_CLIENT_CALLBACK_ERROR_FLAG) === true;
4638
4964
  }
4639
4965
  function isStreamFactoryClientCallbackError(err) {
4640
- return err !== null && typeof err === "object" && STREAM_FACTORY_ERROR_FLAG in err;
4966
+ return readObjectMember2(err, STREAM_FACTORY_ERROR_FLAG) === true;
4641
4967
  }
4642
4968
  function sentRequestForObservedAdapterError(sentRequest, error, observedAfterAdapterResolve) {
4643
4969
  const eff = getEffectiveRequestHeadersFromError(error);
@@ -4650,24 +4976,58 @@ function sentRequestForObservedAdapterError(sentRequest, error, observedAfterAda
4650
4976
  };
4651
4977
  }
4652
4978
  function getEffectiveRequestHeadersFromError(error) {
4653
- if (error && typeof error === "object" && "effectiveRequestHeaders" in error && error.effectiveRequestHeaders) {
4654
- return error.effectiveRequestHeaders;
4979
+ return snapshotHeaderRecord(
4980
+ readObjectMember2(error, "effectiveRequestHeaders")
4981
+ );
4982
+ }
4983
+ function readObjectMember2(source, key) {
4984
+ if (typeof source !== "object" && typeof source !== "function" || source === null) {
4985
+ return void 0;
4986
+ }
4987
+ try {
4988
+ return source[key];
4989
+ } catch {
4990
+ return void 0;
4655
4991
  }
4656
- return void 0;
4992
+ }
4993
+ function snapshotHeaderRecord(value) {
4994
+ if (typeof value !== "object" || value === null) {
4995
+ return void 0;
4996
+ }
4997
+ try {
4998
+ const snapshot = {};
4999
+ for (const [name, headerValue] of Object.entries(value)) {
5000
+ if (typeof headerValue === "string") {
5001
+ snapshot[name] = headerValue;
5002
+ } else if (Array.isArray(headerValue) && headerValue.every((item) => typeof item === "string")) {
5003
+ snapshot[name] = [...headerValue];
5004
+ } else {
5005
+ return void 0;
5006
+ }
5007
+ }
5008
+ return snapshot;
5009
+ } catch {
5010
+ return void 0;
5011
+ }
5012
+ }
5013
+ function hasAdapterMarker(err, flag) {
5014
+ return readObjectMember2(err, flag) === true;
4657
5015
  }
4658
5016
  function isResponseStreamAbortError(err) {
4659
- return err !== null && typeof err === "object" && RESPONSE_STREAM_ABORT_FLAG in err;
5017
+ return hasAdapterMarker(err, RESPONSE_STREAM_ABORT_FLAG);
4660
5018
  }
4661
5019
  function isXHRBrowserTimeout(err) {
4662
- return err !== null && typeof err === "object" && XHR_BROWSER_TIMEOUT_FLAG in err;
5020
+ return hasAdapterMarker(err, XHR_BROWSER_TIMEOUT_FLAG);
4663
5021
  }
4664
5022
  function getResponseStreamAbortInfo(err) {
4665
- if (!err || typeof err !== "object" || !("streamAbortStatus" in err) || !("streamAbortHeaders" in err)) {
5023
+ const status = readObjectMember2(err, "streamAbortStatus");
5024
+ if (typeof status !== "number") {
4666
5025
  return void 0;
4667
5026
  }
4668
- const status = err.streamAbortStatus;
4669
- const headers = err.streamAbortHeaders;
4670
- if (typeof status !== "number" || !headers || typeof headers !== "object") {
5027
+ const headers = snapshotHeaderRecord(
5028
+ readObjectMember2(err, "streamAbortHeaders")
5029
+ );
5030
+ if (headers === void 0) {
4671
5031
  return void 0;
4672
5032
  }
4673
5033
  return {
@@ -4676,7 +5036,8 @@ function getResponseStreamAbortInfo(err) {
4676
5036
  };
4677
5037
  }
4678
5038
  function getSignalCancelReason(signal) {
4679
- return typeof signal.reason === "string" ? signal.reason : void 0;
5039
+ const reason = readObjectMember2(signal, "reason");
5040
+ return typeof reason === "string" ? reason : void 0;
4680
5041
  }
4681
5042
 
4682
5043
  // src/lib/http-client/cookie-jar.ts