@elaraai/e3-rack 0.0.0-bootstrap.0 → 1.0.94

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 (306) hide show
  1. package/README.md +407 -2
  2. package/dist/src/client/client.spec.d.ts +6 -0
  3. package/dist/src/client/client.spec.d.ts.map +1 -0
  4. package/dist/src/client/client.spec.js +150 -0
  5. package/dist/src/client/client.spec.js.map +1 -0
  6. package/dist/src/client/connect.d.ts +52 -0
  7. package/dist/src/client/connect.d.ts.map +1 -0
  8. package/dist/src/client/connect.js +112 -0
  9. package/dist/src/client/connect.js.map +1 -0
  10. package/dist/src/client/hub-client.d.ts +57 -0
  11. package/dist/src/client/hub-client.d.ts.map +1 -0
  12. package/dist/src/client/hub-client.js +87 -0
  13. package/dist/src/client/hub-client.js.map +1 -0
  14. package/dist/src/client/local-http.d.ts +78 -0
  15. package/dist/src/client/local-http.d.ts.map +1 -0
  16. package/dist/src/client/local-http.js +149 -0
  17. package/dist/src/client/local-http.js.map +1 -0
  18. package/dist/src/client/session-attempts.d.ts +20 -0
  19. package/dist/src/client/session-attempts.d.ts.map +1 -0
  20. package/dist/src/client/session-attempts.js +88 -0
  21. package/dist/src/client/session-attempts.js.map +1 -0
  22. package/dist/src/client/session-data-server.d.ts +37 -0
  23. package/dist/src/client/session-data-server.d.ts.map +1 -0
  24. package/dist/src/client/session-data-server.js +280 -0
  25. package/dist/src/client/session-data-server.js.map +1 -0
  26. package/dist/src/client/session-data-server.spec.d.ts +6 -0
  27. package/dist/src/client/session-data-server.spec.d.ts.map +1 -0
  28. package/dist/src/client/session-data-server.spec.js +192 -0
  29. package/dist/src/client/session-data-server.spec.js.map +1 -0
  30. package/dist/src/client/session.d.ts +119 -0
  31. package/dist/src/client/session.d.ts.map +1 -0
  32. package/dist/src/client/session.js +290 -0
  33. package/dist/src/client/session.js.map +1 -0
  34. package/dist/src/hub/config.d.ts +74 -0
  35. package/dist/src/hub/config.d.ts.map +1 -0
  36. package/dist/src/hub/config.js +159 -0
  37. package/dist/src/hub/config.js.map +1 -0
  38. package/dist/src/hub/fair-lease-store.d.ts +36 -0
  39. package/dist/src/hub/fair-lease-store.d.ts.map +1 -0
  40. package/dist/src/hub/fair-lease-store.js +73 -0
  41. package/dist/src/hub/fair-lease-store.js.map +1 -0
  42. package/dist/src/hub/hub.d.ts +91 -0
  43. package/dist/src/hub/hub.d.ts.map +1 -0
  44. package/dist/src/hub/hub.js +641 -0
  45. package/dist/src/hub/hub.js.map +1 -0
  46. package/dist/src/hub/hub.spec.d.ts +6 -0
  47. package/dist/src/hub/hub.spec.d.ts.map +1 -0
  48. package/dist/src/hub/hub.spec.js +363 -0
  49. package/dist/src/hub/hub.spec.js.map +1 -0
  50. package/dist/src/hub/infrastructure.spec.d.ts +6 -0
  51. package/dist/src/hub/infrastructure.spec.d.ts.map +1 -0
  52. package/dist/src/hub/infrastructure.spec.js +211 -0
  53. package/dist/src/hub/infrastructure.spec.js.map +1 -0
  54. package/dist/src/hub/lock.d.ts +62 -0
  55. package/dist/src/hub/lock.d.ts.map +1 -0
  56. package/dist/src/hub/lock.js +165 -0
  57. package/dist/src/hub/lock.js.map +1 -0
  58. package/dist/src/hub/main.d.ts +16 -0
  59. package/dist/src/hub/main.d.ts.map +1 -0
  60. package/dist/src/hub/main.js +56 -0
  61. package/dist/src/hub/main.js.map +1 -0
  62. package/dist/src/hub/session-bridge.d.ts +116 -0
  63. package/dist/src/hub/session-bridge.d.ts.map +1 -0
  64. package/dist/src/hub/session-bridge.js +336 -0
  65. package/dist/src/hub/session-bridge.js.map +1 -0
  66. package/dist/src/identity/file-identity-store.d.ts +18 -0
  67. package/dist/src/identity/file-identity-store.d.ts.map +1 -0
  68. package/dist/src/identity/file-identity-store.js +34 -0
  69. package/dist/src/identity/file-identity-store.js.map +1 -0
  70. package/dist/src/identity/file-identity-store.spec.d.ts +6 -0
  71. package/dist/src/identity/file-identity-store.spec.d.ts.map +1 -0
  72. package/dist/src/identity/file-identity-store.spec.js +59 -0
  73. package/dist/src/identity/file-identity-store.spec.js.map +1 -0
  74. package/dist/src/identity/in-memory-identity-store.d.ts +48 -0
  75. package/dist/src/identity/in-memory-identity-store.d.ts.map +1 -0
  76. package/dist/src/identity/in-memory-identity-store.js +102 -0
  77. package/dist/src/identity/in-memory-identity-store.js.map +1 -0
  78. package/dist/src/identity/machine-identity.d.ts +134 -0
  79. package/dist/src/identity/machine-identity.d.ts.map +1 -0
  80. package/dist/src/identity/machine-identity.js +65 -0
  81. package/dist/src/identity/machine-identity.js.map +1 -0
  82. package/dist/src/index.d.ts +34 -0
  83. package/dist/src/index.d.ts.map +1 -0
  84. package/dist/src/index.js +34 -0
  85. package/dist/src/index.js.map +1 -0
  86. package/dist/src/lease/closure.d.ts +96 -0
  87. package/dist/src/lease/closure.d.ts.map +1 -0
  88. package/dist/src/lease/closure.js +192 -0
  89. package/dist/src/lease/closure.js.map +1 -0
  90. package/dist/src/lease/closure.spec.d.ts +6 -0
  91. package/dist/src/lease/closure.spec.d.ts.map +1 -0
  92. package/dist/src/lease/closure.spec.js +35 -0
  93. package/dist/src/lease/closure.spec.js.map +1 -0
  94. package/dist/src/lease/coordinator.d.ts +34 -0
  95. package/dist/src/lease/coordinator.d.ts.map +1 -0
  96. package/dist/src/lease/coordinator.js +42 -0
  97. package/dist/src/lease/coordinator.js.map +1 -0
  98. package/dist/src/lease/in-memory-lease-store.d.ts +58 -0
  99. package/dist/src/lease/in-memory-lease-store.d.ts.map +1 -0
  100. package/dist/src/lease/in-memory-lease-store.js +132 -0
  101. package/dist/src/lease/in-memory-lease-store.js.map +1 -0
  102. package/dist/src/lease/lease-store.d.ts +169 -0
  103. package/dist/src/lease/lease-store.d.ts.map +1 -0
  104. package/dist/src/lease/lease-store.js +94 -0
  105. package/dist/src/lease/lease-store.js.map +1 -0
  106. package/dist/src/lease/lease-store.spec.d.ts +6 -0
  107. package/dist/src/lease/lease-store.spec.d.ts.map +1 -0
  108. package/dist/src/lease/lease-store.spec.js +8 -0
  109. package/dist/src/lease/lease-store.spec.js.map +1 -0
  110. package/dist/src/lease/rack-dispatch.d.ts +105 -0
  111. package/dist/src/lease/rack-dispatch.d.ts.map +1 -0
  112. package/dist/src/lease/rack-dispatch.js +6 -0
  113. package/dist/src/lease/rack-dispatch.js.map +1 -0
  114. package/dist/src/mutation-queue.d.ts +13 -0
  115. package/dist/src/mutation-queue.d.ts.map +1 -0
  116. package/dist/src/mutation-queue.js +17 -0
  117. package/dist/src/mutation-queue.js.map +1 -0
  118. package/dist/src/paths.d.ts +56 -0
  119. package/dist/src/paths.d.ts.map +1 -0
  120. package/dist/src/paths.js +82 -0
  121. package/dist/src/paths.js.map +1 -0
  122. package/dist/src/protocol/control.d.ts +295 -0
  123. package/dist/src/protocol/control.d.ts.map +1 -0
  124. package/dist/src/protocol/control.js +74 -0
  125. package/dist/src/protocol/control.js.map +1 -0
  126. package/dist/src/protocol/index.d.ts +9 -0
  127. package/dist/src/protocol/index.d.ts.map +1 -0
  128. package/dist/src/protocol/index.js +9 -0
  129. package/dist/src/protocol/index.js.map +1 -0
  130. package/dist/src/protocol/rack-wire.d.ts +357 -0
  131. package/dist/src/protocol/rack-wire.d.ts.map +1 -0
  132. package/dist/src/protocol/rack-wire.js +262 -0
  133. package/dist/src/protocol/rack-wire.js.map +1 -0
  134. package/dist/src/protocol/rack-wire.spec.d.ts +6 -0
  135. package/dist/src/protocol/rack-wire.spec.d.ts.map +1 -0
  136. package/dist/src/protocol/rack-wire.spec.js +14 -0
  137. package/dist/src/protocol/rack-wire.spec.js.map +1 -0
  138. package/dist/src/protocol/registration.d.ts +70 -0
  139. package/dist/src/protocol/registration.d.ts.map +1 -0
  140. package/dist/src/protocol/registration.js +67 -0
  141. package/dist/src/protocol/registration.js.map +1 -0
  142. package/dist/src/protocol/session-data.d.ts +69 -0
  143. package/dist/src/protocol/session-data.d.ts.map +1 -0
  144. package/dist/src/protocol/session-data.js +26 -0
  145. package/dist/src/protocol/session-data.js.map +1 -0
  146. package/dist/src/protocol/task-envelope.d.ts +198 -0
  147. package/dist/src/protocol/task-envelope.d.ts.map +1 -0
  148. package/dist/src/protocol/task-envelope.js +93 -0
  149. package/dist/src/protocol/task-envelope.js.map +1 -0
  150. package/dist/src/protocol/wire-golden.d.ts +8 -0
  151. package/dist/src/protocol/wire-golden.d.ts.map +1 -0
  152. package/dist/src/protocol/wire-golden.js +34 -0
  153. package/dist/src/protocol/wire-golden.js.map +1 -0
  154. package/dist/src/protocol/wire-samples.d.ts +11 -0
  155. package/dist/src/protocol/wire-samples.d.ts.map +1 -0
  156. package/dist/src/protocol/wire-samples.js +52 -0
  157. package/dist/src/protocol/wire-samples.js.map +1 -0
  158. package/dist/src/registry/file-rack-registry.d.ts +68 -0
  159. package/dist/src/registry/file-rack-registry.d.ts.map +1 -0
  160. package/dist/src/registry/file-rack-registry.js +138 -0
  161. package/dist/src/registry/file-rack-registry.js.map +1 -0
  162. package/dist/src/registry/file-rack-registry.spec.d.ts +6 -0
  163. package/dist/src/registry/file-rack-registry.spec.d.ts.map +1 -0
  164. package/dist/src/registry/file-rack-registry.spec.js +50 -0
  165. package/dist/src/registry/file-rack-registry.spec.js.map +1 -0
  166. package/dist/src/registry/rack-registry.d.ts +64 -0
  167. package/dist/src/registry/rack-registry.d.ts.map +1 -0
  168. package/dist/src/registry/rack-registry.js +65 -0
  169. package/dist/src/registry/rack-registry.js.map +1 -0
  170. package/dist/src/registry/rack-registry.spec.d.ts +6 -0
  171. package/dist/src/registry/rack-registry.spec.d.ts.map +1 -0
  172. package/dist/src/registry/rack-registry.spec.js +8 -0
  173. package/dist/src/registry/rack-registry.spec.js.map +1 -0
  174. package/dist/src/routing/eligibility.d.ts +38 -0
  175. package/dist/src/routing/eligibility.d.ts.map +1 -0
  176. package/dist/src/routing/eligibility.js +78 -0
  177. package/dist/src/routing/eligibility.js.map +1 -0
  178. package/dist/src/routing/host-coupling.d.ts +26 -0
  179. package/dist/src/routing/host-coupling.d.ts.map +1 -0
  180. package/dist/src/routing/host-coupling.js +62 -0
  181. package/dist/src/routing/host-coupling.js.map +1 -0
  182. package/dist/src/routing/policy.d.ts +188 -0
  183. package/dist/src/routing/policy.d.ts.map +1 -0
  184. package/dist/src/routing/policy.js +212 -0
  185. package/dist/src/routing/policy.js.map +1 -0
  186. package/dist/src/routing/routing.spec.d.ts +6 -0
  187. package/dist/src/routing/routing.spec.d.ts.map +1 -0
  188. package/dist/src/routing/routing.spec.js +100 -0
  189. package/dist/src/routing/routing.spec.js.map +1 -0
  190. package/dist/src/routing/tiers.d.ts +22 -0
  191. package/dist/src/routing/tiers.d.ts.map +1 -0
  192. package/dist/src/routing/tiers.js +26 -0
  193. package/dist/src/routing/tiers.js.map +1 -0
  194. package/dist/src/runner/api-server.d.ts +45 -0
  195. package/dist/src/runner/api-server.d.ts.map +1 -0
  196. package/dist/src/runner/api-server.js +21 -0
  197. package/dist/src/runner/api-server.js.map +1 -0
  198. package/dist/src/runner/capacity.d.ts +13 -0
  199. package/dist/src/runner/capacity.d.ts.map +1 -0
  200. package/dist/src/runner/capacity.js +18 -0
  201. package/dist/src/runner/capacity.js.map +1 -0
  202. package/dist/src/runner/rack-body.d.ts +43 -0
  203. package/dist/src/runner/rack-body.d.ts.map +1 -0
  204. package/dist/src/runner/rack-body.js +208 -0
  205. package/dist/src/runner/rack-body.js.map +1 -0
  206. package/dist/src/runner/rack-runner.d.ts +62 -0
  207. package/dist/src/runner/rack-runner.d.ts.map +1 -0
  208. package/dist/src/runner/rack-runner.js +75 -0
  209. package/dist/src/runner/rack-runner.js.map +1 -0
  210. package/dist/src/runner/rack-runner.spec.d.ts +6 -0
  211. package/dist/src/runner/rack-runner.spec.d.ts.map +1 -0
  212. package/dist/src/runner/rack-runner.spec.js +302 -0
  213. package/dist/src/runner/rack-runner.spec.js.map +1 -0
  214. package/dist/src/runner/split.spec.d.ts +6 -0
  215. package/dist/src/runner/split.spec.d.ts.map +1 -0
  216. package/dist/src/runner/split.spec.js +188 -0
  217. package/dist/src/runner/split.spec.js.map +1 -0
  218. package/dist/src/runner-event.d.ts +261 -0
  219. package/dist/src/runner-event.d.ts.map +1 -0
  220. package/dist/src/runner-event.js +332 -0
  221. package/dist/src/runner-event.js.map +1 -0
  222. package/dist/src/server/beast2.d.ts +19 -0
  223. package/dist/src/server/beast2.d.ts.map +1 -0
  224. package/dist/src/server/beast2.js +18 -0
  225. package/dist/src/server/beast2.js.map +1 -0
  226. package/dist/src/server/body-limit.d.ts +16 -0
  227. package/dist/src/server/body-limit.d.ts.map +1 -0
  228. package/dist/src/server/body-limit.js +53 -0
  229. package/dist/src/server/body-limit.js.map +1 -0
  230. package/dist/src/server/body-limit.spec.d.ts +2 -0
  231. package/dist/src/server/body-limit.spec.d.ts.map +1 -0
  232. package/dist/src/server/body-limit.spec.js +32 -0
  233. package/dist/src/server/body-limit.spec.js.map +1 -0
  234. package/dist/src/server/bounded.d.ts +16 -0
  235. package/dist/src/server/bounded.d.ts.map +1 -0
  236. package/dist/src/server/bounded.js +39 -0
  237. package/dist/src/server/bounded.js.map +1 -0
  238. package/dist/src/server/dispatch.d.ts +137 -0
  239. package/dist/src/server/dispatch.d.ts.map +1 -0
  240. package/dist/src/server/dispatch.js +267 -0
  241. package/dist/src/server/dispatch.js.map +1 -0
  242. package/dist/src/server/env-publication.d.ts +45 -0
  243. package/dist/src/server/env-publication.d.ts.map +1 -0
  244. package/dist/src/server/env-publication.js +10 -0
  245. package/dist/src/server/env-publication.js.map +1 -0
  246. package/dist/src/server/index.d.ts +16 -0
  247. package/dist/src/server/index.d.ts.map +1 -0
  248. package/dist/src/server/index.js +17 -0
  249. package/dist/src/server/index.js.map +1 -0
  250. package/dist/src/server/protocol.spec.d.ts +6 -0
  251. package/dist/src/server/protocol.spec.d.ts.map +1 -0
  252. package/dist/src/server/protocol.spec.js +78 -0
  253. package/dist/src/server/protocol.spec.js.map +1 -0
  254. package/dist/src/server/rack-routes.d.ts +175 -0
  255. package/dist/src/server/rack-routes.d.ts.map +1 -0
  256. package/dist/src/server/rack-routes.js +755 -0
  257. package/dist/src/server/rack-routes.js.map +1 -0
  258. package/dist/src/server/rack-routes.spec.d.ts +6 -0
  259. package/dist/src/server/rack-routes.spec.d.ts.map +1 -0
  260. package/dist/src/server/rack-routes.spec.js +477 -0
  261. package/dist/src/server/rack-routes.spec.js.map +1 -0
  262. package/dist/src/server/storage-bridge.d.ts +140 -0
  263. package/dist/src/server/storage-bridge.d.ts.map +1 -0
  264. package/dist/src/server/storage-bridge.js +6 -0
  265. package/dist/src/server/storage-bridge.js.map +1 -0
  266. package/dist/src/state-file.d.ts +10 -0
  267. package/dist/src/state-file.d.ts.map +1 -0
  268. package/dist/src/state-file.js +38 -0
  269. package/dist/src/state-file.js.map +1 -0
  270. package/dist/src/testing/in-memory.d.ts +116 -0
  271. package/dist/src/testing/in-memory.d.ts.map +1 -0
  272. package/dist/src/testing/in-memory.js +193 -0
  273. package/dist/src/testing/in-memory.js.map +1 -0
  274. package/dist/src/testing/index.d.ts +14 -0
  275. package/dist/src/testing/index.d.ts.map +1 -0
  276. package/dist/src/testing/index.js +14 -0
  277. package/dist/src/testing/index.js.map +1 -0
  278. package/dist/src/testing/lease-store-contract.d.ts +14 -0
  279. package/dist/src/testing/lease-store-contract.d.ts.map +1 -0
  280. package/dist/src/testing/lease-store-contract.js +78 -0
  281. package/dist/src/testing/lease-store-contract.js.map +1 -0
  282. package/dist/src/testing/protocol-suite.d.ts +38 -0
  283. package/dist/src/testing/protocol-suite.d.ts.map +1 -0
  284. package/dist/src/testing/protocol-suite.js +207 -0
  285. package/dist/src/testing/protocol-suite.js.map +1 -0
  286. package/dist/src/testing/rack-registry-contract.d.ts +15 -0
  287. package/dist/src/testing/rack-registry-contract.d.ts.map +1 -0
  288. package/dist/src/testing/rack-registry-contract.js +106 -0
  289. package/dist/src/testing/rack-registry-contract.js.map +1 -0
  290. package/dist/src/testing/test-rack-agent.d.ts +121 -0
  291. package/dist/src/testing/test-rack-agent.d.ts.map +1 -0
  292. package/dist/src/testing/test-rack-agent.js +316 -0
  293. package/dist/src/testing/test-rack-agent.js.map +1 -0
  294. package/dist/src/tls/tls.d.ts +67 -0
  295. package/dist/src/tls/tls.d.ts.map +1 -0
  296. package/dist/src/tls/tls.js +200 -0
  297. package/dist/src/tls/tls.js.map +1 -0
  298. package/dist/src/tls/tls.spec.d.ts +6 -0
  299. package/dist/src/tls/tls.spec.d.ts.map +1 -0
  300. package/dist/src/tls/tls.spec.js +101 -0
  301. package/dist/src/tls/tls.spec.js.map +1 -0
  302. package/dist/src/version.d.ts +9 -0
  303. package/dist/src/version.d.ts.map +1 -0
  304. package/dist/src/version.js +10 -0
  305. package/dist/src/version.js.map +1 -0
  306. package/package.json +67 -7
