recker 1.0.73 → 1.0.75-next.2e5a94f

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 (100) hide show
  1. package/README.md +5 -18
  2. package/dist/browser/core/client.d.ts +14 -8
  3. package/dist/browser/core/client.js +199 -17
  4. package/dist/browser/core/errors.d.ts +15 -1
  5. package/dist/browser/core/errors.js +140 -9
  6. package/dist/browser/core/request.d.ts +5 -0
  7. package/dist/browser/core/request.js +33 -2
  8. package/dist/browser/core-runtime/plugin-manifest.d.ts +24 -0
  9. package/dist/browser/core-runtime/plugin-manifest.js +159 -0
  10. package/dist/browser/core-runtime/request-context.d.ts +13 -0
  11. package/dist/browser/core-runtime/request-context.js +24 -0
  12. package/dist/browser/core-runtime/typed-events.d.ts +89 -0
  13. package/dist/browser/core-runtime/typed-events.js +34 -0
  14. package/dist/browser/index.iife.min.js +79 -79
  15. package/dist/browser/index.min.js +79 -79
  16. package/dist/browser/index.mini.iife.js +913 -97
  17. package/dist/browser/index.mini.iife.min.js +46 -46
  18. package/dist/browser/index.mini.min.js +46 -46
  19. package/dist/browser/index.mini.umd.js +913 -97
  20. package/dist/browser/index.mini.umd.min.js +46 -46
  21. package/dist/browser/index.umd.min.js +79 -79
  22. package/dist/browser/plugins/auth/aws-sigv4.d.ts +1 -0
  23. package/dist/browser/plugins/auth/aws-sigv4.js +19 -2
  24. package/dist/browser/plugins/retry.js +29 -1
  25. package/dist/browser/presets/aws.d.ts +1 -0
  26. package/dist/browser/presets/aws.js +62 -1
  27. package/dist/browser/runner/request-runner.d.ts +15 -5
  28. package/dist/browser/runner/request-runner.js +164 -30
  29. package/dist/browser/scrape/parser/nodes/html.d.ts +6 -0
  30. package/dist/browser/scrape/parser/nodes/html.js +70 -18
  31. package/dist/browser/scrape/parser/nodes/node.d.ts +1 -0
  32. package/dist/browser/scrape/parser/nodes/node.js +5 -0
  33. package/dist/browser/scrape/spider.d.ts +1 -0
  34. package/dist/browser/scrape/spider.js +39 -26
  35. package/dist/browser/seo/analyzer.d.ts +1 -1
  36. package/dist/browser/seo/analyzer.js +73 -42
  37. package/dist/browser/seo/index.d.ts +1 -1
  38. package/dist/browser/seo/rules/types.d.ts +2 -0
  39. package/dist/browser/seo/seo-spider.d.ts +2 -3
  40. package/dist/browser/seo/seo-spider.js +26 -202
  41. package/dist/browser/seo/types.d.ts +4 -0
  42. package/dist/browser/seo/validators/sitemap.js +9 -2
  43. package/dist/browser/transport/fetch.js +38 -5
  44. package/dist/browser/transport/undici.js +73 -11
  45. package/dist/browser/transport/worker.d.ts +0 -1
  46. package/dist/browser/transport/worker.js +1 -3
  47. package/dist/browser/types/index.d.ts +24 -0
  48. package/dist/cli/commands/mcp.js +5 -3
  49. package/dist/core/client.d.ts +14 -8
  50. package/dist/core/client.js +199 -17
  51. package/dist/core/errors.d.ts +15 -1
  52. package/dist/core/errors.js +140 -9
  53. package/dist/core/request.d.ts +5 -0
  54. package/dist/core/request.js +33 -2
  55. package/dist/core-runtime/plugin-manifest.d.ts +24 -0
  56. package/dist/core-runtime/plugin-manifest.js +159 -0
  57. package/dist/core-runtime/request-context.d.ts +13 -0
  58. package/dist/core-runtime/request-context.js +24 -0
  59. package/dist/core-runtime/typed-events.d.ts +89 -0
  60. package/dist/core-runtime/typed-events.js +34 -0
  61. package/dist/index.d.ts +2 -1
  62. package/dist/index.js +2 -1
  63. package/dist/mcp/cli.js +10 -8
  64. package/dist/mcp/profiles.d.ts +1 -1
  65. package/dist/mcp/profiles.js +31 -6
  66. package/dist/mcp/tools/categories.js +0 -1
  67. package/dist/plugins/auth/aws-sigv4.d.ts +1 -0
  68. package/dist/plugins/auth/aws-sigv4.js +19 -2
  69. package/dist/plugins/retry.js +29 -1
  70. package/dist/presets/aws.d.ts +1 -0
  71. package/dist/presets/aws.js +62 -1
  72. package/dist/recker.d.ts +3 -0
  73. package/dist/recker.js +5 -0
  74. package/dist/runner/request-runner.d.ts +15 -5
  75. package/dist/runner/request-runner.js +164 -30
  76. package/dist/scrape/parser/nodes/html.d.ts +6 -0
  77. package/dist/scrape/parser/nodes/html.js +70 -18
  78. package/dist/scrape/parser/nodes/node.d.ts +1 -0
  79. package/dist/scrape/parser/nodes/node.js +5 -0
  80. package/dist/scrape/spider.d.ts +1 -0
  81. package/dist/scrape/spider.js +39 -26
  82. package/dist/search/google.d.ts +67 -0
  83. package/dist/search/google.js +480 -0
  84. package/dist/search/index.d.ts +3 -0
  85. package/dist/search/index.js +1 -0
  86. package/dist/seo/analyzer.d.ts +1 -1
  87. package/dist/seo/analyzer.js +73 -42
  88. package/dist/seo/index.d.ts +1 -1
  89. package/dist/seo/rules/types.d.ts +2 -0
  90. package/dist/seo/seo-spider.d.ts +2 -3
  91. package/dist/seo/seo-spider.js +26 -202
  92. package/dist/seo/types.d.ts +4 -0
  93. package/dist/seo/validators/sitemap.js +9 -2
  94. package/dist/transport/fetch.js +38 -5
  95. package/dist/transport/undici.js +73 -11
  96. package/dist/transport/worker.d.ts +0 -1
  97. package/dist/transport/worker.js +1 -3
  98. package/dist/types/index.d.ts +24 -0
  99. package/dist/version.js +1 -1
  100. package/package.json +9 -1
@@ -136,6 +136,85 @@ var recker = (() => {
136
136
  }
137
137
  return null;
138
138
  }
139
+ function classifyTransportError(error) {
140
+ var _a2;
141
+ if (error instanceof ReckerError && error.classification) {
142
+ return error.classification;
143
+ }
144
+ if (!error || typeof error !== "object") {
145
+ return void 0;
146
+ }
147
+ const anyError = error;
148
+ const name = anyError.name || "";
149
+ const message = anyError.message || "";
150
+ const code = (_a2 = anyError.code) == null ? void 0 : _a2.toUpperCase();
151
+ if (name === "AbortError" || code === "ABORT_ERR" || code === "UND_ERR_ABORTED" || message.includes("aborted") || message.includes("AbortError")) {
152
+ return {
153
+ category: "queue",
154
+ source: "client",
155
+ severity: "low",
156
+ canRetry: true,
157
+ reason: "Request was aborted"
158
+ };
159
+ }
160
+ if (name === "TimeoutError" || code === "UND_ERR_CONNECT_TIMEOUT" || code === "UND_ERR_HEADERS_TIMEOUT" || code === "UND_ERR_BODY_TIMEOUT" || message.includes("timeout")) {
161
+ return {
162
+ category: "timeout",
163
+ source: "transport",
164
+ severity: "medium",
165
+ canRetry: true,
166
+ reason: message || "Request timed out"
167
+ };
168
+ }
169
+ const networkCodes = /* @__PURE__ */ new Set([
170
+ "ECONNRESET",
171
+ "ECONNREFUSED",
172
+ "ENOTFOUND",
173
+ "EPIPE",
174
+ "ETIMEDOUT",
175
+ "EHOSTUNREACH",
176
+ "ENETUNREACH",
177
+ "ENETDOWN",
178
+ "EAI_AGAIN"
179
+ ]);
180
+ if (code && networkCodes.has(code)) {
181
+ return {
182
+ category: "network",
183
+ source: "transport",
184
+ severity: "medium",
185
+ canRetry: true,
186
+ reason: message || `Network error (${code})`
187
+ };
188
+ }
189
+ if (name === "Http2Error" || message.includes("HTTP/2") || message.includes("RST_STREAM") || message.includes("GOAWAY")) {
190
+ return {
191
+ category: "protocol",
192
+ source: "transport",
193
+ severity: "medium",
194
+ canRetry: true,
195
+ reason: message || "HTTP/2 protocol error"
196
+ };
197
+ }
198
+ if (name === "MaxSizeExceededError" || name === "ParseError") {
199
+ return {
200
+ category: "resource",
201
+ source: "server",
202
+ severity: "low",
203
+ canRetry: false,
204
+ reason: message || "Resource limitation"
205
+ };
206
+ }
207
+ if (name === "ConfigurationError" || name === "ValidationError" || name === "StateError") {
208
+ return {
209
+ category: "state",
210
+ source: "client",
211
+ severity: "high",
212
+ canRetry: false,
213
+ reason: message || "Request cannot be retried"
214
+ };
215
+ }
216
+ return void 0;
217
+ }
139
218
  function isRetryableStatus(status) {
140
219
  return [408, 425, 429, 500, 502, 503, 504].includes(status);
141
220
  }
