@nice-code/action 0.23.0 → 0.25.0
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 +71 -26
- package/build/{ActionPayload.types-B-OSg09t.d.mts → AcceptorHandler-BizUtq4u.d.mts} +1267 -1543
- package/build/{ActionPayload.types-DIOeVapm.d.cts → AcceptorHandler-CxPfZtIl.d.cts} +1267 -1543
- package/build/{ActionDevtoolsCore-BjbhFqc0.d.mts → ActionDevtoolsCore-D9KBBI2V.d.cts} +2 -2
- package/build/{ActionDevtoolsCore-kk7oZBv9.d.cts → ActionDevtoolsCore-xZjAtB4H.d.mts} +2 -2
- package/build/advanced/index.cjs +115 -0
- package/build/advanced/index.cjs.map +1 -0
- package/build/advanced/index.d.cts +249 -0
- package/build/advanced/index.d.mts +249 -0
- package/build/advanced/index.mjs +88 -0
- package/build/advanced/index.mjs.map +1 -0
- package/build/{httpAcceptorCarrier-DJVxzDVd.mjs → createHibernatableWsServerAdapter-BkjESd01.mjs} +243 -429
- package/build/createHibernatableWsServerAdapter-BkjESd01.mjs.map +1 -0
- package/build/{httpAcceptorCarrier-hYPuoNuP.cjs → createHibernatableWsServerAdapter-FSDWrxoF.cjs} +268 -478
- package/build/createHibernatableWsServerAdapter-FSDWrxoF.cjs.map +1 -0
- package/build/devtools/browser/index.d.cts +1 -1
- package/build/devtools/browser/index.d.mts +1 -1
- package/build/devtools/server/index.d.cts +1 -1
- package/build/devtools/server/index.d.mts +1 -1
- package/build/httpAcceptorCarrier-BQYaXI9j.cjs +454 -0
- package/build/httpAcceptorCarrier-BQYaXI9j.cjs.map +1 -0
- package/build/httpAcceptorCarrier-DWqsCz3h.mjs +401 -0
- package/build/httpAcceptorCarrier-DWqsCz3h.mjs.map +1 -0
- package/build/index.cjs +73 -449
- package/build/index.cjs.map +1 -1
- package/build/index.d.cts +2 -2
- package/build/index.d.mts +2 -2
- package/build/index.mjs +13 -365
- package/build/index.mjs.map +1 -1
- package/build/platform/cloudflare/index.cjs +45 -1
- package/build/platform/cloudflare/index.cjs.map +1 -1
- package/build/platform/cloudflare/index.d.cts +42 -4
- package/build/platform/cloudflare/index.d.mts +42 -4
- package/build/platform/cloudflare/index.mjs +45 -2
- package/build/platform/cloudflare/index.mjs.map +1 -1
- package/build/react-query/index.d.cts +1 -1
- package/build/react-query/index.d.mts +1 -1
- package/package.json +15 -4
- package/build/httpAcceptorCarrier-DJVxzDVd.mjs.map +0 -1
- package/build/httpAcceptorCarrier-hYPuoNuP.cjs.map +0 -1
package/build/{httpAcceptorCarrier-hYPuoNuP.cjs → createHibernatableWsServerAdapter-FSDWrxoF.cjs}
RENAMED
|
@@ -1405,11 +1405,13 @@ var ActionRuntime = class {
|
|
|
1405
1405
|
* Used to locate the return-path channel for dispatching results back to the action origin.
|
|
1406
1406
|
* Returns `undefined` if no handler matches (score > 0 required, i.e. at least id must match).
|
|
1407
1407
|
*
|
|
1408
|
-
* A handler that currently holds the origin's *live* connection always wins
|
|
1409
|
-
*
|
|
1410
|
-
*
|
|
1411
|
-
*
|
|
1412
|
-
*
|
|
1408
|
+
* A handler that currently holds the origin's *live* connection always wins, regardless of its
|
|
1409
|
+
* coordinate score — owning the live socket bound to the origin's exact coordinate (set from the
|
|
1410
|
+
* handshake) is a strictly more precise match than any env-level `peerClient` score. This lets one
|
|
1411
|
+
* server accept clients of *several* envs over a single acceptor (a multi-role Durable Object): the
|
|
1412
|
+
* result/push routes back over the carrier the client actually connected on even when the handler's
|
|
1413
|
+
* `clientEnv` is unset or names a different env. Only when no handler owns a live connection do we fall
|
|
1414
|
+
* back to the plain best-coordinate-score pick (the offline-return and connector-only cases).
|
|
1413
1415
|
*/
|
|
1414
1416
|
getReturnHandlerForOrigin(originClient) {
|
|
1415
1417
|
if (originClient.envId === "_unset_") return void 0;
|
|
@@ -1424,12 +1426,12 @@ var ActionRuntime = class {
|
|
|
1424
1426
|
bestScore = score;
|
|
1425
1427
|
bestHandler = handler;
|
|
1426
1428
|
}
|
|
1427
|
-
if (
|
|
1429
|
+
if (handler.ownsLiveConnectionFor(originClient) && score > bestOwnedScore) {
|
|
1428
1430
|
bestOwnedScore = score;
|
|
1429
1431
|
bestOwnedHandler = handler;
|
|
1430
1432
|
}
|
|
1431
1433
|
}
|
|
1432
|
-
if (bestOwnedHandler != null
|
|
1434
|
+
if (bestOwnedHandler != null) return bestOwnedHandler;
|
|
1433
1435
|
return bestScore > 0 ? bestHandler : void 0;
|
|
1434
1436
|
}
|
|
1435
1437
|
resetRuntime() {
|
|
@@ -2172,7 +2174,7 @@ var AcceptorHandler = class extends PeerLinkHandler {
|
|
|
2172
2174
|
_codecByConn = /* @__PURE__ */ new Map();
|
|
2173
2175
|
_sessionByConn = /* @__PURE__ */ new Map();
|
|
2174
2176
|
constructor(options) {
|
|
2175
|
-
super(options.clientEnv);
|
|
2177
|
+
super(options.clientEnv ?? RuntimeCoordinate.unknown);
|
|
2176
2178
|
this._formatMessage = options.formatMessage;
|
|
2177
2179
|
this._createFormatMessage = options.createFormatMessage;
|
|
2178
2180
|
this._send = options.send;
|
|
@@ -2500,7 +2502,7 @@ const createAcceptorHandler = (options) => {
|
|
|
2500
2502
|
//#endregion
|
|
2501
2503
|
//#region src/ActionRuntime/Handler/PeerLink/Acceptor/createSecureActionServer.ts
|
|
2502
2504
|
/** Default accepted set: negotiate per connection to whatever the client picks. */
|
|
2503
|
-
const DEFAULT_SERVER_SECURITY_LEVELS
|
|
2505
|
+
const DEFAULT_SERVER_SECURITY_LEVELS = [
|
|
2504
2506
|
"none",
|
|
2505
2507
|
"authenticated",
|
|
2506
2508
|
"encrypted"
|
|
@@ -2508,14 +2510,14 @@ const DEFAULT_SERVER_SECURITY_LEVELS$1 = [
|
|
|
2508
2510
|
/**
|
|
2509
2511
|
* Build an {@link AcceptorHandler} for the secure binary channel with the boilerplate folded in:
|
|
2510
2512
|
* it creates the {@link ClientCryptoKeyLink} and the storage-backed TOFU resolver from a single
|
|
2511
|
-
* `
|
|
2513
|
+
* `storage`, installs the channel's per-connection codec, and assembles the `security` block
|
|
2512
2514
|
* from the runtime coordinate + channel version (accepting all three levels by default).
|
|
2513
2515
|
*
|
|
2514
2516
|
* For a hibernatable transport (e.g. a Durable Object), pair it with
|
|
2515
2517
|
* {@link createHibernatableWsServerAdapter} to wire persistence + replay.
|
|
2516
2518
|
*/
|
|
2517
2519
|
function createSecureAcceptorHandler(options) {
|
|
2518
|
-
const link = options.link ?? new _nice_code_util.ClientCryptoKeyLink({ storageAdapter: options.
|
|
2520
|
+
const link = options.link ?? new _nice_code_util.ClientCryptoKeyLink({ storageAdapter: options.storage });
|
|
2519
2521
|
return new AcceptorHandler({
|
|
2520
2522
|
clientEnv: options.clientEnv,
|
|
2521
2523
|
createFormatMessage: options.channel.createCodec,
|
|
@@ -2523,30 +2525,247 @@ function createSecureAcceptorHandler(options) {
|
|
|
2523
2525
|
runtime: options.runtime,
|
|
2524
2526
|
defaultTimeout: options.defaultTimeout,
|
|
2525
2527
|
security: {
|
|
2526
|
-
securityLevel: options.securityLevel ?? DEFAULT_SERVER_SECURITY_LEVELS
|
|
2528
|
+
securityLevel: options.securityLevel ?? DEFAULT_SERVER_SECURITY_LEVELS,
|
|
2527
2529
|
link,
|
|
2528
2530
|
localCoordinate: options.runtime.coordinate.toJsonObject(),
|
|
2529
2531
|
dictionaryVersion: options.channel.dictionaryVersion,
|
|
2530
|
-
verifyKeyResolver: options.verifyKeyResolver ?? createStorageTofuVerifyKeyResolver(options.
|
|
2532
|
+
verifyKeyResolver: options.verifyKeyResolver ?? createStorageTofuVerifyKeyResolver(options.storage)
|
|
2531
2533
|
}
|
|
2532
2534
|
});
|
|
2533
2535
|
}
|
|
2534
2536
|
//#endregion
|
|
2535
|
-
//#region src/ActionRuntime/Transport/
|
|
2537
|
+
//#region src/ActionRuntime/Transport/codec/actionWireCodec.ts
|
|
2538
|
+
/**
|
|
2539
|
+
* Tiny integer codes for the payload type, so the verbose `"request"`/`"result"`/`"progress"`
|
|
2540
|
+
* strings never hit the wire. The index in {@link ReversePayloadType} must line up with the value.
|
|
2541
|
+
*/
|
|
2542
|
+
const PayloadTypeToInt = {
|
|
2543
|
+
["request"]: 0,
|
|
2544
|
+
["result"]: 1,
|
|
2545
|
+
["progress"]: 2
|
|
2546
|
+
};
|
|
2547
|
+
const ReversePayloadType = [
|
|
2548
|
+
"request",
|
|
2549
|
+
"result",
|
|
2550
|
+
"progress"
|
|
2551
|
+
];
|
|
2552
|
+
/**
|
|
2553
|
+
* Build the positional `domain:id` ↔ integer dictionary. Both ends of a channel MUST build it from
|
|
2554
|
+
* the same domains in the same order — the mapping is positional, so a mismatch routes to the wrong
|
|
2555
|
+
* action. Add new transported domains to the end of the list.
|
|
2556
|
+
*/
|
|
2557
|
+
function buildActionRouteDictionary(domains) {
|
|
2558
|
+
const routeToInt = /* @__PURE__ */ new Map();
|
|
2559
|
+
const intToRoute = [];
|
|
2560
|
+
for (const dom of domains) for (const actionId of Object.keys(dom.actionSchema)) {
|
|
2561
|
+
const routeKey = `${dom.domain}:${actionId}`;
|
|
2562
|
+
if (routeToInt.has(routeKey)) continue;
|
|
2563
|
+
routeToInt.set(routeKey, intToRoute.length);
|
|
2564
|
+
intToRoute.push({
|
|
2565
|
+
domain: dom.domain,
|
|
2566
|
+
id: actionId,
|
|
2567
|
+
allDomains: dom.allDomains
|
|
2568
|
+
});
|
|
2569
|
+
}
|
|
2570
|
+
return {
|
|
2571
|
+
routeToInt,
|
|
2572
|
+
intToRoute
|
|
2573
|
+
};
|
|
2574
|
+
}
|
|
2575
|
+
/** Pull the type-specific payload (`input` / `result` / `progress`) out of a wire JSON object. */
|
|
2576
|
+
function extractWirePayload(json) {
|
|
2577
|
+
if (json.type === "request") return json.input;
|
|
2578
|
+
if (json.type === "result") return json.result;
|
|
2579
|
+
if (json.type === "progress") return json.progress;
|
|
2580
|
+
}
|
|
2581
|
+
/**
|
|
2582
|
+
* Reassemble a full wire JSON object from its decoded parts. `inputHash`/`outputHash` are emitted
|
|
2583
|
+
* empty — the hydration constructors recompute them — and the result still satisfies
|
|
2584
|
+
* `isActionPayload_Any_JsonObject` so it flows through validation like a JSON frame.
|
|
2585
|
+
*/
|
|
2586
|
+
function assembleWireJson(routeMeta, payloadType, time, context, payloadData) {
|
|
2587
|
+
const base = {
|
|
2588
|
+
form: "data",
|
|
2589
|
+
domain: routeMeta.domain,
|
|
2590
|
+
id: routeMeta.id,
|
|
2591
|
+
allDomains: routeMeta.allDomains,
|
|
2592
|
+
time,
|
|
2593
|
+
context
|
|
2594
|
+
};
|
|
2595
|
+
if (payloadType === "request") return {
|
|
2596
|
+
...base,
|
|
2597
|
+
type: "request",
|
|
2598
|
+
input: payloadData,
|
|
2599
|
+
inputHash: ""
|
|
2600
|
+
};
|
|
2601
|
+
if (payloadType === "result") return {
|
|
2602
|
+
...base,
|
|
2603
|
+
type: "result",
|
|
2604
|
+
result: payloadData,
|
|
2605
|
+
outputHash: ""
|
|
2606
|
+
};
|
|
2607
|
+
return {
|
|
2608
|
+
...base,
|
|
2609
|
+
type: "progress",
|
|
2610
|
+
progress: payloadData
|
|
2611
|
+
};
|
|
2612
|
+
}
|
|
2613
|
+
//#endregion
|
|
2614
|
+
//#region src/ActionRuntime/Transport/codec/createBinaryWireSessionFactory.ts
|
|
2615
|
+
/**
|
|
2616
|
+
* Positional layout of the *session* binary envelope — the leanest frame. Compared to the stateless
|
|
2617
|
+
* adapter it replaces the 21-char `cuid` with a small per-connection integer and only carries
|
|
2618
|
+
* `originClient` on the very first request of each direction (the peer remembers it afterwards).
|
|
2619
|
+
*
|
|
2620
|
+
* [ routeInt, typeInt, corrId, time, originClient?, payloadData ]
|
|
2621
|
+
*/
|
|
2622
|
+
const ENVELOPE = {
|
|
2623
|
+
route: 0,
|
|
2624
|
+
type: 1,
|
|
2625
|
+
corr: 2,
|
|
2626
|
+
time: 3,
|
|
2627
|
+
originClient: 4,
|
|
2628
|
+
payload: 5
|
|
2629
|
+
};
|
|
2630
|
+
const ENVELOPE_LENGTH = 6;
|
|
2536
2631
|
/**
|
|
2537
|
-
*
|
|
2538
|
-
*
|
|
2539
|
-
*
|
|
2632
|
+
* How long a pending correlation entry is kept before it's swept. A correlation only matters until its
|
|
2633
|
+
* action resolves or times out, so anything older than the longest realistic action timeout can be
|
|
2634
|
+
* dropped — this bounds memory when requests time out or a connection dies mid-flight (their replies
|
|
2635
|
+
* would never arrive, leaving the entry orphaned). Generous default so live correlations are never
|
|
2636
|
+
* pruned (the default transport timeout is 10s).
|
|
2540
2637
|
*/
|
|
2541
|
-
|
|
2542
|
-
|
|
2638
|
+
const DEFAULT_CORRELATION_TTL_MS = 5 * 6e4;
|
|
2639
|
+
function isKnownIdentity(coordinate) {
|
|
2640
|
+
return coordinate != null && coordinate.envId !== "_unset_";
|
|
2641
|
+
}
|
|
2642
|
+
/**
|
|
2643
|
+
* Drop entries older than `ttlMs`. Maps keep insertion order and entries are inserted in time order,
|
|
2644
|
+
* so the oldest are first — stop sweeping at the first live entry.
|
|
2645
|
+
*/
|
|
2646
|
+
function pruneExpired(map, now, ttlMs) {
|
|
2647
|
+
for (const [key, entry] of map) {
|
|
2648
|
+
if (now - entry.time <= ttlMs) break;
|
|
2649
|
+
map.delete(key);
|
|
2650
|
+
}
|
|
2651
|
+
}
|
|
2652
|
+
/**
|
|
2653
|
+
* Builds a factory of *stateful, per-connection* codecs for {@link LinkTransport} /
|
|
2654
|
+
* `AcceptorHandler` — the maximally compact binary wire. Call the returned factory once per live
|
|
2655
|
+
* connection (each socket on the client, each accepted connection on the server) so every channel
|
|
2656
|
+
* gets its own correlation + identity state.
|
|
2657
|
+
*
|
|
2658
|
+
* On top of everything {@link createBinaryWireAdapter} drops, a session also drops:
|
|
2659
|
+
* - **`cuid`** — replaced by a per-connection integer correlation id. The initiator maps it to its
|
|
2660
|
+
* real cuid; the responder echoes it; each side reconstructs the cuid from its own map. Correlation
|
|
2661
|
+
* only needs to be unique per socket, so a counter suffices.
|
|
2662
|
+
* - **`originClient` after the first request** — the first request each side sends carries its
|
|
2663
|
+
* identity; the peer remembers it and injects it into later frames. Replies omit it entirely (a
|
|
2664
|
+
* reply carries the initiator's own origin, which the initiator already knows).
|
|
2665
|
+
*
|
|
2666
|
+
* Both ends MUST build the factory from the same domains in the same order (positional dictionary).
|
|
2667
|
+
* Text frames still return `undefined` from `incoming`, so JSON clients remain interoperable.
|
|
2668
|
+
*
|
|
2669
|
+
* Hibernation note: after a server connection is evicted its session resets, so a still-connected
|
|
2670
|
+
* client (whose session persists) will keep omitting `originClient`. The server must therefore restore
|
|
2671
|
+
* the connection→client binding from its own store (see `AcceptorHandler.rehydrateConnection`) and
|
|
2672
|
+
* inject `originClient` from there — the session alone can't recover it.
|
|
2673
|
+
*/
|
|
2674
|
+
function createBinaryWireSessionFactory(domains, options) {
|
|
2675
|
+
const { routeToInt, intToRoute } = buildActionRouteDictionary(domains);
|
|
2676
|
+
const unknownIdentity = RuntimeCoordinate.unknown.toJsonObject();
|
|
2677
|
+
const ttlMs = options?.correlationTtlMs ?? DEFAULT_CORRELATION_TTL_MS;
|
|
2678
|
+
return () => {
|
|
2679
|
+
let outCounter = 0;
|
|
2680
|
+
const corrToCuid = /* @__PURE__ */ new Map();
|
|
2681
|
+
const cuidToCorr = /* @__PURE__ */ new Map();
|
|
2682
|
+
let selfIdentity;
|
|
2683
|
+
let peerIdentity;
|
|
2684
|
+
return {
|
|
2685
|
+
outgoing: (input) => {
|
|
2686
|
+
const json = input.action.toJsonObject();
|
|
2687
|
+
const routeKey = `${json.domain}:${json.id}`;
|
|
2688
|
+
const routeInt = routeToInt.get(routeKey);
|
|
2689
|
+
if (routeInt == null) throw new Error(`[binary-wire] Cannot pack unregistered action route: ${routeKey}`);
|
|
2690
|
+
const now = Date.now();
|
|
2691
|
+
pruneExpired(corrToCuid, now, ttlMs);
|
|
2692
|
+
pruneExpired(cuidToCorr, now, ttlMs);
|
|
2693
|
+
let corr;
|
|
2694
|
+
let wireIdentity;
|
|
2695
|
+
if (json.type === "request") {
|
|
2696
|
+
corr = outCounter++;
|
|
2697
|
+
corrToCuid.set(corr, {
|
|
2698
|
+
value: json.context.cuid,
|
|
2699
|
+
time: now
|
|
2700
|
+
});
|
|
2701
|
+
if (selfIdentity == null && isKnownIdentity(json.context.originClient)) {
|
|
2702
|
+
selfIdentity = json.context.originClient;
|
|
2703
|
+
wireIdentity = json.context.originClient;
|
|
2704
|
+
}
|
|
2705
|
+
} else {
|
|
2706
|
+
corr = cuidToCorr.get(json.context.cuid)?.value ?? -1;
|
|
2707
|
+
if (json.type === "result") cuidToCorr.delete(json.context.cuid);
|
|
2708
|
+
}
|
|
2709
|
+
const envelope = new Array(ENVELOPE_LENGTH);
|
|
2710
|
+
envelope[ENVELOPE.route] = routeInt;
|
|
2711
|
+
envelope[ENVELOPE.type] = PayloadTypeToInt[json.type];
|
|
2712
|
+
envelope[ENVELOPE.corr] = corr;
|
|
2713
|
+
envelope[ENVELOPE.time] = json.time;
|
|
2714
|
+
envelope[ENVELOPE.originClient] = wireIdentity;
|
|
2715
|
+
envelope[ENVELOPE.payload] = extractWirePayload(json);
|
|
2716
|
+
return (0, msgpackr.pack)(envelope);
|
|
2717
|
+
},
|
|
2718
|
+
incoming: (frame) => {
|
|
2719
|
+
let buffer;
|
|
2720
|
+
if (frame instanceof ArrayBuffer) buffer = new Uint8Array(frame);
|
|
2721
|
+
else if (frame instanceof Uint8Array) buffer = frame;
|
|
2722
|
+
else return;
|
|
2723
|
+
try {
|
|
2724
|
+
const envelope = (0, msgpackr.unpack)(buffer);
|
|
2725
|
+
if (!Array.isArray(envelope) || envelope.length !== ENVELOPE_LENGTH) return void 0;
|
|
2726
|
+
const routeMeta = intToRoute[envelope[ENVELOPE.route]];
|
|
2727
|
+
const payloadType = ReversePayloadType[envelope[ENVELOPE.type]];
|
|
2728
|
+
if (routeMeta == null || payloadType == null) return void 0;
|
|
2729
|
+
const now = Date.now();
|
|
2730
|
+
pruneExpired(corrToCuid, now, ttlMs);
|
|
2731
|
+
pruneExpired(cuidToCorr, now, ttlMs);
|
|
2732
|
+
const corr = envelope[ENVELOPE.corr];
|
|
2733
|
+
const time = envelope[ENVELOPE.time];
|
|
2734
|
+
const wireIdentity = envelope[ENVELOPE.originClient];
|
|
2735
|
+
let cuid;
|
|
2736
|
+
let originClient;
|
|
2737
|
+
if (payloadType === "request") {
|
|
2738
|
+
cuid = (0, nanoid.nanoid)();
|
|
2739
|
+
cuidToCorr.set(cuid, {
|
|
2740
|
+
value: corr,
|
|
2741
|
+
time: now
|
|
2742
|
+
});
|
|
2743
|
+
if (isKnownIdentity(wireIdentity)) peerIdentity = wireIdentity;
|
|
2744
|
+
originClient = peerIdentity ?? unknownIdentity;
|
|
2745
|
+
} else {
|
|
2746
|
+
cuid = corrToCuid.get(corr)?.value ?? (0, nanoid.nanoid)();
|
|
2747
|
+
if (payloadType === "result") corrToCuid.delete(corr);
|
|
2748
|
+
originClient = selfIdentity ?? unknownIdentity;
|
|
2749
|
+
}
|
|
2750
|
+
return assembleWireJson(routeMeta, payloadType, time, {
|
|
2751
|
+
cuid,
|
|
2752
|
+
timeCreated: time,
|
|
2753
|
+
routing: [],
|
|
2754
|
+
originClient
|
|
2755
|
+
}, envelope[ENVELOPE.payload]);
|
|
2756
|
+
} catch (e) {
|
|
2757
|
+
console.error("[binary-wire] Failed to unpack binary action session frame", e);
|
|
2758
|
+
return;
|
|
2759
|
+
}
|
|
2760
|
+
}
|
|
2761
|
+
};
|
|
2762
|
+
};
|
|
2543
2763
|
}
|
|
2544
2764
|
//#endregion
|
|
2545
2765
|
//#region src/ActionRuntime/Transport/Transport.ts
|
|
2546
2766
|
/**
|
|
2547
|
-
* Reusable transport definition.
|
|
2548
|
-
* `
|
|
2549
|
-
* `ConnectorHandler`. A single
|
|
2767
|
+
* Reusable transport definition. Built by the internal `transport({ carrier, secure })` factory (which
|
|
2768
|
+
* `connectChannel` / `serveChannel` drive) and passed to a `ConnectorHandler`. A single
|
|
2550
2769
|
* definition can be shared across multiple handlers — each handler builds its own live
|
|
2551
2770
|
* {@link TransportConnection} via {@link TransportConnection._createConnection}.
|
|
2552
2771
|
*/
|
|
@@ -3161,175 +3380,6 @@ var LinkTransport = class LinkTransport extends Transport {
|
|
|
3161
3380
|
}
|
|
3162
3381
|
};
|
|
3163
3382
|
//#endregion
|
|
3164
|
-
//#region src/ActionRuntime/Transport/plainTransport.ts
|
|
3165
|
-
function plainTransport(options) {
|
|
3166
|
-
const carrier = options.carrier;
|
|
3167
|
-
if (isExchangeCarrierSource(carrier)) return ExchangeTransport.create({
|
|
3168
|
-
openCarrier: carrier.open,
|
|
3169
|
-
getTransportCacheKey: carrier.getCacheKey,
|
|
3170
|
-
available: options.available,
|
|
3171
|
-
getRouteInfo: carrier.getRouteInfo,
|
|
3172
|
-
label: options.label ?? carrier.carrierLabel,
|
|
3173
|
-
updateRunConfig: options.updateRunConfig
|
|
3174
|
-
});
|
|
3175
|
-
return LinkTransport.create({
|
|
3176
|
-
openChannel: carrier.open,
|
|
3177
|
-
formatMessage: options.formatMessage,
|
|
3178
|
-
createFormatMessage: options.createFormatMessage,
|
|
3179
|
-
getTransportCacheKey: carrier.getCacheKey,
|
|
3180
|
-
available: options.available,
|
|
3181
|
-
getRouteInfo: carrier.getRouteInfo,
|
|
3182
|
-
label: options.label ?? carrier.carrierLabel,
|
|
3183
|
-
updateRunConfig: options.updateRunConfig
|
|
3184
|
-
});
|
|
3185
|
-
}
|
|
3186
|
-
//#endregion
|
|
3187
|
-
//#region src/ActionRuntime/Transport/secureTransport.ts
|
|
3188
|
-
function secureTransport(options) {
|
|
3189
|
-
const link = options.link ?? (options.storageAdapter != null ? new _nice_code_util.ClientCryptoKeyLink({ storageAdapter: options.storageAdapter }) : void 0);
|
|
3190
|
-
if (link == null) throw new Error("secureTransport: provide `link` or `storageAdapter` for the crypto identity.");
|
|
3191
|
-
const security = {
|
|
3192
|
-
securityLevel: options.securityLevel,
|
|
3193
|
-
link,
|
|
3194
|
-
localCoordinate: options.runtime.coordinate.toJsonObject(),
|
|
3195
|
-
dictionaryVersion: options.channel.dictionaryVersion
|
|
3196
|
-
};
|
|
3197
|
-
const carrier = options.carrier;
|
|
3198
|
-
if (isExchangeCarrierSource(carrier)) return ExchangeTransport.create({
|
|
3199
|
-
openCarrier: carrier.open,
|
|
3200
|
-
getTransportCacheKey: carrier.getCacheKey,
|
|
3201
|
-
available: options.available,
|
|
3202
|
-
getRouteInfo: carrier.getRouteInfo,
|
|
3203
|
-
label: carrier.carrierLabel,
|
|
3204
|
-
security
|
|
3205
|
-
});
|
|
3206
|
-
return LinkTransport.create({
|
|
3207
|
-
openChannel: carrier.open,
|
|
3208
|
-
createFormatMessage: options.channel.createCodec,
|
|
3209
|
-
getTransportCacheKey: carrier.getCacheKey,
|
|
3210
|
-
available: options.available,
|
|
3211
|
-
getRouteInfo: carrier.getRouteInfo,
|
|
3212
|
-
label: carrier.carrierLabel,
|
|
3213
|
-
security
|
|
3214
|
-
});
|
|
3215
|
-
}
|
|
3216
|
-
//#endregion
|
|
3217
|
-
//#region src/ActionRuntime/Channel/ActionChannel.ts
|
|
3218
|
-
/**
|
|
3219
|
-
* Declare a transport-agnostic channel by role. Use it for HTTP, custom transports, or as the routing
|
|
3220
|
-
* half of a richer channel. The order of each list is part of the contract for wire formats that pack
|
|
3221
|
-
* positionally (see `defineSecureChannel`) — add new domains to the end of their list. (`domains` is
|
|
3222
|
-
* accepted as a legacy alias for `toAcceptor`.)
|
|
3223
|
-
*/
|
|
3224
|
-
function defineChannel(options) {
|
|
3225
|
-
return {
|
|
3226
|
-
toAcceptorDomains: options.toAcceptor,
|
|
3227
|
-
toConnectorDomains: options.toConnector
|
|
3228
|
-
};
|
|
3229
|
-
}
|
|
3230
|
-
/**
|
|
3231
|
-
* Open a connection to a peer from a single call — the dial-out dual of `serveChannel`. The channel is
|
|
3232
|
-
* the single source of truth for *what* is routed (`toAcceptor` domains forwarded to the peer,
|
|
3233
|
-
* `toConnector` pushes handled locally from `onPush`); the call binds the shared facts — the channel's
|
|
3234
|
-
* codec/dictionary version, the runtime, and one crypto identity (a {@link ClientCryptoKeyLink} over
|
|
3235
|
-
* `storage`) — into every transport in `transports`, so none of them restate the channel or runtime.
|
|
3236
|
-
* List several transports to make the path transport-agnostic (secure WS preferred, HTTP fallback):
|
|
3237
|
-
* ```ts
|
|
3238
|
-
* const handler = connectChannel(runtime, lobbyChannel, {
|
|
3239
|
-
* peer: runtime_coordinate_lobby_do,
|
|
3240
|
-
* storage,
|
|
3241
|
-
* transports: [{ carrier: wsCarrier(() => ({ url })) }, { carrier: httpCarrier(...), secure: false }],
|
|
3242
|
-
* onPush: { player_joined: (p) => { … } },
|
|
3243
|
-
* });
|
|
3244
|
-
* ```
|
|
3245
|
-
* Returns the {@link ConnectorHandler} so the caller can later `clearTransportCache()` it.
|
|
3246
|
-
*/
|
|
3247
|
-
function connectChannel(runtime, channel, options) {
|
|
3248
|
-
const securityLevel = options.securityLevel ?? "authenticated";
|
|
3249
|
-
const anySecure = options.transports.some((transport) => transport.secure ?? true);
|
|
3250
|
-
let link = options.link;
|
|
3251
|
-
if (anySecure && link == null) {
|
|
3252
|
-
if (options.storage == null) throw new Error("connectChannel: a secure transport requires `storage` (or `link`). Pass it, or set `secure: false` on the transport for a plain connection.");
|
|
3253
|
-
link = new _nice_code_util.ClientCryptoKeyLink({ storageAdapter: options.storage });
|
|
3254
|
-
}
|
|
3255
|
-
const transports = options.transports.map((transport) => {
|
|
3256
|
-
const carrier = transport.carrier;
|
|
3257
|
-
const secure = transport.secure ?? true;
|
|
3258
|
-
if (isExchangeCarrierSource(carrier)) return secure ? secureTransport({
|
|
3259
|
-
channel,
|
|
3260
|
-
runtime,
|
|
3261
|
-
link,
|
|
3262
|
-
securityLevel: transport.securityLevel ?? securityLevel,
|
|
3263
|
-
available: transport.available,
|
|
3264
|
-
carrier
|
|
3265
|
-
}) : plainTransport({
|
|
3266
|
-
carrier,
|
|
3267
|
-
available: transport.available,
|
|
3268
|
-
label: transport.label
|
|
3269
|
-
});
|
|
3270
|
-
return secure ? secureTransport({
|
|
3271
|
-
channel,
|
|
3272
|
-
runtime,
|
|
3273
|
-
link,
|
|
3274
|
-
securityLevel: transport.securityLevel ?? securityLevel,
|
|
3275
|
-
available: transport.available,
|
|
3276
|
-
carrier
|
|
3277
|
-
}) : plainTransport({
|
|
3278
|
-
carrier,
|
|
3279
|
-
createFormatMessage: channel.createCodec,
|
|
3280
|
-
available: transport.available,
|
|
3281
|
-
label: transport.label
|
|
3282
|
-
});
|
|
3283
|
-
});
|
|
3284
|
-
const pushHandlers = options.onPush != null ? channel.toConnectorDomains.map((domain) => domain.wrapAsPartialLocalHandler(options.onPush)) : [];
|
|
3285
|
-
return runtime.connectTo(options.peer, {
|
|
3286
|
-
transports,
|
|
3287
|
-
domains: [...channel.toAcceptorDomains],
|
|
3288
|
-
localHandlers: pushHandlers,
|
|
3289
|
-
defaultTimeout: options.defaultTimeout
|
|
3290
|
-
});
|
|
3291
|
-
}
|
|
3292
|
-
/**
|
|
3293
|
-
* Register an acceptor handler's execution for a channel straight from its definition: the channel's
|
|
3294
|
-
* `toAcceptor` domains are served together with one merged, connection-aware case map (each case gets
|
|
3295
|
-
* the primed request + the originating connection, as with
|
|
3296
|
-
* {@link AcceptorHandler.forConnectionDomainCases}). The domain list is taken from the channel,
|
|
3297
|
-
* never restated. Add the returned handler to the runtime alongside the acceptor handler:
|
|
3298
|
-
* ```ts
|
|
3299
|
-
* runtime.addHandlers([acceptChannelConnections(serverHandler, channel, { … }), serverHandler]);
|
|
3300
|
-
* ```
|
|
3301
|
-
*
|
|
3302
|
-
* The case's second argument is the raw connection (`TConn | undefined`). For the richer state +
|
|
3303
|
-
* broadcast + pushBack context, serve the channel through `serveChannel`'s `channelCases` instead.
|
|
3304
|
-
*/
|
|
3305
|
-
function acceptChannelConnections(serverHandler, channel, cases) {
|
|
3306
|
-
return serverHandler.forConnectionDomainCasesMulti(channel.toAcceptorDomains, cases, (connection) => connection);
|
|
3307
|
-
}
|
|
3308
|
-
/**
|
|
3309
|
-
* Build the secure {@link AcceptorHandler} for a channel — the accept-in counterpart to
|
|
3310
|
-
* {@link connectChannel}. It folds in the same boilerplate as {@link createSecureAcceptorHandler} (the
|
|
3311
|
-
* `ClientCryptoKeyLink` + storage-backed TOFU resolver from one `storageAdapter`, the channel's codec +
|
|
3312
|
-
* dictionary version, the `security` block from the runtime coordinate) but takes the `(runtime, channel,
|
|
3313
|
-
* options)` shape of the channel family. Pair it with {@link acceptChannelConnections} for execution:
|
|
3314
|
-
* ```ts
|
|
3315
|
-
* const acceptor = acceptChannel(runtime, gameChannel, { clientEnv, storageAdapter, send });
|
|
3316
|
-
* runtime.addHandlers([acceptChannelConnections(acceptor, gameChannel, { … }), acceptor]);
|
|
3317
|
-
* ```
|
|
3318
|
-
*/
|
|
3319
|
-
function acceptChannel(runtime, channel, options) {
|
|
3320
|
-
return createSecureAcceptorHandler({
|
|
3321
|
-
channel,
|
|
3322
|
-
runtime,
|
|
3323
|
-
clientEnv: options.clientEnv,
|
|
3324
|
-
storageAdapter: options.storageAdapter,
|
|
3325
|
-
link: options.link,
|
|
3326
|
-
send: options.send,
|
|
3327
|
-
securityLevel: options.securityLevel,
|
|
3328
|
-
verifyKeyResolver: options.verifyKeyResolver,
|
|
3329
|
-
defaultTimeout: options.defaultTimeout
|
|
3330
|
-
});
|
|
3331
|
-
}
|
|
3332
|
-
//#endregion
|
|
3333
3383
|
//#region src/ActionRuntime/Transport/SecureSession/exchangeAcceptor.ts
|
|
3334
3384
|
const textEncoder = new TextEncoder();
|
|
3335
3385
|
const textDecoder = new TextDecoder();
|
|
@@ -3667,242 +3717,6 @@ function createHibernatableWsServerAdapter(options) {
|
|
|
3667
3717
|
};
|
|
3668
3718
|
}
|
|
3669
3719
|
//#endregion
|
|
3670
|
-
//#region src/ActionRuntime/Transport/Carrier/AcceptorCarrier.types.ts
|
|
3671
|
-
/**
|
|
3672
|
-
* Build the inert lifecycle slot a duplex carrier factory spreads into its handle: `receive`/`drop` throw
|
|
3673
|
-
* (or no-op) until `serveChannel` calls `_activate` with the carrier's live router. Shared by every duplex
|
|
3674
|
-
* carrier factory (`wsAcceptorCarrier`, a WebRTC carrier, the Cloudflare DO helper, …) so the
|
|
3675
|
-
* stateful-handle wiring lives in exactly one place.
|
|
3676
|
-
*/
|
|
3677
|
-
function createDuplexCarrierLifecycle() {
|
|
3678
|
-
let router;
|
|
3679
|
-
return {
|
|
3680
|
-
receive(connection, frame) {
|
|
3681
|
-
if (router == null) throw new Error("acceptor carrier not served yet — pass it to serveChannel() before feeding frames");
|
|
3682
|
-
router.receive(connection, frame);
|
|
3683
|
-
},
|
|
3684
|
-
drop(connection) {
|
|
3685
|
-
router?.drop(connection);
|
|
3686
|
-
},
|
|
3687
|
-
_activate(liveRouter) {
|
|
3688
|
-
router = liveRouter;
|
|
3689
|
-
}
|
|
3690
|
-
};
|
|
3691
|
-
}
|
|
3692
|
-
/**
|
|
3693
|
-
* Narrow an acceptor carrier to the exchange shape via its `shape` discriminant — the one branch
|
|
3694
|
-
* `serveChannel` uses to pick the duplex (push-capable) vs exchange (request/reply) wiring. A duplex
|
|
3695
|
-
* carrier carries `shape: ETransportShape.duplex`, so the `else` branch is the duplex one.
|
|
3696
|
-
*/
|
|
3697
|
-
function isExchangeAcceptorCarrier(carrier) {
|
|
3698
|
-
return carrier.shape === "exchange";
|
|
3699
|
-
}
|
|
3700
|
-
//#endregion
|
|
3701
|
-
//#region src/ActionRuntime/Channel/serveChannel.ts
|
|
3702
|
-
/** Default accepted set, shared by every carrier: negotiate per connection to whatever the client picks. */
|
|
3703
|
-
const DEFAULT_SERVER_SECURITY_LEVELS = [
|
|
3704
|
-
"none",
|
|
3705
|
-
"authenticated",
|
|
3706
|
-
"encrypted"
|
|
3707
|
-
];
|
|
3708
|
-
function serveChannel(runtime, channel, options) {
|
|
3709
|
-
const duplexCarriers = options.carriers.filter((carrier) => !isExchangeAcceptorCarrier(carrier));
|
|
3710
|
-
const exchangeCarriers = options.carriers.filter(isExchangeAcceptorCarrier);
|
|
3711
|
-
if (exchangeCarriers.length > 1) throw new Error("serveChannel: at most one exchange carrier is supported");
|
|
3712
|
-
const exchangeCarrier = exchangeCarriers[0];
|
|
3713
|
-
const singleDuplex = duplexCarriers.length === 1;
|
|
3714
|
-
if (options.connectionState != null && !singleDuplex) throw new Error("serveChannel: `connectionState` requires exactly one duplex carrier");
|
|
3715
|
-
if (options.channelCases != null && !singleDuplex) throw new Error("serveChannel: `channelCases` requires exactly one duplex carrier");
|
|
3716
|
-
const exchangeSecure = exchangeCarrier != null && (exchangeCarrier.secure ?? true);
|
|
3717
|
-
const anyDuplexSecure = duplexCarriers.some((carrier) => carrier.secure ?? true);
|
|
3718
|
-
const securityLevel = options.securityLevel ?? DEFAULT_SERVER_SECURITY_LEVELS;
|
|
3719
|
-
let secure;
|
|
3720
|
-
if (anyDuplexSecure || exchangeSecure) {
|
|
3721
|
-
const storage = options.storage;
|
|
3722
|
-
if (storage == null) throw new Error("serveChannel: a secure carrier requires `storage`. Pass it, or set `secure: false` on the carrier for a plain endpoint.");
|
|
3723
|
-
secure = {
|
|
3724
|
-
storage,
|
|
3725
|
-
link: options.link ?? new _nice_code_util.ClientCryptoKeyLink({ storageAdapter: storage }),
|
|
3726
|
-
verifyKeyResolver: options.verifyKeyResolver ?? createStorageTofuVerifyKeyResolver(storage)
|
|
3727
|
-
};
|
|
3728
|
-
}
|
|
3729
|
-
const plainRouter = (handler) => ({
|
|
3730
|
-
receive: (connection, frame) => handler.receive(connection, frame),
|
|
3731
|
-
drop: (connection) => handler.dropConnection(connection)
|
|
3732
|
-
});
|
|
3733
|
-
const asObject = (value) => typeof value === "object" && value != null ? value : {};
|
|
3734
|
-
const handlers = [];
|
|
3735
|
-
let connections;
|
|
3736
|
-
for (const carrier of duplexCarriers) {
|
|
3737
|
-
const handler = (carrier.secure ?? true) && secure != null ? acceptChannel(runtime, channel, {
|
|
3738
|
-
clientEnv: options.clientEnv,
|
|
3739
|
-
storageAdapter: secure.storage,
|
|
3740
|
-
link: secure.link,
|
|
3741
|
-
verifyKeyResolver: secure.verifyKeyResolver,
|
|
3742
|
-
securityLevel,
|
|
3743
|
-
send: carrier.send,
|
|
3744
|
-
defaultTimeout: options.defaultTimeout
|
|
3745
|
-
}) : createAcceptorHandler({
|
|
3746
|
-
clientEnv: options.clientEnv,
|
|
3747
|
-
createFormatMessage: channel.createCodec,
|
|
3748
|
-
send: carrier.send,
|
|
3749
|
-
runtime,
|
|
3750
|
-
defaultTimeout: options.defaultTimeout
|
|
3751
|
-
});
|
|
3752
|
-
const attach = carrier.attachmentStore;
|
|
3753
|
-
let router;
|
|
3754
|
-
if (attach == null) router = plainRouter(handler);
|
|
3755
|
-
else if (options.connectionState != null) {
|
|
3756
|
-
connections = createConnectionStateStore(handler, {
|
|
3757
|
-
schema: options.connectionState.schema,
|
|
3758
|
-
getConnections: attach.getConnections,
|
|
3759
|
-
read: attach.read,
|
|
3760
|
-
write: attach.write
|
|
3761
|
-
});
|
|
3762
|
-
router = plainRouter(handler);
|
|
3763
|
-
} else router = createHibernatableWsServerAdapter({
|
|
3764
|
-
handler,
|
|
3765
|
-
getConnections: attach.getConnections,
|
|
3766
|
-
getAttachment: (connection) => attach.read(connection)?.binding,
|
|
3767
|
-
setAttachment: (connection, binding) => attach.write(connection, {
|
|
3768
|
-
...asObject(attach.read(connection)),
|
|
3769
|
-
binding
|
|
3770
|
-
})
|
|
3771
|
-
});
|
|
3772
|
-
carrier._activate(router);
|
|
3773
|
-
handlers.push(handler);
|
|
3774
|
-
}
|
|
3775
|
-
runtime.addHandlers([...options.handlers ?? [], ...handlers]);
|
|
3776
|
-
const soleDuplex = singleDuplex ? duplexCarriers[0] : void 0;
|
|
3777
|
-
const receive = (connection, frame) => {
|
|
3778
|
-
if (soleDuplex == null) throw new Error(duplexCarriers.length === 0 ? "serveChannel: no duplex carrier to receive on (this server has no socket transport)" : "serveChannel: several duplex carriers — feed each carrier handle's receive() directly");
|
|
3779
|
-
soleDuplex.receive(connection, frame);
|
|
3780
|
-
};
|
|
3781
|
-
const drop = (connection) => {
|
|
3782
|
-
soleDuplex?.drop(connection);
|
|
3783
|
-
};
|
|
3784
|
-
const pushToClient = (target, request, pushOptions) => {
|
|
3785
|
-
const owner = target instanceof RuntimeCoordinate ? handlers.find((handler) => handler.ownsLiveConnectionFor(target)) : handlers.find((handler) => handler.hasConnection(target));
|
|
3786
|
-
if (owner == null) throw new Error("serveChannel: no duplex carrier holds a connection for the push target");
|
|
3787
|
-
return owner.pushToClient(runtime, target, request, pushOptions);
|
|
3788
|
-
};
|
|
3789
|
-
const broadcast = (makeRequest, broadcastOptions) => {
|
|
3790
|
-
if (!singleDuplex) throw new Error("serveChannel: broadcast requires exactly one duplex carrier — broadcast over a specific handlers[i] instead");
|
|
3791
|
-
handlers[0].broadcast(makeRequest, {
|
|
3792
|
-
runtime,
|
|
3793
|
-
...broadcastOptions
|
|
3794
|
-
});
|
|
3795
|
-
};
|
|
3796
|
-
const makeConnectionContext = (connection, request) => ({
|
|
3797
|
-
connection: connection ?? null,
|
|
3798
|
-
origin: request.context.originClient,
|
|
3799
|
-
get state() {
|
|
3800
|
-
return connection != null && connections != null ? connections.get(connection) : null;
|
|
3801
|
-
},
|
|
3802
|
-
setState(value) {
|
|
3803
|
-
if (connection != null && connections != null) connections.set(connection, value);
|
|
3804
|
-
},
|
|
3805
|
-
clearState() {
|
|
3806
|
-
if (connection != null && connections != null) connections.clearApp(connection);
|
|
3807
|
-
},
|
|
3808
|
-
broadcast(makeRequest, contextOptions) {
|
|
3809
|
-
broadcast(makeRequest, {
|
|
3810
|
-
except: contextOptions?.exceptSelf ? connection ?? null : null,
|
|
3811
|
-
where: contextOptions?.where,
|
|
3812
|
-
timeout: contextOptions?.timeout,
|
|
3813
|
-
onError: contextOptions?.onError
|
|
3814
|
-
});
|
|
3815
|
-
},
|
|
3816
|
-
pushBack(pushRequest, pushOptions) {
|
|
3817
|
-
if (connection == null) throw new Error("serveChannel: connection context has no live socket to push back to (HTTP-exchange path)");
|
|
3818
|
-
return pushToClient(connection, pushRequest, pushOptions);
|
|
3819
|
-
}
|
|
3820
|
-
});
|
|
3821
|
-
if (options.channelCases != null) runtime.addHandlers([handlers[0].forConnectionDomainCasesMulti(channel.toAcceptorDomains, options.channelCases, makeConnectionContext)]);
|
|
3822
|
-
const exchangeSecurity = exchangeSecure && secure != null ? {
|
|
3823
|
-
link: secure.link,
|
|
3824
|
-
verifyKeyResolver: secure.verifyKeyResolver,
|
|
3825
|
-
localCoordinate: runtime.coordinate.toJsonObject(),
|
|
3826
|
-
dictionaryVersion: channel.dictionaryVersion,
|
|
3827
|
-
securityLevel
|
|
3828
|
-
} : void 0;
|
|
3829
|
-
const defaultIsUpgrade = (request) => request.headers.get("Upgrade") === "websocket";
|
|
3830
|
-
const upgraders = [];
|
|
3831
|
-
for (const carrier of duplexCarriers) {
|
|
3832
|
-
if (carrier.upgrade == null) continue;
|
|
3833
|
-
upgraders.push({
|
|
3834
|
-
isUpgrade: carrier.isUpgrade ?? defaultIsUpgrade,
|
|
3835
|
-
upgrade: carrier.upgrade
|
|
3836
|
-
});
|
|
3837
|
-
}
|
|
3838
|
-
return {
|
|
3839
|
-
handlers,
|
|
3840
|
-
fetch: createActionFetchHandler(runtime, {
|
|
3841
|
-
cors: exchangeCarrier?.cors,
|
|
3842
|
-
onWebSocketUpgrade: upgraders.length === 0 ? void 0 : (request, url) => (upgraders.find((u) => u.isUpgrade(request, url)) ?? upgraders[0]).upgrade(request, url),
|
|
3843
|
-
isWebSocketUpgrade: upgraders.length === 0 ? void 0 : (request, url) => upgraders.some((u) => u.isUpgrade(request, url)),
|
|
3844
|
-
isActionPath: exchangeCarrier != null ? exchangeCarrier.isActionPath ?? (() => true) : () => false,
|
|
3845
|
-
security: exchangeSecurity,
|
|
3846
|
-
useErrorStatus: exchangeCarrier?.useErrorStatus
|
|
3847
|
-
}),
|
|
3848
|
-
receive,
|
|
3849
|
-
drop,
|
|
3850
|
-
pushToClient,
|
|
3851
|
-
broadcast,
|
|
3852
|
-
connections
|
|
3853
|
-
};
|
|
3854
|
-
}
|
|
3855
|
-
//#endregion
|
|
3856
|
-
//#region src/ActionRuntime/Channel/serveHost.ts
|
|
3857
|
-
function serveHost(runtime, channel, host, options) {
|
|
3858
|
-
const server = serveChannel(runtime, channel, {
|
|
3859
|
-
...options,
|
|
3860
|
-
carriers: host.carriers,
|
|
3861
|
-
storage: host.storage
|
|
3862
|
-
});
|
|
3863
|
-
host.onServed?.(server);
|
|
3864
|
-
return server;
|
|
3865
|
-
}
|
|
3866
|
-
//#endregion
|
|
3867
|
-
//#region src/ActionRuntime/Transport/Carrier/duplex/ws/wsAcceptorCarrier.ts
|
|
3868
|
-
/**
|
|
3869
|
-
* A WebSocket {@link IDuplexAcceptorCarrier}: the accept-in dual of {@link wsCarrier}. It describes how to
|
|
3870
|
-
* write frames back to a live socket, how to upgrade an inbound request into one, and (optionally) how to
|
|
3871
|
-
* persist bindings across hibernation. Hand it to `serveChannel`'s `carriers` list — the secure session,
|
|
3872
|
-
* codec, and crypto identity are supplied centrally there, so this only carries the WS-specific surface.
|
|
3873
|
-
*/
|
|
3874
|
-
function wsAcceptorCarrier(options) {
|
|
3875
|
-
return {
|
|
3876
|
-
...createDuplexCarrierLifecycle(),
|
|
3877
|
-
shape: "duplex",
|
|
3878
|
-
carrierLabel: options.carrierLabel ?? "ws",
|
|
3879
|
-
secure: options.secure,
|
|
3880
|
-
send: options.send,
|
|
3881
|
-
upgrade: options.upgrade,
|
|
3882
|
-
isUpgrade: options.isUpgrade ?? ((request) => request.headers.get("Upgrade") === "websocket"),
|
|
3883
|
-
attachmentStore: options.attachmentStore
|
|
3884
|
-
};
|
|
3885
|
-
}
|
|
3886
|
-
//#endregion
|
|
3887
|
-
//#region src/ActionRuntime/Transport/Carrier/exchange/http/httpAcceptorCarrier.ts
|
|
3888
|
-
/**
|
|
3889
|
-
* An HTTP {@link IExchangeAcceptorCarrier}: the accept-in dual of {@link httpCarrier}. It serves the
|
|
3890
|
-
* secure exchange protocol (handshake → token session → encrypted frames) over web-standard
|
|
3891
|
-
* `Request`/`Response`. The crypto identity, runtime coordinate, dictionary version, and accepted security
|
|
3892
|
-
* levels are all supplied centrally by `serveChannel`, so this only needs to say which requests carry an
|
|
3893
|
-
* action envelope and how to answer CORS.
|
|
3894
|
-
*/
|
|
3895
|
-
function httpAcceptorCarrier(options = {}) {
|
|
3896
|
-
return {
|
|
3897
|
-
shape: "exchange",
|
|
3898
|
-
carrierLabel: options.carrierLabel ?? "http",
|
|
3899
|
-
secure: options.secure,
|
|
3900
|
-
isActionPath: options.isActionPath,
|
|
3901
|
-
cors: options.cors,
|
|
3902
|
-
useErrorStatus: options.useErrorStatus
|
|
3903
|
-
};
|
|
3904
|
-
}
|
|
3905
|
-
//#endregion
|
|
3906
3720
|
Object.defineProperty(exports, "AcceptorHandler", {
|
|
3907
3721
|
enumerable: true,
|
|
3908
3722
|
get: function() {
|
|
@@ -4035,58 +3849,58 @@ Object.defineProperty(exports, "LinkTransport", {
|
|
|
4035
3849
|
return LinkTransport;
|
|
4036
3850
|
}
|
|
4037
3851
|
});
|
|
4038
|
-
Object.defineProperty(exports, "
|
|
3852
|
+
Object.defineProperty(exports, "PayloadTypeToInt", {
|
|
4039
3853
|
enumerable: true,
|
|
4040
3854
|
get: function() {
|
|
4041
|
-
return
|
|
3855
|
+
return PayloadTypeToInt;
|
|
4042
3856
|
}
|
|
4043
3857
|
});
|
|
4044
|
-
Object.defineProperty(exports, "
|
|
3858
|
+
Object.defineProperty(exports, "PeerLinkHandler", {
|
|
4045
3859
|
enumerable: true,
|
|
4046
3860
|
get: function() {
|
|
4047
|
-
return
|
|
3861
|
+
return PeerLinkHandler;
|
|
4048
3862
|
}
|
|
4049
3863
|
});
|
|
4050
|
-
Object.defineProperty(exports, "
|
|
3864
|
+
Object.defineProperty(exports, "ReversePayloadType", {
|
|
4051
3865
|
enumerable: true,
|
|
4052
3866
|
get: function() {
|
|
4053
|
-
return
|
|
3867
|
+
return ReversePayloadType;
|
|
4054
3868
|
}
|
|
4055
3869
|
});
|
|
4056
|
-
Object.defineProperty(exports, "
|
|
3870
|
+
Object.defineProperty(exports, "RunningAction", {
|
|
4057
3871
|
enumerable: true,
|
|
4058
3872
|
get: function() {
|
|
4059
|
-
return
|
|
3873
|
+
return RunningAction;
|
|
4060
3874
|
}
|
|
4061
3875
|
});
|
|
4062
|
-
Object.defineProperty(exports, "
|
|
3876
|
+
Object.defineProperty(exports, "RuntimeCoordinate", {
|
|
4063
3877
|
enumerable: true,
|
|
4064
3878
|
get: function() {
|
|
4065
|
-
return
|
|
3879
|
+
return RuntimeCoordinate;
|
|
4066
3880
|
}
|
|
4067
3881
|
});
|
|
4068
|
-
Object.defineProperty(exports, "
|
|
3882
|
+
Object.defineProperty(exports, "Transport", {
|
|
4069
3883
|
enumerable: true,
|
|
4070
3884
|
get: function() {
|
|
4071
|
-
return
|
|
3885
|
+
return Transport;
|
|
4072
3886
|
}
|
|
4073
3887
|
});
|
|
4074
|
-
Object.defineProperty(exports, "
|
|
3888
|
+
Object.defineProperty(exports, "actionSchema", {
|
|
4075
3889
|
enumerable: true,
|
|
4076
3890
|
get: function() {
|
|
4077
|
-
return
|
|
3891
|
+
return actionSchema;
|
|
4078
3892
|
}
|
|
4079
3893
|
});
|
|
4080
|
-
Object.defineProperty(exports, "
|
|
3894
|
+
Object.defineProperty(exports, "assembleWireJson", {
|
|
4081
3895
|
enumerable: true,
|
|
4082
3896
|
get: function() {
|
|
4083
|
-
return
|
|
3897
|
+
return assembleWireJson;
|
|
4084
3898
|
}
|
|
4085
3899
|
});
|
|
4086
|
-
Object.defineProperty(exports, "
|
|
3900
|
+
Object.defineProperty(exports, "buildActionRouteDictionary", {
|
|
4087
3901
|
enumerable: true,
|
|
4088
3902
|
get: function() {
|
|
4089
|
-
return
|
|
3903
|
+
return buildActionRouteDictionary;
|
|
4090
3904
|
}
|
|
4091
3905
|
});
|
|
4092
3906
|
Object.defineProperty(exports, "createAcceptorHandler", {
|
|
@@ -4107,6 +3921,12 @@ Object.defineProperty(exports, "createActionFrameCrypto", {
|
|
|
4107
3921
|
return createActionFrameCrypto;
|
|
4108
3922
|
}
|
|
4109
3923
|
});
|
|
3924
|
+
Object.defineProperty(exports, "createBinaryWireSessionFactory", {
|
|
3925
|
+
enumerable: true,
|
|
3926
|
+
get: function() {
|
|
3927
|
+
return createBinaryWireSessionFactory;
|
|
3928
|
+
}
|
|
3929
|
+
});
|
|
4110
3930
|
Object.defineProperty(exports, "createClientHandshake", {
|
|
4111
3931
|
enumerable: true,
|
|
4112
3932
|
get: function() {
|
|
@@ -4185,12 +4005,6 @@ Object.defineProperty(exports, "decodeHandshakeMessage", {
|
|
|
4185
4005
|
return decodeHandshakeMessage;
|
|
4186
4006
|
}
|
|
4187
4007
|
});
|
|
4188
|
-
Object.defineProperty(exports, "defineChannel", {
|
|
4189
|
-
enumerable: true,
|
|
4190
|
-
get: function() {
|
|
4191
|
-
return defineChannel;
|
|
4192
|
-
}
|
|
4193
|
-
});
|
|
4194
4008
|
Object.defineProperty(exports, "encodeExchange", {
|
|
4195
4009
|
enumerable: true,
|
|
4196
4010
|
get: function() {
|
|
@@ -4221,10 +4035,10 @@ Object.defineProperty(exports, "err_nice_transport", {
|
|
|
4221
4035
|
return err_nice_transport;
|
|
4222
4036
|
}
|
|
4223
4037
|
});
|
|
4224
|
-
Object.defineProperty(exports, "
|
|
4038
|
+
Object.defineProperty(exports, "extractWirePayload", {
|
|
4225
4039
|
enumerable: true,
|
|
4226
4040
|
get: function() {
|
|
4227
|
-
return
|
|
4041
|
+
return extractWirePayload;
|
|
4228
4042
|
}
|
|
4229
4043
|
});
|
|
4230
4044
|
Object.defineProperty(exports, "isActionPayload_Any_JsonObject", {
|
|
@@ -4251,12 +4065,6 @@ Object.defineProperty(exports, "isAction_Base_JsonObject", {
|
|
|
4251
4065
|
return isAction_Base_JsonObject;
|
|
4252
4066
|
}
|
|
4253
4067
|
});
|
|
4254
|
-
Object.defineProperty(exports, "isExchangeAcceptorCarrier", {
|
|
4255
|
-
enumerable: true,
|
|
4256
|
-
get: function() {
|
|
4257
|
-
return isExchangeAcceptorCarrier;
|
|
4258
|
-
}
|
|
4259
|
-
});
|
|
4260
4068
|
Object.defineProperty(exports, "runtimeCoordinateToStringIds", {
|
|
4261
4069
|
enumerable: true,
|
|
4262
4070
|
get: function() {
|
|
@@ -4269,23 +4077,5 @@ Object.defineProperty(exports, "runtimeLinkId", {
|
|
|
4269
4077
|
return runtimeLinkId;
|
|
4270
4078
|
}
|
|
4271
4079
|
});
|
|
4272
|
-
Object.defineProperty(exports, "serveChannel", {
|
|
4273
|
-
enumerable: true,
|
|
4274
|
-
get: function() {
|
|
4275
|
-
return serveChannel;
|
|
4276
|
-
}
|
|
4277
|
-
});
|
|
4278
|
-
Object.defineProperty(exports, "serveHost", {
|
|
4279
|
-
enumerable: true,
|
|
4280
|
-
get: function() {
|
|
4281
|
-
return serveHost;
|
|
4282
|
-
}
|
|
4283
|
-
});
|
|
4284
|
-
Object.defineProperty(exports, "wsAcceptorCarrier", {
|
|
4285
|
-
enumerable: true,
|
|
4286
|
-
get: function() {
|
|
4287
|
-
return wsAcceptorCarrier;
|
|
4288
|
-
}
|
|
4289
|
-
});
|
|
4290
4080
|
|
|
4291
|
-
//# sourceMappingURL=
|
|
4081
|
+
//# sourceMappingURL=createHibernatableWsServerAdapter-FSDWrxoF.cjs.map
|