brass-runtime 1.15.0 → 1.16.1

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 (209) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/README.md +673 -136
  3. package/dist/agent/cli/main.cjs +40 -35
  4. package/dist/agent/cli/main.js +9 -4
  5. package/dist/agent/cli/main.mjs +9 -4
  6. package/dist/agent/index.cjs +8 -4
  7. package/dist/agent/index.d.ts +1 -1
  8. package/dist/agent/index.js +7 -3
  9. package/dist/agent/index.mjs +7 -3
  10. package/dist/chunk-2HQTDLHF.mjs +683 -0
  11. package/dist/chunk-36I3M4UC.mjs +370 -0
  12. package/dist/chunk-3AYM6WPJ.js +1629 -0
  13. package/dist/chunk-3LOYJFRR.cjs +300 -0
  14. package/dist/chunk-3RG5ZIWI.js +10 -0
  15. package/dist/chunk-3Y2RIUMM.js +300 -0
  16. package/dist/{chunk-VEZNF5GZ.cjs → chunk-4ROBZFL6.cjs} +130 -126
  17. package/dist/{chunk-3QMOKAS5.js → chunk-52OB2ROS.js} +9 -5
  18. package/dist/chunk-52PPNNI4.cjs +416 -0
  19. package/dist/chunk-5EC274J5.cjs +2874 -0
  20. package/dist/chunk-5QC7LRZ3.js +229 -0
  21. package/dist/chunk-5VRJNBLZ.mjs +2874 -0
  22. package/dist/chunk-62AZW6UT.cjs +313 -0
  23. package/dist/chunk-6IXXWIUM.js +683 -0
  24. package/dist/chunk-74ZTY6CP.js +2871 -0
  25. package/dist/chunk-76YMRMH2.cjs +777 -0
  26. package/dist/chunk-7CMJS3QE.mjs +2871 -0
  27. package/dist/{chunk-4NHES7VK.mjs → chunk-7JIJOVCT.js} +27 -13
  28. package/dist/chunk-A2OM6NEH.mjs +194 -0
  29. package/dist/chunk-AGR5B2BC.cjs +683 -0
  30. package/dist/chunk-AVNQLJ5V.js +777 -0
  31. package/dist/chunk-B33ICAKP.js +313 -0
  32. package/dist/{chunk-ELOOF35R.mjs → chunk-B5JD23U7.mjs} +1 -1
  33. package/dist/chunk-BABBZK4Y.js +2024 -0
  34. package/dist/chunk-C3MDXTRZ.js +354 -0
  35. package/dist/chunk-CIZFIMK5.js +2193 -0
  36. package/dist/chunk-CZIVE6NT.cjs +354 -0
  37. package/dist/chunk-DNFJLJMW.mjs +354 -0
  38. package/dist/chunk-DNFO2EIZ.mjs +777 -0
  39. package/dist/chunk-EJ6BPYVR.mjs +416 -0
  40. package/dist/chunk-ENKODRU3.cjs +2193 -0
  41. package/dist/chunk-EOC4UHBS.mjs +229 -0
  42. package/dist/{chunk-BMH5AV44.js → chunk-FH2X7BVP.js} +756 -440
  43. package/dist/{chunk-PPUXIH5R.js → chunk-FHQGHPMO.mjs} +27 -13
  44. package/dist/{chunk-TGIFUAK4.cjs → chunk-GLE2WY7Z.cjs} +951 -635
  45. package/dist/{chunk-BDF4AMWX.mjs → chunk-GYM3LLGS.mjs} +756 -440
  46. package/dist/chunk-HLWLMW2F.mjs +2024 -0
  47. package/dist/chunk-JF5WGYJJ.cjs +194 -0
  48. package/dist/chunk-KH4SYAOS.mjs +1629 -0
  49. package/dist/chunk-KN32XNTH.mjs +313 -0
  50. package/dist/chunk-KQLYONSE.cjs +2871 -0
  51. package/dist/{chunk-STVLQ3XD.cjs → chunk-KZJQ723N.cjs} +92 -78
  52. package/dist/chunk-L2SYFEBS.js +194 -0
  53. package/dist/chunk-L6VB5N7Q.cjs +104 -0
  54. package/dist/{chunk-K6M7MDZ4.mjs → chunk-MBEJI5HF.mjs} +9 -5
  55. package/dist/chunk-MIIYDLGM.js +2874 -0
  56. package/dist/chunk-MOO4L7F4.mjs +104 -0
  57. package/dist/chunk-MT3OWDPC.mjs +2193 -0
  58. package/dist/chunk-MVGUEJ5Z.cjs +370 -0
  59. package/dist/chunk-OBGZSXTJ.cjs +10 -0
  60. package/dist/chunk-PD4EJTQC.cjs +229 -0
  61. package/dist/chunk-PWC3RBQE.mjs +300 -0
  62. package/dist/chunk-Q2I37RP3.cjs +1629 -0
  63. package/dist/chunk-RKGKFN2A.js +416 -0
  64. package/dist/{chunk-R3R2FVLG.cjs → chunk-SA6HUJVI.cjs} +5 -5
  65. package/dist/chunk-TRM4JUZQ.js +104 -0
  66. package/dist/chunk-UB4B6OFY.js +370 -0
  67. package/dist/{chunk-TO7IKXYT.js → chunk-UCUBNWM2.js} +1 -1
  68. package/dist/chunk-VN44DYYT.cjs +2024 -0
  69. package/dist/chunk-Y6FXYEAI.mjs +10 -0
  70. package/dist/client-CZHU674n.d.ts +820 -0
  71. package/dist/core/index.cjs +198 -4
  72. package/dist/core/index.d.ts +311 -212
  73. package/dist/core/index.js +237 -43
  74. package/dist/core/index.mjs +237 -43
  75. package/dist/{effect-CMOQKX8y.d.ts → effect-DIUHZ9IN.d.ts} +195 -1
  76. package/dist/effectRunner-CFLC32IK.cjs +8 -0
  77. package/dist/effectRunner-L4S7IPT3.js +8 -0
  78. package/dist/effectRunner-NNGG75QA.mjs +8 -0
  79. package/dist/http/index.cjs +1227 -2971
  80. package/dist/http/index.d.ts +826 -280
  81. package/dist/http/index.js +1089 -2833
  82. package/dist/http/index.mjs +1089 -2833
  83. package/dist/http/testing.cjs +161 -0
  84. package/dist/http/testing.d.ts +43 -0
  85. package/dist/http/testing.js +161 -0
  86. package/dist/http/testing.mjs +161 -0
  87. package/dist/index.cjs +486 -250
  88. package/dist/index.d.ts +87 -95
  89. package/dist/index.js +391 -155
  90. package/dist/index.mjs +391 -155
  91. package/dist/observability/index.cjs +162 -0
  92. package/dist/observability/index.d.ts +152 -0
  93. package/dist/observability/index.js +162 -0
  94. package/dist/observability/index.mjs +162 -0
  95. package/dist/perf/cli.cjs +401 -0
  96. package/dist/perf/cli.d.ts +1 -0
  97. package/dist/perf/cli.js +401 -0
  98. package/dist/perf/cli.mjs +401 -0
  99. package/dist/perf/index.cjs +141 -0
  100. package/dist/perf/index.d.ts +483 -0
  101. package/dist/perf/index.js +141 -0
  102. package/dist/perf/index.mjs +141 -0
  103. package/dist/schedule-CK3Ml_7p.d.ts +259 -0
  104. package/dist/schema/index.cjs +29 -0
  105. package/dist/schema/index.d.ts +179 -0
  106. package/dist/schema/index.js +29 -0
  107. package/dist/schema/index.mjs +29 -0
  108. package/dist/server-GJPg8ZSG.d.ts +675 -0
  109. package/dist/{stream-FQm9h4Mg.d.ts → stream-B4oK9JFP.d.ts} +1 -1
  110. package/dist/tracer-Hwt1cl7h.d.ts +189 -0
  111. package/dist/tracing-DqbTKGcf.d.ts +148 -0
  112. package/docs/ARCHITECTURE.md +292 -0
  113. package/docs/README.md +63 -0
  114. package/docs/adr/0001-ai-context-pack.md +32 -0
  115. package/docs/agent-apply-mode.md +104 -0
  116. package/docs/agent-approvals.md +110 -0
  117. package/docs/agent-batch.md +185 -0
  118. package/docs/agent-boundaries.md +112 -0
  119. package/docs/agent-chat-sessions.md +160 -0
  120. package/docs/agent-ci.md +17 -0
  121. package/docs/agent-cli.md +405 -0
  122. package/docs/agent-config.md +480 -0
  123. package/docs/agent-context-discovery.md +159 -0
  124. package/docs/agent-copilot-like-dx.md +126 -0
  125. package/docs/agent-declarative-optimized-planning.md +138 -0
  126. package/docs/agent-dx.md +224 -0
  127. package/docs/agent-env-files.md +126 -0
  128. package/docs/agent-follow-up-context.md +43 -0
  129. package/docs/agent-global-usage.md +180 -0
  130. package/docs/agent-init.md +109 -0
  131. package/docs/agent-install-and-configure.md +516 -0
  132. package/docs/agent-language-workspace-ux.md +99 -0
  133. package/docs/agent-llm-adapters.md +123 -0
  134. package/docs/agent-local-install.md +190 -0
  135. package/docs/agent-local-tests.md +51 -0
  136. package/docs/agent-observability.md +155 -0
  137. package/docs/agent-patch-quality-loop.md +162 -0
  138. package/docs/agent-presets.md +22 -0
  139. package/docs/agent-project-commands.md +237 -0
  140. package/docs/agent-project-intelligence.md +156 -0
  141. package/docs/agent-redaction.md +18 -0
  142. package/docs/agent-release-readiness.md +76 -0
  143. package/docs/agent-rollback-safety.md +162 -0
  144. package/docs/agent-rollback.md +23 -0
  145. package/docs/agent-run-artifacts.md +16 -0
  146. package/docs/agent-vscode-auto-discovery.md +137 -0
  147. package/docs/agent-vscode-batch-runner.md +100 -0
  148. package/docs/agent-vscode-chat-layout.md +90 -0
  149. package/docs/agent-vscode-clean-install.md +147 -0
  150. package/docs/agent-vscode-code-actions.md +70 -0
  151. package/docs/agent-vscode-diff-preview.md +45 -0
  152. package/docs/agent-vscode-inline-assist.md +56 -0
  153. package/docs/agent-vscode-install.md +186 -0
  154. package/docs/agent-vscode-model-setup.md +97 -0
  155. package/docs/agent-vscode-patch-preview.md +92 -0
  156. package/docs/agent-vscode-problems.md +79 -0
  157. package/docs/agent-vscode-project-dashboard.md +106 -0
  158. package/docs/agent-vscode-run-history.md +92 -0
  159. package/docs/agent-vscode-ux.md +73 -0
  160. package/docs/ai/INVARIANTS.md +84 -0
  161. package/docs/ai/PROJECT_MAP.md +338 -0
  162. package/docs/ai/PUBLIC_API.md +336 -0
  163. package/docs/ai/VALIDATION_MATRIX.md +67 -0
  164. package/docs/api-polish.md +37 -0
  165. package/docs/cancellation.md +162 -0
  166. package/docs/coverage.md +46 -0
  167. package/docs/getting-started.md +159 -0
  168. package/docs/guides/README.md +40 -0
  169. package/docs/guides/circuit-breaker.md +89 -0
  170. package/docs/guides/error-handling.md +91 -0
  171. package/docs/guides/getting-started.md +107 -0
  172. package/docs/guides/layers.md +189 -0
  173. package/docs/guides/metrics.md +101 -0
  174. package/docs/guides/resource-management.md +141 -0
  175. package/docs/guides/retry.md +215 -0
  176. package/docs/guides/semaphore.md +66 -0
  177. package/docs/guides/streams.md +117 -0
  178. package/docs/guides/supervisors.md +98 -0
  179. package/docs/guides/testing.md +162 -0
  180. package/docs/guides/tracing.md +71 -0
  181. package/docs/http-recipes.md +399 -0
  182. package/docs/http.md +749 -0
  183. package/docs/modules.md +285 -0
  184. package/docs/observability-collector-smoke.md +31 -0
  185. package/docs/observability-framework-examples.md +98 -0
  186. package/docs/observability.md +542 -0
  187. package/docs/otel-collector-smoke.yaml +27 -0
  188. package/docs/performance-profiler.md +199 -0
  189. package/docs/production-readiness.md +73 -0
  190. package/docs/recipes/README.md +12 -0
  191. package/docs/recipes/http-server.md +45 -0
  192. package/docs/recipes/layers.md +44 -0
  193. package/docs/recipes/performance.md +47 -0
  194. package/docs/recipes/runtime.md +41 -0
  195. package/docs/recipes/testing.md +41 -0
  196. package/docs/release.md +53 -0
  197. package/docs/wasm-bounded-queues.md +44 -0
  198. package/docs/wasm-engine-observability-benchmarks.md +85 -0
  199. package/docs/wasm-fiber-engine.md +117 -0
  200. package/docs/wasm-scheduler-state-machine.md +122 -0
  201. package/docs/wasm-stream-chunks.md +54 -0
  202. package/package.json +48 -2
  203. package/dist/chunk-AR22SXML.js +0 -1043
  204. package/dist/chunk-BDYEENHT.js +0 -224
  205. package/dist/chunk-JFPU5GQI.mjs +0 -1043
  206. package/dist/chunk-MS34J5LY.cjs +0 -224
  207. package/dist/chunk-UMAZLXAB.mjs +0 -224
  208. package/dist/chunk-XPZNXSVN.cjs +0 -1043
  209. package/dist/tracing-DNT9jEbr.d.ts +0 -106