@@ -0,0 +1,332 @@
1
+ /**
2
+ * Copyright (c) 2025 Elara AI Pty Ltd
3
+ * Licensed under BSL 1.1. See LICENSE for details.
4
+ */
5
+ /**
6
+ * The runner event, v2 (#205): what a launcher sends a runner container, and
7
+ * what the container answers.
8
+ *
9
+ * The event is JSON. A value e3-core types as an East value (a detached call's
10
+ * runner, an intake's declared type) is in East's JSON encoding, whose
11
+ * integers are strings, and bytes are base64. Each mode names e3-core's own
12
+ * call the container makes:
13
+ * - `task`: `taskExecute`, a task over its inputs;
14
+ * - `unit`: `taskExecuteUnit`, a piece or a merge of a split task, which its
15
+ * caller planned;
16
+ * - `run-detached`: `runDetached`, a function or one-shot call;
17
+ * - `intake`: `runIntake`, a delivery the store holds, or a run of its
18
+ * segments.
19
+ *
20
+ * A launcher builds the event with the `…ToWire` functions here and sends it
21
+ * as JSON; the container reads it back with {@link decodeRunnerEvent} and the
22
+ * `…FromWire` functions.
23
+ */
24
+ import { EastTypeType, fromJSONFor, toJSONFor } from '@elaraai/east';
25
+ import { DeliveryRefusedError, isObjectHash, isUuidv7, } from '@elaraai/e3-core';
26
+ import { RunnerType } from '@elaraai/e3-types';
27
+ // =============================================================================
28
+ // To and from the wire
29
+ // =============================================================================
30
+ const runnerToJSON = toJSONFor(RunnerType);
31
+ const runnerFromJSON = fromJSONFor(RunnerType);
32
+ const typeToJSON = toJSONFor(EastTypeType);
33
+ const typeFromJSON = fromJSONFor(EastTypeType);
34
+ /**
35
+ * A unit as the wire carries it.
36
+ *
37
+ * @param unit - The unit
38
+ * @returns Its wire form
39
+ */
40
+ export function splitUnitToWire(unit) {
41
+ return {
42
+ inputs: [...unit.inputs],
43
+ merge: unit.merge === null ? null : { parts: [...unit.merge.parts], range: unit.merge.range },
44
+ own: unit.own,
45
+ };
46
+ }
47
+ /**
48
+ * A unit, from the wire.
49
+ *
50
+ * @param wire - Its wire form
51
+ * @returns The unit
52
+ */
53
+ export function splitUnitFromWire(wire) {
54
+ return {
55
+ inputs: [...wire.inputs],
56
+ merge: wire.merge === null ? null : { parts: [...wire.merge.parts], range: wire.merge.range },
57
+ own: wire.own,
58
+ };
59
+ }
60
+ /**
61
+ * A detached call as the wire carries it.
62
+ *
63
+ * @param spec - The call
64
+ * @returns Its wire form
65
+ */
66
+ export function detachedSpecToWire(spec) {
67
+ return {
68
+ bodyIr: Buffer.from(spec.bodyIr).toString('base64'),
69
+ args: spec.args.map((arg) => arg instanceof Uint8Array ? Buffer.from(arg).toString('base64') : { dataset: arg.dataset }),
70
+ runner: runnerToJSON(spec.runner),
71
+ limits: { timeoutMs: spec.limits.timeoutMs, maxResultBytes: spec.limits.maxResultBytes, maxLogBytes: spec.limits.maxLogBytes },
72
+ ...(spec.environment !== undefined && { environment: spec.environment }),
73
+ };
74
+ }
75
+ /**
76
+ * A detached call, from the wire.
77
+ *
78
+ * @param wire - Its wire form
79
+ * @returns The call
80
+ * @throws {RunnerEventError} When its runner does not decode as a `RunnerType`
81
+ */
82
+ export function detachedSpecFromWire(wire) {
83
+ return {
84
+ bodyIr: new Uint8Array(Buffer.from(wire.bodyIr, 'base64')),
85
+ args: wire.args.map((arg) => typeof arg === 'string'
86
+ ? new Uint8Array(Buffer.from(arg, 'base64'))
87
+ : { dataset: arg.dataset }),
88
+ runner: decodeEast(runnerFromJSON, wire.runner, 'spec.runner'),
89
+ limits: { timeoutMs: wire.limits.timeoutMs, maxResultBytes: wire.limits.maxResultBytes, maxLogBytes: wire.limits.maxLogBytes },
90
+ ...(wire.environment !== undefined && { environment: wire.environment }),
91
+ };
92
+ }
93
+ /**
94
+ * An intake as the wire carries it.
95
+ *
96
+ * @param spec - The intake: of a delivery the store holds
97
+ * @returns Its wire form
98
+ * @throws {Error} When the delivery is a file, which a runner container
99
+ * cannot read
100
+ */
101
+ export function intakeSpecToWire(spec) {
102
+ if (!('object' in spec.source)) {
103
+ throw new Error('a runner container takes in a delivery the store holds: this intake names a file');
104
+ }
105
+ return {
106
+ object: spec.source.object,
107
+ type: typeToJSON(spec.type),
108
+ ...(spec.segments !== undefined && { segments: { from: spec.segments.from, to: spec.segments.to } }),
109
+ };
110
+ }
111
+ /**
112
+ * An intake, from the wire.
113
+ *
114
+ * @param wire - Its wire form
115
+ * @returns The intake
116
+ * @throws {RunnerEventError} When its type does not decode as an East type
117
+ */
118
+ export function intakeSpecFromWire(wire) {
119
+ return {
120
+ source: { object: wire.object },
121
+ type: decodeEast(typeFromJSON, wire.type, 'spec.type'),
122
+ ...(wire.segments !== undefined && { segments: { from: wire.segments.from, to: wire.segments.to } }),
123
+ };
124
+ }
125
+ /**
126
+ * A detached call's outcome as the container answers it.
127
+ *
128
+ * @param result - The outcome
129
+ * @returns Its wire form
130
+ */
131
+ export function detachedResultToWire(result) {
132
+ return result.kind === 'success' ? { ...result, value: Buffer.from(result.value).toString('base64') } : result;
133
+ }
134
+ /**
135
+ * A detached call's outcome, from the container's answer.
136
+ *
137
+ * @param response - The answer
138
+ * @returns The outcome
139
+ */
140
+ export function detachedResultFromWire(response) {
141
+ return response.kind === 'success' ? { ...response, value: new Uint8Array(Buffer.from(response.value, 'base64')) } : response;
142
+ }
143
+ /**
144
+ * What an intake stored, from the container's answer.
145
+ *
146
+ * @param response - The answer
147
+ * @returns What the intake stored
148
+ * @throws {DeliveryRefusedError} When the runner refused the delivery
149
+ */
150
+ export function intakeResultFromWire(response) {
151
+ if (response.kind === 'refused') {
152
+ throw new DeliveryRefusedError(response.runner, response.refusal, response.stderr, response.delivery);
153
+ }
154
+ return {
155
+ hash: response.hash,
156
+ runner: response.runner,
157
+ ...(response.fallback !== undefined && { fallback: response.fallback }),
158
+ ...(response.peakBytes !== undefined && { peakBytes: response.peakBytes }),
159
+ };
160
+ }
161
+ // =============================================================================
162
+ // Reading an event
163
+ // =============================================================================
164
+ /** A runner event that does not read: what is wrong with it. */
165
+ export class RunnerEventError extends Error {
166
+ /**
167
+ * @param problem - What is wrong with the event
168
+ */
169
+ constructor(problem) {
170
+ super(`runner event: ${problem}`);
171
+ this.name = 'RunnerEventError';
172
+ }
173
+ }
174
+ /**
175
+ * Reads a runner event: the JSON value a container was handed, checked
176
+ * against the v2 shape.
177
+ *
178
+ * @param value - The event, parsed from its JSON
179
+ * @returns The event
180
+ * @throws {RunnerEventError} When it is not a v2 runner event: a v1 event
181
+ * (which no launcher sends since elaraai/e3-cloud#205), an unknown mode, or
182
+ * a field that is missing or of the wrong kind
183
+ */
184
+ export function decodeRunnerEvent(value) {
185
+ const event = record(value, 'the event');
186
+ if (event.mode === undefined && 'taskName' in event) {
187
+ throw new RunnerEventError('a v1 task event, which this runner no longer runs: launchers send v2 events since elaraai/e3-cloud#205');
188
+ }
189
+ const base = {
190
+ launchId: uuid(event.launchId, 'launchId'),
191
+ repo: text(event.repo, 'repo'),
192
+ timeoutMs: positive(event.timeoutMs, 'timeoutMs'),
193
+ };
194
+ switch (event.mode) {
195
+ case 'task':
196
+ return { mode: 'task', ...base, ...executionFields(event), inputHashes: hashes(event.inputHashes, 'inputHashes') };
197
+ case 'unit':
198
+ return { mode: 'unit', ...base, ...executionFields(event), unit: splitUnitWire(event.unit) };
199
+ case 'run-detached':
200
+ return {
201
+ mode: 'run-detached',
202
+ ...base,
203
+ spec: detachedSpecWire(event.spec),
204
+ ...(event.verbose !== undefined && { verbose: flag(event.verbose, 'verbose') }),
205
+ ...(event.deadline !== undefined && { deadline: count(event.deadline, 'deadline') }),
206
+ };
207
+ case 'intake':
208
+ return { mode: 'intake', ...base, spec: intakeSpecWire(event.spec) };
209
+ default:
210
+ throw new RunnerEventError(`mode is ${JSON.stringify(event.mode)}, not task, unit, run-detached or intake`);
211
+ }
212
+ }
213
+ /** The fields a task and a unit event share, checked. */
214
+ function executionFields(event) {
215
+ return {
216
+ taskHash: objectHash(event.taskHash, 'taskHash'),
217
+ ...(event.run !== undefined && { run: runOf(event.run) }),
218
+ ...(event.force !== undefined && { force: flag(event.force, 'force') }),
219
+ ...(event.verbose !== undefined && { verbose: flag(event.verbose, 'verbose') }),
220
+ ...(event.expectedPeakBytes !== undefined && { expectedPeakBytes: count(event.expectedPeakBytes, 'expectedPeakBytes') }),
221
+ ...(event.notice !== undefined && { notice: text(event.notice, 'notice') }),
222
+ };
223
+ }
224
+ function runOf(value) {
225
+ const run = record(value, 'run');
226
+ return { workspace: text(run.workspace, 'run.workspace'), id: uuid(run.id, 'run.id') };
227
+ }
228
+ function splitUnitWire(value) {
229
+ const unit = record(value, 'unit');
230
+ let merge = null;
231
+ if (unit.merge !== null) {
232
+ const parts = record(unit.merge, 'unit.merge');
233
+ merge = {
234
+ parts: hashes(parts.parts, 'unit.merge.parts'),
235
+ range: parts.range === null ? null : objectHash(parts.range, 'unit.merge.range'),
236
+ };
237
+ }
238
+ // A merge unit's inputs name its tag and its parts, so they are text, not hashes
239
+ return { inputs: texts(unit.inputs, 'unit.inputs'), merge, own: flag(unit.own, 'unit.own') };
240
+ }
241
+ function detachedSpecWire(value) {
242
+ const spec = record(value, 'spec');
243
+ const limits = record(spec.limits, 'spec.limits');
244
+ const wire = {
245
+ bodyIr: text(spec.bodyIr, 'spec.bodyIr', true),
246
+ args: list(spec.args, 'spec.args').map((arg, i) => typeof arg === 'string'
247
+ ? arg
248
+ : { dataset: objectHash(record(arg, `spec.args[${i}]`).dataset, `spec.args[${i}].dataset`) }),
249
+ runner: spec.runner,
250
+ limits: {
251
+ timeoutMs: positive(limits.timeoutMs, 'spec.limits.timeoutMs'),
252
+ maxResultBytes: count(limits.maxResultBytes, 'spec.limits.maxResultBytes'),
253
+ maxLogBytes: count(limits.maxLogBytes, 'spec.limits.maxLogBytes'),
254
+ },
255
+ ...(spec.environment !== undefined && { environment: objectHash(spec.environment, 'spec.environment') }),
256
+ };
257
+ // The runner is checked now, so that a malformed one is refused before anything runs
258
+ decodeEast(runnerFromJSON, wire.runner, 'spec.runner');
259
+ return wire;
260
+ }
261
+ function intakeSpecWire(value) {
262
+ const spec = record(value, 'spec');
263
+ let segments;
264
+ if (spec.segments !== undefined) {
265
+ const run = record(spec.segments, 'spec.segments');
266
+ segments = { from: count(run.from, 'spec.segments.from'), to: count(run.to, 'spec.segments.to') };
267
+ }
268
+ decodeEast(typeFromJSON, spec.type, 'spec.type');
269
+ return {
270
+ object: objectHash(spec.object, 'spec.object'),
271
+ type: spec.type,
272
+ ...(segments !== undefined && { segments }),
273
+ };
274
+ }
275
+ function decodeEast(decode, value, at) {
276
+ try {
277
+ return decode(value);
278
+ }
279
+ catch (err) {
280
+ throw new RunnerEventError(`${at} does not decode: ${err instanceof Error ? err.message : String(err)}`);
281
+ }
282
+ }
283
+ function record(value, at) {
284
+ if (typeof value !== 'object' || value === null || Array.isArray(value)) {
285
+ throw new RunnerEventError(`${at} is not an object`);
286
+ }
287
+ return value;
288
+ }
289
+ function list(value, at) {
290
+ if (!Array.isArray(value))
291
+ throw new RunnerEventError(`${at} is not an array`);
292
+ return value;
293
+ }
294
+ function text(value, at, empty = false) {
295
+ if (typeof value !== 'string' || (!empty && value === ''))
296
+ throw new RunnerEventError(`${at} is not a string`);
297
+ return value;
298
+ }
299
+ function texts(value, at) {
300
+ return list(value, at).map((item, i) => text(item, `${at}[${i}]`));
301
+ }
302
+ function objectHash(value, at) {
303
+ if (typeof value !== 'string' || !isObjectHash(value))
304
+ throw new RunnerEventError(`${at} is not an object hash`);
305
+ return value;
306
+ }
307
+ function hashes(value, at) {
308
+ return list(value, at).map((item, i) => objectHash(item, `${at}[${i}]`));
309
+ }
310
+ function uuid(value, at) {
311
+ if (typeof value !== 'string' || !isUuidv7(value))
312
+ throw new RunnerEventError(`${at} is not a UUIDv7`);
313
+ return value;
314
+ }
315
+ function flag(value, at) {
316
+ if (typeof value !== 'boolean')
317
+ throw new RunnerEventError(`${at} is not a boolean`);
318
+ return value;
319
+ }
320
+ function count(value, at) {
321
+ if (typeof value !== 'number' || !Number.isSafeInteger(value) || value < 0) {
322
+ throw new RunnerEventError(`${at} is not a whole number`);
323
+ }
324
+ return value;
325
+ }
326
+ function positive(value, at) {
327
+ if (typeof value !== 'number' || !Number.isFinite(value) || value <= 0) {
328
+ throw new RunnerEventError(`${at} is not a positive number`);
329
+ }
330
+ return value;
331
+ }
332
+ //# sourceMappingURL=runner-event.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner-event.js","sourceRoot":"","sources":["../../src/runner-event.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Copyright (c) 2025 Elara AI Pty Ltd
3
+ * Licensed under BSL 1.1. See LICENSE for details.
4
+ */
5
+ /**
6
+ * The BEAST2 envelopes over a Hono context: e3-types' request and answer
7
+ * helpers, as e3-api-server's `/beast2` entry wraps them. Declared here so
8
+ * this package needs nothing of the server, whose optional peer it is.
9
+ */
10
+ import type { EastType, ValueTypeOf } from '@elaraai/east';
11
+ import { type Error as ApiError } from '@elaraai/e3-types';
12
+ import type { Context } from 'hono';
13
+ /** Decodes a route's BEAST2 body as a value of a type. */
14
+ export declare function decodeBody<T extends EastType>(c: Context, type: T): Promise<ValueTypeOf<T>>;
15
+ /** Answers a success envelope. */
16
+ export declare function sendSuccess<T extends EastType>(type: T, value: ValueTypeOf<T>): Response;
17
+ /** Answers an error envelope. */
18
+ export declare function sendError<T extends EastType>(type: T, error: ApiError): Response;
19
+ //# sourceMappingURL=beast2.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"beast2.d.ts","sourceRoot":"","sources":["../../../src/server/beast2.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;GAIG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC3D,OAAO,EAAmD,KAAK,KAAK,IAAI,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC5G,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAEpC,0DAA0D;AAC1D,wBAAgB,UAAU,CAAC,CAAC,SAAS,QAAQ,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAE3F;AAED,kCAAkC;AAClC,wBAAgB,WAAW,CAAC,CAAC,SAAS,QAAQ,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG,QAAQ,CAExF;AAED,iCAAiC;AACjC,wBAAgB,SAAS,CAAC,CAAC,SAAS,QAAQ,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,QAAQ,GAAG,QAAQ,CAEhF"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Copyright (c) 2025 Elara AI Pty Ltd
3
+ * Licensed under BSL 1.1. See LICENSE for details.
4
+ */
5
+ import { beast2Error, beast2Success, decodeBeast2Request } from '@elaraai/e3-types';
6
+ /** Decodes a route's BEAST2 body as a value of a type. */
7
+ export function decodeBody(c, type) {
8
+ return decodeBeast2Request(c.req.raw, type);
9
+ }
10
+ /** Answers a success envelope. */
11
+ export function sendSuccess(type, value) {
12
+ return beast2Success(type, value);
13
+ }
14
+ /** Answers an error envelope. */
15
+ export function sendError(type, error) {
16
+ return beast2Error(type, error);
17
+ }
18
+ //# sourceMappingURL=beast2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"beast2.js","sourceRoot":"","sources":["../../../src/server/beast2.ts"],"names":[],"mappings":"AAAA;;;GAGG;AASH,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,mBAAmB,EAA0B,MAAM,mBAAmB,CAAC;AAG5G,0DAA0D;AAC1D,MAAM,UAAU,UAAU,CAAqB,CAAU,EAAE,IAAO;IAChE,OAAO,mBAAmB,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;AAC9C,CAAC;AAED,kCAAkC;AAClC,MAAM,UAAU,WAAW,CAAqB,IAAO,EAAE,KAAqB;IAC5E,OAAO,aAAa,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;AACpC,CAAC;AAED,iCAAiC;AACjC,MAAM,UAAU,SAAS,CAAqB,IAAO,EAAE,KAAe;IACpE,OAAO,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;AAClC,CAAC"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Copyright (c) 2025 Elara AI Pty Ltd
3
+ * Licensed under BSL 1.1. See LICENSE for details.
4
+ */
5
+ import type { MiddlewareHandler } from 'hono';
6
+ /**
7
+ * Bound control messages before BEAST2 decoding, counting streamed bytes
8
+ * even when Content-Length lies. Object transfers use separate routes.
9
+ * @param maxBytes - Maximum encoded body size
10
+ * @param timeoutMs - Maximum time to receive the body
11
+ * @returns Middleware answering 413 on excess and 408 on timeout
12
+ * @example
13
+ * app.use('/api/rack/enroll', rackBodyLimit(64 * 1024));
14
+ */
15
+ export declare function rackBodyLimit(maxBytes: number, timeoutMs?: number): MiddlewareHandler;
16
+ //# sourceMappingURL=body-limit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"body-limit.d.ts","sourceRoot":"","sources":["../../../src/server/body-limit.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAC;AAE9C;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,SAAS,GAAG,iBAAiB,CAgCrF"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Bound control messages before BEAST2 decoding, counting streamed bytes
3
+ * even when Content-Length lies. Object transfers use separate routes.
4
+ * @param maxBytes - Maximum encoded body size
5
+ * @param timeoutMs - Maximum time to receive the body
6
+ * @returns Middleware answering 413 on excess and 408 on timeout
7
+ * @example
8
+ * app.use('/api/rack/enroll', rackBodyLimit(64 * 1024));
9
+ */
10
+ export function rackBodyLimit(maxBytes, timeoutMs = 15_000) {
11
+ return async (c, next) => {
12
+ const body = c.req.raw.body;
13
+ if (body === null) {
14
+ await next();
15
+ return;
16
+ }
17
+ const reader = body.getReader();
18
+ const chunks = [];
19
+ let bytes = 0;
20
+ let timer;
21
+ const timeout = new Promise((_resolve, reject) => {
22
+ timer = setTimeout(() => reject(new Error('Rack body timeout')), timeoutMs);
23
+ });
24
+ try {
25
+ for (;;) {
26
+ const chunk = await Promise.race([reader.read(), timeout]);
27
+ if (chunk.done)
28
+ break;
29
+ bytes += chunk.value.byteLength;
30
+ if (bytes > maxBytes)
31
+ return c.text('Rack request body too large', 413);
32
+ chunks.push(chunk.value);
33
+ }
34
+ const data = new Uint8Array(bytes);
35
+ let offset = 0;
36
+ for (const chunk of chunks) {
37
+ data.set(chunk, offset);
38
+ offset += chunk.byteLength;
39
+ }
40
+ c.req.raw = new Request(c.req.raw, { body: data });
41
+ }
42
+ catch (error) {
43
+ return c.text('Rack request body could not be received', error instanceof Error && error.message === 'Rack body timeout' ? 408 : 400);
44
+ }
45
+ finally {
46
+ clearTimeout(timer);
47
+ void reader.cancel().catch(() => { });
48
+ reader.releaseLock();
49
+ }
50
+ await next();
51
+ };
52
+ }
53
+ //# sourceMappingURL=body-limit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"body-limit.js","sourceRoot":"","sources":["../../../src/server/body-limit.ts"],"names":[],"mappings":"AAMA;;;;;;;;GAQG;AACH,MAAM,UAAU,aAAa,CAAC,QAAgB,EAAE,SAAS,GAAG,MAAM;IAChE,OAAO,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE;QACvB,MAAM,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC;QAC5B,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;YAAC,MAAM,IAAI,EAAE,CAAC;YAAC,OAAO;QAAC,CAAC;QAC5C,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;QAChC,MAAM,MAAM,GAAiB,EAAE,CAAC;QAChC,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,IAAI,KAAgD,CAAC;QACrD,MAAM,OAAO,GAAG,IAAI,OAAO,CAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE;YACtD,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;QAC9E,CAAC,CAAC,CAAC;QACH,IAAI,CAAC;YACH,SAAS,CAAC;gBACR,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC;gBAC3D,IAAI,KAAK,CAAC,IAAI;oBAAE,MAAM;gBACtB,KAAK,IAAI,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC;gBAChC,IAAI,KAAK,GAAG,QAAQ;oBAAE,OAAO,CAAC,CAAC,IAAI,CAAC,6BAA6B,EAAE,GAAG,CAAC,CAAC;gBACxE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YAC3B,CAAC;YACD,MAAM,IAAI,GAAG,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC;YACnC,IAAI,MAAM,GAAG,CAAC,CAAC;YACf,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;gBAAC,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;gBAAC,MAAM,IAAI,KAAK,CAAC,UAAU,CAAC;YAAC,CAAC;YACpF,CAAC,CAAC,GAAG,CAAC,GAAG,GAAG,IAAI,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QACrD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,CAAC,IAAI,CAAC,yCAAyC,EAAE,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,OAAO,KAAK,mBAAmB,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QACxI,CAAC;gBAAS,CAAC;YACT,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,KAAK,MAAM,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAA6C,CAAC,CAAC,CAAC;YAChF,MAAM,CAAC,WAAW,EAAE,CAAC;QACvB,CAAC;QACD,MAAM,IAAI,EAAE,CAAC;IACf,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=body-limit.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"body-limit.spec.d.ts","sourceRoot":"","sources":["../../../src/server/body-limit.spec.ts"],"names":[],"mappings":""}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Copyright (c) 2025 Elara AI Pty Ltd
3
+ * Licensed under BSL 1.1. See LICENSE for details.
4
+ */
5
+ import { it } from 'node:test';
6
+ import assert from 'node:assert/strict';
7
+ import { Hono } from 'hono';
8
+ import { rackBodyLimit } from './body-limit.js';
9
+ it('bounds actual request bytes before decoding, regardless of Content-Length', async () => {
10
+ const app = new Hono();
11
+ let decoded = 0;
12
+ app.use('*', rackBodyLimit(4));
13
+ app.post('/', async (c) => { decoded++; return c.text(await c.req.text()); });
14
+ const ok = await app.request('/', { method: 'POST', body: 'four' });
15
+ assert.equal(await ok.text(), 'four');
16
+ for (const headers of [new Headers(), new Headers({ 'content-length': '1' })]) {
17
+ const rejected = await app.request('/', { method: 'POST', body: 'too large', headers });
18
+ assert.equal(rejected.status, 413);
19
+ }
20
+ assert.equal(decoded, 1);
21
+ });
22
+ it('times out stalled bodies and cancels their streams', async () => {
23
+ const app = new Hono();
24
+ app.use('*', rackBodyLimit(4, 10));
25
+ app.post('/', c => c.text('unexpected'));
26
+ let cancelled = false;
27
+ const body = new ReadableStream({ cancel() { cancelled = true; } });
28
+ const request = new Request('http://localhost/', { method: 'POST', body, duplex: 'half' });
29
+ assert.equal((await app.request(request)).status, 408);
30
+ assert.ok(cancelled);
31
+ });
32
+ //# sourceMappingURL=body-limit.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"body-limit.spec.js","sourceRoot":"","sources":["../../../src/server/body-limit.spec.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,EAAE,EAAE,MAAM,WAAW,CAAC;AAC/B,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD,EAAE,CAAC,2EAA2E,EAAE,KAAK,IAAI,EAAE;IACvF,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;IACvB,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/B,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,EAAC,CAAC,EAAC,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5E,MAAM,EAAE,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IACpE,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,MAAM,CAAC,CAAC;IACtC,KAAK,MAAM,OAAO,IAAI,CAAC,IAAI,OAAO,EAAE,EAAE,IAAI,OAAO,CAAC,EAAE,gBAAgB,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC;QAC5E,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC,CAAC;QACxF,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACvC,CAAC;IACD,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;AAC7B,CAAC,CAAC,CAAC;AAEH,EAAE,CAAC,oDAAoD,EAAE,KAAK,IAAI,EAAE;IAChE,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;IACvB,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,aAAa,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;IACnC,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC;IACzC,IAAI,SAAS,GAAG,KAAK,CAAC;IACtB,MAAM,IAAI,GAAG,IAAI,cAAc,CAAa,EAAE,MAAM,KAAK,SAAS,GAAG,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAChF,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,mBAAmB,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAiB,CAAC,CAAC;IAC1G,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACvD,MAAM,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC;AACzB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Copyright (c) 2025 Elara AI Pty Ltd
3
+ * Licensed under BSL 1.1. See LICENSE for details.
4
+ */
5
+ /**
6
+ * Maps backend work with bounded concurrency, preserving request order.
7
+ * Stops scheduling after a failure and joins every started operation before
8
+ * rejecting, so the caller's lease fence covers all in-flight side effects.
9
+ * @param items - Backend requests
10
+ * @param atOnce - Maximum concurrent operations
11
+ * @param map - Operation for one request
12
+ * @returns Results in request order
13
+ * @internal
14
+ */
15
+ export declare function mapBounded<T, R>(items: readonly T[], atOnce: number, map: (item: T) => Promise<R>): Promise<R[]>;
16
+ //# sourceMappingURL=bounded.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bounded.d.ts","sourceRoot":"","sources":["../../../src/server/bounded.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;;;;;GASG;AACH,wBAAsB,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC,CAkBtH"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Copyright (c) 2025 Elara AI Pty Ltd
3
+ * Licensed under BSL 1.1. See LICENSE for details.
4
+ */
5
+ /**
6
+ * Maps backend work with bounded concurrency, preserving request order.
7
+ * Stops scheduling after a failure and joins every started operation before
8
+ * rejecting, so the caller's lease fence covers all in-flight side effects.
9
+ * @param items - Backend requests
10
+ * @param atOnce - Maximum concurrent operations
11
+ * @param map - Operation for one request
12
+ * @returns Results in request order
13
+ * @internal
14
+ */
15
+ export async function mapBounded(items, atOnce, map) {
16
+ const answers = new Array(items.length);
17
+ let next = 0;
18
+ let failed = false;
19
+ let failure;
20
+ const worker = async () => {
21
+ while (next < items.length && !failed) {
22
+ const index = next++;
23
+ try {
24
+ answers[index] = await map(items[index]);
25
+ }
26
+ catch (error) {
27
+ if (!failed) {
28
+ failed = true;
29
+ failure = error;
30
+ }
31
+ }
32
+ }
33
+ };
34
+ await Promise.all(Array.from({ length: Math.min(Math.max(1, atOnce), items.length) }, worker));
35
+ if (failed)
36
+ throw failure;
37
+ return answers;
38
+ }
39
+ //# sourceMappingURL=bounded.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bounded.js","sourceRoot":"","sources":["../../../src/server/bounded.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAO,KAAmB,EAAE,MAAc,EAAE,GAA4B;IACtG,MAAM,OAAO,GAAG,IAAI,KAAK,CAAI,KAAK,CAAC,MAAM,CAAC,CAAC;IAC3C,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,IAAI,MAAM,GAAG,KAAK,CAAC;IACnB,IAAI,OAAgB,CAAC;IACrB,MAAM,MAAM,GAAG,KAAK,IAAmB,EAAE;QACvC,OAAO,IAAI,GAAG,KAAK,CAAC,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC;YACtC,MAAM,KAAK,GAAG,IAAI,EAAE,CAAC;YACrB,IAAI,CAAC;gBACH,OAAO,CAAC,KAAK,CAAC,GAAG,MAAM,GAAG,CAAC,KAAK,CAAC,KAAK,CAAE,CAAC,CAAC;YAC5C,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,IAAI,CAAC,MAAM,EAAE,CAAC;oBAAC,MAAM,GAAG,IAAI,CAAC;oBAAC,OAAO,GAAG,KAAK,CAAC;gBAAC,CAAC;YAClD,CAAC;QACH,CAAC;IACH,CAAC,CAAC;IACF,MAAM,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC;IAC/F,IAAI,MAAM;QAAE,MAAM,OAAO,CAAC;IAC1B,OAAO,OAAO,CAAC;AACjB,CAAC"}