@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.
- package/README.md +407 -2
- package/dist/src/client/client.spec.d.ts +6 -0
- package/dist/src/client/client.spec.d.ts.map +1 -0
- package/dist/src/client/client.spec.js +150 -0
- package/dist/src/client/client.spec.js.map +1 -0
- package/dist/src/client/connect.d.ts +52 -0
- package/dist/src/client/connect.d.ts.map +1 -0
- package/dist/src/client/connect.js +112 -0
- package/dist/src/client/connect.js.map +1 -0
- package/dist/src/client/hub-client.d.ts +57 -0
- package/dist/src/client/hub-client.d.ts.map +1 -0
- package/dist/src/client/hub-client.js +87 -0
- package/dist/src/client/hub-client.js.map +1 -0
- package/dist/src/client/local-http.d.ts +78 -0
- package/dist/src/client/local-http.d.ts.map +1 -0
- package/dist/src/client/local-http.js +149 -0
- package/dist/src/client/local-http.js.map +1 -0
- package/dist/src/client/session-attempts.d.ts +20 -0
- package/dist/src/client/session-attempts.d.ts.map +1 -0
- package/dist/src/client/session-attempts.js +88 -0
- package/dist/src/client/session-attempts.js.map +1 -0
- package/dist/src/client/session-data-server.d.ts +37 -0
- package/dist/src/client/session-data-server.d.ts.map +1 -0
- package/dist/src/client/session-data-server.js +280 -0
- package/dist/src/client/session-data-server.js.map +1 -0
- package/dist/src/client/session-data-server.spec.d.ts +6 -0
- package/dist/src/client/session-data-server.spec.d.ts.map +1 -0
- package/dist/src/client/session-data-server.spec.js +192 -0
- package/dist/src/client/session-data-server.spec.js.map +1 -0
- package/dist/src/client/session.d.ts +119 -0
- package/dist/src/client/session.d.ts.map +1 -0
- package/dist/src/client/session.js +290 -0
- package/dist/src/client/session.js.map +1 -0
- package/dist/src/hub/config.d.ts +74 -0
- package/dist/src/hub/config.d.ts.map +1 -0
- package/dist/src/hub/config.js +159 -0
- package/dist/src/hub/config.js.map +1 -0
- package/dist/src/hub/fair-lease-store.d.ts +36 -0
- package/dist/src/hub/fair-lease-store.d.ts.map +1 -0
- package/dist/src/hub/fair-lease-store.js +73 -0
- package/dist/src/hub/fair-lease-store.js.map +1 -0
- package/dist/src/hub/hub.d.ts +91 -0
- package/dist/src/hub/hub.d.ts.map +1 -0
- package/dist/src/hub/hub.js +641 -0
- package/dist/src/hub/hub.js.map +1 -0
- package/dist/src/hub/hub.spec.d.ts +6 -0
- package/dist/src/hub/hub.spec.d.ts.map +1 -0
- package/dist/src/hub/hub.spec.js +363 -0
- package/dist/src/hub/hub.spec.js.map +1 -0
- package/dist/src/hub/infrastructure.spec.d.ts +6 -0
- package/dist/src/hub/infrastructure.spec.d.ts.map +1 -0
- package/dist/src/hub/infrastructure.spec.js +211 -0
- package/dist/src/hub/infrastructure.spec.js.map +1 -0
- package/dist/src/hub/lock.d.ts +62 -0
- package/dist/src/hub/lock.d.ts.map +1 -0
- package/dist/src/hub/lock.js +165 -0
- package/dist/src/hub/lock.js.map +1 -0
- package/dist/src/hub/main.d.ts +16 -0
- package/dist/src/hub/main.d.ts.map +1 -0
- package/dist/src/hub/main.js +56 -0
- package/dist/src/hub/main.js.map +1 -0
- package/dist/src/hub/session-bridge.d.ts +116 -0
- package/dist/src/hub/session-bridge.d.ts.map +1 -0
- package/dist/src/hub/session-bridge.js +336 -0
- package/dist/src/hub/session-bridge.js.map +1 -0
- package/dist/src/identity/file-identity-store.d.ts +18 -0
- package/dist/src/identity/file-identity-store.d.ts.map +1 -0
- package/dist/src/identity/file-identity-store.js +34 -0
- package/dist/src/identity/file-identity-store.js.map +1 -0
- package/dist/src/identity/file-identity-store.spec.d.ts +6 -0
- package/dist/src/identity/file-identity-store.spec.d.ts.map +1 -0
- package/dist/src/identity/file-identity-store.spec.js +59 -0
- package/dist/src/identity/file-identity-store.spec.js.map +1 -0
- package/dist/src/identity/in-memory-identity-store.d.ts +48 -0
- package/dist/src/identity/in-memory-identity-store.d.ts.map +1 -0
- package/dist/src/identity/in-memory-identity-store.js +102 -0
- package/dist/src/identity/in-memory-identity-store.js.map +1 -0
- package/dist/src/identity/machine-identity.d.ts +134 -0
- package/dist/src/identity/machine-identity.d.ts.map +1 -0
- package/dist/src/identity/machine-identity.js +65 -0
- package/dist/src/identity/machine-identity.js.map +1 -0
- package/dist/src/index.d.ts +34 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +34 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/lease/closure.d.ts +96 -0
- package/dist/src/lease/closure.d.ts.map +1 -0
- package/dist/src/lease/closure.js +192 -0
- package/dist/src/lease/closure.js.map +1 -0
- package/dist/src/lease/closure.spec.d.ts +6 -0
- package/dist/src/lease/closure.spec.d.ts.map +1 -0
- package/dist/src/lease/closure.spec.js +35 -0
- package/dist/src/lease/closure.spec.js.map +1 -0
- package/dist/src/lease/coordinator.d.ts +34 -0
- package/dist/src/lease/coordinator.d.ts.map +1 -0
- package/dist/src/lease/coordinator.js +42 -0
- package/dist/src/lease/coordinator.js.map +1 -0
- package/dist/src/lease/in-memory-lease-store.d.ts +58 -0
- package/dist/src/lease/in-memory-lease-store.d.ts.map +1 -0
- package/dist/src/lease/in-memory-lease-store.js +132 -0
- package/dist/src/lease/in-memory-lease-store.js.map +1 -0
- package/dist/src/lease/lease-store.d.ts +169 -0
- package/dist/src/lease/lease-store.d.ts.map +1 -0
- package/dist/src/lease/lease-store.js +94 -0
- package/dist/src/lease/lease-store.js.map +1 -0
- package/dist/src/lease/lease-store.spec.d.ts +6 -0
- package/dist/src/lease/lease-store.spec.d.ts.map +1 -0
- package/dist/src/lease/lease-store.spec.js +8 -0
- package/dist/src/lease/lease-store.spec.js.map +1 -0
- package/dist/src/lease/rack-dispatch.d.ts +105 -0
- package/dist/src/lease/rack-dispatch.d.ts.map +1 -0
- package/dist/src/lease/rack-dispatch.js +6 -0
- package/dist/src/lease/rack-dispatch.js.map +1 -0
- package/dist/src/mutation-queue.d.ts +13 -0
- package/dist/src/mutation-queue.d.ts.map +1 -0
- package/dist/src/mutation-queue.js +17 -0
- package/dist/src/mutation-queue.js.map +1 -0
- package/dist/src/paths.d.ts +56 -0
- package/dist/src/paths.d.ts.map +1 -0
- package/dist/src/paths.js +82 -0
- package/dist/src/paths.js.map +1 -0
- package/dist/src/protocol/control.d.ts +295 -0
- package/dist/src/protocol/control.d.ts.map +1 -0
- package/dist/src/protocol/control.js +74 -0
- package/dist/src/protocol/control.js.map +1 -0
- package/dist/src/protocol/index.d.ts +9 -0
- package/dist/src/protocol/index.d.ts.map +1 -0
- package/dist/src/protocol/index.js +9 -0
- package/dist/src/protocol/index.js.map +1 -0
- package/dist/src/protocol/rack-wire.d.ts +357 -0
- package/dist/src/protocol/rack-wire.d.ts.map +1 -0
- package/dist/src/protocol/rack-wire.js +262 -0
- package/dist/src/protocol/rack-wire.js.map +1 -0
- package/dist/src/protocol/rack-wire.spec.d.ts +6 -0
- package/dist/src/protocol/rack-wire.spec.d.ts.map +1 -0
- package/dist/src/protocol/rack-wire.spec.js +14 -0
- package/dist/src/protocol/rack-wire.spec.js.map +1 -0
- package/dist/src/protocol/registration.d.ts +70 -0
- package/dist/src/protocol/registration.d.ts.map +1 -0
- package/dist/src/protocol/registration.js +67 -0
- package/dist/src/protocol/registration.js.map +1 -0
- package/dist/src/protocol/session-data.d.ts +69 -0
- package/dist/src/protocol/session-data.d.ts.map +1 -0
- package/dist/src/protocol/session-data.js +26 -0
- package/dist/src/protocol/session-data.js.map +1 -0
- package/dist/src/protocol/task-envelope.d.ts +198 -0
- package/dist/src/protocol/task-envelope.d.ts.map +1 -0
- package/dist/src/protocol/task-envelope.js +93 -0
- package/dist/src/protocol/task-envelope.js.map +1 -0
- package/dist/src/protocol/wire-golden.d.ts +8 -0
- package/dist/src/protocol/wire-golden.d.ts.map +1 -0
- package/dist/src/protocol/wire-golden.js +34 -0
- package/dist/src/protocol/wire-golden.js.map +1 -0
- package/dist/src/protocol/wire-samples.d.ts +11 -0
- package/dist/src/protocol/wire-samples.d.ts.map +1 -0
- package/dist/src/protocol/wire-samples.js +52 -0
- package/dist/src/protocol/wire-samples.js.map +1 -0
- package/dist/src/registry/file-rack-registry.d.ts +68 -0
- package/dist/src/registry/file-rack-registry.d.ts.map +1 -0
- package/dist/src/registry/file-rack-registry.js +138 -0
- package/dist/src/registry/file-rack-registry.js.map +1 -0
- package/dist/src/registry/file-rack-registry.spec.d.ts +6 -0
- package/dist/src/registry/file-rack-registry.spec.d.ts.map +1 -0
- package/dist/src/registry/file-rack-registry.spec.js +50 -0
- package/dist/src/registry/file-rack-registry.spec.js.map +1 -0
- package/dist/src/registry/rack-registry.d.ts +64 -0
- package/dist/src/registry/rack-registry.d.ts.map +1 -0
- package/dist/src/registry/rack-registry.js +65 -0
- package/dist/src/registry/rack-registry.js.map +1 -0
- package/dist/src/registry/rack-registry.spec.d.ts +6 -0
- package/dist/src/registry/rack-registry.spec.d.ts.map +1 -0
- package/dist/src/registry/rack-registry.spec.js +8 -0
- package/dist/src/registry/rack-registry.spec.js.map +1 -0
- package/dist/src/routing/eligibility.d.ts +38 -0
- package/dist/src/routing/eligibility.d.ts.map +1 -0
- package/dist/src/routing/eligibility.js +78 -0
- package/dist/src/routing/eligibility.js.map +1 -0
- package/dist/src/routing/host-coupling.d.ts +26 -0
- package/dist/src/routing/host-coupling.d.ts.map +1 -0
- package/dist/src/routing/host-coupling.js +62 -0
- package/dist/src/routing/host-coupling.js.map +1 -0
- package/dist/src/routing/policy.d.ts +188 -0
- package/dist/src/routing/policy.d.ts.map +1 -0
- package/dist/src/routing/policy.js +212 -0
- package/dist/src/routing/policy.js.map +1 -0
- package/dist/src/routing/routing.spec.d.ts +6 -0
- package/dist/src/routing/routing.spec.d.ts.map +1 -0
- package/dist/src/routing/routing.spec.js +100 -0
- package/dist/src/routing/routing.spec.js.map +1 -0
- package/dist/src/routing/tiers.d.ts +22 -0
- package/dist/src/routing/tiers.d.ts.map +1 -0
- package/dist/src/routing/tiers.js +26 -0
- package/dist/src/routing/tiers.js.map +1 -0
- package/dist/src/runner/api-server.d.ts +45 -0
- package/dist/src/runner/api-server.d.ts.map +1 -0
- package/dist/src/runner/api-server.js +21 -0
- package/dist/src/runner/api-server.js.map +1 -0
- package/dist/src/runner/capacity.d.ts +13 -0
- package/dist/src/runner/capacity.d.ts.map +1 -0
- package/dist/src/runner/capacity.js +18 -0
- package/dist/src/runner/capacity.js.map +1 -0
- package/dist/src/runner/rack-body.d.ts +43 -0
- package/dist/src/runner/rack-body.d.ts.map +1 -0
- package/dist/src/runner/rack-body.js +208 -0
- package/dist/src/runner/rack-body.js.map +1 -0
- package/dist/src/runner/rack-runner.d.ts +62 -0
- package/dist/src/runner/rack-runner.d.ts.map +1 -0
- package/dist/src/runner/rack-runner.js +75 -0
- package/dist/src/runner/rack-runner.js.map +1 -0
- package/dist/src/runner/rack-runner.spec.d.ts +6 -0
- package/dist/src/runner/rack-runner.spec.d.ts.map +1 -0
- package/dist/src/runner/rack-runner.spec.js +302 -0
- package/dist/src/runner/rack-runner.spec.js.map +1 -0
- package/dist/src/runner/split.spec.d.ts +6 -0
- package/dist/src/runner/split.spec.d.ts.map +1 -0
- package/dist/src/runner/split.spec.js +188 -0
- package/dist/src/runner/split.spec.js.map +1 -0
- package/dist/src/runner-event.d.ts +261 -0
- package/dist/src/runner-event.d.ts.map +1 -0
- package/dist/src/runner-event.js +332 -0
- package/dist/src/runner-event.js.map +1 -0
- package/dist/src/server/beast2.d.ts +19 -0
- package/dist/src/server/beast2.d.ts.map +1 -0
- package/dist/src/server/beast2.js +18 -0
- package/dist/src/server/beast2.js.map +1 -0
- package/dist/src/server/body-limit.d.ts +16 -0
- package/dist/src/server/body-limit.d.ts.map +1 -0
- package/dist/src/server/body-limit.js +53 -0
- package/dist/src/server/body-limit.js.map +1 -0
- package/dist/src/server/body-limit.spec.d.ts +2 -0
- package/dist/src/server/body-limit.spec.d.ts.map +1 -0
- package/dist/src/server/body-limit.spec.js +32 -0
- package/dist/src/server/body-limit.spec.js.map +1 -0
- package/dist/src/server/bounded.d.ts +16 -0
- package/dist/src/server/bounded.d.ts.map +1 -0
- package/dist/src/server/bounded.js +39 -0
- package/dist/src/server/bounded.js.map +1 -0
- package/dist/src/server/dispatch.d.ts +137 -0
- package/dist/src/server/dispatch.d.ts.map +1 -0
- package/dist/src/server/dispatch.js +267 -0
- package/dist/src/server/dispatch.js.map +1 -0
- package/dist/src/server/env-publication.d.ts +45 -0
- package/dist/src/server/env-publication.d.ts.map +1 -0
- package/dist/src/server/env-publication.js +10 -0
- package/dist/src/server/env-publication.js.map +1 -0
- package/dist/src/server/index.d.ts +16 -0
- package/dist/src/server/index.d.ts.map +1 -0
- package/dist/src/server/index.js +17 -0
- package/dist/src/server/index.js.map +1 -0
- package/dist/src/server/protocol.spec.d.ts +6 -0
- package/dist/src/server/protocol.spec.d.ts.map +1 -0
- package/dist/src/server/protocol.spec.js +78 -0
- package/dist/src/server/protocol.spec.js.map +1 -0
- package/dist/src/server/rack-routes.d.ts +175 -0
- package/dist/src/server/rack-routes.d.ts.map +1 -0
- package/dist/src/server/rack-routes.js +755 -0
- package/dist/src/server/rack-routes.js.map +1 -0
- package/dist/src/server/rack-routes.spec.d.ts +6 -0
- package/dist/src/server/rack-routes.spec.d.ts.map +1 -0
- package/dist/src/server/rack-routes.spec.js +477 -0
- package/dist/src/server/rack-routes.spec.js.map +1 -0
- package/dist/src/server/storage-bridge.d.ts +140 -0
- package/dist/src/server/storage-bridge.d.ts.map +1 -0
- package/dist/src/server/storage-bridge.js +6 -0
- package/dist/src/server/storage-bridge.js.map +1 -0
- package/dist/src/state-file.d.ts +10 -0
- package/dist/src/state-file.d.ts.map +1 -0
- package/dist/src/state-file.js +38 -0
- package/dist/src/state-file.js.map +1 -0
- package/dist/src/testing/in-memory.d.ts +116 -0
- package/dist/src/testing/in-memory.d.ts.map +1 -0
- package/dist/src/testing/in-memory.js +193 -0
- package/dist/src/testing/in-memory.js.map +1 -0
- package/dist/src/testing/index.d.ts +14 -0
- package/dist/src/testing/index.d.ts.map +1 -0
- package/dist/src/testing/index.js +14 -0
- package/dist/src/testing/index.js.map +1 -0
- package/dist/src/testing/lease-store-contract.d.ts +14 -0
- package/dist/src/testing/lease-store-contract.d.ts.map +1 -0
- package/dist/src/testing/lease-store-contract.js +78 -0
- package/dist/src/testing/lease-store-contract.js.map +1 -0
- package/dist/src/testing/protocol-suite.d.ts +38 -0
- package/dist/src/testing/protocol-suite.d.ts.map +1 -0
- package/dist/src/testing/protocol-suite.js +207 -0
- package/dist/src/testing/protocol-suite.js.map +1 -0
- package/dist/src/testing/rack-registry-contract.d.ts +15 -0
- package/dist/src/testing/rack-registry-contract.d.ts.map +1 -0
- package/dist/src/testing/rack-registry-contract.js +106 -0
- package/dist/src/testing/rack-registry-contract.js.map +1 -0
- package/dist/src/testing/test-rack-agent.d.ts +121 -0
- package/dist/src/testing/test-rack-agent.d.ts.map +1 -0
- package/dist/src/testing/test-rack-agent.js +316 -0
- package/dist/src/testing/test-rack-agent.js.map +1 -0
- package/dist/src/tls/tls.d.ts +67 -0
- package/dist/src/tls/tls.d.ts.map +1 -0
- package/dist/src/tls/tls.js +200 -0
- package/dist/src/tls/tls.js.map +1 -0
- package/dist/src/tls/tls.spec.d.ts +6 -0
- package/dist/src/tls/tls.spec.d.ts.map +1 -0
- package/dist/src/tls/tls.spec.js +101 -0
- package/dist/src/tls/tls.spec.js.map +1 -0
- package/dist/src/version.d.ts +9 -0
- package/dist/src/version.d.ts.map +1 -0
- package/dist/src/version.js +10 -0
- package/dist/src/version.js.map +1 -0
- 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 @@
|
|
|
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"}
|