@@ -0,0 +1,2871 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class; var _class2; var _class3;
2
+
3
+
4
+
5
+
6
+
7
+
8
+
9
+
10
+ var _chunk5EC274J5cjs = require('./chunk-5EC274J5.cjs');
11
+
12
+
13
+ var _chunkL6VB5N7Qcjs = require('./chunk-L6VB5N7Q.cjs');
14
+
15
+
16
+
17
+ var _chunk3LOYJFRRcjs = require('./chunk-3LOYJFRR.cjs');
18
+
19
+
20
+ var _chunkGLE2WY7Zcjs = require('./chunk-GLE2WY7Z.cjs');
21
+
22
+
23
+
24
+
25
+
26
+
27
+
28
+
29
+ var _chunkMVGUEJ5Zcjs = require('./chunk-MVGUEJ5Z.cjs');
30
+
31
+
32
+
33
+
34
+
35
+ var _chunkCZIVE6NTcjs = require('./chunk-CZIVE6NT.cjs');
36
+
37
+
38
+ var _chunkOBGZSXTJcjs = require('./chunk-OBGZSXTJ.cjs');
39
+
40
+ // src/http/validation.ts
41
+ function decodeJsonBody(bodyText, validator, options = {}) {
42
+ let parsed;
43
+ try {
44
+ parsed = JSON.parse(bodyText);
45
+ } catch (error) {
46
+ return {
47
+ success: false,
48
+ error: {
49
+ _tag: "ValidationError",
50
+ message: `JSON parse error: ${error instanceof Error ? error.message : String(error)}`,
51
+ body: bodyText,
52
+ phase: "response",
53
+ schema: options.schemaName,
54
+ issues: [_chunkCZIVE6NTcjs.makeSchemaIssue.call(void 0, [], "valid JSON", bodyText, "Response body is not valid JSON")]
55
+ }
56
+ };
57
+ }
58
+ if (!validator) return { success: true, data: parsed };
59
+ let legacyMessage;
60
+ const validation = _chunkCZIVE6NTcjs.isSchema.call(void 0, validator) ? validator.safeParse(parsed) : (() => {
61
+ const result = validator(parsed);
62
+ if (result.success) return { success: true, data: result.data };
63
+ legacyMessage = result.error;
64
+ return {
65
+ success: false,
66
+ issues: _nullishCoalesce(result.issues, () => ( [_chunkCZIVE6NTcjs.makeSchemaIssue.call(void 0, [], "valid JSON shape", parsed, result.error)]))
67
+ };
68
+ })();
69
+ if (validation.success) return { success: true, data: validation.data };
70
+ return {
71
+ success: false,
72
+ error: {
73
+ _tag: "ValidationError",
74
+ message: _nullishCoalesce(legacyMessage, () => ( `JSON response failed validation: ${_chunkCZIVE6NTcjs.formatIssues.call(void 0, validation.issues)}`)),
75
+ body: bodyText,
76
+ phase: "response",
77
+ schema: options.schemaName,
78
+ issues: validation.issues
79
+ }
80
+ };
81
+ }
82
+ function encodeJsonBodyEffect(bodyObj, validator, options = {}) {
83
+ if (validator) {
84
+ const validation = _chunkCZIVE6NTcjs.validateValue.call(void 0, bodyObj, validator);
85
+ if (!validation.success) {
86
+ return _chunkMVGUEJ5Zcjs.asyncFail.call(void 0, {
87
+ _tag: "ValidationError",
88
+ message: `JSON request body failed validation: ${_chunkCZIVE6NTcjs.formatIssues.call(void 0, validation.issues)}`,
89
+ body: previewJson(bodyObj),
90
+ phase: "request",
91
+ schema: options.schemaName,
92
+ issues: validation.issues
93
+ });
94
+ }
95
+ }
96
+ try {
97
+ return _chunkMVGUEJ5Zcjs.asyncSucceed.call(void 0, JSON.stringify(_nullishCoalesce(bodyObj, () => ( {}))));
98
+ } catch (error) {
99
+ return _chunkMVGUEJ5Zcjs.asyncFail.call(void 0, {
100
+ _tag: "ValidationError",
101
+ message: `JSON request body could not be serialized: ${error instanceof Error ? error.message : String(error)}`,
102
+ body: "",
103
+ phase: "request",
104
+ schema: options.schemaName,
105
+ issues: [
106
+ _chunkCZIVE6NTcjs.makeSchemaIssue.call(void 0, [], "JSON-serializable value", bodyObj, "Request body could not be serialized to JSON")
107
+ ]
108
+ });
109
+ }
110
+ }
111
+ function decodeJsonBodyEffect(bodyText, validator, options) {
112
+ const result = decodeJsonBody(bodyText, validator, options);
113
+ return result.success ? _chunkMVGUEJ5Zcjs.asyncSucceed.call(void 0, result.data) : _chunkMVGUEJ5Zcjs.asyncFail.call(void 0, result.error);
114
+ }
115
+ function validatedJson(client, validator) {
116
+ return (req) => _chunkMVGUEJ5Zcjs.asyncFold.call(void 0,
117
+ client(req),
118
+ (error) => _chunkMVGUEJ5Zcjs.asyncFail.call(void 0, error),
119
+ (response) => decodeJsonBodyEffect(response.bodyText, validator)
120
+ );
121
+ }
122
+ function validatedJsonResponse(client, validator) {
123
+ return (req) => _chunkMVGUEJ5Zcjs.asyncFold.call(void 0,
124
+ client(req),
125
+ (error) => _chunkMVGUEJ5Zcjs.asyncFail.call(void 0, error),
126
+ (response) => _chunkMVGUEJ5Zcjs.asyncFlatMap.call(void 0,
127
+ decodeJsonBodyEffect(response.bodyText, validator),
128
+ (body) => _chunkMVGUEJ5Zcjs.asyncSucceed.call(void 0, { ...response, body })
129
+ )
130
+ );
131
+ }
132
+ function previewJson(value) {
133
+ try {
134
+ return JSON.stringify(value);
135
+ } catch (e2) {
136
+ return "[unserializable]";
137
+ }
138
+ }
139
+
140
+ // src/http/body.ts
141
+ function httpBodyByteLength(body) {
142
+ if (body === void 0) return 0;
143
+ if (typeof body === "string") return Buffer.byteLength(body, "utf8");
144
+ if (body instanceof ArrayBuffer) return body.byteLength;
145
+ return body.byteLength;
146
+ }
147
+ function httpBodyToBuffer(body) {
148
+ if (typeof body === "string") return Buffer.from(body, "utf8");
149
+ if (body instanceof ArrayBuffer) return Buffer.from(body);
150
+ return Buffer.from(body);
151
+ }
152
+ function httpBodyKeyPart(body) {
153
+ if (body === void 0) return "";
154
+ if (typeof body === "string") return body;
155
+ return `base64:${httpBodyToBuffer(body).toString("base64")}`;
156
+ }
157
+
158
+ // src/http/lifecycle/cacheKey.ts
159
+ var SEPARATOR = "\0";
160
+ var DEFAULT_CACHE_RELEVANT_HEADERS = ["accept", "authorization", "content-type"];
161
+ function computeCacheKey(req, baseUrl, extraHeaders = []) {
162
+ const method = req.method.toUpperCase();
163
+ const resolvedUrl = resolveKeyUrl(req.url, baseUrl);
164
+ const relevantSet = /* @__PURE__ */ new Set([
165
+ ...DEFAULT_CACHE_RELEVANT_HEADERS,
166
+ ...extraHeaders.map((h) => h.toLowerCase())
167
+ ]);
168
+ const headers = _nullishCoalesce(req.headers, () => ( {}));
169
+ const sortedHeaders = Object.keys(headers).filter((k) => relevantSet.has(k.toLowerCase())).sort().map((k) => `${k.toLowerCase()}:${headers[k]}`).join(",");
170
+ const body = httpBodyKeyPart(req.body);
171
+ return `${method}${SEPARATOR}${resolvedUrl}${SEPARATOR}${sortedHeaders}${SEPARATOR}${body}`;
172
+ }
173
+ function resolveKeyUrl(url, baseUrl) {
174
+ if (url.length > 0 && url.charCodeAt(0) === 47 && url.charCodeAt(1) !== 47 && baseUrl) {
175
+ const origin = absoluteOrigin(baseUrl);
176
+ if (origin) return `${origin}${url}`;
177
+ }
178
+ return new URL(url, baseUrl || void 0).toString();
179
+ }
180
+ function absoluteOrigin(url) {
181
+ const schemeIdx = url.indexOf("://");
182
+ if (schemeIdx <= 0) return void 0;
183
+ const authorityStart = schemeIdx + 3;
184
+ const pathIdx = url.indexOf("/", authorityStart);
185
+ return pathIdx === -1 ? url : url.slice(0, pathIdx);
186
+ }
187
+ function parseCacheKey(key) {
188
+ const [method, resolvedUrl, headersStr, ...bodyParts] = key.split(SEPARATOR);
189
+ const body = bodyParts.join(SEPARATOR);
190
+ const headers = {};
191
+ if (headersStr) {
192
+ for (const entry of headersStr.split(",")) {
193
+ const colonIdx = entry.indexOf(":");
194
+ if (colonIdx > 0) {
195
+ headers[entry.slice(0, colonIdx)] = entry.slice(colonIdx + 1);
196
+ }
197
+ }
198
+ }
199
+ return { method, resolvedUrl, headers, body };
200
+ }
201
+
202
+ // src/http/lifecycle/dedupKey.ts
203
+ var HOP_BY_HOP = /* @__PURE__ */ new Set([
204
+ "connection",
205
+ "keep-alive",
206
+ "proxy-authenticate",
207
+ "proxy-authorization",
208
+ "te",
209
+ "trailer",
210
+ "transfer-encoding",
211
+ "upgrade"
212
+ ]);
213
+ var SAFE_METHODS = /* @__PURE__ */ new Set(["GET", "HEAD", "OPTIONS"]);
214
+ function computeDedupKey(req, baseUrl) {
215
+ const method = req.method.toUpperCase();
216
+ const resolvedUrl = resolveKeyUrl(req.url, baseUrl);
217
+ const headers = _nullishCoalesce(req.headers, () => ( {}));
218
+ const sortedHeaders = Object.keys(headers).filter((k) => {
219
+ const lower = k.toLowerCase();
220
+ return !HOP_BY_HOP.has(lower) && lower !== "authorization";
221
+ }).sort().map((k) => `${k.toLowerCase()}:${headers[k]}`).join(",");
222
+ const body = httpBodyKeyPart(req.body);
223
+ return `${method}${SEPARATOR}${resolvedUrl}${SEPARATOR}${sortedHeaders}${SEPARATOR}${body}`;
224
+ }
225
+
226
+ // src/http/lifecycle/dedup.ts
227
+ function safeEmit(onEvent, event) {
228
+ if (!onEvent) return;
229
+ try {
230
+ onEvent(event);
231
+ } catch (e3) {
232
+ }
233
+ }
234
+ function causeDefectMessage(cause) {
235
+ const defect = _chunkMVGUEJ5Zcjs.Cause.firstDefect(cause);
236
+ if (defect._tag === "Some") return String(defect.value);
237
+ return _chunkMVGUEJ5Zcjs.Cause.pretty(cause, { singleLine: true });
238
+ }
239
+ function withDedup(config) {
240
+ const inFlight = /* @__PURE__ */ new Map();
241
+ const customKeyFn = _optionalChain([config, 'optionalAccess', _ => _.dedupKey]);
242
+ const onEvent = _optionalChain([config, 'optionalAccess', _2 => _2.onEvent]);
243
+ return (next) => {
244
+ return (req) => {
245
+ if (!SAFE_METHODS.has(req.method.toUpperCase())) {
246
+ return next(req);
247
+ }
248
+ let key;
249
+ const policyKey = _chunk3LOYJFRRcjs.getHttpRequestPolicy.call(void 0, req).dedupKey;
250
+ if (policyKey !== void 0) {
251
+ key = policyKey;
252
+ if (!key) {
253
+ return next(req);
254
+ }
255
+ } else if (customKeyFn) {
256
+ try {
257
+ key = customKeyFn(req);
258
+ } catch (e4) {
259
+ return next(req);
260
+ }
261
+ if (!key) {
262
+ return next(req);
263
+ }
264
+ } else {
265
+ key = computeDedupKey(req, "");
266
+ }
267
+ return {
268
+ _tag: "Async",
269
+ register: (_env, cb) => {
270
+ const existing = inFlight.get(key);
271
+ let callerDone = false;
272
+ const finishCaller = (exit) => {
273
+ if (callerDone) return;
274
+ callerDone = true;
275
+ cb(exit);
276
+ };
277
+ if (existing) {
278
+ safeEmit(onEvent, { type: "dedup-hit", cacheKey: key });
279
+ existing.refCount++;
280
+ const waiter = {
281
+ resolve: (res) => {
282
+ finishCaller({ _tag: "Success", value: res });
283
+ },
284
+ reject: (err) => {
285
+ finishCaller({ _tag: "Failure", cause: _chunkMVGUEJ5Zcjs.Cause.fail(err) });
286
+ }
287
+ };
288
+ existing.waiters.push(waiter);
289
+ return () => {
290
+ if (callerDone) return;
291
+ existing.refCount--;
292
+ const idx = existing.waiters.indexOf(waiter);
293
+ if (idx >= 0) {
294
+ existing.waiters.splice(idx, 1);
295
+ }
296
+ if (existing.refCount <= 0) {
297
+ inFlight.delete(key);
298
+ safeEmit(onEvent, { type: "dedup-active", active: inFlight.size });
299
+ existing.controller.abort();
300
+ }
301
+ finishCaller({ _tag: "Failure", cause: _chunkMVGUEJ5Zcjs.Cause.interrupt() });
302
+ };
303
+ }
304
+ safeEmit(onEvent, { type: "dedup-miss", cacheKey: key });
305
+ const controller = new AbortController();
306
+ const entry = {
307
+ key,
308
+ controller,
309
+ refCount: 1,
310
+ waiters: []
311
+ };
312
+ inFlight.set(key, entry);
313
+ safeEmit(onEvent, { type: "dedup-active", active: inFlight.size });
314
+ const dedupReq = {
315
+ ...req,
316
+ init: {
317
+ ..._nullishCoalesce(req.init, () => ( {})),
318
+ signal: controller.signal
319
+ }
320
+ };
321
+ const innerEffect = next(dedupReq);
322
+ const innerCancel = _chunkL6VB5N7Qcjs.registerHttpEffect.call(void 0, innerEffect, _env, (exit) => {
323
+ inFlight.delete(key);
324
+ safeEmit(onEvent, { type: "dedup-active", active: inFlight.size });
325
+ if (exit._tag === "Success") {
326
+ resolveAll(entry, exit.value);
327
+ finishCaller(exit);
328
+ return;
329
+ }
330
+ if (_chunkMVGUEJ5Zcjs.Cause.isInterruptedOnly(exit.cause)) {
331
+ rejectAll(entry, { _tag: "Abort" });
332
+ finishCaller({ _tag: "Failure", cause: _chunkMVGUEJ5Zcjs.Cause.interrupt() });
333
+ return;
334
+ }
335
+ const failure = _chunkMVGUEJ5Zcjs.Cause.firstFailure(exit.cause);
336
+ if (failure._tag === "Some") {
337
+ rejectAll(entry, failure.value);
338
+ finishCaller(exit);
339
+ return;
340
+ }
341
+ const err = { _tag: "FetchError", message: causeDefectMessage(exit.cause) };
342
+ rejectAll(entry, err);
343
+ finishCaller({ _tag: "Failure", cause: _chunkMVGUEJ5Zcjs.Cause.fail(err) });
344
+ });
345
+ return () => {
346
+ if (callerDone) return;
347
+ entry.refCount--;
348
+ if (entry.refCount <= 0) {
349
+ inFlight.delete(key);
350
+ safeEmit(onEvent, { type: "dedup-active", active: inFlight.size });
351
+ controller.abort();
352
+ if (innerCancel) {
353
+ innerCancel();
354
+ }
355
+ }
356
+ finishCaller({ _tag: "Failure", cause: _chunkMVGUEJ5Zcjs.Cause.interrupt() });
357
+ };
358
+ }
359
+ };
360
+ };
361
+ };
362
+ }
363
+ function resolveAll(entry, res) {
364
+ const waiters = entry.waiters.slice();
365
+ for (const w of waiters) {
366
+ w.resolve(res);
367
+ }
368
+ }
369
+ function rejectAll(entry, err) {
370
+ const waiters = entry.waiters.slice();
371
+ for (const w of waiters) {
372
+ w.reject(err);
373
+ }
374
+ }
375
+
376
+ // src/http/lifecycle/batch.ts
377
+ function clamp(value, min, max) {
378
+ if (!Number.isFinite(value)) return min;
379
+ return Math.max(min, Math.min(max, Math.floor(value)));
380
+ }
381
+ function safeEmitBatch(onEvent, event) {
382
+ if (!onEvent) return;
383
+ try {
384
+ onEvent(event);
385
+ } catch (e5) {
386
+ }
387
+ }
388
+ function causeDefectMessage2(cause) {
389
+ const defect = _chunkMVGUEJ5Zcjs.Cause.firstDefect(cause);
390
+ if (defect._tag === "Some") return String(defect.value);
391
+ return _chunkMVGUEJ5Zcjs.Cause.pretty(cause, { singleLine: true });
392
+ }
393
+ function withBatch(config, onEvent) {
394
+ const windowMs = clamp(config.windowMs, 1, 5e3);
395
+ const maxBatchSize = clamp(config.maxBatchSize, 2, 1e4);
396
+ const { batch, batchKey } = config;
397
+ const groups = /* @__PURE__ */ new Map();
398
+ return (next) => {
399
+ function dispatch(group) {
400
+ group.dispatched = true;
401
+ if (group.timer !== null) {
402
+ clearTimeout(group.timer);
403
+ group.timer = null;
404
+ }
405
+ groups.delete(group.key);
406
+ const requests = group.waiters.map((w) => w.request);
407
+ const waiterCount = group.waiters.length;
408
+ let coalescedReq;
409
+ try {
410
+ coalescedReq = batch.coalesce(requests);
411
+ } catch (err) {
412
+ const error = { _tag: "FetchError", message: String(err) };
413
+ rejectAllWaiters(group, error);
414
+ return;
415
+ }
416
+ coalescedReq = {
417
+ ...coalescedReq,
418
+ init: {
419
+ ..._nullishCoalesce(coalescedReq.init, () => ( {})),
420
+ signal: group.controller.signal
421
+ }
422
+ };
423
+ safeEmitBatch(onEvent, { type: "batch-dispatch", batchKey: group.key, batchSize: waiterCount });
424
+ const innerEffect = next(coalescedReq);
425
+ _chunkL6VB5N7Qcjs.registerHttpEffect.call(void 0, innerEffect, void 0, (exit) => {
426
+ if (exit._tag === "Success") {
427
+ let responses;
428
+ try {
429
+ responses = batch.split(exit.value, requests);
430
+ } catch (err2) {
431
+ const error = { _tag: "FetchError", message: String(err2) };
432
+ rejectAllWaiters(group, error);
433
+ return;
434
+ }
435
+ if (responses.length !== waiterCount) {
436
+ const error = {
437
+ _tag: "BatchSplitError",
438
+ expected: waiterCount,
439
+ actual: responses.length,
440
+ message: `split returned ${responses.length} responses but expected ${waiterCount}`
441
+ };
442
+ rejectAllWaiters(group, error);
443
+ return;
444
+ }
445
+ const waiters = group.waiters.slice();
446
+ for (let i = 0; i < waiters.length; i++) {
447
+ waiters[i].resolve(responses[i]);
448
+ }
449
+ return;
450
+ }
451
+ const failure = _chunkMVGUEJ5Zcjs.Cause.firstFailure(exit.cause);
452
+ if (failure._tag === "Some") {
453
+ rejectAllWaiters(group, failure.value);
454
+ return;
455
+ }
456
+ if (_chunkMVGUEJ5Zcjs.Cause.isInterruptedOnly(exit.cause)) {
457
+ rejectAllWaiters(group, { _tag: "Abort" });
458
+ return;
459
+ }
460
+ const err = { _tag: "FetchError", message: causeDefectMessage2(exit.cause) };
461
+ rejectAllWaiters(group, err);
462
+ });
463
+ }
464
+ return (req) => {
465
+ let key;
466
+ try {
467
+ key = batchKey(req);
468
+ } catch (e6) {
469
+ return next(req);
470
+ }
471
+ if (!key) {
472
+ return next(req);
473
+ }
474
+ return {
475
+ _tag: "Async",
476
+ register: (_env, cb) => {
477
+ let callerDone = false;
478
+ const finishCaller = (exit) => {
479
+ if (callerDone) return;
480
+ callerDone = true;
481
+ cb(exit);
482
+ };
483
+ const waiter = {
484
+ request: req,
485
+ resolve: (res) => {
486
+ finishCaller({ _tag: "Success", value: res });
487
+ },
488
+ reject: (err) => {
489
+ finishCaller({ _tag: "Failure", cause: _chunkMVGUEJ5Zcjs.Cause.fail(err) });
490
+ }
491
+ };
492
+ const existing = groups.get(key);
493
+ if (existing && !existing.dispatched) {
494
+ existing.waiters.push(waiter);
495
+ safeEmitBatch(onEvent, { type: "batch-hit", batchKey: key });
496
+ if (existing.waiters.length >= maxBatchSize) {
497
+ dispatch(existing);
498
+ }
499
+ return () => {
500
+ if (callerDone) return;
501
+ const idx = existing.waiters.indexOf(waiter);
502
+ if (idx >= 0) {
503
+ existing.waiters.splice(idx, 1);
504
+ }
505
+ if (existing.waiters.length === 0 && !existing.dispatched) {
506
+ if (existing.timer !== null) {
507
+ clearTimeout(existing.timer);
508
+ existing.timer = null;
509
+ }
510
+ groups.delete(key);
511
+ }
512
+ if (existing.waiters.length === 0 && existing.dispatched) {
513
+ existing.controller.abort();
514
+ }
515
+ finishCaller({ _tag: "Failure", cause: _chunkMVGUEJ5Zcjs.Cause.interrupt() });
516
+ };
517
+ }
518
+ const controller = new AbortController();
519
+ const group = {
520
+ key,
521
+ controller,
522
+ waiters: [waiter],
523
+ timer: null,
524
+ dispatched: false
525
+ };
526
+ group.timer = setTimeout(() => {
527
+ if (!group.dispatched && group.waiters.length > 0) {
528
+ dispatch(group);
529
+ }
530
+ }, windowMs);
531
+ groups.set(key, group);
532
+ return () => {
533
+ if (callerDone) return;
534
+ const idx = group.waiters.indexOf(waiter);
535
+ if (idx >= 0) {
536
+ group.waiters.splice(idx, 1);
537
+ }
538
+ if (group.waiters.length === 0 && !group.dispatched) {
539
+ if (group.timer !== null) {
540
+ clearTimeout(group.timer);
541
+ group.timer = null;
542
+ }
543
+ groups.delete(key);
544
+ }
545
+ if (group.waiters.length === 0 && group.dispatched) {
546
+ group.controller.abort();
547
+ }
548
+ finishCaller({ _tag: "Failure", cause: _chunkMVGUEJ5Zcjs.Cause.interrupt() });
549
+ };
550
+ }
551
+ };
552
+ };
553
+ };
554
+ }
555
+ function rejectAllWaiters(group, err) {
556
+ const waiters = group.waiters.slice();
557
+ for (const w of waiters) {
558
+ w.reject(err);
559
+ }
560
+ }
561
+
562
+ // src/http/lifecycle/timing.ts
563
+ var now = typeof performance !== "undefined" && typeof performance.now === "function" ? () => performance.now() : () => Date.now();
564
+
565
+ // src/http/lifecycle/lruCache.ts
566
+ function isExpired(node) {
567
+ return now() - node.storedAt >= node.ttlMs;
568
+ }
569
+ var LRUCache = (_class = class {
570
+ __init() {this.map = /* @__PURE__ */ new Map()}
571
+ __init2() {this.head = null}
572
+ __init3() {this.tail = null}
573
+
574
+
575
+ /**
576
+ * Creates a new LRU cache instance.
577
+ *
578
+ * @param config - Cache configuration options.
579
+ * @param config.maxEntries - Maximum number of entries. Must be >= 1. Default: 1024.
580
+ * @param config.onEvict - Optional eviction callback.
581
+ *
582
+ * @example
583
+ * ```typescript
584
+ * import { LRUCache } from "./lruCache";
585
+ *
586
+ * const cache = new LRUCache<number>({ maxEntries: 50 });
587
+ * ```
588
+ */
589
+ constructor(config = {}) {;_class.prototype.__init.call(this);_class.prototype.__init2.call(this);_class.prototype.__init3.call(this);
590
+ const max = _nullishCoalesce(config.maxEntries, () => ( 1024));
591
+ this.maxEntries = Math.max(1, Math.floor(max));
592
+ this.onEvict = config.onEvict;
593
+ }
594
+ /**
595
+ * Returns the number of entries currently in the cache.
596
+ *
597
+ * @returns The current entry count.
598
+ *
599
+ * @example
600
+ * ```typescript
601
+ * import { LRUCache } from "./lruCache";
602
+ *
603
+ * const cache = new LRUCache<string>();
604
+ * cache.set("a", "1", 10_000);
605
+ * console.log(cache.size); // 1
606
+ * ```
607
+ */
608
+ get size() {
609
+ return this.map.size;
610
+ }
611
+ /**
612
+ * Retrieves a value by key.
613
+ *
614
+ * Returns `undefined` if the key is not found or the entry has expired.
615
+ * On a hit (non-expired), the entry is moved to the head (most recently used).
616
+ * Expired entries are lazily removed on access.
617
+ *
618
+ * @param key - The cache key to look up.
619
+ * @returns The cached value, or `undefined` if not found or expired.
620
+ *
621
+ * @example
622
+ * ```typescript
623
+ * import { LRUCache } from "./lruCache";
624
+ *
625
+ * const cache = new LRUCache<string>();
626
+ * cache.set("greeting", "hello", 30_000);
627
+ * const val = cache.get("greeting"); // "hello"
628
+ * const miss = cache.get("unknown"); // undefined
629
+ * ```
630
+ */
631
+ get(key) {
632
+ const node = this.map.get(key);
633
+ if (!node) return void 0;
634
+ if (isExpired(node)) {
635
+ this.removeNode(node);
636
+ this.map.delete(key);
637
+ return void 0;
638
+ }
639
+ this.moveToHead(node);
640
+ return node.value;
641
+ }
642
+ /**
643
+ * Inserts or updates an entry in the cache.
644
+ *
645
+ * If the key already exists, the value and TTL are updated and the entry is
646
+ * moved to the head. If inserting a new entry causes the cache to exceed
647
+ * `maxEntries` (must be >= 1), the least recently used entry is evicted.
648
+ *
649
+ * @param key - The cache key.
650
+ * @param value - The value to store.
651
+ * @param ttlMs - Time-to-live in milliseconds. The entry expires after this duration.
652
+ *
653
+ * @example
654
+ * ```typescript
655
+ * import { LRUCache } from "./lruCache";
656
+ *
657
+ * const cache = new LRUCache<string>({ maxEntries: 2 });
658
+ * cache.set("a", "alpha", 60_000);
659
+ * cache.set("b", "beta", 60_000);
660
+ * cache.set("c", "gamma", 60_000); // evicts "a" (LRU)
661
+ * ```
662
+ */
663
+ set(key, value, ttlMs) {
664
+ const existing = this.map.get(key);
665
+ if (existing) {
666
+ existing.value = value;
667
+ existing.storedAt = now();
668
+ existing.ttlMs = ttlMs;
669
+ this.moveToHead(existing);
670
+ return;
671
+ }
672
+ const node = {
673
+ key,
674
+ value,
675
+ storedAt: now(),
676
+ ttlMs,
677
+ prev: null,
678
+ next: null
679
+ };
680
+ this.map.set(key, node);
681
+ this.addToHead(node);
682
+ if (this.map.size > this.maxEntries) {
683
+ this.evictTail();
684
+ }
685
+ }
686
+ /**
687
+ * Removes an entry by key.
688
+ *
689
+ * @param key - The cache key to remove.
690
+ * @returns `true` if the entry was found and removed, `false` otherwise.
691
+ *
692
+ * @example
693
+ * ```typescript
694
+ * import { LRUCache } from "./lruCache";
695
+ *
696
+ * const cache = new LRUCache<string>();
697
+ * cache.set("x", "value", 10_000);
698
+ * cache.delete("x"); // true
699
+ * cache.delete("x"); // false (already removed)
700
+ * ```
701
+ */
702
+ delete(key) {
703
+ const node = this.map.get(key);
704
+ if (!node) return false;
705
+ this.removeNode(node);
706
+ this.map.delete(key);
707
+ return true;
708
+ }
709
+ /**
710
+ * Removes all entries from the cache, resetting it to an empty state.
711
+ *
712
+ * @example
713
+ * ```typescript
714
+ * import { LRUCache } from "./lruCache";
715
+ *
716
+ * const cache = new LRUCache<string>();
717
+ * cache.set("a", "1", 10_000);
718
+ * cache.clear();
719
+ * console.log(cache.size); // 0
720
+ * ```
721
+ */
722
+ clear() {
723
+ this.map.clear();
724
+ this.head = null;
725
+ this.tail = null;
726
+ }
727
+ // --- Doubly-linked list operations ---
728
+ /** Adds a node to the head of the list (most recently used position). */
729
+ addToHead(node) {
730
+ node.prev = null;
731
+ node.next = this.head;
732
+ if (this.head) {
733
+ this.head.prev = node;
734
+ }
735
+ this.head = node;
736
+ if (!this.tail) {
737
+ this.tail = node;
738
+ }
739
+ }
740
+ /** Removes a node from its current position in the list. */
741
+ removeNode(node) {
742
+ if (node.prev) {
743
+ node.prev.next = node.next;
744
+ } else {
745
+ this.head = node.next;
746
+ }
747
+ if (node.next) {
748
+ node.next.prev = node.prev;
749
+ } else {
750
+ this.tail = node.prev;
751
+ }
752
+ node.prev = null;
753
+ node.next = null;
754
+ }
755
+ /** Moves an existing node to the head of the list. */
756
+ moveToHead(node) {
757
+ if (this.head === node) return;
758
+ this.removeNode(node);
759
+ this.addToHead(node);
760
+ }
761
+ /** Evicts the tail node (least recently used) and notifies via callback. */
762
+ evictTail() {
763
+ if (!this.tail) return;
764
+ const evicted = this.tail;
765
+ this.removeNode(evicted);
766
+ this.map.delete(evicted.key);
767
+ if (this.onEvict) {
768
+ this.onEvict(1);
769
+ }
770
+ }
771
+ }, _class);
772
+
773
+ // src/http/lifecycle/responseCache.ts
774
+ function clamp2(n, min, max) {
775
+ return Math.max(min, Math.min(max, n));
776
+ }
777
+ function safeEmit2(onEvent, event) {
778
+ if (!onEvent) return;
779
+ try {
780
+ onEvent(event);
781
+ } catch (e7) {
782
+ }
783
+ }
784
+ function withCache(config) {
785
+ const ttlSeconds = clamp2(_nullishCoalesce(_optionalChain([config, 'optionalAccess', _3 => _3.ttlSeconds]), () => ( 60)), 1, 86400);
786
+ const ttlMs = ttlSeconds * 1e3;
787
+ const maxEntries = Math.max(1, Math.floor(_nullishCoalesce(_optionalChain([config, 'optionalAccess', _4 => _4.maxEntries]), () => ( 1024))));
788
+ const staleWhileRevalidate = _nullishCoalesce(_optionalChain([config, 'optionalAccess', _5 => _5.staleWhileRevalidate]), () => ( false));
789
+ const cachePolicy = _optionalChain([config, 'optionalAccess', _6 => _6.cachePolicy]);
790
+ const cacheRelevantHeaders = _nullishCoalesce(_optionalChain([config, 'optionalAccess', _7 => _7.cacheRelevantHeaders]), () => ( []));
791
+ const baseUrl = _nullishCoalesce(_optionalChain([config, 'optionalAccess', _8 => _8.baseUrl]), () => ( ""));
792
+ const onEvent = _optionalChain([config, 'optionalAccess', _9 => _9.onEvent]);
793
+ const onLifecycleEvent = _optionalChain([config, 'optionalAccess', _10 => _10.onLifecycleEvent]);
794
+ const cache = new LRUCache({
795
+ maxEntries,
796
+ onEvict: (count) => _optionalChain([onLifecycleEvent, 'optionalCall', _11 => _11({ type: "cache-eviction", count })])
797
+ });
798
+ const revalidating = /* @__PURE__ */ new Set();
799
+ const invalidate = (key) => {
800
+ cache.delete(key);
801
+ };
802
+ const clear = () => {
803
+ cache.clear();
804
+ };
805
+ const middleware = (next) => {
806
+ return (req) => {
807
+ const method = req.method.toUpperCase();
808
+ if (!SAFE_METHODS.has(method) && !cachePolicy) {
809
+ return next(req);
810
+ }
811
+ const key = computeCacheKey(req, baseUrl, cacheRelevantHeaders);
812
+ return {
813
+ _tag: "Async",
814
+ register: (env, cb) => {
815
+ const cached = cache.get(key);
816
+ if (cached !== void 0) {
817
+ _optionalChain([onLifecycleEvent, 'optionalCall', _12 => _12({ type: "cache-hit", cacheKey: key })]);
818
+ cb({ _tag: "Success", value: cached });
819
+ return;
820
+ }
821
+ _optionalChain([onLifecycleEvent, 'optionalCall', _13 => _13({ type: "cache-miss", cacheKey: key })]);
822
+ const innerEffect = next(req);
823
+ return _chunkL6VB5N7Qcjs.registerHttpEffect.call(void 0, innerEffect, env, (exit) => {
824
+ if (exit._tag === "Success") {
825
+ storeIfCacheable(req, exit.value, key);
826
+ }
827
+ cb(exit);
828
+ });
829
+ }
830
+ };
831
+ };
832
+ };
833
+ function storeIfCacheable(req, res, key) {
834
+ const method = req.method.toUpperCase();
835
+ if (cachePolicy) {
836
+ const result = cachePolicy(req, res);
837
+ if (!result.cacheable) return;
838
+ const entryTtlMs = result.ttlSeconds !== void 0 ? clamp2(result.ttlSeconds, 1, 86400) * 1e3 : ttlMs;
839
+ cache.set(key, res, entryTtlMs);
840
+ return;
841
+ }
842
+ if (!SAFE_METHODS.has(method)) return;
843
+ cache.set(key, res, ttlMs);
844
+ }
845
+ function triggerRevalidation(next, req, key) {
846
+ if (revalidating.has(key)) return;
847
+ revalidating.add(key);
848
+ const innerEffect = next(req);
849
+ const handleExit = (exit) => {
850
+ revalidating.delete(key);
851
+ if (exit._tag === "Success") {
852
+ storeIfCacheable(req, exit.value, key);
853
+ } else {
854
+ safeEmit2(onEvent, {
855
+ type: "revalidation-failure",
856
+ cacheKey: key,
857
+ error: _chunkMVGUEJ5Zcjs.Cause.squash(exit.cause)
858
+ });
859
+ }
860
+ };
861
+ _chunkL6VB5N7Qcjs.registerHttpEffect.call(void 0, innerEffect, void 0, handleExit);
862
+ }
863
+ const expirationMap = /* @__PURE__ */ new Map();
864
+ const swrMiddleware = (next) => {
865
+ return (req) => {
866
+ const method = req.method.toUpperCase();
867
+ if (!SAFE_METHODS.has(method) && !cachePolicy) {
868
+ return next(req);
869
+ }
870
+ const key = computeCacheKey(req, baseUrl, cacheRelevantHeaders);
871
+ return {
872
+ _tag: "Async",
873
+ register: (env, cb) => {
874
+ const cached = cache.get(key);
875
+ if (cached !== void 0) {
876
+ const expiresAt = expirationMap.get(key);
877
+ if (expiresAt !== void 0 && now() < expiresAt) {
878
+ _optionalChain([onLifecycleEvent, 'optionalCall', _14 => _14({ type: "cache-hit", cacheKey: key })]);
879
+ cb({ _tag: "Success", value: cached });
880
+ return;
881
+ }
882
+ _optionalChain([onLifecycleEvent, 'optionalCall', _15 => _15({ type: "cache-hit", cacheKey: key })]);
883
+ cb({ _tag: "Success", value: cached });
884
+ triggerRevalidation(next, req, key);
885
+ return;
886
+ }
887
+ _optionalChain([onLifecycleEvent, 'optionalCall', _16 => _16({ type: "cache-miss", cacheKey: key })]);
888
+ const innerEffect = next(req);
889
+ const handleSuccess = (res) => {
890
+ swrStoreIfCacheable(req, res, key);
891
+ };
892
+ return _chunkL6VB5N7Qcjs.registerHttpEffect.call(void 0, innerEffect, env, (exit) => {
893
+ if (exit._tag === "Success") {
894
+ handleSuccess(exit.value);
895
+ }
896
+ cb(exit);
897
+ });
898
+ }
899
+ };
900
+ };
901
+ };
902
+ function swrStoreIfCacheable(req, res, key) {
903
+ const method = req.method.toUpperCase();
904
+ let entryTtlMs = ttlMs;
905
+ if (cachePolicy) {
906
+ const result = cachePolicy(req, res);
907
+ if (!result.cacheable) return;
908
+ entryTtlMs = result.ttlSeconds !== void 0 ? clamp2(result.ttlSeconds, 1, 86400) * 1e3 : ttlMs;
909
+ } else if (!SAFE_METHODS.has(method)) {
910
+ return;
911
+ }
912
+ const lruTtl = Number.MAX_SAFE_INTEGER;
913
+ cache.set(key, res, lruTtl);
914
+ expirationMap.set(key, now() + entryTtlMs);
915
+ }
916
+ const swrInvalidate = (key) => {
917
+ cache.delete(key);
918
+ expirationMap.delete(key);
919
+ };
920
+ const swrClear = () => {
921
+ cache.clear();
922
+ expirationMap.clear();
923
+ };
924
+ if (staleWhileRevalidate) {
925
+ return {
926
+ middleware: swrMiddleware,
927
+ invalidate: swrInvalidate,
928
+ clear: swrClear
929
+ };
930
+ }
931
+ return {
932
+ middleware,
933
+ invalidate,
934
+ clear
935
+ };
936
+ }
937
+
938
+ // src/http/lifecycle/priorityQueue.ts
939
+ function clampPriority(value) {
940
+ if (value === void 0 || !Number.isFinite(value)) return 5;
941
+ return Math.max(0, Math.min(9, Math.trunc(value)));
942
+ }
943
+ function comparePriority(a, b) {
944
+ if (a.priority !== b.priority) return a.priority - b.priority;
945
+ return a.arrivalOrder - b.arrivalOrder;
946
+ }
947
+ var PriorityQueue = (_class2 = class {constructor() { _class2.prototype.__init4.call(this);_class2.prototype.__init5.call(this); }
948
+ __init4() {this.heap = []}
949
+ __init5() {this.counter = 0}
950
+ /**
951
+ * Returns the number of entries in the queue (including cancelled entries).
952
+ *
953
+ * @returns The total number of entries in the internal heap.
954
+ *
955
+ * @example
956
+ * ```typescript
957
+ * import { PriorityQueue } from "./priorityQueue";
958
+ *
959
+ * const queue = new PriorityQueue<string>();
960
+ * queue.enqueue("task", 5);
961
+ * console.log(queue.size); // 1
962
+ * ```
963
+ */
964
+ get size() {
965
+ return this.heap.length;
966
+ }
967
+ /** Returns the number of entries that have not been cancelled. */
968
+ get activeSize() {
969
+ return this.heap.reduce((n, entry) => n + (entry.cancelled ? 0 : 1), 0);
970
+ }
971
+ /**
972
+ * Adds a value to the queue with the given priority.
973
+ *
974
+ * Priority is clamped to the valid range [0, 9] via `clampPriority`.
975
+ * Returns the created entry, which can be used for later cancellation
976
+ * by setting `entry.cancelled = true`.
977
+ *
978
+ * @param value - The value to enqueue.
979
+ * @param priority - Priority level, integer from 0 (highest) to 9 (lowest).
980
+ * Clamped to [0, 9]. Defaults to 5 if undefined.
981
+ * @returns The created queue entry.
982
+ *
983
+ * @example
984
+ * ```typescript
985
+ * import { PriorityQueue } from "./priorityQueue";
986
+ *
987
+ * const queue = new PriorityQueue<string>();
988
+ * const entry = queue.enqueue("urgent-task", 0);
989
+ * entry.cancelled = true; // cancel later if needed
990
+ * ```
991
+ */
992
+ enqueue(value, priority) {
993
+ const entry = {
994
+ priority: clampPriority(priority),
995
+ arrivalOrder: this.counter++,
996
+ value,
997
+ cancelled: false
998
+ };
999
+ this.heap.push(entry);
1000
+ this.bubbleUp(this.heap.length - 1);
1001
+ return entry;
1002
+ }
1003
+ /**
1004
+ * Removes and returns the highest-priority non-cancelled entry.
1005
+ *
1006
+ * Skips (and discards) any cancelled entries at the top of the heap.
1007
+ * Returns `undefined` if the queue is empty or all entries are cancelled.
1008
+ *
1009
+ * @returns The highest-priority non-cancelled entry, or `undefined` if none available.
1010
+ *
1011
+ * @example
1012
+ * ```typescript
1013
+ * import { PriorityQueue } from "./priorityQueue";
1014
+ *
1015
+ * const queue = new PriorityQueue<string>();
1016
+ * queue.enqueue("first", 1);
1017
+ * queue.enqueue("second", 2);
1018
+ * const entry = queue.dequeue(); // { value: "first", priority: 1, ... }
1019
+ * ```
1020
+ */
1021
+ dequeue() {
1022
+ while (this.heap.length > 0) {
1023
+ const top = this.heap[0];
1024
+ if (top.cancelled) {
1025
+ this.removeTop();
1026
+ continue;
1027
+ }
1028
+ this.removeTop();
1029
+ return top;
1030
+ }
1031
+ return void 0;
1032
+ }
1033
+ /**
1034
+ * Returns the highest-priority non-cancelled entry without removing it.
1035
+ *
1036
+ * Discards cancelled entries at the top of the heap as a side effect.
1037
+ * Returns `undefined` if the queue is empty or all entries are cancelled.
1038
+ *
1039
+ * @returns The highest-priority non-cancelled entry, or `undefined` if none available.
1040
+ *
1041
+ * @example
1042
+ * ```typescript
1043
+ * import { PriorityQueue } from "./priorityQueue";
1044
+ *
1045
+ * const queue = new PriorityQueue<string>();
1046
+ * queue.enqueue("task", 3);
1047
+ * const top = queue.peek(); // { value: "task", priority: 3, ... }
1048
+ * console.log(queue.size); // 1 (not removed)
1049
+ * ```
1050
+ */
1051
+ peek() {
1052
+ while (this.heap.length > 0) {
1053
+ const top = this.heap[0];
1054
+ if (top.cancelled) {
1055
+ this.removeTop();
1056
+ continue;
1057
+ }
1058
+ return top;
1059
+ }
1060
+ return void 0;
1061
+ }
1062
+ /**
1063
+ * Marks all entries matching the predicate as cancelled (lazy removal).
1064
+ *
1065
+ * Cancelled entries are skipped on subsequent dequeue/peek calls.
1066
+ * This does not immediately remove entries from the heap; they are
1067
+ * discarded lazily when encountered at the top during dequeue or peek.
1068
+ *
1069
+ * @param predicate - A function that returns `true` for entries to cancel.
1070
+ * @returns The number of entries marked as cancelled.
1071
+ *
1072
+ * @example
1073
+ * ```typescript
1074
+ * import { PriorityQueue } from "./priorityQueue";
1075
+ *
1076
+ * const queue = new PriorityQueue<string>();
1077
+ * queue.enqueue("a", 1);
1078
+ * queue.enqueue("b", 2);
1079
+ * const removed = queue.remove((e) => e.value === "a"); // 1
1080
+ * ```
1081
+ */
1082
+ remove(predicate) {
1083
+ let count = 0;
1084
+ for (const entry of this.heap) {
1085
+ if (!entry.cancelled && predicate(entry)) {
1086
+ entry.cancelled = true;
1087
+ count++;
1088
+ }
1089
+ }
1090
+ return count;
1091
+ }
1092
+ // --- Binary heap operations ---
1093
+ /** Removes the top element from the heap and restores heap property. */
1094
+ removeTop() {
1095
+ const last = this.heap.pop();
1096
+ if (this.heap.length > 0 && last !== void 0) {
1097
+ this.heap[0] = last;
1098
+ this.sinkDown(0);
1099
+ }
1100
+ }
1101
+ /** Moves an element up the heap until the heap property is restored. */
1102
+ bubbleUp(index) {
1103
+ while (index > 0) {
1104
+ const parentIndex = index - 1 >>> 1;
1105
+ const current = this.heap[index];
1106
+ const parent = this.heap[parentIndex];
1107
+ if (comparePriority(current, parent) >= 0) break;
1108
+ this.heap[index] = parent;
1109
+ this.heap[parentIndex] = current;
1110
+ index = parentIndex;
1111
+ }
1112
+ }
1113
+ /** Moves an element down the heap until the heap property is restored. */
1114
+ sinkDown(index) {
1115
+ const length = this.heap.length;
1116
+ while (true) {
1117
+ const leftIndex = 2 * index + 1;
1118
+ const rightIndex = 2 * index + 2;
1119
+ let smallest = index;
1120
+ if (leftIndex < length && comparePriority(this.heap[leftIndex], this.heap[smallest]) < 0) {
1121
+ smallest = leftIndex;
1122
+ }
1123
+ if (rightIndex < length && comparePriority(this.heap[rightIndex], this.heap[smallest]) < 0) {
1124
+ smallest = rightIndex;
1125
+ }
1126
+ if (smallest === index) break;
1127
+ const temp = this.heap[index];
1128
+ this.heap[index] = this.heap[smallest];
1129
+ this.heap[smallest] = temp;
1130
+ index = smallest;
1131
+ }
1132
+ }
1133
+ }, _class2);
1134
+
1135
+ // src/http/lifecycle/priorityScheduler.ts
1136
+ var DEFAULT_CONCURRENCY = 32;
1137
+ function extractPriority(req) {
1138
+ const fromPolicy = _chunk3LOYJFRRcjs.getHttpRequestPolicy.call(void 0, req).priority;
1139
+ if (fromPolicy !== void 0) return clampPriority(fromPolicy);
1140
+ const fromInit = _optionalChain([req, 'access', _17 => _17.init, 'optionalAccess', _18 => _18.priority]);
1141
+ if (fromInit !== void 0) return clampPriority(fromInit);
1142
+ return 5;
1143
+ }
1144
+ function safeEmit3(onEvent, event) {
1145
+ if (!onEvent) return;
1146
+ try {
1147
+ onEvent(event);
1148
+ } catch (e8) {
1149
+ }
1150
+ }
1151
+ function withPriority(config) {
1152
+ const concurrency = resolveConcurrency(_optionalChain([config, 'optionalAccess', _19 => _19.concurrency]));
1153
+ const queueTimeoutMs = resolveQueueTimeout(_optionalChain([config, 'optionalAccess', _20 => _20.queueTimeoutMs]));
1154
+ const onEvent = _optionalChain([config, 'optionalAccess', _21 => _21.onEvent]);
1155
+ const queue = new PriorityQueue();
1156
+ let inFlight = 0;
1157
+ const queueDepth = () => {
1158
+ return queue.activeSize;
1159
+ };
1160
+ const middleware = (next) => {
1161
+ return (req) => {
1162
+ const priority = extractPriority(req);
1163
+ return {
1164
+ _tag: "Async",
1165
+ register: (env, cb) => {
1166
+ if (inFlight < concurrency) {
1167
+ return dispatchRequest(next, req, env, cb);
1168
+ }
1169
+ const queued = { req, env, cb, signal: getSignal(req) };
1170
+ const entry = queue.enqueue(queued, priority);
1171
+ safeEmit3(onEvent, { type: "queue-enqueue", priority });
1172
+ if (queueTimeoutMs !== void 0) {
1173
+ queued.timer = setTimeout(() => {
1174
+ entry.cancelled = true;
1175
+ queued.timer = void 0;
1176
+ cb({
1177
+ _tag: "Failure",
1178
+ cause: _chunkMVGUEJ5Zcjs.Cause.fail({
1179
+ _tag: "PoolTimeout",
1180
+ key: "priority",
1181
+ timeoutMs: queueTimeoutMs,
1182
+ message: `Priority queue did not dispatch within ${queueTimeoutMs}ms`
1183
+ })
1184
+ });
1185
+ }, queueTimeoutMs);
1186
+ }
1187
+ const signal = queued.signal;
1188
+ let abortHandler;
1189
+ if (signal && !signal.aborted) {
1190
+ abortHandler = () => {
1191
+ entry.cancelled = true;
1192
+ if (queued.timer !== void 0) {
1193
+ clearTimeout(queued.timer);
1194
+ queued.timer = void 0;
1195
+ }
1196
+ cb({ _tag: "Failure", cause: _chunkMVGUEJ5Zcjs.Cause.fail({ _tag: "Abort" }) });
1197
+ };
1198
+ signal.addEventListener("abort", abortHandler, { once: true });
1199
+ } else if (_optionalChain([signal, 'optionalAccess', _22 => _22.aborted])) {
1200
+ entry.cancelled = true;
1201
+ cb({ _tag: "Failure", cause: _chunkMVGUEJ5Zcjs.Cause.fail({ _tag: "Abort" }) });
1202
+ return;
1203
+ }
1204
+ return () => {
1205
+ entry.cancelled = true;
1206
+ if (queued.timer !== void 0) {
1207
+ clearTimeout(queued.timer);
1208
+ queued.timer = void 0;
1209
+ }
1210
+ if (abortHandler && signal) {
1211
+ signal.removeEventListener("abort", abortHandler);
1212
+ }
1213
+ cb({ _tag: "Failure", cause: _chunkMVGUEJ5Zcjs.Cause.interrupt() });
1214
+ };
1215
+ }
1216
+ };
1217
+ };
1218
+ function dispatchRequest(downstream, req, env, cb) {
1219
+ inFlight++;
1220
+ safeEmit3(onEvent, { type: "queue-dispatch", priority: extractPriority(req) });
1221
+ const innerEffect = downstream(req);
1222
+ let completed = false;
1223
+ const onComplete = (exit) => {
1224
+ if (completed) return;
1225
+ completed = true;
1226
+ inFlight--;
1227
+ cb(exit);
1228
+ drainNext(downstream);
1229
+ };
1230
+ const innerCancel = _chunkL6VB5N7Qcjs.registerHttpEffect.call(void 0, innerEffect, env, onComplete);
1231
+ return () => {
1232
+ innerCancel();
1233
+ };
1234
+ }
1235
+ function drainNext(downstream) {
1236
+ while (inFlight < concurrency) {
1237
+ const entry = queue.dequeue();
1238
+ if (!entry) break;
1239
+ if (entry.cancelled) continue;
1240
+ const queued = entry.value;
1241
+ if (queued.timer !== void 0) {
1242
+ clearTimeout(queued.timer);
1243
+ queued.timer = void 0;
1244
+ }
1245
+ if (_optionalChain([queued, 'access', _23 => _23.signal, 'optionalAccess', _24 => _24.aborted])) {
1246
+ queued.cb({ _tag: "Failure", cause: _chunkMVGUEJ5Zcjs.Cause.fail({ _tag: "Abort" }) });
1247
+ continue;
1248
+ }
1249
+ dispatchRequest(downstream, queued.req, queued.env, queued.cb);
1250
+ }
1251
+ }
1252
+ };
1253
+ return Object.assign(middleware, { queueDepth });
1254
+ }
1255
+ function resolveConcurrency(value) {
1256
+ if (value === void 0 || !Number.isFinite(value)) return DEFAULT_CONCURRENCY;
1257
+ return Math.max(1, Math.floor(value));
1258
+ }
1259
+ function resolveQueueTimeout(value) {
1260
+ if (value === void 0 || !Number.isFinite(value)) return void 0;
1261
+ const n = Math.floor(value);
1262
+ return n > 0 ? n : void 0;
1263
+ }
1264
+ function getSignal(req) {
1265
+ return _optionalChain([req, 'access', _25 => _25.init, 'optionalAccess', _26 => _26.signal]);
1266
+ }
1267
+
1268
+ // src/http/lifecycle/stats.ts
1269
+ var LifecycleStatsTracker = (_class3 = class {
1270
+ __init6() {this._cacheHits = 0}
1271
+ __init7() {this._cacheMisses = 0}
1272
+ __init8() {this._cacheEvictions = 0}
1273
+ __init9() {this._dedupHits = 0}
1274
+ __init10() {this._dedupActive = 0}
1275
+ __init11() {this._queueDepth = 0}
1276
+ __init12() {this._requestsStarted = 0}
1277
+ __init13() {this._requestsCompleted = 0}
1278
+ __init14() {this._requestsFailed = 0}
1279
+ __init15() {this._retries = 0}
1280
+ __init16() {this._batchDispatches = 0}
1281
+ __init17() {this._batchedRequests = 0}
1282
+
1283
+
1284
+ /**
1285
+ * Creates a new lifecycle stats tracker.
1286
+ *
1287
+ * @param opts - Configuration options for the tracker.
1288
+ * @param opts.onEvent - Optional callback invoked on each lifecycle event.
1289
+ * Errors thrown by this callback are silently discarded.
1290
+ * @param opts.wireStats - A function returning the current wire-level HTTP client stats.
1291
+ *
1292
+ * @example
1293
+ * ```typescript
1294
+ * import { LifecycleStatsTracker } from "./stats";
1295
+ *
1296
+ * const tracker = new LifecycleStatsTracker({
1297
+ * wireStats: () => ({ requestCount: 0, errorCount: 0 }),
1298
+ * });
1299
+ * ```
1300
+ */
1301
+ constructor(opts) {;_class3.prototype.__init6.call(this);_class3.prototype.__init7.call(this);_class3.prototype.__init8.call(this);_class3.prototype.__init9.call(this);_class3.prototype.__init10.call(this);_class3.prototype.__init11.call(this);_class3.prototype.__init12.call(this);_class3.prototype.__init13.call(this);_class3.prototype.__init14.call(this);_class3.prototype.__init15.call(this);_class3.prototype.__init16.call(this);_class3.prototype.__init17.call(this);
1302
+ this._onEvent = opts.onEvent;
1303
+ this._wireStats = opts.wireStats;
1304
+ }
1305
+ // --- Increment methods ---
1306
+ /**
1307
+ * Records a cache hit. Increments the cache hit counter by 1.
1308
+ *
1309
+ * @example
1310
+ * ```typescript
1311
+ * import { LifecycleStatsTracker } from "./stats";
1312
+ *
1313
+ * const tracker = new LifecycleStatsTracker({ wireStats: () => ({ requestCount: 0, errorCount: 0 }) });
1314
+ * tracker.cacheHit();
1315
+ * ```
1316
+ */
1317
+ cacheHit() {
1318
+ this._cacheHits++;
1319
+ }
1320
+ /**
1321
+ * Records a cache miss. Increments the cache miss counter by 1.
1322
+ *
1323
+ * @example
1324
+ * ```typescript
1325
+ * import { LifecycleStatsTracker } from "./stats";
1326
+ *
1327
+ * const tracker = new LifecycleStatsTracker({ wireStats: () => ({ requestCount: 0, errorCount: 0 }) });
1328
+ * tracker.cacheMiss();
1329
+ * ```
1330
+ */
1331
+ cacheMiss() {
1332
+ this._cacheMisses++;
1333
+ }
1334
+ /**
1335
+ * Records a cache eviction. Increments the cache eviction counter by 1.
1336
+ *
1337
+ * @example
1338
+ * ```typescript
1339
+ * import { LifecycleStatsTracker } from "./stats";
1340
+ *
1341
+ * const tracker = new LifecycleStatsTracker({ wireStats: () => ({ requestCount: 0, errorCount: 0 }) });
1342
+ * tracker.cacheEviction();
1343
+ * ```
1344
+ */
1345
+ cacheEviction() {
1346
+ this._cacheEvictions++;
1347
+ }
1348
+ /**
1349
+ * Records a dedup hit (a request that joined an in-flight duplicate).
1350
+ * Increments the dedup hit counter by 1.
1351
+ *
1352
+ * @example
1353
+ * ```typescript
1354
+ * import { LifecycleStatsTracker } from "./stats";
1355
+ *
1356
+ * const tracker = new LifecycleStatsTracker({ wireStats: () => ({ requestCount: 0, errorCount: 0 }) });
1357
+ * tracker.dedupHit();
1358
+ * ```
1359
+ */
1360
+ dedupHit() {
1361
+ this._dedupHits++;
1362
+ }
1363
+ /**
1364
+ * Sets the current number of active dedup groups.
1365
+ *
1366
+ * @param n - The current count of active dedup groups. Must be >= 0.
1367
+ *
1368
+ * @example
1369
+ * ```typescript
1370
+ * import { LifecycleStatsTracker } from "./stats";
1371
+ *
1372
+ * const tracker = new LifecycleStatsTracker({ wireStats: () => ({ requestCount: 0, errorCount: 0 }) });
1373
+ * tracker.setDedupActive(3);
1374
+ * ```
1375
+ */
1376
+ setDedupActive(n) {
1377
+ this._dedupActive = n;
1378
+ }
1379
+ /**
1380
+ * Sets the current priority queue depth.
1381
+ *
1382
+ * @param n - The current number of entries in the priority queue. Must be >= 0.
1383
+ *
1384
+ * @example
1385
+ * ```typescript
1386
+ * import { LifecycleStatsTracker } from "./stats";
1387
+ *
1388
+ * const tracker = new LifecycleStatsTracker({ wireStats: () => ({ requestCount: 0, errorCount: 0 }) });
1389
+ * tracker.setQueueDepth(5);
1390
+ * ```
1391
+ */
1392
+ setQueueDepth(n) {
1393
+ this._queueDepth = n;
1394
+ }
1395
+ /**
1396
+ * Records that a request has started. Increments the requests started counter by 1.
1397
+ *
1398
+ * @example
1399
+ * ```typescript
1400
+ * import { LifecycleStatsTracker } from "./stats";
1401
+ *
1402
+ * const tracker = new LifecycleStatsTracker({ wireStats: () => ({ requestCount: 0, errorCount: 0 }) });
1403
+ * tracker.requestStarted();
1404
+ * ```
1405
+ */
1406
+ requestStarted() {
1407
+ this._requestsStarted++;
1408
+ }
1409
+ /**
1410
+ * Records that a request has completed successfully.
1411
+ * Increments the requests completed counter by 1.
1412
+ *
1413
+ * @example
1414
+ * ```typescript
1415
+ * import { LifecycleStatsTracker } from "./stats";
1416
+ *
1417
+ * const tracker = new LifecycleStatsTracker({ wireStats: () => ({ requestCount: 0, errorCount: 0 }) });
1418
+ * tracker.requestCompleted();
1419
+ * ```
1420
+ */
1421
+ requestCompleted() {
1422
+ this._requestsCompleted++;
1423
+ }
1424
+ /**
1425
+ * Records that a request has failed.
1426
+ * Increments the requests failed counter by 1.
1427
+ *
1428
+ * @example
1429
+ * ```typescript
1430
+ * import { LifecycleStatsTracker } from "./stats";
1431
+ *
1432
+ * const tracker = new LifecycleStatsTracker({ wireStats: () => ({ requestCount: 0, errorCount: 0 }) });
1433
+ * tracker.requestFailed();
1434
+ * ```
1435
+ */
1436
+ requestFailed() {
1437
+ this._requestsFailed++;
1438
+ }
1439
+ retry() {
1440
+ this._retries++;
1441
+ }
1442
+ /**
1443
+ * Records a batch dispatch. Increments the batch dispatches counter by 1.
1444
+ */
1445
+ batchDispatch() {
1446
+ this._batchDispatches++;
1447
+ }
1448
+ /**
1449
+ * Records requests that were coalesced into a batch.
1450
+ * @param count - The number of individual requests in the batch.
1451
+ */
1452
+ batchedRequests(count) {
1453
+ this._batchedRequests += count;
1454
+ }
1455
+ // --- Event emission ---
1456
+ /**
1457
+ * Emits a lifecycle event to the registered `onEvent` callback.
1458
+ *
1459
+ * The callback is wrapped in a try-catch so that any exception thrown by
1460
+ * the callback is silently discarded and request processing continues
1461
+ * unaffected. If no `onEvent` callback was provided, this is a no-op.
1462
+ *
1463
+ * @param type - The lifecycle event type to emit (e.g., `"cache-hit"`, `"request-start"`).
1464
+ * @param extra - Optional additional event data.
1465
+ *
1466
+ * @example
1467
+ * ```typescript
1468
+ * import { LifecycleStatsTracker } from "./stats";
1469
+ *
1470
+ * const tracker = new LifecycleStatsTracker({
1471
+ * onEvent: (event) => console.log(event.type, event.timestamp),
1472
+ * wireStats: () => ({ requestCount: 0, errorCount: 0 }),
1473
+ * });
1474
+ * tracker.emit("cache-hit", { cacheKey: "GET|/api/users" });
1475
+ * ```
1476
+ */
1477
+ emit(type, extra) {
1478
+ if (!this._onEvent) return;
1479
+ try {
1480
+ const event = {
1481
+ type,
1482
+ timestamp: now(),
1483
+ ...extra
1484
+ };
1485
+ this._onEvent(event);
1486
+ } catch (e9) {
1487
+ }
1488
+ }
1489
+ // --- Snapshot ---
1490
+ /**
1491
+ * Returns a frozen snapshot of all lifecycle statistics including wire stats.
1492
+ *
1493
+ * The returned object is frozen (immutable) and represents a point-in-time
1494
+ * view of all counters and gauges.
1495
+ *
1496
+ * @returns A frozen `LifecycleStats` object containing all current statistics.
1497
+ *
1498
+ * @example
1499
+ * ```typescript
1500
+ * import { LifecycleStatsTracker } from "./stats";
1501
+ *
1502
+ * const tracker = new LifecycleStatsTracker({
1503
+ * wireStats: () => ({ requestCount: 10, errorCount: 1 }),
1504
+ * });
1505
+ * tracker.cacheHit();
1506
+ * tracker.cacheHit();
1507
+ * const stats = tracker.snapshot();
1508
+ * console.log(stats.cacheHits); // 2
1509
+ * ```
1510
+ */
1511
+ snapshot() {
1512
+ return Object.freeze({
1513
+ cacheHits: this._cacheHits,
1514
+ cacheMisses: this._cacheMisses,
1515
+ cacheEvictions: this._cacheEvictions,
1516
+ dedupHits: this._dedupHits,
1517
+ dedupActive: this._dedupActive,
1518
+ queueDepth: this._queueDepth,
1519
+ requestsStarted: this._requestsStarted,
1520
+ requestsCompleted: this._requestsCompleted,
1521
+ requestsFailed: this._requestsFailed,
1522
+ retries: this._retries,
1523
+ batchDispatches: this._batchDispatches,
1524
+ batchedRequests: this._batchedRequests,
1525
+ wire: this._wireStats()
1526
+ });
1527
+ }
1528
+ }, _class3);
1529
+
1530
+ // src/http/prewarm/validation.ts
1531
+ function validateOrigin(origin) {
1532
+ if (!origin || typeof origin !== "string") {
1533
+ throw new Error(`validateOrigin: origin must be a non-empty string, got "${origin}"`);
1534
+ }
1535
+ const trimmed = origin.trim();
1536
+ if (!trimmed) {
1537
+ throw new Error(`validateOrigin: origin must be a non-empty string, got "${origin}"`);
1538
+ }
1539
+ const stripped = stripTrailingSlashes(trimmed);
1540
+ const lower = stripped.toLowerCase();
1541
+ if (!lower.startsWith("http://") && !lower.startsWith("https://")) {
1542
+ throw new Error(
1543
+ `validateOrigin: invalid origin "${origin}" \u2014 must start with http:// or https://`
1544
+ );
1545
+ }
1546
+ let parsed;
1547
+ try {
1548
+ parsed = new URL(stripped);
1549
+ } catch (e10) {
1550
+ throw new Error(
1551
+ `validateOrigin: invalid origin "${origin}" \u2014 must be a valid URL origin (scheme + host + optional port)`
1552
+ );
1553
+ }
1554
+ if (parsed.pathname !== "/" && parsed.pathname !== "") {
1555
+ throw new Error(
1556
+ `validateOrigin: invalid origin "${origin}" \u2014 must not contain a path`
1557
+ );
1558
+ }
1559
+ if (parsed.search) {
1560
+ throw new Error(
1561
+ `validateOrigin: invalid origin "${origin}" \u2014 must not contain query parameters`
1562
+ );
1563
+ }
1564
+ if (parsed.hash) {
1565
+ throw new Error(
1566
+ `validateOrigin: invalid origin "${origin}" \u2014 must not contain a fragment`
1567
+ );
1568
+ }
1569
+ return parsed.origin;
1570
+ }
1571
+ function stripTrailingSlashes(value) {
1572
+ let end = value.length;
1573
+ while (end > 0 && value.charCodeAt(end - 1) === 47) {
1574
+ end--;
1575
+ }
1576
+ return end === value.length ? value : value.slice(0, end);
1577
+ }
1578
+
1579
+ // src/http/prewarm/platform.ts
1580
+ function detectPlatform() {
1581
+ return typeof window !== "undefined" && typeof window.document !== "undefined" ? "browser" : "node";
1582
+ }
1583
+ function validateFetchAvailable() {
1584
+ if (typeof globalThis.fetch !== "function") {
1585
+ throw new Error(
1586
+ "makePrewarmManager: global fetch is not available. Requires Node.js 18+ or modern browser."
1587
+ );
1588
+ }
1589
+ if (typeof globalThis.AbortController !== "function") {
1590
+ throw new Error(
1591
+ "makePrewarmManager: global AbortController is not available."
1592
+ );
1593
+ }
1594
+ }
1595
+
1596
+ // src/http/prewarm/probe.ts
1597
+ async function executeProbe(origin, options) {
1598
+ const { timeoutMs, signal, platform } = options;
1599
+ const url = `${origin}/`;
1600
+ const start = Date.now();
1601
+ const timeoutController = new AbortController();
1602
+ const timeoutId = setTimeout(() => timeoutController.abort(), timeoutMs);
1603
+ const onExternalAbort = () => timeoutController.abort();
1604
+ signal.addEventListener("abort", onExternalAbort);
1605
+ try {
1606
+ if (options.client) {
1607
+ const result = await executeProbeViaClient(options.client, url, timeoutController.signal);
1608
+ const durationMs2 = Date.now() - start;
1609
+ if (result.ok) {
1610
+ return { ok: true, durationMs: durationMs2 };
1611
+ }
1612
+ return { ok: false, durationMs: durationMs2, error: result.error };
1613
+ }
1614
+ const fetchOptions = {
1615
+ method: "HEAD",
1616
+ signal: timeoutController.signal,
1617
+ // Prevent caching of probe requests
1618
+ cache: "no-store"
1619
+ };
1620
+ if (platform === "browser") {
1621
+ fetchOptions.mode = "no-cors";
1622
+ }
1623
+ await globalThis.fetch(url, fetchOptions);
1624
+ const durationMs = Date.now() - start;
1625
+ return { ok: true, durationMs };
1626
+ } catch (err) {
1627
+ const durationMs = Date.now() - start;
1628
+ if (signal.aborted) {
1629
+ return { ok: false, durationMs, error: "cancelled" };
1630
+ }
1631
+ if (timeoutController.signal.aborted && !signal.aborted) {
1632
+ return { ok: false, durationMs, error: `Probe timed out after ${timeoutMs}ms` };
1633
+ }
1634
+ const message = err instanceof Error ? err.message : String(err);
1635
+ return { ok: false, durationMs, error: message };
1636
+ } finally {
1637
+ clearTimeout(timeoutId);
1638
+ signal.removeEventListener("abort", onExternalAbort);
1639
+ }
1640
+ }
1641
+ async function executeProbeViaClient(client, url, signal) {
1642
+ const { registerHttpEffect: registerHttpEffect2 } = await Promise.resolve().then(() => _interopRequireWildcard(require("./effectRunner-CFLC32IK.cjs")));
1643
+ return new Promise((resolve) => {
1644
+ const effect = client({
1645
+ method: "HEAD",
1646
+ url,
1647
+ init: { signal }
1648
+ });
1649
+ const cancel = registerHttpEffect2(effect, {}, (exit) => {
1650
+ if (exit._tag === "Success") {
1651
+ resolve({ ok: true });
1652
+ } else {
1653
+ const cause = exit.cause;
1654
+ if (_optionalChain([cause, 'optionalAccess', _27 => _27._tag]) === "Fail") {
1655
+ const err = cause.error;
1656
+ resolve({ ok: false, error: _nullishCoalesce(_nullishCoalesce(_optionalChain([err, 'optionalAccess', _28 => _28.message]), () => ( _optionalChain([err, 'optionalAccess', _29 => _29._tag]))), () => ( "Unknown error")) });
1657
+ } else {
1658
+ resolve({ ok: false, error: "cancelled" });
1659
+ }
1660
+ }
1661
+ });
1662
+ if (signal.aborted) {
1663
+ cancel();
1664
+ } else {
1665
+ signal.addEventListener("abort", () => {
1666
+ cancel();
1667
+ }, { once: true });
1668
+ }
1669
+ });
1670
+ }
1671
+
1672
+ // src/http/prewarm/connectionState.ts
1673
+ function makeConnectionStateMap(origins, keepAliveDurationMs) {
1674
+ const entries = /* @__PURE__ */ new Map();
1675
+ for (const origin of origins) {
1676
+ entries.set(origin, {
1677
+ origin,
1678
+ status: "idle",
1679
+ lastProbeAt: void 0,
1680
+ warmUntil: void 0
1681
+ });
1682
+ }
1683
+ function markWarm(origin, now2) {
1684
+ const entry = entries.get(origin);
1685
+ if (!entry) return;
1686
+ const timestamp = _nullishCoalesce(now2, () => ( Date.now()));
1687
+ entry.status = "warm";
1688
+ entry.lastProbeAt = timestamp;
1689
+ entry.warmUntil = timestamp + keepAliveDurationMs;
1690
+ }
1691
+ function markExpired(origin) {
1692
+ const entry = entries.get(origin);
1693
+ if (!entry) return;
1694
+ entry.status = "expired";
1695
+ }
1696
+ function markIdle(origin) {
1697
+ const entry = entries.get(origin);
1698
+ if (!entry) return;
1699
+ entry.status = "idle";
1700
+ entry.lastProbeAt = void 0;
1701
+ entry.warmUntil = void 0;
1702
+ }
1703
+ function markProbing(origin) {
1704
+ const entry = entries.get(origin);
1705
+ if (!entry) return;
1706
+ entry.status = "probing";
1707
+ }
1708
+ function isWarm(origin, now2) {
1709
+ const entry = entries.get(origin);
1710
+ if (!entry) return false;
1711
+ if (entry.status !== "warm") return false;
1712
+ if (entry.lastProbeAt === void 0 || entry.warmUntil === void 0) return false;
1713
+ const currentTime = _nullishCoalesce(now2, () => ( Date.now()));
1714
+ if (currentTime >= entry.warmUntil) {
1715
+ entry.status = "expired";
1716
+ return false;
1717
+ }
1718
+ return true;
1719
+ }
1720
+ function getState(origin) {
1721
+ const entry = entries.get(origin);
1722
+ if (!entry) return void 0;
1723
+ return {
1724
+ origin: entry.origin,
1725
+ status: entry.status,
1726
+ lastProbeAt: entry.lastProbeAt,
1727
+ warmUntil: entry.warmUntil
1728
+ };
1729
+ }
1730
+ function snapshot() {
1731
+ const result = [];
1732
+ for (const entry of entries.values()) {
1733
+ result.push({
1734
+ origin: entry.origin,
1735
+ status: entry.status,
1736
+ lastProbeAt: entry.lastProbeAt,
1737
+ warmUntil: entry.warmUntil
1738
+ });
1739
+ }
1740
+ return { origins: result };
1741
+ }
1742
+ return { markWarm, markExpired, markIdle, markProbing, isWarm, getState, snapshot };
1743
+ }
1744
+
1745
+ // src/http/prewarm/budgetSemaphore.ts
1746
+ function makeBudgetSemaphore(capacity) {
1747
+ if (capacity < 1 || !Number.isFinite(capacity)) {
1748
+ throw new Error(`makeBudgetSemaphore: capacity must be >= 1, got ${capacity}`);
1749
+ }
1750
+ capacity = Math.floor(capacity);
1751
+ let active = 0;
1752
+ const waiters = [];
1753
+ function release() {
1754
+ active--;
1755
+ if (waiters.length > 0) {
1756
+ const next = waiters.shift();
1757
+ active++;
1758
+ next({ release });
1759
+ }
1760
+ }
1761
+ function acquire() {
1762
+ if (active < capacity) {
1763
+ active++;
1764
+ return Promise.resolve({ release });
1765
+ }
1766
+ return new Promise((resolve) => {
1767
+ waiters.push(resolve);
1768
+ });
1769
+ }
1770
+ function tryAcquire() {
1771
+ if (active < capacity) {
1772
+ active++;
1773
+ return { release };
1774
+ }
1775
+ return void 0;
1776
+ }
1777
+ function available() {
1778
+ return capacity - active;
1779
+ }
1780
+ function queued() {
1781
+ return waiters.length;
1782
+ }
1783
+ return { acquire, tryAcquire, available, queued };
1784
+ }
1785
+
1786
+ // src/http/prewarm/prewarmManager.ts
1787
+ var DEFAULTS = {
1788
+ keepAliveDurationMs: 55e3,
1789
+ budget: 4,
1790
+ probeTimeoutMs: 5e3,
1791
+ autoRefresh: false,
1792
+ useClientPool: false
1793
+ };
1794
+ function makePrewarmManager(config) {
1795
+ validateFetchAvailable();
1796
+ const keepAliveDurationMs = _nullishCoalesce(config.keepAliveDurationMs, () => ( DEFAULTS.keepAliveDurationMs));
1797
+ const budget = _nullishCoalesce(config.budget, () => ( DEFAULTS.budget));
1798
+ const probeTimeoutMs = _nullishCoalesce(config.probeTimeoutMs, () => ( DEFAULTS.probeTimeoutMs));
1799
+ const autoRefresh = _nullishCoalesce(config.autoRefresh, () => ( DEFAULTS.autoRefresh));
1800
+ const useClientPool = _nullishCoalesce(config.useClientPool, () => ( DEFAULTS.useClientPool));
1801
+ const onEvent = config.onEvent;
1802
+ const client = config.client;
1803
+ const origins = config.origins.map((o) => validateOrigin(o));
1804
+ const platform = detectPlatform();
1805
+ const stateMap = makeConnectionStateMap(origins, keepAliveDurationMs);
1806
+ const semaphore = makeBudgetSemaphore(budget);
1807
+ const abortControllers = /* @__PURE__ */ new Map();
1808
+ const refreshTimers = /* @__PURE__ */ new Map();
1809
+ let disposed = false;
1810
+ function emit(event) {
1811
+ if (onEvent) {
1812
+ try {
1813
+ onEvent(event);
1814
+ } catch (e11) {
1815
+ }
1816
+ }
1817
+ }
1818
+ function scheduleAutoRefresh(origin) {
1819
+ if (!autoRefresh || disposed) return;
1820
+ clearRefreshTimer(origin);
1821
+ const delay = Math.floor(0.8 * keepAliveDurationMs);
1822
+ const timer = setTimeout(() => {
1823
+ refreshTimers.delete(origin);
1824
+ if (disposed) return;
1825
+ if (stateMap.isWarm(origin)) {
1826
+ stateMap.markExpired(origin);
1827
+ emit({
1828
+ type: "connection-expired",
1829
+ origin,
1830
+ timestamp: Date.now()
1831
+ });
1832
+ }
1833
+ warm(origin).catch(() => {
1834
+ });
1835
+ }, delay);
1836
+ if (typeof timer === "object" && "unref" in timer) {
1837
+ timer.unref();
1838
+ }
1839
+ refreshTimers.set(origin, timer);
1840
+ }
1841
+ function clearRefreshTimer(origin) {
1842
+ const timer = refreshTimers.get(origin);
1843
+ if (timer !== void 0) {
1844
+ clearTimeout(timer);
1845
+ refreshTimers.delete(origin);
1846
+ }
1847
+ }
1848
+ function clearAllRefreshTimers() {
1849
+ for (const [, timer] of refreshTimers) {
1850
+ clearTimeout(timer);
1851
+ }
1852
+ refreshTimers.clear();
1853
+ }
1854
+ async function warm(origin) {
1855
+ if (disposed) {
1856
+ return { origin, status: "cancelled", durationMs: 0 };
1857
+ }
1858
+ if (stateMap.isWarm(origin)) {
1859
+ return { origin, status: "already-warm", durationMs: 0 };
1860
+ }
1861
+ const { release } = await semaphore.acquire();
1862
+ if (disposed) {
1863
+ release();
1864
+ return { origin, status: "cancelled", durationMs: 0 };
1865
+ }
1866
+ const controller = new AbortController();
1867
+ abortControllers.set(origin, controller);
1868
+ stateMap.markProbing(origin);
1869
+ try {
1870
+ const probeOptions = {
1871
+ timeoutMs: probeTimeoutMs,
1872
+ signal: controller.signal,
1873
+ platform,
1874
+ client: useClientPool ? client : void 0
1875
+ };
1876
+ const outcome = await executeProbe(origin, probeOptions);
1877
+ if (controller.signal.aborted) {
1878
+ stateMap.markIdle(origin);
1879
+ emit({
1880
+ type: "connection-cancelled",
1881
+ origin,
1882
+ timestamp: Date.now()
1883
+ });
1884
+ return { origin, status: "cancelled", durationMs: outcome.durationMs };
1885
+ }
1886
+ if (outcome.ok) {
1887
+ stateMap.markWarm(origin);
1888
+ emit({
1889
+ type: "connection-warmed",
1890
+ origin,
1891
+ timestamp: Date.now(),
1892
+ durationMs: outcome.durationMs
1893
+ });
1894
+ scheduleAutoRefresh(origin);
1895
+ return { origin, status: "warmed", durationMs: outcome.durationMs };
1896
+ } else {
1897
+ stateMap.markIdle(origin);
1898
+ emit({
1899
+ type: "connection-failed",
1900
+ origin,
1901
+ timestamp: Date.now(),
1902
+ error: outcome.error
1903
+ });
1904
+ return { origin, status: "failed", durationMs: outcome.durationMs, error: outcome.error };
1905
+ }
1906
+ } catch (err) {
1907
+ stateMap.markIdle(origin);
1908
+ const error = err instanceof Error ? err.message : String(err);
1909
+ emit({
1910
+ type: "connection-failed",
1911
+ origin,
1912
+ timestamp: Date.now(),
1913
+ error
1914
+ });
1915
+ return { origin, status: "failed", durationMs: 0, error };
1916
+ } finally {
1917
+ abortControllers.delete(origin);
1918
+ release();
1919
+ }
1920
+ }
1921
+ async function warmAll() {
1922
+ const results = await Promise.all(origins.map((o) => warm(o)));
1923
+ return results;
1924
+ }
1925
+ function cancel(origin) {
1926
+ const controller = abortControllers.get(origin);
1927
+ if (controller) {
1928
+ controller.abort();
1929
+ }
1930
+ clearRefreshTimer(origin);
1931
+ }
1932
+ function cancelAll() {
1933
+ for (const [, controller] of abortControllers) {
1934
+ controller.abort();
1935
+ }
1936
+ clearAllRefreshTimers();
1937
+ }
1938
+ function isWarm(origin) {
1939
+ if (disposed) return false;
1940
+ return stateMap.isWarm(origin);
1941
+ }
1942
+ function status() {
1943
+ return stateMap.snapshot();
1944
+ }
1945
+ function dispose() {
1946
+ if (disposed) return;
1947
+ disposed = true;
1948
+ cancelAll();
1949
+ for (const origin of origins) {
1950
+ stateMap.markIdle(origin);
1951
+ }
1952
+ }
1953
+ return {
1954
+ warm,
1955
+ warmAll,
1956
+ isWarm,
1957
+ cancel,
1958
+ cancelAll,
1959
+ status,
1960
+ dispose
1961
+ };
1962
+ }
1963
+
1964
+ // src/http/lifecycle/lifecycleClient.ts
1965
+ function validateGlobals(config) {
1966
+ if (config.transport === void 0 && typeof fetch === "undefined") {
1967
+ throw new Error(
1968
+ "makeLifecycleClient: global `fetch` is not available. Ensure you are running in an environment with fetch support (Node.js 18+ or modern browser), or provide `transport` in the client config."
1969
+ );
1970
+ }
1971
+ if (typeof AbortController === "undefined") {
1972
+ throw new Error(
1973
+ "makeLifecycleClient: global `AbortController` is not available. Ensure you are running in an environment with AbortController support (Node.js 15+ or modern browser)."
1974
+ );
1975
+ }
1976
+ }
1977
+ function extractWireConfig(config) {
1978
+ const { dedup, batch, cache, priority, retry, prewarm, onEvent, ...wireConfig } = config;
1979
+ return wireConfig;
1980
+ }
1981
+ function makeLifecycleClient(config = {}) {
1982
+ _chunk5EC274J5cjs.validateLifecycleClientConfig.call(void 0, config);
1983
+ validateGlobals(config);
1984
+ const wireConfig = extractWireConfig(config);
1985
+ const wireClient = _chunk5EC274J5cjs.makeHttp.call(void 0, wireConfig);
1986
+ const activeControllers = /* @__PURE__ */ new Set();
1987
+ const tracker = new LifecycleStatsTracker({
1988
+ onEvent: config.onEvent,
1989
+ wireStats: wireClient.stats
1990
+ });
1991
+ const hasDedup = config.dedup !== void 0 && config.dedup !== false;
1992
+ const hasBatch = config.batch !== void 0 && config.batch !== false;
1993
+ const hasCache = config.cache !== void 0 && config.cache !== false;
1994
+ const hasPriority = config.priority !== void 0 && config.priority !== false;
1995
+ const hasRetry = config.retry !== void 0 && config.retry !== false;
1996
+ if (!hasDedup && !hasBatch && !hasCache && !hasPriority && !hasRetry) {
1997
+ let prewarmMgr2;
1998
+ const hasPrewarm2 = config.prewarm !== void 0 && config.prewarm !== false;
1999
+ if (hasPrewarm2) {
2000
+ const prewarmConfig = config.prewarm;
2001
+ const prewarmOrigins = _nullishCoalesce(prewarmConfig.origins, () => ( []));
2002
+ if (prewarmOrigins.length > 0) {
2003
+ prewarmMgr2 = makePrewarmManager({
2004
+ origins: prewarmOrigins,
2005
+ keepAliveDurationMs: prewarmConfig.keepAliveDurationMs,
2006
+ budget: prewarmConfig.budget,
2007
+ probeTimeoutMs: prewarmConfig.probeTimeoutMs,
2008
+ autoRefresh: prewarmConfig.autoRefresh,
2009
+ useClientPool: prewarmConfig.useClientPool,
2010
+ client: prewarmConfig.useClientPool ? wireClient : void 0,
2011
+ onEvent: prewarmConfig.onEvent
2012
+ });
2013
+ }
2014
+ }
2015
+ return buildLifecycleClient(wireClient, tracker, {
2016
+ cacheInvalidate: noopInvalidate,
2017
+ cacheClear: noopClear,
2018
+ cancelAll: () => cancelControllers(activeControllers, prewarmMgr2),
2019
+ shutdown: () => shutdownClient(activeControllers, prewarmMgr2, wireClient.shutdown),
2020
+ activeControllers,
2021
+ adaptiveLimiter: wireClient.adaptiveLimiter,
2022
+ prewarmManager: prewarmMgr2,
2023
+ afterResponse: hasPrewarm2 ? config.prewarm.afterResponse : void 0
2024
+ });
2025
+ }
2026
+ let priorityMiddleware;
2027
+ if (hasPriority) {
2028
+ const priorityConfig = config.priority;
2029
+ priorityMiddleware = withPriority({
2030
+ ...priorityConfig,
2031
+ onEvent: (event) => {
2032
+ tracker.setQueueDepth(_nullishCoalesce(_optionalChain([priorityMiddleware, 'optionalAccess', _30 => _30.queueDepth, 'call', _31 => _31()]), () => ( 0)));
2033
+ tracker.emit(event.type, { priority: event.priority });
2034
+ }
2035
+ });
2036
+ }
2037
+ let cacheLayer;
2038
+ if (hasCache) {
2039
+ const cacheConfig = config.cache;
2040
+ cacheLayer = withCache({
2041
+ ...cacheConfig,
2042
+ baseUrl: wireConfig.baseUrl,
2043
+ onLifecycleEvent: (event) => {
2044
+ if (event.type === "cache-hit") tracker.cacheHit();
2045
+ if (event.type === "cache-miss") tracker.cacheMiss();
2046
+ if (event.type === "cache-eviction") tracker.cacheEviction();
2047
+ if (event.type === "cache-hit" || event.type === "cache-miss") {
2048
+ tracker.emit(event.type, { cacheKey: event.cacheKey });
2049
+ }
2050
+ }
2051
+ });
2052
+ }
2053
+ let dedupMiddleware;
2054
+ if (hasDedup) {
2055
+ const dedupConfig = config.dedup;
2056
+ const baseUrl = _nullishCoalesce(wireConfig.baseUrl, () => ( ""));
2057
+ const effectiveDedupConfig = dedupConfig.dedupKey || !baseUrl ? dedupConfig : { ...dedupConfig, dedupKey: (req) => computeDedupKey(req, baseUrl) };
2058
+ dedupMiddleware = withDedup({
2059
+ ...effectiveDedupConfig,
2060
+ onEvent: (event) => {
2061
+ if (event.type === "dedup-hit") tracker.dedupHit();
2062
+ if (event.type === "dedup-active") {
2063
+ tracker.setDedupActive(_nullishCoalesce(event.active, () => ( 0)));
2064
+ return;
2065
+ }
2066
+ tracker.emit(event.type, { cacheKey: event.cacheKey });
2067
+ }
2068
+ });
2069
+ }
2070
+ let batchMiddleware;
2071
+ if (hasBatch) {
2072
+ const batchConfig = config.batch;
2073
+ batchMiddleware = withBatch(batchConfig, (event) => {
2074
+ if (event.type === "batch-dispatch") {
2075
+ tracker.batchDispatch();
2076
+ tracker.batchedRequests(_nullishCoalesce(event.batchSize, () => ( 0)));
2077
+ }
2078
+ tracker.emit(event.type, { batchKey: event.batchKey, batchSize: event.batchSize });
2079
+ });
2080
+ }
2081
+ let composedFn = wireClient;
2082
+ if (priorityMiddleware) {
2083
+ composedFn = priorityMiddleware(composedFn);
2084
+ }
2085
+ if (hasRetry) {
2086
+ const retryConfig = config.retry;
2087
+ composedFn = _chunk5EC274J5cjs.withRetry.call(void 0, {
2088
+ ...retryConfig,
2089
+ onRetry: (event) => {
2090
+ tracker.retry();
2091
+ tracker.emit("retry", {
2092
+ attempt: event.attempt,
2093
+ delayMs: event.delayMs,
2094
+ status: event.status,
2095
+ errorTag: _optionalChain([event, 'access', _32 => _32.error, 'optionalAccess', _33 => _33._tag])
2096
+ });
2097
+ _optionalChain([retryConfig, 'access', _34 => _34.onRetry, 'optionalCall', _35 => _35(event)]);
2098
+ }
2099
+ })(composedFn);
2100
+ }
2101
+ if (cacheLayer) {
2102
+ composedFn = cacheLayer.middleware(composedFn);
2103
+ }
2104
+ if (batchMiddleware) {
2105
+ composedFn = batchMiddleware(composedFn);
2106
+ }
2107
+ if (dedupMiddleware) {
2108
+ composedFn = dedupMiddleware(composedFn);
2109
+ }
2110
+ let prewarmMgr;
2111
+ const hasPrewarm = config.prewarm !== void 0 && config.prewarm !== false;
2112
+ if (hasPrewarm) {
2113
+ const prewarmConfig = config.prewarm;
2114
+ const prewarmOrigins = _nullishCoalesce(prewarmConfig.origins, () => ( []));
2115
+ if (prewarmOrigins.length > 0) {
2116
+ prewarmMgr = makePrewarmManager({
2117
+ origins: prewarmOrigins,
2118
+ keepAliveDurationMs: prewarmConfig.keepAliveDurationMs,
2119
+ budget: prewarmConfig.budget,
2120
+ probeTimeoutMs: prewarmConfig.probeTimeoutMs,
2121
+ autoRefresh: prewarmConfig.autoRefresh,
2122
+ useClientPool: prewarmConfig.useClientPool,
2123
+ client: prewarmConfig.useClientPool ? wireClient : void 0,
2124
+ onEvent: prewarmConfig.onEvent
2125
+ });
2126
+ }
2127
+ }
2128
+ return buildLifecycleClient(composedFn, tracker, {
2129
+ cacheInvalidate: _nullishCoalesce(_optionalChain([cacheLayer, 'optionalAccess', _36 => _36.invalidate]), () => ( noopInvalidate)),
2130
+ cacheClear: _nullishCoalesce(_optionalChain([cacheLayer, 'optionalAccess', _37 => _37.clear]), () => ( noopClear)),
2131
+ cancelAll: () => cancelControllers(activeControllers, prewarmMgr),
2132
+ shutdown: () => shutdownClient(activeControllers, prewarmMgr, wireClient.shutdown),
2133
+ activeControllers,
2134
+ adaptiveLimiter: wireClient.adaptiveLimiter,
2135
+ queueDepth: _optionalChain([priorityMiddleware, 'optionalAccess', _38 => _38.queueDepth]),
2136
+ prewarmManager: prewarmMgr,
2137
+ afterResponse: hasPrewarm ? config.prewarm.afterResponse : void 0
2138
+ });
2139
+ }
2140
+ function makeHttpClient(config = {}) {
2141
+ return makeLifecycleClient(config);
2142
+ }
2143
+ function noopInvalidate(_key) {
2144
+ }
2145
+ function noopClear() {
2146
+ }
2147
+ function buildLifecycleClient(fn, tracker, internals) {
2148
+ const client = (req) => trackRequest(fn, req, tracker, internals);
2149
+ const stats = () => {
2150
+ tracker.setQueueDepth(_nullishCoalesce(_optionalChain([internals, 'access', _39 => _39.queueDepth, 'optionalCall', _40 => _40()]), () => ( 0)));
2151
+ return tracker.snapshot();
2152
+ };
2153
+ const withMw = (mw) => {
2154
+ const wrappedFn = mw(withLifecycleMetadata(fn, internals));
2155
+ return buildLifecycleClient(wrappedFn, tracker, internals);
2156
+ };
2157
+ const lifecycleClient = Object.assign(client, {
2158
+ with: withMw,
2159
+ stats,
2160
+ cancelAll: internals.cancelAll,
2161
+ shutdown: internals.shutdown,
2162
+ adaptiveLimiter: internals.adaptiveLimiter,
2163
+ cache: {
2164
+ invalidate: internals.cacheInvalidate,
2165
+ clear: internals.cacheClear
2166
+ }
2167
+ });
2168
+ return lifecycleClient;
2169
+ }
2170
+ function withLifecycleMetadata(fn, internals) {
2171
+ if (!internals.adaptiveLimiter) return fn;
2172
+ return Object.assign(((req) => fn(req)), {
2173
+ adaptiveLimiter: internals.adaptiveLimiter
2174
+ });
2175
+ }
2176
+ function cancelControllers(activeControllers, prewarmMgr) {
2177
+ for (const controller of Array.from(activeControllers)) {
2178
+ try {
2179
+ controller.abort();
2180
+ } catch (e12) {
2181
+ }
2182
+ }
2183
+ if (prewarmMgr) {
2184
+ prewarmMgr.cancelAll();
2185
+ }
2186
+ return _chunkMVGUEJ5Zcjs.asyncSucceed.call(void 0, void 0);
2187
+ }
2188
+ function shutdownClient(activeControllers, prewarmMgr, wireShutdown) {
2189
+ cancelControllers(activeControllers, prewarmMgr);
2190
+ _optionalChain([wireShutdown, 'optionalCall', _41 => _41()]);
2191
+ return _chunkMVGUEJ5Zcjs.asyncSucceed.call(void 0, void 0);
2192
+ }
2193
+ function trackRequest(fn, req, tracker, internals) {
2194
+ return {
2195
+ _tag: "Async",
2196
+ register: (env, cb) => {
2197
+ const controller = new AbortController();
2198
+ const previousSignal = _optionalChain([req, 'access', _42 => _42.init, 'optionalAccess', _43 => _43.signal]);
2199
+ let done = false;
2200
+ let abortedByPreviousSignal = false;
2201
+ let cancelInner;
2202
+ const abortFromPrevious = () => {
2203
+ abortedByPreviousSignal = true;
2204
+ try {
2205
+ controller.abort(_optionalChain([previousSignal, 'optionalAccess', _44 => _44.reason]));
2206
+ } catch (e13) {
2207
+ controller.abort();
2208
+ }
2209
+ _optionalChain([cancelInner, 'optionalCall', _45 => _45()]);
2210
+ };
2211
+ if (_optionalChain([previousSignal, 'optionalAccess', _46 => _46.aborted])) {
2212
+ abortFromPrevious();
2213
+ } else {
2214
+ _optionalChain([previousSignal, 'optionalAccess', _47 => _47.addEventListener, 'call', _48 => _48("abort", abortFromPrevious, { once: true })]);
2215
+ }
2216
+ internals.activeControllers.add(controller);
2217
+ tracker.requestStarted();
2218
+ tracker.emit("request-start");
2219
+ const finish = (exit0) => {
2220
+ if (done) return;
2221
+ done = true;
2222
+ const exit = abortedByPreviousSignal && exit0._tag === "Failure" && _chunkMVGUEJ5Zcjs.Cause.isInterruptedOnly(exit0.cause) ? { _tag: "Failure", cause: _chunkMVGUEJ5Zcjs.Cause.fail({ _tag: "Abort" }) } : exit0;
2223
+ _optionalChain([previousSignal, 'optionalAccess', _49 => _49.removeEventListener, 'call', _50 => _50("abort", abortFromPrevious)]);
2224
+ internals.activeControllers.delete(controller);
2225
+ if (exit._tag === "Success") {
2226
+ tracker.requestCompleted();
2227
+ if (internals.afterResponse && internals.prewarmManager) {
2228
+ try {
2229
+ const originsToWarm = internals.afterResponse(exit.value, req);
2230
+ if (originsToWarm && originsToWarm.length > 0) {
2231
+ for (const origin of originsToWarm) {
2232
+ internals.prewarmManager.warm(origin).catch(() => {
2233
+ });
2234
+ }
2235
+ }
2236
+ } catch (e14) {
2237
+ }
2238
+ }
2239
+ } else {
2240
+ tracker.requestFailed();
2241
+ }
2242
+ tracker.emit("request-end");
2243
+ cb(exit);
2244
+ };
2245
+ const trackedReq = {
2246
+ ...req,
2247
+ init: {
2248
+ ..._nullishCoalesce(req.init, () => ( {})),
2249
+ signal: controller.signal
2250
+ }
2251
+ };
2252
+ try {
2253
+ cancelInner = _chunkL6VB5N7Qcjs.registerHttpEffect.call(void 0, fn(trackedReq), env, finish);
2254
+ } catch (error) {
2255
+ finish({
2256
+ _tag: "Failure",
2257
+ cause: _chunkMVGUEJ5Zcjs.Cause.fail({ _tag: "FetchError", message: String(error) })
2258
+ });
2259
+ }
2260
+ return () => {
2261
+ if (done) return;
2262
+ try {
2263
+ controller.abort();
2264
+ } catch (e15) {
2265
+ }
2266
+ if (cancelInner) {
2267
+ cancelInner();
2268
+ } else {
2269
+ finish({ _tag: "Failure", cause: _chunkMVGUEJ5Zcjs.Cause.interrupt() });
2270
+ }
2271
+ };
2272
+ }
2273
+ };
2274
+ }
2275
+
2276
+ // src/http/compression/types.ts
2277
+ var SUPPORTED_ENCODINGS = ["br", "gzip", "deflate"];
2278
+ function emptyStats() {
2279
+ return {
2280
+ decompressed: { gzip: 0, br: 0, deflate: 0 },
2281
+ compressedBytes: 0,
2282
+ decompressedBytes: 0,
2283
+ passthroughCount: 0,
2284
+ errorCount: 0,
2285
+ unsupportedEncodingCount: 0
2286
+ };
2287
+ }
2288
+ function emptyRequestCompressionStats() {
2289
+ return {
2290
+ compressedCount: 0,
2291
+ skippedCount: 0,
2292
+ errorCount: 0,
2293
+ originalBytes: 0,
2294
+ compressedBytes: 0
2295
+ };
2296
+ }
2297
+
2298
+ // src/http/compression/decompressor.ts
2299
+ var _zlib = require('zlib'); var _zlib2 = _interopRequireDefault(_zlib);
2300
+
2301
+ // src/http/compression/environment.ts
2302
+ function isNodeEnvironment() {
2303
+ return typeof process !== "undefined" && process.versions != null && process.versions.node != null;
2304
+ }
2305
+
2306
+ // src/http/compression/decompressor.node.ts
2307
+ function createNodeDecompressor(zlib2) {
2308
+ return {
2309
+ isPassthrough: false,
2310
+ decompress(data, encoding) {
2311
+ try {
2312
+ const input = Buffer.isBuffer(data) ? data : Buffer.from(data);
2313
+ let result;
2314
+ switch (encoding) {
2315
+ case "gzip":
2316
+ result = zlib2.gunzipSync(input);
2317
+ break;
2318
+ case "br":
2319
+ result = zlib2.brotliDecompressSync(input);
2320
+ break;
2321
+ case "deflate":
2322
+ result = zlib2.inflateSync(input);
2323
+ break;
2324
+ default:
2325
+ return { ok: false, error: `Unsupported encoding: ${encoding}` };
2326
+ }
2327
+ return { ok: true, data: result };
2328
+ } catch (err) {
2329
+ const message = err instanceof Error ? err.message : String(err);
2330
+ return { ok: false, error: message };
2331
+ }
2332
+ }
2333
+ };
2334
+ }
2335
+
2336
+ // src/http/compression/decompressor.noop.ts
2337
+ function createNoopDecompressor() {
2338
+ return {
2339
+ isPassthrough: true,
2340
+ decompress(data, _encoding) {
2341
+ const buf = Buffer.isBuffer(data) ? data : Buffer.from(data);
2342
+ return { ok: true, data: buf };
2343
+ }
2344
+ };
2345
+ }
2346
+
2347
+ // src/http/compression/decompressor.ts
2348
+ function createDecompressor() {
2349
+ if (isNodeEnvironment()) {
2350
+ return createNodeDecompressor(_zlib2.default);
2351
+ }
2352
+ return createNoopDecompressor();
2353
+ }
2354
+
2355
+ // src/http/compression/middleware.ts
2356
+ function injectAcceptEncoding(req, encodings) {
2357
+ const headers = _nullishCoalesce(req.headers, () => ( {}));
2358
+ const hasAcceptEncoding = Object.keys(headers).some(
2359
+ (k) => k.toLowerCase() === "accept-encoding"
2360
+ );
2361
+ if (hasAcceptEncoding) return req;
2362
+ return {
2363
+ ...req,
2364
+ headers: {
2365
+ ...headers,
2366
+ "Accept-Encoding": encodings.join(", ")
2367
+ }
2368
+ };
2369
+ }
2370
+ function isSupportedEncoding(enc) {
2371
+ return SUPPORTED_ENCODINGS.includes(enc);
2372
+ }
2373
+ function processResponse(res, decompressor, enabledEncodings, stats) {
2374
+ const contentEncodingKey = Object.keys(res.headers).find(
2375
+ (k) => k.toLowerCase() === "content-encoding"
2376
+ );
2377
+ const contentEncodingValue = contentEncodingKey ? _optionalChain([res, 'access', _51 => _51.headers, 'access', _52 => _52[contentEncodingKey], 'optionalAccess', _53 => _53.trim, 'call', _54 => _54()]) : void 0;
2378
+ if (!contentEncodingValue || contentEncodingValue.toLowerCase() === "identity") {
2379
+ stats.passthroughCount++;
2380
+ return res;
2381
+ }
2382
+ const encodings = contentEncodingValue.split(",").map((e) => e.trim().toLowerCase());
2383
+ const reversedEncodings = [...encodings].reverse();
2384
+ let currentData = Buffer.from(res.bodyText, "latin1");
2385
+ let decompressedCount = 0;
2386
+ for (let i = 0; i < reversedEncodings.length; i++) {
2387
+ const enc = reversedEncodings[i];
2388
+ if (!isSupportedEncoding(enc)) {
2389
+ stats.unsupportedEncodingCount++;
2390
+ if (decompressedCount === 0) {
2391
+ stats.passthroughCount++;
2392
+ return res;
2393
+ }
2394
+ const remainingEncodings = reversedEncodings.slice(i).reverse();
2395
+ const newHeaders2 = { ...res.headers };
2396
+ if (contentEncodingKey) {
2397
+ newHeaders2[contentEncodingKey] = remainingEncodings.join(", ");
2398
+ }
2399
+ newHeaders2["Content-Length"] = String(currentData.byteLength);
2400
+ return {
2401
+ ...res,
2402
+ headers: newHeaders2,
2403
+ bodyText: currentData.toString("latin1")
2404
+ };
2405
+ }
2406
+ if (!enabledEncodings.includes(enc)) {
2407
+ stats.passthroughCount++;
2408
+ if (decompressedCount === 0) {
2409
+ return res;
2410
+ }
2411
+ const remainingEncodings = reversedEncodings.slice(i).reverse();
2412
+ const newHeaders2 = { ...res.headers };
2413
+ if (contentEncodingKey) {
2414
+ newHeaders2[contentEncodingKey] = remainingEncodings.join(", ");
2415
+ }
2416
+ newHeaders2["Content-Length"] = String(currentData.byteLength);
2417
+ return {
2418
+ ...res,
2419
+ headers: newHeaders2,
2420
+ bodyText: currentData.toString("latin1")
2421
+ };
2422
+ }
2423
+ const result = decompressor.decompress(currentData, enc);
2424
+ if (!result.ok) {
2425
+ stats.errorCount++;
2426
+ return res;
2427
+ }
2428
+ stats.compressedBytes += currentData.byteLength;
2429
+ stats.decompressedBytes += result.data.byteLength;
2430
+ stats.decompressed[enc]++;
2431
+ decompressedCount++;
2432
+ currentData = result.data;
2433
+ }
2434
+ const newHeaders = { ...res.headers };
2435
+ if (contentEncodingKey) {
2436
+ delete newHeaders[contentEncodingKey];
2437
+ }
2438
+ const lowerKey = Object.keys(newHeaders).find(
2439
+ (k) => k.toLowerCase() === "content-encoding"
2440
+ );
2441
+ if (lowerKey) {
2442
+ delete newHeaders[lowerKey];
2443
+ }
2444
+ newHeaders["Content-Length"] = String(currentData.byteLength);
2445
+ return {
2446
+ ...res,
2447
+ headers: newHeaders,
2448
+ bodyText: currentData.toString("utf-8")
2449
+ };
2450
+ }
2451
+ function makeCompressionMiddleware(config) {
2452
+ const enabledEncodings = _nullishCoalesce(_optionalChain([config, 'optionalAccess', _55 => _55.encodings]), () => ( [...SUPPORTED_ENCODINGS]));
2453
+ const decompressor = createDecompressor();
2454
+ const mutableStats = emptyStats();
2455
+ const middleware = (next) => {
2456
+ return (req) => {
2457
+ const modifiedReq = injectAcceptEncoding(req, enabledEncodings);
2458
+ return _chunkMVGUEJ5Zcjs.asyncFold.call(void 0,
2459
+ next(modifiedReq),
2460
+ // Pass HttpErrors through unchanged
2461
+ (error) => _chunkMVGUEJ5Zcjs.asyncFail.call(void 0, error),
2462
+ // Process successful responses
2463
+ (res) => {
2464
+ if (decompressor.isPassthrough) {
2465
+ mutableStats.passthroughCount++;
2466
+ return _chunkMVGUEJ5Zcjs.asyncSucceed.call(void 0, res);
2467
+ }
2468
+ const processed = processResponse(
2469
+ res,
2470
+ decompressor,
2471
+ enabledEncodings,
2472
+ mutableStats
2473
+ );
2474
+ return _chunkMVGUEJ5Zcjs.asyncSucceed.call(void 0, processed);
2475
+ }
2476
+ );
2477
+ };
2478
+ };
2479
+ const stats = () => Object.freeze({
2480
+ decompressed: Object.freeze({ ...mutableStats.decompressed }),
2481
+ compressedBytes: mutableStats.compressedBytes,
2482
+ decompressedBytes: mutableStats.decompressedBytes,
2483
+ passthroughCount: mutableStats.passthroughCount,
2484
+ errorCount: mutableStats.errorCount,
2485
+ unsupportedEncodingCount: mutableStats.unsupportedEncodingCount
2486
+ });
2487
+ return { middleware, stats };
2488
+ }
2489
+ var makeResponseCompressionMiddleware = makeCompressionMiddleware;
2490
+ var DEFAULT_REQUEST_COMPRESS_METHODS = ["POST", "PUT", "PATCH"];
2491
+ function makeRequestCompressionMiddleware(config) {
2492
+ const encoding = _nullishCoalesce(_optionalChain([config, 'optionalAccess', _56 => _56.encoding]), () => ( "gzip"));
2493
+ const minBytes = Math.max(0, Math.floor(_nullishCoalesce(_optionalChain([config, 'optionalAccess', _57 => _57.minBytes]), () => ( 1024))));
2494
+ const methods = new Set((_nullishCoalesce(_optionalChain([config, 'optionalAccess', _58 => _58.methods]), () => ( DEFAULT_REQUEST_COMPRESS_METHODS))).map((m) => m.toUpperCase()));
2495
+ const mutableStats = emptyRequestCompressionStats();
2496
+ const middleware = (next) => {
2497
+ return (req) => {
2498
+ const compressed = compressRequest(req, encoding, minBytes, methods, mutableStats);
2499
+ return next(compressed);
2500
+ };
2501
+ };
2502
+ const stats = () => Object.freeze({
2503
+ compressedCount: mutableStats.compressedCount,
2504
+ skippedCount: mutableStats.skippedCount,
2505
+ errorCount: mutableStats.errorCount,
2506
+ originalBytes: mutableStats.originalBytes,
2507
+ compressedBytes: mutableStats.compressedBytes
2508
+ });
2509
+ return { middleware, stats };
2510
+ }
2511
+ function compressRequest(req, encoding, minBytes, methods, stats) {
2512
+ if (!methods.has(req.method.toUpperCase())) {
2513
+ stats.skippedCount++;
2514
+ return req;
2515
+ }
2516
+ if (req.body === void 0 || hasHeader(req.headers, "content-encoding")) {
2517
+ stats.skippedCount++;
2518
+ return req;
2519
+ }
2520
+ const originalBytes = httpBodyByteLength(req.body);
2521
+ if (originalBytes < minBytes) {
2522
+ stats.skippedCount++;
2523
+ return req;
2524
+ }
2525
+ try {
2526
+ const compressed = compressBuffer(httpBodyToBuffer(req.body), encoding);
2527
+ stats.compressedCount++;
2528
+ stats.originalBytes += originalBytes;
2529
+ stats.compressedBytes += compressed.byteLength;
2530
+ return {
2531
+ ...req,
2532
+ body: compressed,
2533
+ headers: setHeaders(req.headers, {
2534
+ "Content-Encoding": encoding,
2535
+ "Content-Length": String(compressed.byteLength)
2536
+ })
2537
+ };
2538
+ } catch (e16) {
2539
+ stats.errorCount++;
2540
+ return req;
2541
+ }
2542
+ }
2543
+ function compressBuffer(input, encoding) {
2544
+ const zlib2 = _chunkOBGZSXTJcjs.__require.call(void 0, "zlib");
2545
+ switch (encoding) {
2546
+ case "gzip":
2547
+ return zlib2.gzipSync(input);
2548
+ case "br":
2549
+ return zlib2.brotliCompressSync(input);
2550
+ case "deflate":
2551
+ return zlib2.deflateSync(input);
2552
+ }
2553
+ }
2554
+ function hasHeader(headers, name) {
2555
+ if (!headers) return false;
2556
+ const lower = name.toLowerCase();
2557
+ return Object.keys(headers).some((key) => key.toLowerCase() === lower);
2558
+ }
2559
+ function setHeaders(headers, values) {
2560
+ const out = { ..._nullishCoalesce(headers, () => ( {})) };
2561
+ for (const [key, value] of Object.entries(values)) {
2562
+ const existing = Object.keys(out).find((h) => h.toLowerCase() === key.toLowerCase());
2563
+ if (existing) out[existing] = value;
2564
+ else out[key] = value;
2565
+ }
2566
+ return out;
2567
+ }
2568
+
2569
+ // src/http/requestBuilder.ts
2570
+ var isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
2571
+ function splitHttpRequestInit(init) {
2572
+ const {
2573
+ headers,
2574
+ timeoutMs,
2575
+ poolKey,
2576
+ policy,
2577
+ lane,
2578
+ dedupKey,
2579
+ priority,
2580
+ retry,
2581
+ schema: _schema,
2582
+ schemaName: _schemaName,
2583
+ bodySchema: _bodySchema,
2584
+ bodySchemaName: _bodySchemaName,
2585
+ ...rest
2586
+ } = _nullishCoalesce(init, () => ( {}));
2587
+ const policyFields = {
2588
+ ...isRecord(policy) ? policy : {},
2589
+ ...typeof lane === "string" ? { lane } : {},
2590
+ ...typeof dedupKey === "string" ? { dedupKey } : {},
2591
+ ...typeof priority === "number" ? { priority } : {},
2592
+ ...retry !== void 0 ? { retry } : {}
2593
+ };
2594
+ const policyRef = typeof policy === "string" ? Object.keys(policyFields).length > 0 ? { preset: policy, ...policyFields } : policy : Object.keys(policyFields).length > 0 ? policyFields : void 0;
2595
+ return {
2596
+ headers: _chunk5EC274J5cjs.normalizeHeadersInit.call(void 0, headers),
2597
+ timeoutMs: typeof timeoutMs === "number" ? timeoutMs : void 0,
2598
+ poolKey: typeof poolKey === "string" ? poolKey : void 0,
2599
+ policy: policyRef,
2600
+ init: rest
2601
+ };
2602
+ }
2603
+ function buildHttpRequest(method, url, init, body) {
2604
+ const split = splitHttpRequestInit(init);
2605
+ const req = {
2606
+ method,
2607
+ url,
2608
+ ...body && body.length > 0 ? { body } : {},
2609
+ ...split.timeoutMs !== void 0 ? { timeoutMs: split.timeoutMs } : {},
2610
+ ...split.poolKey !== void 0 ? { poolKey: split.poolKey } : {},
2611
+ ...split.policy !== void 0 ? { policy: split.policy } : {},
2612
+ init: split.init
2613
+ };
2614
+ return split.headers ? _chunk5EC274J5cjs.mergeHeaders.call(void 0, split.headers)(req) : req;
2615
+ }
2616
+
2617
+ // src/http/defaultClient.ts
2618
+ var MINIMAL_PRESET_CONFIG = {
2619
+ timeoutMs: 3e4
2620
+ };
2621
+ var BALANCED_PRESET_CONFIG = {
2622
+ ...MINIMAL_PRESET_CONFIG,
2623
+ dedup: {},
2624
+ priority: {
2625
+ concurrency: 32,
2626
+ queueTimeoutMs: 3e4
2627
+ },
2628
+ retry: {
2629
+ maxRetries: 2,
2630
+ baseDelayMs: 100,
2631
+ maxDelayMs: 1e3,
2632
+ maxElapsedMs: 5e3,
2633
+ respectRetryAfter: true
2634
+ },
2635
+ adaptiveLimiter: _chunk5EC274J5cjs.makeAdaptiveLimiterConfig.call(void 0, "balanced")
2636
+ };
2637
+ var DEFAULT_CACHEABLE_METHODS = /* @__PURE__ */ new Set(["GET", "HEAD", "OPTIONS"]);
2638
+ var DEFAULT_PRESET_CONFIG = {
2639
+ ...BALANCED_PRESET_CONFIG,
2640
+ cache: {
2641
+ ttlSeconds: 60,
2642
+ maxEntries: 1024,
2643
+ staleWhileRevalidate: true,
2644
+ cachePolicy: (req, res) => ({ cacheable: isDefaultCacheableResponse(req, res) })
2645
+ },
2646
+ priority: {
2647
+ concurrency: 64,
2648
+ queueTimeoutMs: 3e4
2649
+ },
2650
+ retry: {
2651
+ maxRetries: 3,
2652
+ baseDelayMs: 100,
2653
+ maxDelayMs: 2e3,
2654
+ maxElapsedMs: 1e4,
2655
+ respectRetryAfter: true
2656
+ },
2657
+ adaptiveLimiter: _chunk5EC274J5cjs.makeAdaptiveLimiterConfig.call(void 0, "aggressive")
2658
+ };
2659
+ var PRESET_CONFIGS = {
2660
+ minimal: MINIMAL_PRESET_CONFIG,
2661
+ balanced: BALANCED_PRESET_CONFIG,
2662
+ default: DEFAULT_PRESET_CONFIG,
2663
+ production: DEFAULT_PRESET_CONFIG
2664
+ };
2665
+ function isDefaultCacheableResponse(req, res) {
2666
+ if (!DEFAULT_CACHEABLE_METHODS.has(req.method)) return false;
2667
+ if (res.status < 200 || res.status >= 400) return false;
2668
+ const cacheControl = _optionalChain([headerValue, 'call', _59 => _59(res.headers, "cache-control"), 'optionalAccess', _60 => _60.toLowerCase, 'call', _61 => _61()]);
2669
+ if (cacheControl) {
2670
+ const directives = cacheControl.split(",").map((part) => part.trim());
2671
+ if (directives.includes("no-store") || directives.includes("no-cache")) return false;
2672
+ }
2673
+ if (_optionalChain([headerValue, 'call', _62 => _62(res.headers, "pragma"), 'optionalAccess', _63 => _63.toLowerCase, 'call', _64 => _64()]) === "no-cache") return false;
2674
+ if (headerValue(res.headers, "set-cookie") !== void 0) return false;
2675
+ return true;
2676
+ }
2677
+ function headerValue(headers, name) {
2678
+ return _nullishCoalesce(_nullishCoalesce(headers[name], () => ( headers[name.toLowerCase()])), () => ( headers[name.toUpperCase()]));
2679
+ }
2680
+ var defaultHttpClientPreset = "default";
2681
+ function makeDefaultHttpClient(config = {}) {
2682
+ _chunk5EC274J5cjs.validateDefaultHttpClientConfig.call(void 0, config);
2683
+ const {
2684
+ preset = defaultHttpClientPreset,
2685
+ compression,
2686
+ middleware = [],
2687
+ policyPresets,
2688
+ ...lifecycleOverrides
2689
+ } = config;
2690
+ const lifecycleConfig = mergeLifecycleConfig(PRESET_CONFIGS[preset], lifecycleOverrides);
2691
+ let wire = makeLifecycleClient(lifecycleConfig);
2692
+ const compressionResult = compression === false || compression === void 0 && preset === "minimal" ? void 0 : makeCompressionMiddleware(compression === void 0 ? void 0 : compression);
2693
+ if (compressionResult) {
2694
+ wire = wire.with(compressionResult.middleware);
2695
+ }
2696
+ for (const mw of middleware) {
2697
+ wire = wire.with(mw);
2698
+ }
2699
+ if (policyPresets && Object.keys(policyPresets).length > 0) {
2700
+ wire = wire.with(_chunk3LOYJFRRcjs.withHttpPolicyPresets.call(void 0, policyPresets));
2701
+ }
2702
+ const features = featureSnapshot(lifecycleConfig, compressionResult !== void 0, middleware.length);
2703
+ return buildDefaultClient(wire, {
2704
+ preset,
2705
+ features,
2706
+ compressionStats: _optionalChain([compressionResult, 'optionalAccess', _65 => _65.stats])
2707
+ });
2708
+ }
2709
+ function buildDefaultClient(wire, meta) {
2710
+ const withPromise = (eff) => _chunkMVGUEJ5Zcjs.withAsyncPromise.call(void 0, (e, env) => _chunkGLE2WY7Zcjs.toPromise.call(void 0, e, env))(eff);
2711
+ const requestRaw = (req) => wire(req);
2712
+ const request = (req) => withPromise(requestRaw(req));
2713
+ const get = (url, init) => request(buildHttpRequest("GET", url, init));
2714
+ const post = (url, body, init) => request(buildHttpRequest("POST", url, init, body));
2715
+ const getText = (url, init) => {
2716
+ const req = buildHttpRequest("GET", url, init);
2717
+ return withPromise(
2718
+ _chunkMVGUEJ5Zcjs.mapTryAsync.call(void 0, requestRaw(req), (w) => toResponse(w, w.bodyText))
2719
+ );
2720
+ };
2721
+ const getJson = ((url, init) => {
2722
+ const req = _chunk5EC274J5cjs.setHeaderIfMissing.call(void 0, "accept", "application/json")(
2723
+ buildHttpRequest("GET", url, init)
2724
+ );
2725
+ return withPromise(
2726
+ _chunkMVGUEJ5Zcjs.asyncFlatMap.call(void 0, requestRaw(req), (w) => decodeResponse(w, _optionalChain([init, 'optionalAccess', _66 => _66.schema]), _optionalChain([init, 'optionalAccess', _67 => _67.schemaName])))
2727
+ );
2728
+ });
2729
+ const postJson = ((url, bodyObj, init) => {
2730
+ return withPromise(
2731
+ _chunkMVGUEJ5Zcjs.asyncFlatMap.call(void 0,
2732
+ encodeJsonBodyEffect(bodyObj, _optionalChain([init, 'optionalAccess', _68 => _68.bodySchema]), { schemaName: _optionalChain([init, 'optionalAccess', _69 => _69.bodySchemaName]) }),
2733
+ (bodyText) => {
2734
+ const req = _chunk5EC274J5cjs.setHeaderIfMissing.call(void 0, "content-type", "application/json")(
2735
+ _chunk5EC274J5cjs.setHeaderIfMissing.call(void 0, "accept", "application/json")(
2736
+ buildHttpRequest("POST", url, init, bodyText)
2737
+ )
2738
+ );
2739
+ return _chunkMVGUEJ5Zcjs.asyncFlatMap.call(void 0, requestRaw(req), (w) => decodeResponse(w, _optionalChain([init, 'optionalAccess', _70 => _70.schema]), _optionalChain([init, 'optionalAccess', _71 => _71.schemaName])));
2740
+ }
2741
+ )
2742
+ );
2743
+ });
2744
+ return {
2745
+ request,
2746
+ get,
2747
+ post,
2748
+ getText,
2749
+ getJson,
2750
+ postJson,
2751
+ with: (mw) => buildDefaultClient(wire.with(mw), {
2752
+ ...meta,
2753
+ features: {
2754
+ ...meta.features,
2755
+ middleware: meta.features.middleware + 1
2756
+ }
2757
+ }),
2758
+ wire,
2759
+ stats: () => wire.stats(),
2760
+ cache: wire.cache,
2761
+ cancelAll: wire.cancelAll,
2762
+ shutdown: wire.shutdown,
2763
+ preset: meta.preset,
2764
+ features: meta.features,
2765
+ ...meta.compressionStats ? {
2766
+ compression: {
2767
+ stats: meta.compressionStats
2768
+ }
2769
+ } : {}
2770
+ };
2771
+ }
2772
+ function toResponse(wire, body) {
2773
+ return {
2774
+ status: wire.status,
2775
+ statusText: wire.statusText,
2776
+ headers: wire.headers,
2777
+ body
2778
+ };
2779
+ }
2780
+ function decodeResponse(wire, schema, schemaName) {
2781
+ return _chunkMVGUEJ5Zcjs.asyncFlatMap.call(void 0,
2782
+ decodeJsonBodyEffect(wire.bodyText, schema, { schemaName }),
2783
+ (body) => _chunkMVGUEJ5Zcjs.asyncSucceed.call(void 0, toResponse(wire, body))
2784
+ );
2785
+ }
2786
+ function mergeLifecycleConfig(defaults, overrides) {
2787
+ return {
2788
+ ...defaults,
2789
+ ...overrides,
2790
+ headers: mergeRecord(defaults.headers, overrides.headers),
2791
+ dedup: mergeLayer(defaults.dedup, overrides.dedup),
2792
+ batch: mergeLayer(defaults.batch, overrides.batch),
2793
+ cache: mergeLayer(defaults.cache, overrides.cache),
2794
+ priority: mergeLayer(defaults.priority, overrides.priority),
2795
+ retry: mergeLayer(defaults.retry, overrides.retry),
2796
+ prewarm: mergeLayer(defaults.prewarm, overrides.prewarm),
2797
+ adaptiveLimiter: mergeAdaptiveLimiterLayer(defaults.adaptiveLimiter, overrides.adaptiveLimiter),
2798
+ pool: mergeLayer(defaults.pool, overrides.pool)
2799
+ };
2800
+ }
2801
+ function mergeRecord(defaults, overrides) {
2802
+ if (!defaults) return overrides;
2803
+ if (!overrides) return defaults;
2804
+ return { ...defaults, ...overrides };
2805
+ }
2806
+ function mergeLayer(defaults, overrides) {
2807
+ if (overrides === void 0) return defaults;
2808
+ if (overrides === false) return false;
2809
+ if (defaults === void 0 || defaults === false) return overrides;
2810
+ return { ...defaults, ...overrides };
2811
+ }
2812
+ function mergeAdaptiveLimiterLayer(defaults, overrides) {
2813
+ if (overrides === void 0) return defaults;
2814
+ if (overrides === false) return false;
2815
+ if (defaults === void 0 || defaults === false) return overrides;
2816
+ if (overrides.preset !== void 0) return overrides;
2817
+ return { ...defaults, ...overrides };
2818
+ }
2819
+ function featureSnapshot(config, compression, middleware) {
2820
+ return Object.freeze({
2821
+ dedup: isEnabled(config.dedup),
2822
+ batch: isEnabled(config.batch),
2823
+ cache: isEnabled(config.cache),
2824
+ priority: isEnabled(config.priority),
2825
+ retry: isEnabled(config.retry),
2826
+ prewarm: isEnabled(config.prewarm),
2827
+ adaptiveLimiter: isEnabled(config.adaptiveLimiter),
2828
+ compression,
2829
+ middleware
2830
+ });
2831
+ }
2832
+ function isEnabled(value) {
2833
+ return value !== void 0 && value !== false;
2834
+ }
2835
+
2836
+
2837
+
2838
+
2839
+
2840
+
2841
+
2842
+
2843
+
2844
+
2845
+
2846
+
2847
+
2848
+
2849
+
2850
+
2851
+
2852
+
2853
+
2854
+
2855
+
2856
+
2857
+
2858
+
2859
+
2860
+
2861
+
2862
+
2863
+
2864
+
2865
+
2866
+
2867
+
2868
+
2869
+
2870
+
2871
+ exports.decodeJsonBody = decodeJsonBody; exports.encodeJsonBodyEffect = encodeJsonBodyEffect; exports.decodeJsonBodyEffect = decodeJsonBodyEffect; exports.validatedJson = validatedJson; exports.validatedJsonResponse = validatedJsonResponse; exports.buildHttpRequest = buildHttpRequest; exports.SEPARATOR = SEPARATOR; exports.DEFAULT_CACHE_RELEVANT_HEADERS = DEFAULT_CACHE_RELEVANT_HEADERS; exports.computeCacheKey = computeCacheKey; exports.parseCacheKey = parseCacheKey; exports.withDedup = withDedup; exports.withBatch = withBatch; exports.now = now; exports.LRUCache = LRUCache; exports.withCache = withCache; exports.clampPriority = clampPriority; exports.PriorityQueue = PriorityQueue; exports.withPriority = withPriority; exports.LifecycleStatsTracker = LifecycleStatsTracker; exports.validateOrigin = validateOrigin; exports.detectPlatform = detectPlatform; exports.validateFetchAvailable = validateFetchAvailable; exports.executeProbe = executeProbe; exports.makeConnectionStateMap = makeConnectionStateMap; exports.makeBudgetSemaphore = makeBudgetSemaphore; exports.makePrewarmManager = makePrewarmManager; exports.makeLifecycleClient = makeLifecycleClient; exports.makeHttpClient = makeHttpClient; exports.SUPPORTED_ENCODINGS = SUPPORTED_ENCODINGS; exports.makeCompressionMiddleware = makeCompressionMiddleware; exports.makeResponseCompressionMiddleware = makeResponseCompressionMiddleware; exports.makeRequestCompressionMiddleware = makeRequestCompressionMiddleware; exports.defaultHttpClientPreset = defaultHttpClientPreset; exports.makeDefaultHttpClient = makeDefaultHttpClient;