@@ -148,20 +227,30 @@ var recker = (() => {
148
227
  response;
149
228
  suggestions;
150
229
  retriable;
151
- constructor(message, request7, response, suggestions = [], retriable = false) {
230
+ classification;
231
+ constructor(message, request7, response, suggestions = [], retriable = false, classification) {
152
232
  super(message);
153
233
  this.name = "ReckerError";
154
234
  this.request = request7;
155
235
  this.response = response;
156
236
  this.suggestions = suggestions;
157
237
  this.retriable = retriable;
238
+ this.classification = classification;
158
239
  }
159
240
  };
160
241
  HttpError = class extends ReckerError {
161
242
  status;
162
243
  statusText;
163
244
  constructor(response, request7) {
164
- super(`Request failed with status code ${response.status} ${response.statusText}`, request7, response, ["Check the upstream service response body for error details.", "Inspect request headers/body to ensure they match the API contract.", "Retry if this is a transient 5xx/429 error."], isRetryableStatus(response.status));
245
+ const retriable = isRetryableStatus(response.status);
246
+ super(`Request failed with status code ${response.status} ${response.statusText}`, request7, response, ["Check the upstream service response body for error details.", "Inspect request headers/body to ensure they match the API contract.", "Retry if this is a transient 5xx/429 error."], retriable, {
247
+ category: "http",
248
+ source: "server",
249
+ severity: response.status >= 500 ? "high" : "medium",
250
+ canRetry: retriable,
251
+ reason: `HTTP ${response.status}`,
252
+ statusCode: response.status
253
+ });
165
254
  this.name = "HttpError";
166
255
  this.status = response.status;
167
256
  this.statusText = response.statusText;
@@ -198,7 +287,13 @@ var recker = (() => {
198
287
  "Increase the specific timeout phase or optimize the upstream response time.",
199
288
  "Reduce concurrent requests if the connection pool is exhausted."
200
289
  ];
201
- super(message, request7, void 0, suggestions, true);
290
+ super(message, request7, void 0, suggestions, true, {
291
+ category: "timeout",
292
+ source: "transport",
293
+ severity: "medium",
294
+ canRetry: true,
295
+ reason: `Timeout while ${phase}`
296
+ });
202
297
  this.name = "TimeoutError";
203
298
  this.phase = phase;
204
299
  this.timeout = timeout ?? 0;
@@ -214,7 +309,13 @@ var recker = (() => {
214
309
  "Check proxy/VPN/firewall settings that might block the request.",
215
310
  "Retry the request or switch transport if this is transient."
216
311
  ];
217
- super(message, request7, void 0, suggestions, true);
312
+ super(message, request7, void 0, suggestions, true, {
313
+ category: "network",
314
+ source: "transport",
315
+ severity: code ? "medium" : "low",
316
+ canRetry: true,
317
+ reason: code ? `Network error (${code})` : message
318
+ });
218
319
  this.name = "NetworkError";
219
320
  this.code = code;
220
321
  }
@@ -228,7 +329,14 @@ var recker = (() => {
228
329
  const retriable = isRetriableHttp2Error(errorCode);
229
330
  const suggestFallback = shouldFallbackToHttp1(errorCode);
230
331
  const suggestions = getHttp2ErrorSuggestions(errorCode, suggestFallback);
231
- super(message, options2.request, void 0, suggestions, retriable);
332
+ super(message, options2.request, void 0, suggestions, retriable, {
333
+ category: "protocol",
334
+ source: "transport",
335
+ severity: retriable ? "medium" : "high",
336
+ canRetry: retriable,
337
+ reason: `HTTP/2 ${errorCode}`,
338
+ statusCode: errorCode ? Number.parseInt(String(errorCode), 10) || void 0 : void 0
339
+ });
232
340
  this.name = "Http2Error";
233
341
  this.errorCode = errorCode;
234
342
  this.level = options2.level ?? "stream";
@@ -245,7 +353,13 @@ var recker = (() => {
245
353
  "Increase maxResponseSize if the larger payload is expected.",
246
354
  "Add pagination/streaming to reduce payload size.",
247
355
  "Ensure the upstream is not returning unexpected large responses."
248
- ], false);
356
+ ], false, {
357
+ category: "resource",
358
+ source: "server",
359
+ severity: "medium",
360
+ canRetry: false,
361
+ reason: "Response size exceeded configured max"
362
+ });
249
363
  this.name = "MaxSizeExceededError";
250
364
  this.maxSize = maxSize;
251
365
  this.actualSize = actualSize;
@@ -258,7 +372,13 @@ var recker = (() => {
258
372
  "Check if the abort was intentional (user-triggered or timeout).",
259
373
  "Increase timeout if the request needs more time to complete.",
260
374
  "Ensure AbortController is not being triggered prematurely."
261
- ], true);
375
+ ], true, {
376
+ category: "timeout",
377
+ source: "client",
378
+ severity: "low",
379
+ canRetry: true,
380
+ reason: reason ? `Request was aborted: ${reason}` : "Request was aborted"
381
+ });
262
382
  this.name = "AbortError";
263
383
  this.reason = reason;
264
384
  }
@@ -272,7 +392,13 @@ var recker = (() => {
272
392
  "Verify the host and port are correct and the service is running.",
273
393
  "Check network connectivity and firewall rules.",
274
394
  "Ensure the service is accepting connections on the specified port."
275
- ], (options2 == null ? void 0 : options2.retriable) ?? true);
395
+ ], (options2 == null ? void 0 : options2.retriable) ?? true, {
396
+ category: "network",
397
+ source: "transport",
398
+ severity: (options2 == null ? void 0 : options2.retriable) === false ? "high" : "medium",
399
+ canRetry: (options2 == null ? void 0 : options2.retriable) ?? true,
400
+ reason: (options2 == null ? void 0 : options2.code) ? `Connection error (${options2.code})` : "Connection error"
401
+ });
276
402
  this.name = "ConnectionError";
277
403
  this.host = options2 == null ? void 0 : options2.host;
278
404
  this.port = options2 == null ? void 0 : options2.port;
@@ -430,7 +556,13 @@ var recker = (() => {
430
556
  "This is typically expected during shutdown.",
431
557
  "Check if the queue was manually cleared.",
432
558
  "Retry the operation if the queue is still active."
433
- ], true);
559
+ ], true, {
560
+ category: "queue",
561
+ source: "client",
562
+ severity: "low",
563
+ canRetry: true,
564
+ reason: message || "Queue was cancelled"
565
+ });
434
566
  this.name = "QueueCancelledError";
435
567
  this.queueName = options2 == null ? void 0 : options2.queueName;
436
568
  }
@@ -7223,6 +7355,9 @@ var recker = (() => {
7223
7355
  }
7224
7356
  remove() {
7225
7357
  if (this.parentNode) {
7358
+ if (typeof this.parentNode.invalidateSelectorCacheRecursively === "function") {
7359
+ this.parentNode.invalidateSelectorCacheRecursively();
7360
+ }
7226
7361
  const children = this.parentNode.childNodes;
7227
7362
  this.parentNode.childNodes = children.filter((child) => {
7228
7363
  return this !== child;
@@ -7231,6 +7366,8 @@ var recker = (() => {
7231
7366
  }
7232
7367
  return this;
7233
7368
  }
7369
+ invalidateSelectorCacheRecursively() {
7370
+ }
7234
7371
  get innerText() {
7235
7372
  return this.rawText;
7236
7373
  }
@@ -7773,11 +7910,32 @@ var recker = (() => {
7773
7910
  voidTag;
7774
7911
  _attrs;
7775
7912
  _rawAttrs;
7913
+ _queryCache;
7776
7914
  _parseOptions;
7777
7915
  rawTagName;
7778
7916
  id;
7779
7917
  classList;
7780
7918
  nodeType = type_default.ELEMENT_NODE;
7919
+ get isSelectorCacheEnabled() {
7920
+ var _a2;
7921
+ return ((_a2 = this._parseOptions) == null ? void 0 : _a2.selectorCache) !== false;
7922
+ }
7923
+ getQueryCache() {
7924
+ if (!this._queryCache) {
7925
+ this._queryCache = /* @__PURE__ */ new Map();
7926
+ }
7927
+ return this._queryCache;
7928
+ }
7929
+ clearQueryCache() {
7930
+ this._queryCache = void 0;
7931
+ }
7932
+ invalidateSelectorCacheRecursively() {
7933
+ let current = this;
7934
+ while (current) {
7935
+ current.clearQueryCache();
7936
+ current = current.parentNode;
7937
+ }
7938
+ }
7781
7939
  quoteAttribute(attr) {
7782
7940
  if (attr == null) {
7783
7941
  return "null";
@@ -7814,6 +7972,7 @@ var recker = (() => {
7814
7972
  this.childNodes = this.childNodes.filter((child) => {
7815
7973
  return child !== node;
7816
7974
  });
7975
+ this.invalidateSelectorCacheRecursively();
7817
7976
  return this;
7818
7977
  }
7819
7978
  exchangeChild(oldNode, newNode) {
@@ -7824,6 +7983,7 @@ var recker = (() => {
7824
7983
  }
7825
7984
  return child;
7826
7985
  });
7986
+ this.invalidateSelectorCacheRecursively();
7827
7987
  return this;
7828
7988
  }
7829
7989
  get tagName() {
@@ -7852,6 +8012,7 @@ var recker = (() => {
7852
8012
  set textContent(val) {
7853
8013
  const content = [new TextNode(val, this)];
7854
8014
  this.childNodes = content;
8015
+ this.invalidateSelectorCacheRecursively();
7855
8016
  }
7856
8017
  get text() {
7857
8018
  return decode(this.rawText);
@@ -7909,6 +8070,7 @@ var recker = (() => {
7909
8070
  resetParent(nodes, this);
7910
8071
  resetParent(this.childNodes, null);
7911
8072
  this.childNodes = nodes;
8073
+ this.invalidateSelectorCacheRecursively();
7912
8074
  }
7913
8075
  set_content(content, options2 = {}) {
7914
8076
  if (content instanceof Node) {
@@ -7921,6 +8083,7 @@ var recker = (() => {
7921
8083
  resetParent(this.childNodes, null);
7922
8084
  resetParent(content, this);
7923
8085
  this.childNodes = content;
8086
+ this.invalidateSelectorCacheRecursively();
7924
8087
  return this;
7925
8088
  }
7926
8089
  replaceWith(...nodes) {
@@ -7945,6 +8108,7 @@ var recker = (() => {
7945
8108
  ...resetParent(content, parent),
7946
8109
  ...parent.childNodes.slice(idx + 1)
7947
8110
  ];
8111
+ parent.invalidateSelectorCacheRecursively();
7948
8112
  return this;
7949
8113
  }
7950
8114
  get outerHTML() {
@@ -7963,6 +8127,7 @@ var recker = (() => {
7963
8127
  }
7964
8128
  }
7965
8129
  }
8130
+ this.invalidateSelectorCacheRecursively();
7966
8131
  return this;
7967
8132
  }
7968
8133
  get structure() {
@@ -8004,6 +8169,7 @@ var recker = (() => {
8004
8169
  this.childNodes[o++] = node;
8005
8170
  });
8006
8171
  this.childNodes.length = o;
8172
+ this.invalidateSelectorCacheRecursively();
8007
8173
  const attrs = Object.keys(this.rawAttributes).map((key) => {
8008
8174
  const val = this.rawAttributes[key];
8009
8175
  return `${key}=${JSON.stringify(val)}`;
@@ -8013,16 +8179,49 @@ var recker = (() => {
8013
8179
  return this;
8014
8180
  }
8015
8181
  querySelectorAll(selector) {
8016
- return selectAll(selector, this, {
8182
+ if (this.isSelectorCacheEnabled) {
8183
+ const cached = this.getQueryCache().get(selector);
8184
+ if (cached == null ? void 0 : cached.all) {
8185
+ return cached.all.slice();
8186
+ }
8187
+ }
8188
+ const nodes = selectAll(selector, this, {
8017
8189
  xmlMode: false,
8018
8190
  adapter: matcher_default
8019
8191
  });
8192
+ if (this.isSelectorCacheEnabled) {
8193
+ const cacheEntry = this.getQueryCache().get(selector) || {};
8194
+ cacheEntry.all = nodes;
8195
+ if (cacheEntry.first === void 0) {
8196
+ cacheEntry.first = nodes[0] || null;
8197
+ }
8198
+ this.getQueryCache().set(selector, cacheEntry);
8199
+ }
8200
+ return nodes;
8020
8201
  }
8021
8202
  querySelector(selector) {
8022
- return selectOne(selector, this, {
8203
+ if (this.isSelectorCacheEnabled) {
8204
+ const cached = this.getQueryCache().get(selector);
8205
+ if ((cached == null ? void 0 : cached.first) !== void 0) {
8206
+ return cached.first || null;
8207
+ }
8208
+ if (cached == null ? void 0 : cached.all) {
8209
+ const first = cached.all[0] || null;
8210
+ cached.first = first;
8211
+ this.getQueryCache().set(selector, cached);
8212
+ return first;
8213
+ }
8214
+ }
8215
+ const result = selectOne(selector, this, {
8023
8216
  xmlMode: false,
8024
8217
  adapter: matcher_default
8025
8218
  });
8219
+ if (this.isSelectorCacheEnabled) {
8220
+ const cacheEntry = this.getQueryCache().get(selector) || {};
8221
+ cacheEntry.first = result;
8222
+ this.getQueryCache().set(selector, cacheEntry);
8223
+ }
8224
+ return result;
8026
8225
  }
8027
8226
  getElementsByTagName(tagName) {
8028
8227
  const upperCasedTagName = tagName.toUpperCase();
@@ -8083,21 +8282,6 @@ var recker = (() => {
8083
8282
  const mapChild = /* @__PURE__ */ new Map();
8084
8283
  let el = this;
8085
8284
  let old = null;
8086
- function findOne4(test, elems) {
8087
- let elem = null;
8088
- for (let i = 0, l = elems.length; i < l && !elem; i++) {
8089
- const el2 = elems[i];
8090
- if (test(el2)) {
8091
- elem = el2;
8092
- } else {
8093
- const child = mapChild.get(el2);
8094
- if (child) {
8095
- elem = findOne4(test, [child]);
8096
- }
8097
- }
8098
- }
8099
- return elem;
8100
- }
8101
8285
  while (el) {
8102
8286
  if (old)
8103
8287
  mapChild.set(el, old);
@@ -8185,6 +8369,7 @@ var recker = (() => {
8185
8369
  if (key === "id") {
8186
8370
  this.id = "";
8187
8371
  }
8372
+ this.invalidateSelectorCacheRecursively();
8188
8373
  return this;
8189
8374
  }
8190
8375
  hasAttribute(key) {
@@ -8218,6 +8403,7 @@ var recker = (() => {
8218
8403
  if (key === "id") {
8219
8404
  this.id = value;
8220
8405
  }
8406
+ this.invalidateSelectorCacheRecursively();
8221
8407
  return this;
8222
8408
  }
8223
8409
  setAttributes(attributes) {
@@ -8233,6 +8419,7 @@ var recker = (() => {
8233
8419
  return name;
8234
8420
  return `${name}=${this.quoteAttribute(String(val))}`;
8235
8421
  }).join(" ");
8422
+ this.invalidateSelectorCacheRecursively();
8236
8423
  return this;
8237
8424
  }
8238
8425
  insertAdjacentHTML(where, html) {
@@ -8257,11 +8444,13 @@ var recker = (() => {
8257
8444
  const nodes = resolveInsertable(insertable, this._parseOptions);
8258
8445
  resetParent(nodes, this);
8259
8446
  this.childNodes.unshift(...nodes);
8447
+ this.invalidateSelectorCacheRecursively();
8260
8448
  }
8261
8449
  append(...insertable) {
8262
8450
  const nodes = resolveInsertable(insertable, this._parseOptions);
8263
8451
  resetParent(nodes, this);
8264
8452
  this.childNodes.push(...nodes);
8453
+ this.invalidateSelectorCacheRecursively();
8265
8454
  }
8266
8455
  before(...insertable) {
8267
8456
  if (!this.parentNode)
@@ -8270,6 +8459,7 @@ var recker = (() => {
8270
8459
  const siblings = this.parentNode.childNodes;
8271
8460
  resetParent(nodes, this.parentNode);
8272
8461
  siblings.splice(siblings.indexOf(this), 0, ...nodes);
8462
+ this.parentNode.invalidateSelectorCacheRecursively();
8273
8463
  }
8274
8464
  after(...insertable) {
8275
8465
  if (!this.parentNode)
@@ -8278,6 +8468,7 @@ var recker = (() => {
8278
8468
  const siblings = this.parentNode.childNodes;
8279
8469
  resetParent(nodes, this.parentNode);
8280
8470
  siblings.splice(siblings.indexOf(this) + 1, 0, ...nodes);
8471
+ this.parentNode.invalidateSelectorCacheRecursively();
8281
8472
  }
8282
8473
  get nextSibling() {
8283
8474
  if (this.parentNode) {
@@ -10695,6 +10886,32 @@ var recker = (() => {
10695
10886
  __export(undici_exports, {
10696
10887
  UndiciTransport: () => UndiciTransport
10697
10888
  });
10889
+ function getAbortReason2(error) {
10890
+ return (error == null ? void 0 : error.cause) ?? (error == null ? void 0 : error.reason);
10891
+ }
10892
+ function isTimeoutAbortReason(reason) {
10893
+ if (reason instanceof TimeoutError) {
10894
+ return true;
10895
+ }
10896
+ if (!reason || typeof reason !== "object") {
10897
+ return false;
10898
+ }
10899
+ const timeoutReason = reason;
10900
+ return timeoutReason.name === "TimeoutError";
10901
+ }
10902
+ function isTotalRequestTimeoutError(error, timeoutReason, timeoutMs) {
10903
+ if (!timeoutMs) {
10904
+ return false;
10905
+ }
10906
+ if (timeoutReason !== void 0) {
10907
+ return true;
10908
+ }
10909
+ const causeOrReason = getAbortReason2(error);
10910
+ const message = error == null ? void 0 : error.message;
10911
+ const hasTimeoutMessage = typeof message === "string" && (message.includes("Request timed out (total time exceeded)") || message.includes("timed out (total time exceeded)"));
10912
+ const hasRequestAbortMessage = typeof message === "string" && message.toLowerCase() === "request was aborted";
10913
+ return error instanceof TimeoutError || isTimeoutAbortReason(causeOrReason) || isTimeoutAbortReason(error) || error instanceof errors5.RequestAbortedError || hasTimeoutMessage || hasRequestAbortMessage || (error == null ? void 0 : error.code) === "ABORT_ERR" || (error == null ? void 0 : error.code) === "UND_ERR_REQUEST_TIMEOUT";
10914
+ }
10698
10915
  function mapTimeoutOptions(requestTimeout, transportDefaults) {
10699
10916
  return {
10700
10917
  connectTimeout: (requestTimeout == null ? void 0 : requestTimeout.connect) ?? (requestTimeout == null ? void 0 : requestTimeout.secureConnect) ?? (transportDefaults == null ? void 0 : transportDefaults.connectTimeout),
@@ -10959,7 +11176,7 @@ var recker = (() => {
10959
11176
  }
10960
11177
  }
10961
11178
  });
10962
- undiciBodySentChannel.subscribe((message) => {
11179
+ undiciBodySentChannel.subscribe((_message) => {
10963
11180
  const store = requestStorage.getStore();
10964
11181
  if ((store == null ? void 0 : store.hooks) && store.hooks.onRequestSent) {
10965
11182
  store.hooks.onRequestSent();
@@ -11216,6 +11433,9 @@ var recker = (() => {
11216
11433
  });
11217
11434
  let timeoutController;
11218
11435
  let timeoutId;
11436
+ let timeoutReason;
11437
+ let timeoutError;
11438
+ let cancelOriginalAbortListener;
11219
11439
  if (!this.observability) {
11220
11440
  return this.dispatchFast(req, headers, currentUrl, timeouts, handleRedirectsManually, maxRedirects, followRedirects, uploadTotal);
11221
11441
  }
@@ -11240,22 +11460,30 @@ var recker = (() => {
11240
11460
  let effectiveSignal = req.signal;
11241
11461
  if (timeouts.totalTimeout) {
11242
11462
  timeoutController = new AbortController();
11463
+ timeoutError = new TimeoutError(req, {
11464
+ phase: "request",
11465
+ timeout: timeouts.totalTimeout
11466
+ });
11243
11467
  if (req.signal) {
11244
11468
  const originalSignal = req.signal;
11245
11469
  effectiveSignal = timeoutController.signal;
11246
11470
  const onOriginalAbort = () => {
11247
- timeoutController.abort();
11471
+ timeoutReason = originalSignal.reason ?? new Error("Request aborted by external signal");
11472
+ timeoutController.abort(timeoutReason);
11248
11473
  };
11249
11474
  if (originalSignal.aborted) {
11250
- timeoutController.abort();
11475
+ timeoutReason = originalSignal.reason ?? new Error("Request aborted by external signal");
11476
+ timeoutController.abort(timeoutReason);
11251
11477
  } else {
11252
11478
  originalSignal.addEventListener("abort", onOriginalAbort, { once: true });
11479
+ cancelOriginalAbortListener = () => originalSignal.removeEventListener("abort", onOriginalAbort);
11253
11480
  }
11254
11481
  } else {
11255
11482
  effectiveSignal = timeoutController.signal;
11256
11483
  }
11257
11484
  timeoutId = setTimeout(() => {
11258
- timeoutController.abort();
11485
+ timeoutReason = timeoutError;
11486
+ timeoutController.abort(timeoutReason);
11259
11487
  }, timeouts.totalTimeout);
11260
11488
  }
11261
11489
  while (true) {
@@ -11469,8 +11697,8 @@ var recker = (() => {
11469
11697
  timeout: timeouts.bodyTimeout
11470
11698
  });
11471
11699
  }
11472
- if (error.name === "AbortError" || error.code === "ABORT_ERR") {
11473
- throw new TimeoutError(req, {
11700
+ if (isTotalRequestTimeoutError(error, timeoutReason, timeouts.totalTimeout)) {
11701
+ throw timeoutError ?? new TimeoutError(req, {
11474
11702
  phase: "request",
11475
11703
  timeout: timeouts.totalTimeout
11476
11704
  });
@@ -11486,6 +11714,9 @@ var recker = (() => {
11486
11714
  }
11487
11715
  throw new NetworkError(error.message, code, req);
11488
11716
  } finally {
11717
+ if (typeof cancelOriginalAbortListener === "function") {
11718
+ cancelOriginalAbortListener();
11719
+ }
11489
11720
  if (timeoutId) {
11490
11721
  clearTimeout(timeoutId);
11491
11722
  }
@@ -11496,6 +11727,9 @@ var recker = (() => {
11496
11727
  var _a2, _b;
11497
11728
  let timeoutController;
11498
11729
  let timeoutId;
11730
+ let timeoutReason;
11731
+ let timeoutError;
11732
+ let cancelOriginalAbortListener;
11499
11733
  try {
11500
11734
  let redirectCount = 0;
11501
11735
  let currentMethod = req.method;
@@ -11504,22 +11738,30 @@ var recker = (() => {
11504
11738
  let effectiveSignal = req.signal;
11505
11739
  if (timeouts.totalTimeout) {
11506
11740
  timeoutController = new AbortController();
11741
+ timeoutError = new TimeoutError(req, {
11742
+ phase: "request",
11743
+ timeout: timeouts.totalTimeout
11744
+ });
11507
11745
  if (req.signal) {
11508
11746
  const originalSignal = req.signal;
11509
11747
  effectiveSignal = timeoutController.signal;
11510
11748
  const onOriginalAbort = () => {
11511
- timeoutController.abort();
11749
+ timeoutReason = originalSignal.reason ?? new Error("Request aborted by external signal");
11750
+ timeoutController.abort(timeoutReason);
11512
11751
  };
11513
11752
  if (originalSignal.aborted) {
11514
- timeoutController.abort();
11753
+ timeoutReason = originalSignal.reason ?? new Error("Request aborted by external signal");
11754
+ timeoutController.abort(timeoutReason);
11515
11755
  } else {
11516
11756
  originalSignal.addEventListener("abort", onOriginalAbort, { once: true });
11757
+ cancelOriginalAbortListener = () => originalSignal.removeEventListener("abort", onOriginalAbort);
11517
11758
  }
11518
11759
  } else {
11519
11760
  effectiveSignal = timeoutController.signal;
11520
11761
  }
11521
11762
  timeoutId = setTimeout(() => {
11522
- timeoutController.abort();
11763
+ timeoutReason = timeoutError;
11764
+ timeoutController.abort(timeoutReason);
11523
11765
  }, timeouts.totalTimeout);
11524
11766
  }
11525
11767
  while (true) {
@@ -11679,8 +11921,8 @@ var recker = (() => {
11679
11921
  timeout: timeouts.bodyTimeout
11680
11922
  });
11681
11923
  }
11682
- if (error.name === "AbortError" || error.code === "ABORT_ERR") {
11683
- throw new TimeoutError(req, {
11924
+ if (isTotalRequestTimeoutError(error, timeoutReason, timeouts.totalTimeout)) {
11925
+ throw timeoutError ?? new TimeoutError(req, {
11684
11926
  phase: "request",
11685
11927
  timeout: timeouts.totalTimeout
11686
11928
  });
@@ -11696,6 +11938,9 @@ var recker = (() => {
11696
11938
  }
11697
11939
  throw new NetworkError(error.message, code, req);
11698
11940
  } finally {
11941
+ if (typeof cancelOriginalAbortListener === "function") {
11942
+ cancelOriginalAbortListener();
11943
+ }
11699
11944
  if (timeoutId) {
11700
11945
  clearTimeout(timeoutId);
11701
11946
  }
@@ -12686,6 +12931,7 @@ var recker = (() => {
12686
12931
  XmlRpcClient: () => XmlRpcClient,
12687
12932
  browserCrypto: () => browserCrypto,
12688
12933
  circuitBreakerPlugin: () => circuitBreakerPlugin,
12934
+ classifyTransportError: () => classifyTransportError,
12689
12935
  compression: () => compression2,
12690
12936
  consoleLogger: () => consoleLogger,
12691
12937
  cookieJarPlugin: () => cookieJarPlugin,
@@ -13659,6 +13905,32 @@ var recker = (() => {
13659
13905
  }
13660
13906
  };
13661
13907
 
13908
+ // dist/browser/core-runtime/request-context.js
13909
+ var requestSeq = 0;
13910
+ function createRequestContext(seed = {}) {
13911
+ requestSeq += 1;
13912
+ const requestId = `${Date.now().toString(36)}-${requestSeq.toString(36)}-${Math.random().toString(16).slice(2, 8)}`;
13913
+ return {
13914
+ requestId,
13915
+ correlationId: seed.correlationId || requestId,
13916
+ tenant: seed.tenant,
13917
+ policyTags: seed.policyTags ?? [],
13918
+ policySource: seed.policySource,
13919
+ createdAt: Date.now(),
13920
+ traceId: seed.traceId
13921
+ };
13922
+ }
13923
+ function attachRequestContext(request7, context) {
13924
+ if (!request7) {
13925
+ return request7;
13926
+ }
13927
+ request7._runtime = context;
13928
+ return request7;
13929
+ }
13930
+ function getRequestContext(request7) {
13931
+ return request7._runtime;
13932
+ }
13933
+
13662
13934
  // dist/browser/core/request.js
13663
13935
  function normalizeTimeout(timeout) {
13664
13936
  if (timeout === void 0)
@@ -13684,6 +13956,11 @@ var recker = (() => {
13684
13956
  followRedirects;
13685
13957
  http2;
13686
13958
  useCurl;
13959
+ correlationId;
13960
+ tenant;
13961
+ policyTags;
13962
+ policySource;
13963
+ traceId;
13687
13964
  constructor(url, options2 = {}) {
13688
13965
  this.url = url;
13689
13966
  this.method = options2.method || "GET";
@@ -13700,11 +13977,17 @@ var recker = (() => {
13700
13977
  this.followRedirects = options2.followRedirects;
13701
13978
  this.http2 = options2.http2;
13702
13979
  this.useCurl = options2.useCurl;
13980
+ this.correlationId = options2.correlationId;
13981
+ this.tenant = options2.tenant;
13982
+ this.policyTags = options2.policyTags ?? [];
13983
+ this.policySource = options2.policySource;
13984
+ this.traceId = options2.traceId;
13703
13985
  }
13704
13986
  withHeader(name, value) {
13987
+ const context = getRequestContext(this);
13705
13988
  const newHeaders = new Headers(this.headers);
13706
13989
  newHeaders.set(name, value);
13707
- return new _HttpRequest(this.url, {
13990
+ const request7 = new _HttpRequest(this.url, {
13708
13991
  method: this.method,
13709
13992
  headers: newHeaders,
13710
13993
  body: this.body,
@@ -13718,11 +14001,21 @@ var recker = (() => {
13718
14001
  maxRedirects: this.maxRedirects,
13719
14002
  followRedirects: this.followRedirects,
13720
14003
  http2: this.http2,
13721
- useCurl: this.useCurl
14004
+ useCurl: this.useCurl,
14005
+ correlationId: this.correlationId,
14006
+ tenant: this.tenant,
14007
+ policyTags: this.policyTags,
14008
+ policySource: this.policySource,
14009
+ traceId: this.traceId
13722
14010
  });
14011
+ if (context) {
14012
+ return attachRequestContext(request7, context);
14013
+ }
14014
+ return request7;
13723
14015
  }
13724
14016
  withBody(body) {
13725
- return new _HttpRequest(this.url, {
14017
+ const context = getRequestContext(this);
14018
+ const request7 = new _HttpRequest(this.url, {
13726
14019
  method: this.method,
13727
14020
  headers: this.headers,
13728
14021
  body,
@@ -13736,8 +14029,17 @@ var recker = (() => {
13736
14029
  maxRedirects: this.maxRedirects,
13737
14030
  followRedirects: this.followRedirects,
13738
14031
  http2: this.http2,
13739
- useCurl: this.useCurl
14032
+ useCurl: this.useCurl,
14033
+ correlationId: this.correlationId,
14034
+ tenant: this.tenant,
14035
+ policyTags: this.policyTags,
14036
+ policySource: this.policySource,
14037
+ traceId: this.traceId
13740
14038
  });
14039
+ if (context) {
14040
+ return attachRequestContext(request7, context);
14041
+ }
14042
+ return request7;
13741
14043
  }
13742
14044
  };
13743
14045
 
@@ -13985,6 +14287,166 @@ var recker = (() => {
13985
14287
  }
13986
14288
  };
13987
14289
 
14290
+ // dist/browser/core-runtime/typed-events.js
14291
+ function createNoopEventBus() {
14292
+ return {
14293
+ on: () => () => void 0,
14294
+ emit: () => void 0
14295
+ };
14296
+ }
14297
+
14298
+ // dist/browser/core-runtime/plugin-manifest.js
14299
+ var DEFAULT_SCOPE = "request";
14300
+ var DEFAULT_PRIORITY = 0;
14301
+ function attachPluginManifest(plugin, manifest) {
14302
+ plugin.__reckerManifest = normalizeManifest(plugin, manifest);
14303
+ return plugin;
14304
+ }
14305
+ function normalizePluginManifest(plugin, options2 = {}) {
14306
+ return normalizeManifest(plugin, options2);
14307
+ }
14308
+ function getPluginManifest(plugin) {
14309
+ return plugin.__reckerManifest;
14310
+ }
14311
+ function normalizeManifest(plugin, manifest) {
14312
+ const pluginId = (manifest == null ? void 0 : manifest.name) || inferPluginName(plugin);
14313
+ return {
14314
+ name: pluginId,
14315
+ version: (manifest == null ? void 0 : manifest.version) || "1",
14316
+ scope: (manifest == null ? void 0 : manifest.scope) || DEFAULT_SCOPE,
14317
+ priority: (manifest == null ? void 0 : manifest.priority) ?? DEFAULT_PRIORITY,
14318
+ dependsOn: (manifest == null ? void 0 : manifest.dependsOn) || [],
14319
+ setup: manifest == null ? void 0 : manifest.setup,
14320
+ teardown: manifest == null ? void 0 : manifest.teardown
14321
+ };
14322
+ }
14323
+ function inferPluginName(plugin) {
14324
+ return plugin.name && plugin.name !== "anonymous" ? plugin.name : `plugin-${Math.random().toString(16).slice(2, 10)}`;
14325
+ }
14326
+ function assertUniqueName(name, existing, source) {
14327
+ if (existing.has(name)) {
14328
+ throw new Error(`Invalid plugin manifest: duplicate plugin name '${name}'. ${source}`);
14329
+ }
14330
+ existing.add(name);
14331
+ }
14332
+ function buildDependencyError(path, target) {
14333
+ return `${target} -> ${path.join(" -> ")} -> ${target}`;
14334
+ }
14335
+ function formatSortState(names) {
14336
+ return names.join(" -> ");
14337
+ }
14338
+ function toSortedPlugins(plugins) {
14339
+ return plugins.map((plugin, registrationIndex) => ({
14340
+ plugin,
14341
+ manifest: normalizePluginManifest(plugin, getPluginManifest(plugin)),
14342
+ registrationIndex
14343
+ }));
14344
+ }
14345
+ function normalizePlugins(registrations) {
14346
+ const byName = /* @__PURE__ */ new Map();
14347
+ const seenNames = /* @__PURE__ */ new Set();
14348
+ registrations.forEach((entry) => {
14349
+ const manifest = entry.manifest;
14350
+ const name = manifest.name;
14351
+ assertUniqueName(name, seenNames, "Use explicit `manifest.name` to avoid collisions for anonymous plugin factories.");
14352
+ byName.set(name, entry);
14353
+ });
14354
+ const edges = /* @__PURE__ */ new Map();
14355
+ const indegree = /* @__PURE__ */ new Map();
14356
+ registrations.forEach((entry) => {
14357
+ const { name, dependsOn } = entry.manifest;
14358
+ indegree.set(name, 0);
14359
+ edges.set(name, /* @__PURE__ */ new Set());
14360
+ for (const dependency of dependsOn) {
14361
+ if (!byName.has(dependency)) {
14362
+ throw new Error(`Invalid plugin dependency for '${name}': missing plugin '${dependency}'. Available plugins: ` + Array.from(byName.keys()).sort().join(", "));
14363
+ }
14364
+ edges.get(dependency).add(name);
14365
+ indegree.set(name, (indegree.get(name) || 0) + 1);
14366
+ }
14367
+ });
14368
+ const queue = [];
14369
+ byName.forEach((_entry, name) => {
14370
+ if ((indegree.get(name) || 0) === 0) {
14371
+ queue.push(name);
14372
+ }
14373
+ });
14374
+ const ordered = [];
14375
+ const nextReady = (names) => names.sort((a, b) => {
14376
+ const aMeta = byName.get(a);
14377
+ const bMeta = byName.get(b);
14378
+ const priorityDiff = bMeta.manifest.priority - aMeta.manifest.priority;
14379
+ if (priorityDiff !== 0) {
14380
+ return priorityDiff;
14381
+ }
14382
+ return aMeta.registrationIndex - bMeta.registrationIndex;
14383
+ });
14384
+ while (queue.length > 0) {
14385
+ const current = nextReady(queue).splice(0, 1)[0];
14386
+ const index = queue.indexOf(current);
14387
+ if (index >= 0) {
14388
+ queue.splice(index, 1);
14389
+ }
14390
+ const currentEntry = byName.get(current);
14391
+ if (!currentEntry) {
14392
+ continue;
14393
+ }
14394
+ ordered.push(currentEntry);
14395
+ const dependents = edges.get(current);
14396
+ if (!dependents) {
14397
+ continue;
14398
+ }
14399
+ for (const dependentName of dependents) {
14400
+ const currentDegree = (indegree.get(dependentName) || 0) - 1;
14401
+ indegree.set(dependentName, currentDegree);
14402
+ if (currentDegree === 0) {
14403
+ queue.push(dependentName);
14404
+ }
14405
+ }
14406
+ }
14407
+ if (ordered.length !== registrations.length) {
14408
+ const unresolved = Array.from(indegree.entries()).filter(([, degree]) => degree > 0).map(([name]) => name);
14409
+ const cycle = detectCycle(unresolved, edges);
14410
+ throw new Error(`Invalid plugin manifest: circular dependency detected. Unresolved nodes: ${formatSortState(unresolved)}. ` + (cycle ? `Detected cycle: ${cycle}.` : "Refactor dependency graph to a DAG."));
14411
+ }
14412
+ const debugOrder = ordered.map((entry) => `${entry.manifest.name}:${entry.manifest.scope}:${entry.manifest.priority}`);
14413
+ return { ordered, debugOrder };
14414
+ }
14415
+ function detectCycle(nodes, edges) {
14416
+ const visited = /* @__PURE__ */ new Set();
14417
+ const inStack = /* @__PURE__ */ new Set();
14418
+ const dfs = (node, stack) => {
14419
+ if (inStack.has(node)) {
14420
+ const cycleStart = stack.indexOf(node);
14421
+ if (cycleStart >= 0) {
14422
+ return buildDependencyError(stack.slice(cycleStart), node);
14423
+ }
14424
+ return null;
14425
+ }
14426
+ if (visited.has(node)) {
14427
+ return null;
14428
+ }
14429
+ visited.add(node);
14430
+ inStack.add(node);
14431
+ const nextNodes = edges.get(node) || /* @__PURE__ */ new Set();
14432
+ for (const next of nextNodes) {
14433
+ const hit = dfs(next, [...stack, next]);
14434
+ if (hit) {
14435
+ return hit;
14436
+ }
14437
+ }
14438
+ inStack.delete(node);
14439
+ return null;
14440
+ };
14441
+ for (const node of nodes) {
14442
+ const cycle = dfs(node, [node]);
14443
+ if (cycle) {
14444
+ return cycle;
14445
+ }
14446
+ }
14447
+ return null;
14448
+ }
14449
+
13988
14450
  // dist/browser/utils/concurrency.js
13989
14451
  var DEFAULT_INTERVAL = 1 * 1e3;
13990
14452
  function normalizeConcurrency(options2) {
@@ -14244,6 +14706,7 @@ var recker = (() => {
14244
14706
 
14245
14707
  // dist/browser/transport/fetch.js
14246
14708
  init_progress();
14709
+ init_errors();
14247
14710
  function parseContentLength(headers) {
14248
14711
  const raw = headers.get("content-length");
14249
14712
  if (!raw)
@@ -14251,6 +14714,19 @@ var recker = (() => {
14251
14714
  const parsed = parseInt(raw, 10);
14252
14715
  return Number.isFinite(parsed) ? parsed : void 0;
14253
14716
  }
14717
+ function getAbortReason(error) {
14718
+ return (error == null ? void 0 : error.cause) ?? (error == null ? void 0 : error.reason);
14719
+ }
14720
+ function isTimeoutReason(reason) {
14721
+ if (reason instanceof TimeoutError) {
14722
+ return true;
14723
+ }
14724
+ if (!reason || typeof reason !== "object") {
14725
+ return false;
14726
+ }
14727
+ const timeoutReason = reason;
14728
+ return timeoutReason.name === "TimeoutError";
14729
+ }
14254
14730
  function wrapDownloadResponse(response, onProgress) {
14255
14731
  if (!onProgress || !response.body)
14256
14732
  return response;
@@ -14308,10 +14784,16 @@ var recker = (() => {
14308
14784
  let abortController;
14309
14785
  const timeoutMs = typeof req.timeout === "number" ? req.timeout : (_a2 = req.timeout) == null ? void 0 : _a2.request;
14310
14786
  let signal = req.signal;
14787
+ const requestTimeoutError = timeoutMs ? new TimeoutError(req, {
14788
+ phase: "request",
14789
+ timeout: timeoutMs
14790
+ }) : void 0;
14311
14791
  if (timeoutMs && !signal) {
14312
14792
  abortController = new AbortController();
14313
14793
  signal = abortController.signal;
14314
- timeoutId = setTimeout(() => abortController.abort(), timeoutMs);
14794
+ timeoutId = setTimeout(() => {
14795
+ timeoutControllerAbort(abortController, requestTimeoutError);
14796
+ }, timeoutMs);
14315
14797
  }
14316
14798
  const followRedirects = req.followRedirects !== false;
14317
14799
  const maxRedirects = req.maxRedirects ?? 20;
@@ -14387,10 +14869,11 @@ var recker = (() => {
14387
14869
  return new FetchResponseWrapper(finalResponse, timings);
14388
14870
  }
14389
14871
  } catch (error) {
14390
- if (error.name === "AbortError" && abortController) {
14391
- const timeoutError = new Error(`Request timeout after ${timeoutMs}ms`);
14392
- timeoutError.name = "TimeoutError";
14393
- throw timeoutError;
14872
+ if (timeoutMs && (error.name === "AbortError" || error.name === "TimeoutError")) {
14873
+ const timeoutReason = getAbortReason(error);
14874
+ if (isTimeoutReason(timeoutReason) || isTimeoutReason(getAbortReason(signal)) || abortController && isTimeoutReason(requestTimeoutError)) {
14875
+ throw timeoutReason instanceof TimeoutError ? timeoutReason : requestTimeoutError ?? error;
14876
+ }
14394
14877
  }
14395
14878
  throw error;
14396
14879
  } finally {
@@ -14399,6 +14882,15 @@ var recker = (() => {
14399
14882
  }
14400
14883
  }
14401
14884
  };
14885
+ function timeoutControllerAbort(controller, reason) {
14886
+ if (!controller.signal.aborted) {
14887
+ if (reason) {
14888
+ controller.abort(reason);
14889
+ } else {
14890
+ controller.abort();
14891
+ }
14892
+ }
14893
+ }
14402
14894
  var FetchResponseWrapper = class _FetchResponseWrapper {
14403
14895
  raw;
14404
14896
  timings;
@@ -14667,6 +15159,13 @@ var recker = (() => {
14667
15159
  if (error instanceof HttpError) {
14668
15160
  return statusCodes.includes(error.status);
14669
15161
  }
15162
+ const classification = classifyTransportError(error);
15163
+ if (classification && classification.canRetry === false) {
15164
+ return false;
15165
+ }
15166
+ if (classification) {
15167
+ return classification.canRetry;
15168
+ }
14670
15169
  if (error && typeof error === "object" && "code" in error) {
14671
15170
  const code = error.code;
14672
15171
  return code === "ECONNRESET" || code === "ETIMEDOUT" || code === "ENOTFOUND";
@@ -14675,6 +15174,24 @@ var recker = (() => {
14675
15174
  };
14676
15175
  const shouldRetry = options2.shouldRetry || defaultShouldRetry;
14677
15176
  return (client) => {
15177
+ const emitRequestRetry = (error, attempt, delayMs, req) => {
15178
+ const eventBus = client.runtimeEventBus;
15179
+ if (!(eventBus == null ? void 0 : eventBus.emit)) {
15180
+ return;
15181
+ }
15182
+ const context = getRequestContext(req);
15183
+ if (!context) {
15184
+ return;
15185
+ }
15186
+ const classification = classifyTransportError(error);
15187
+ eventBus.emit("request:retry", {
15188
+ context,
15189
+ req,
15190
+ attempt,
15191
+ delayMs,
15192
+ reason: (classification == null ? void 0 : classification.reason) || (error == null ? void 0 : error.message) || "retry requested"
15193
+ });
15194
+ };
14678
15195
  const middleware = async (req, next) => {
14679
15196
  var _a2, _b;
14680
15197
  let attempt = 0;
@@ -14691,6 +15208,7 @@ var recker = (() => {
14691
15208
  delayMs = calculateDelay(attempt, baseDelay, maxDelay, backoffStrategy, useJitter);
14692
15209
  }
14693
15210
  const err = new HttpError(res, req);
15211
+ emitRequestRetry(err, attempt, delayMs, req);
14694
15212
  if (onRetry) {
14695
15213
  onRetry(attempt, err, delayMs);
14696
15214
  }
@@ -14706,6 +15224,7 @@ var recker = (() => {
14706
15224
  } catch (error) {
14707
15225
  if (attempt < maxAttempts && shouldRetry(error)) {
14708
15226
  const delayMs = calculateDelay(attempt, baseDelay, maxDelay, backoffStrategy, useJitter);
15227
+ emitRequestRetry(error, attempt, delayMs, req);
14709
15228
  if (onRetry) {
14710
15229
  onRetry(attempt, error, delayMs);
14711
15230
  }
@@ -15945,6 +16464,7 @@ var recker = (() => {
15945
16464
  init_csv();
15946
16465
 
15947
16466
  // dist/browser/runner/request-runner.js
16467
+ init_errors();
15948
16468
  var SimpleEmitter = class {
15949
16469
  listeners = /* @__PURE__ */ new Map();
15950
16470
  on(event, listener) {
@@ -15990,10 +16510,14 @@ var recker = (() => {
15990
16510
  queue = [];
15991
16511
  activeCount = 0;
15992
16512
  paused = false;
15993
- results = /* @__PURE__ */ new Map();
15994
16513
  stats = { total: 0, successful: 0, failed: 0 };
15995
16514
  startTime = 0;
15996
16515
  pendingRetries = 0;
16516
+ isCancelled = false;
16517
+ cancelReason = new QueueCancelledError("Request runner cancelled");
16518
+ retryTimers = /* @__PURE__ */ new Map();
16519
+ timeoutId;
16520
+ abortUnsubscribe;
15997
16521
  constructor(options2 = {}) {
15998
16522
  super();
15999
16523
  this.concurrency = options2.concurrency || 5;
@@ -16014,49 +16538,140 @@ var recker = (() => {
16014
16538
  this.processNext();
16015
16539
  }
16016
16540
  async run(items, processor, options2 = {}) {
16541
+ this.queue = [];
16542
+ this.activeCount = 0;
16543
+ this.pendingRetries = 0;
16544
+ this.stats = { total: 0, successful: 0, failed: 0 };
16545
+ this.isCancelled = false;
16546
+ if (this.retryTimers.size > 0) {
16547
+ for (const [, timer] of this.retryTimers) {
16548
+ clearTimeout(timer);
16549
+ }
16550
+ this.retryTimers.clear();
16551
+ }
16552
+ if (this.timeoutId) {
16553
+ clearTimeout(this.timeoutId);
16554
+ this.timeoutId = void 0;
16555
+ }
16556
+ if (this.abortUnsubscribe) {
16557
+ this.abortUnsubscribe();
16558
+ this.abortUnsubscribe = void 0;
16559
+ }
16017
16560
  this.startTime = Date.now();
16018
16561
  this.stats = { total: items.length, successful: 0, failed: 0 };
16019
- this.results.clear();
16020
- const promises6 = items.map((item, index) => {
16021
- return new Promise((resolve8) => {
16022
- this.add(() => processor(item, index), {
16023
- priority: options2.priority,
16024
- id: String(index),
16025
- retries: options2.retries,
16026
- resolve: resolve8,
16027
- trackTotal: false
16562
+ this.isCancelled = false;
16563
+ this.cancelReason = new QueueCancelledError("Request runner cancelled", {
16564
+ queueName: "request-runner",
16565
+ request: void 0
16566
+ });
16567
+ if (options2.signal) {
16568
+ const signal = options2.signal;
16569
+ if (signal.aborted) {
16570
+ const reason = signal.reason instanceof Error ? signal.reason : new QueueCancelledError("Request runner signal was aborted", {
16571
+ queueName: "request-runner",
16572
+ request: void 0
16573
+ });
16574
+ this.cancelAll(reason);
16575
+ } else {
16576
+ const handleAbort = () => {
16577
+ const reason = signal.reason instanceof Error ? signal.reason : new QueueCancelledError("Request runner signal was aborted", {
16578
+ queueName: "request-runner",
16579
+ request: void 0
16580
+ });
16581
+ this.cancelAll(reason);
16582
+ };
16583
+ signal.addEventListener("abort", handleAbort, { once: true });
16584
+ this.abortUnsubscribe = () => signal.removeEventListener("abort", handleAbort);
16585
+ }
16586
+ }
16587
+ if (options2.deadlineMs !== void 0) {
16588
+ const deadline = options2.deadlineMs;
16589
+ if (deadline <= 0) {
16590
+ this.cancelAll(new QueueCancelledError("Request runner deadline elapsed", {
16591
+ queueName: "request-runner",
16592
+ request: void 0
16593
+ }));
16594
+ } else {
16595
+ this.timeoutId = setTimeout(() => {
16596
+ this.cancelAll(new QueueCancelledError("Request runner deadline exceeded", {
16597
+ queueName: "request-runner",
16598
+ request: void 0
16599
+ }));
16600
+ }, deadline);
16601
+ }
16602
+ }
16603
+ try {
16604
+ const promises6 = items.map((item, index) => {
16605
+ return new Promise((resolve8) => {
16606
+ this.add(() => processor(item, index), {
16607
+ priority: options2.priority,
16608
+ id: String(index),
16609
+ retries: options2.retries,
16610
+ resolve: resolve8,
16611
+ trackTotal: false
16612
+ });
16028
16613
  });
16029
16614
  });
16030
- });
16031
- const results = await Promise.all(promises6);
16032
- return {
16033
- results,
16034
- stats: {
16035
- ...this.stats,
16036
- duration: Date.now() - this.startTime
16615
+ const results = await Promise.all(promises6);
16616
+ return {
16617
+ results,
16618
+ stats: {
16619
+ ...this.stats,
16620
+ duration: Date.now() - this.startTime
16621
+ }
16622
+ };
16623
+ } finally {
16624
+ if (this.timeoutId) {
16625
+ clearTimeout(this.timeoutId);
16626
+ this.timeoutId = void 0;
16037
16627
  }
16038
- };
16628
+ if (this.abortUnsubscribe) {
16629
+ this.abortUnsubscribe();
16630
+ this.abortUnsubscribe = void 0;
16631
+ }
16632
+ }
16039
16633
  }
16040
16634
  queueTask(task) {
16041
16635
  this.queue.push(task);
16042
16636
  this.queue.sort((a, b) => b.priority - a.priority);
16043
16637
  }
16044
16638
  scheduleRetry(task, delay) {
16045
- this.pendingRetries++;
16046
- if (delay > 0) {
16047
- setTimeout(() => {
16048
- this.pendingRetries--;
16049
- this.queueTask(task);
16050
- this.processNext();
16051
- }, delay);
16639
+ if (this.isCancelled) {
16640
+ this.resolveTask(task, this.cancelReason);
16052
16641
  return;
16053
16642
  }
16054
- this.pendingRetries--;
16055
- this.queueTask(task);
16056
- this.processNext();
16643
+ if (delay <= 0) {
16644
+ this.queueTask(task);
16645
+ this.processNext();
16646
+ return;
16647
+ }
16648
+ const timerKey = `${task.id}-${Date.now()}-${Math.random().toString(16).slice(2, 8)}`;
16649
+ const enqueueTask = () => {
16650
+ this.retryTimers.delete(timerKey);
16651
+ this.pendingRetries--;
16652
+ if (this.isCancelled) {
16653
+ return;
16654
+ }
16655
+ this.queueTask(task);
16656
+ this.processNext();
16657
+ };
16658
+ this.retryTimers.set(timerKey, setTimeout(() => {
16659
+ if (this.isCancelled) {
16660
+ this.pendingRetries--;
16661
+ this.retryTimers.delete(timerKey);
16662
+ this.resolveTask(task, this.cancelReason);
16663
+ return;
16664
+ }
16665
+ enqueueTask();
16666
+ }, delay));
16667
+ this.pendingRetries++;
16057
16668
  }
16058
16669
  async processNext() {
16059
- var _a2, _b;
16670
+ var _a2;
16671
+ if (this.isCancelled) {
16672
+ this.resolveQueue();
16673
+ return;
16674
+ }
16060
16675
  if (this.paused || this.activeCount >= this.concurrency || this.queue.length === 0) {
16061
16676
  return;
16062
16677
  }
@@ -16071,14 +16686,17 @@ var recker = (() => {
16071
16686
  (_a2 = task.resolve) == null ? void 0 : _a2.call(task, result);
16072
16687
  this.emit("taskComplete", { task, result });
16073
16688
  } catch (error) {
16689
+ if (this.isCancelled) {
16690
+ this.resolveTask(task, this.cancelReason);
16691
+ return;
16692
+ }
16074
16693
  const remaining = task.retries ?? 0;
16075
16694
  if (remaining > 0) {
16076
16695
  task.retries = remaining - 1;
16077
16696
  this.emit("taskRetry", { task, error, remaining: task.retries, delay: this.retryDelay });
16078
16697
  this.scheduleRetry(task, this.retryDelay);
16079
16698
  } else {
16080
- this.stats.failed++;
16081
- (_b = task.resolve) == null ? void 0 : _b.call(task, error);
16699
+ this.resolveTask(task, error);
16082
16700
  this.emit("taskError", { task, error });
16083
16701
  }
16084
16702
  } finally {
@@ -16090,6 +16708,35 @@ var recker = (() => {
16090
16708
  this.processNext();
16091
16709
  }
16092
16710
  }
16711
+ cancelAll(reason) {
16712
+ if (this.isCancelled) {
16713
+ return;
16714
+ }
16715
+ this.isCancelled = true;
16716
+ this.cancelReason = reason;
16717
+ for (const [, timer] of this.retryTimers) {
16718
+ clearTimeout(timer);
16719
+ }
16720
+ this.retryTimers.clear();
16721
+ this.pendingRetries = 0;
16722
+ this.resolveQueue();
16723
+ }
16724
+ resolveQueue() {
16725
+ while (this.queue.length > 0) {
16726
+ const task = this.queue.shift();
16727
+ if (task) {
16728
+ this.resolveTask(task, this.cancelReason);
16729
+ }
16730
+ }
16731
+ }
16732
+ resolveTask(task, error) {
16733
+ var _a2;
16734
+ if (!task.resolve) {
16735
+ return;
16736
+ }
16737
+ this.stats.failed++;
16738
+ (_a2 = task.resolve) == null ? void 0 : _a2.call(task, error);
16739
+ }
16093
16740
  getProgress() {
16094
16741
  const completed = this.stats.successful + this.stats.failed;
16095
16742
  return {
@@ -17133,6 +17780,10 @@ var recker = (() => {
17133
17780
  concurrencyConfig;
17134
17781
  requestPool;
17135
17782
  maxResponseSize;
17783
+ runtimeEventBus;
17784
+ shouldEmitRuntimeEvents;
17785
+ runtimeEventBusProviderAttached = false;
17786
+ runtimeEventListenerCount = 0;
17136
17787
  cookieJar;
17137
17788
  cookieIgnoreInvalid = false;
17138
17789
  defaultTimeout;
@@ -17161,6 +17812,17 @@ var recker = (() => {
17161
17812
  this.defaultParams = ((_f = options2.defaults) == null ? void 0 : _f.params) || {};
17162
17813
  this.paginationConfig = options2.pagination;
17163
17814
  this.maxResponseSize = options2.maxResponseSize;
17815
+ const runtimeEventBus = options2.runtimeEventBus;
17816
+ if (runtimeEventBus) {
17817
+ this.runtimeEventBus = {
17818
+ on: (name, handler) => runtimeEventBus.on(name, handler),
17819
+ emit: (name, event) => runtimeEventBus.emit(name, event)
17820
+ };
17821
+ } else {
17822
+ this.runtimeEventBus = createNoopEventBus();
17823
+ }
17824
+ this.shouldEmitRuntimeEvents = runtimeEventBus !== void 0;
17825
+ this.runtimeEventBusProviderAttached = runtimeEventBus !== void 0;
17164
17826
  this.debugEnabled = options2.debug === true;
17165
17827
  if (this.debugEnabled) {
17166
17828
  this.logger = options2.logger ?? consoleLogger;
@@ -17218,8 +17880,20 @@ var recker = (() => {
17218
17880
  this.transport = new FetchTransport();
17219
17881
  this.transportKind = "fetch";
17220
17882
  }
17883
+ const registerPlugin = (plugin, manifest = {}) => {
17884
+ const existingManifest = getPluginManifest(plugin);
17885
+ pluginRegistrations.push(attachPluginManifest(plugin, {
17886
+ ...existingManifest,
17887
+ ...manifest
17888
+ }));
17889
+ };
17890
+ const pluginRegistrations = [];
17221
17891
  if (options2.retry) {
17222
- retryPlugin(options2.retry)(this);
17892
+ registerPlugin(retryPlugin(options2.retry), {
17893
+ name: "recker:retry",
17894
+ priority: 120,
17895
+ scope: "request"
17896
+ });
17223
17897
  }
17224
17898
  if (this.concurrencyConfig.max < Infinity || this.concurrencyConfig.requestsPerInterval < Infinity) {
17225
17899
  this.requestPool = new RequestPool({
@@ -17227,7 +17901,13 @@ var recker = (() => {
17227
17901
  requestsPerInterval: this.concurrencyConfig.requestsPerInterval,
17228
17902
  interval: this.concurrencyConfig.interval
17229
17903
  });
17230
- this.middlewares.unshift(this.requestPool.asMiddleware());
17904
+ registerPlugin((client) => {
17905
+ client.middlewares.unshift(this.requestPool.asMiddleware());
17906
+ }, {
17907
+ name: "recker:request-pool",
17908
+ priority: 130,
17909
+ scope: "runtime"
17910
+ });
17231
17911
  if (this.debugEnabled && this.logger) {
17232
17912
  this.logger.debug(`Global concurrency limit: ${this.concurrencyConfig.max} concurrent requests`);
17233
17913
  }
@@ -17237,7 +17917,11 @@ var recker = (() => {
17237
17917
  }
17238
17918
  }
17239
17919
  if (options2.dedup) {
17240
- dedupPlugin(options2.dedup)(this);
17920
+ registerPlugin(dedupPlugin(options2.dedup), {
17921
+ name: "recker:dedup",
17922
+ priority: 110,
17923
+ scope: "request"
17924
+ });
17241
17925
  }
17242
17926
  if (options2.cache) {
17243
17927
  let storage;
@@ -17248,13 +17932,31 @@ var recker = (() => {
17248
17932
  } else {
17249
17933
  storage = createDefaultCacheStorage();
17250
17934
  }
17251
- cachePlugin({
17935
+ registerPlugin(cachePlugin({
17252
17936
  ...options2.cache,
17253
17937
  storage
17254
- })(this);
17938
+ }), {
17939
+ name: "recker:cache",
17940
+ priority: 100,
17941
+ scope: "request"
17942
+ });
17255
17943
  }
17256
17944
  if (options2.plugins) {
17257
- options2.plugins.forEach((plugin) => plugin(this));
17945
+ options2.plugins.forEach((plugin, index) => {
17946
+ const existingManifest = getPluginManifest(plugin);
17947
+ registerPlugin(plugin, {
17948
+ name: (existingManifest == null ? void 0 : existingManifest.name) || `user-plugin:${index}`,
17949
+ priority: (existingManifest == null ? void 0 : existingManifest.priority) ?? 90 - index,
17950
+ scope: (existingManifest == null ? void 0 : existingManifest.scope) || "request"
17951
+ });
17952
+ });
17953
+ }
17954
+ const { ordered, debugOrder } = normalizePlugins(toSortedPlugins(pluginRegistrations));
17955
+ ordered.forEach(({ plugin }) => {
17956
+ plugin(this);
17957
+ });
17958
+ if (this.debugEnabled && this.logger) {
17959
+ this.logger.debug(`Applied plugins in order: ${debugOrder.join(" | ")}`);
17258
17960
  }
17259
17961
  if (options2.compression) {
17260
17962
  const compressionMiddleware = createCompressionMiddleware(options2.compression);
@@ -17385,13 +18087,45 @@ var recker = (() => {
17385
18087
  return header.split(/,(?=\s*[a-zA-Z0-9_-]+=)/g).map((s) => s.trim());
17386
18088
  }
17387
18089
  async dispatch(req) {
17388
- if (req.useCurl && this.transportKind !== "curl") {
17389
- if (!this.curlTransport) {
17390
- this.curlTransport = createLazyCurlTransport();
18090
+ const context = getRequestContext(req);
18091
+ const transportStart = context ? Date.now() : 0;
18092
+ if (context) {
18093
+ this.runtimeEventBus.emit("transport:start", { context, req });
18094
+ }
18095
+ try {
18096
+ if (req.useCurl && this.transportKind !== "curl") {
18097
+ if (!this.curlTransport) {
18098
+ this.curlTransport = createLazyCurlTransport();
18099
+ }
18100
+ const response2 = await this.curlTransport.dispatch(req);
18101
+ if (context) {
18102
+ this.runtimeEventBus.emit("transport:finish", {
18103
+ context,
18104
+ req,
18105
+ durationMs: Date.now() - transportStart
18106
+ });
18107
+ }
18108
+ return response2;
18109
+ }
18110
+ const response = await this.transport.dispatch(req);
18111
+ if (context) {
18112
+ this.runtimeEventBus.emit("transport:finish", {
18113
+ context,
18114
+ req,
18115
+ durationMs: Date.now() - transportStart
18116
+ });
18117
+ }
18118
+ return response;
18119
+ } catch (error) {
18120
+ if (context) {
18121
+ this.runtimeEventBus.emit("transport:error", {
18122
+ context,
18123
+ req,
18124
+ error: error instanceof Error ? error : new Error(String(error))
18125
+ });
17391
18126
  }
17392
- return this.curlTransport.dispatch(req);
18127
+ throw error;
17393
18128
  }
17394
- return this.transport.dispatch(req);
17395
18129
  }
17396
18130
  composeMiddlewares() {
17397
18131
  var _a2, _b;
@@ -17490,6 +18224,20 @@ var recker = (() => {
17490
18224
  this.canFastPath = false;
17491
18225
  return this;
17492
18226
  }
18227
+ onRuntimeEvent(name, handler) {
18228
+ this.shouldEmitRuntimeEvents = true;
18229
+ this.runtimeEventListenerCount += 1;
18230
+ const unsubscribe = this.runtimeEventBus.on(name, handler);
18231
+ return () => {
18232
+ unsubscribe();
18233
+ if (this.runtimeEventListenerCount > 0) {
18234
+ this.runtimeEventListenerCount -= 1;
18235
+ }
18236
+ if (!this.runtimeEventBusProviderAttached && this.runtimeEventListenerCount === 0) {
18237
+ this.shouldEmitRuntimeEvents = false;
18238
+ }
18239
+ };
18240
+ }
17493
18241
  buildUrl(path, requestParams) {
17494
18242
  const hasRequestParams = requestParams && Object.keys(requestParams).length > 0;
17495
18243
  const hasDefaultParams = Object.keys(this.defaultParams).length > 0;
@@ -17508,7 +18256,7 @@ var recker = (() => {
17508
18256
  const mergedParams = { ...this.defaultParams, ...requestParams };
17509
18257
  const usedParams = /* @__PURE__ */ new Set();
17510
18258
  if (finalPath.includes(":")) {
17511
- finalPath = finalPath.replace(/:([a-zA-Z0-9_]+)/g, (match, paramName) => {
18259
+ finalPath = finalPath.replace(/:([a-zA-Z0-9_]+)/g, (_match, paramName) => {
17512
18260
  if (mergedParams && paramName in mergedParams) {
17513
18261
  usedParams.add(paramName);
17514
18262
  return encodeURIComponent(String(mergedParams[paramName]));
@@ -17540,16 +18288,54 @@ var recker = (() => {
17540
18288
  return finalUrl;
17541
18289
  }
17542
18290
  request(path, options2 = {}) {
18291
+ var _a2, _b;
17543
18292
  const url = this.buildUrl(path, options2.params);
18293
+ const canRequestMutateHeaders = (((_a2 = this.hooks.beforeRequest) == null ? void 0 : _a2.length) ?? 0) > 0 || this.middlewares.length > 0;
18294
+ const shouldAttachContext = this.shouldEmitRuntimeEvents || !!options2.correlationId || !!options2.tenant || !!options2.traceId || !!options2.policySource || (((_b = options2.policyTags) == null ? void 0 : _b.length) ?? 0) > 0;
18295
+ const createContextSeed = () => createRequestContext({
18296
+ correlationId: options2.correlationId,
18297
+ tenant: options2.tenant,
18298
+ policyTags: options2.policyTags,
18299
+ policySource: options2.policySource,
18300
+ traceId: options2.traceId
18301
+ });
17544
18302
  const usesFastPath = this.canFastPath && !options2.headers && !options2.timeout && !options2.signal && options2.maxResponseSize === void 0;
17545
18303
  if (usesFastPath) {
17546
- const req2 = new HttpRequest(url, {
18304
+ let req2 = new HttpRequest(url, {
17547
18305
  method: options2.method || "GET",
17548
18306
  body: options2.body,
17549
18307
  headers: this.defaultHeadersObj,
17550
18308
  throwHttpErrors: options2.throwHttpErrors
17551
18309
  });
17552
- const responsePromise2 = this.fastHandler(req2);
18310
+ if (shouldAttachContext) {
18311
+ req2 = attachRequestContext(req2, createContextSeed());
18312
+ }
18313
+ const requestContext2 = getRequestContext(req2);
18314
+ const startTime2 = Date.now();
18315
+ if (requestContext2) {
18316
+ this.runtimeEventBus.emit("request:start", { context: requestContext2, req: req2 });
18317
+ }
18318
+ let responsePromise2 = this.fastHandler(req2);
18319
+ if (requestContext2) {
18320
+ responsePromise2 = responsePromise2.then((response) => {
18321
+ this.runtimeEventBus.emit("request:success", {
18322
+ context: requestContext2,
18323
+ req: req2,
18324
+ res: response,
18325
+ durationMs: Date.now() - startTime2
18326
+ });
18327
+ return response;
18328
+ }, (error) => {
18329
+ const requestError = error instanceof Error ? error : new Error(String(error));
18330
+ this.runtimeEventBus.emit("request:failed", {
18331
+ context: requestContext2,
18332
+ req: req2,
18333
+ error: requestError,
18334
+ durationMs: Date.now() - startTime2
18335
+ });
18336
+ throw error;
18337
+ });
18338
+ }
17553
18339
  return new RequestPromise(responsePromise2);
17554
18340
  }
17555
18341
  let mergedHeaders;
@@ -17557,6 +18343,8 @@ var recker = (() => {
17557
18343
  mergedHeaders = new Headers(this.defaultHeadersObj);
17558
18344
  const optHeaders = options2.headers instanceof Headers ? options2.headers : new Headers(options2.headers);
17559
18345
  optHeaders.forEach((value, key) => mergedHeaders.set(key, value));
18346
+ } else if (canRequestMutateHeaders) {
18347
+ mergedHeaders = new Headers(this.defaultHeadersObj);
17560
18348
  } else {
17561
18349
  mergedHeaders = this.defaultHeadersObj;
17562
18350
  }
@@ -17589,13 +18377,41 @@ var recker = (() => {
17589
18377
  }
17590
18378
  }
17591
18379
  }
17592
- const req = new HttpRequest(url, {
18380
+ let req = new HttpRequest(url, {
17593
18381
  ...options2,
17594
18382
  headers: mergedHeaders,
17595
18383
  signal,
17596
18384
  maxResponseSize: options2.maxResponseSize ?? this.maxResponseSize
17597
18385
  });
17598
- const responsePromise = this.handler(req);
18386
+ if (shouldAttachContext) {
18387
+ req = attachRequestContext(req, createContextSeed());
18388
+ }
18389
+ const requestContext = getRequestContext(req);
18390
+ const startTime = Date.now();
18391
+ if (requestContext) {
18392
+ this.runtimeEventBus.emit("request:start", { context: requestContext, req });
18393
+ }
18394
+ let responsePromise = this.handler(req);
18395
+ if (requestContext) {
18396
+ responsePromise = responsePromise.then((response) => {
18397
+ this.runtimeEventBus.emit("request:success", {
18398
+ context: requestContext,
18399
+ req,
18400
+ res: response,
18401
+ durationMs: Date.now() - startTime
18402
+ });
18403
+ return response;
18404
+ }, (error) => {
18405
+ const requestError = error instanceof Error ? error : new Error(String(error));
18406
+ this.runtimeEventBus.emit("request:failed", {
18407
+ context: requestContext,
18408
+ req,
18409
+ error: requestError,
18410
+ durationMs: Date.now() - startTime
18411
+ });
18412
+ throw error;
18413
+ });
18414
+ }
17599
18415
  if (timeoutId || externalAbortCleanup) {
17600
18416
  responsePromise.finally(() => {
17601
18417
  if (timeoutId)
@@ -17625,6 +18441,9 @@ var recker = (() => {
17625
18441
  const runnerResult = await runner.run(requests, async (item) => {
17626
18442
  const res = await this.request(item.path, item.options);
17627
18443
  return mapResponse(res);
18444
+ }, {
18445
+ signal: options2.signal,
18446
+ deadlineMs: options2.deadlineMs
17628
18447
  });
17629
18448
  return runnerResult;
17630
18449
  }
@@ -17760,7 +18579,6 @@ var recker = (() => {
17760
18579
  page(path, pageNumber, options2 = {}) {
17761
18580
  var _a2;
17762
18581
  const pageParam = options2.pageParam || ((_a2 = this.paginationConfig) == null ? void 0 : _a2.pageParam) || "page";
17763
- const url = new URL(path.startsWith("http") ? path : `http://base${path}`);
17764
18582
  const params = { ...options2.params, [pageParam]: pageNumber };
17765
18583
  return this.request(path, { ...options2, params });
17766
18584
  }
@@ -17972,13 +18790,11 @@ self.onmessage = async (event) => {
17972
18790
  };
17973
18791
  `;
17974
18792
  var WorkerTransport = class _WorkerTransport {
17975
- options;
17976
18793
  workers = [];
17977
18794
  workerIndex = 0;
17978
18795
  pendingRequests = /* @__PURE__ */ new Map();
17979
18796
  workerUrl;
17980
18797
  constructor(options2 = {}) {
17981
- this.options = options2;
17982
18798
  const poolSize = options2.poolSize ?? (typeof navigator !== "undefined" ? navigator.hardwareConcurrency : 4) ?? 4;
17983
18799
  const blob = new Blob([WORKER_SCRIPT], { type: "application/javascript" });
17984
18800
  this.workerUrl = URL.createObjectURL(blob);
@@ -18074,7 +18890,7 @@ self.onmessage = async (event) => {
18074
18890
  }
18075
18891
  this.workers = [];
18076
18892
  URL.revokeObjectURL(this.workerUrl);
18077
- for (const [id, pending] of this.pendingRequests) {
18893
+ for (const pending of this.pendingRequests.values()) {
18078
18894
  pending.reject(new Error("Transport terminated"));
18079
18895
  }
18080
18896
  this.pendingRequests.clear();