@nice-code/action 0.16.0 → 0.17.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 +2 -2
- package/build/{ActionDevtoolsCore-B3JwSaRH.d.cts → ActionDevtoolsCore-C5XrQI1K.d.mts} +2 -2
- package/build/{ActionDevtoolsCore-C4TDUY7-.d.mts → ActionDevtoolsCore-Dd1qJAwK.d.cts} +2 -2
- package/build/{ActionPayload.types-CO_hXlBc.d.cts → ActionPayload.types-BchJrBIX.d.mts} +468 -152
- package/build/{ActionPayload.types-fieMKAgt.d.mts → ActionPayload.types-snDlSIF-.d.cts} +468 -152
- 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/index.cjs +224 -79
- 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 +219 -78
- package/build/index.mjs.map +1 -1
- package/build/platform/cloudflare/index.cjs +56 -0
- package/build/platform/cloudflare/index.cjs.map +1 -0
- package/build/platform/cloudflare/index.d.cts +67 -0
- package/build/platform/cloudflare/index.d.mts +67 -0
- package/build/platform/cloudflare/index.mjs +54 -0
- package/build/platform/cloudflare/index.mjs.map +1 -0
- package/build/react-query/index.d.cts +1 -1
- package/build/react-query/index.d.mts +1 -1
- package/build/wsAcceptorCarrier-CXGlQU_f.mjs +80 -0
- package/build/wsAcceptorCarrier-CXGlQU_f.mjs.map +1 -0
- package/build/wsAcceptorCarrier-DHRbsY1X.cjs +103 -0
- package/build/wsAcceptorCarrier-DHRbsY1X.cjs.map +1 -0
- package/package.json +15 -4
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as TDevtoolsActionStatus, i as IDevtoolsObservableDomain, n as IActionDevtoolsCoreOptions, o as TDevtoolsListener, r as IDevtoolsActionEntry, s as TDevtoolsPosition, t as ActionDevtoolsCore } from "../../ActionDevtoolsCore-
|
|
1
|
+
import { a as TDevtoolsActionStatus, i as IDevtoolsObservableDomain, n as IActionDevtoolsCoreOptions, o as TDevtoolsListener, r as IDevtoolsActionEntry, s as TDevtoolsPosition, t as ActionDevtoolsCore } from "../../ActionDevtoolsCore-Dd1qJAwK.cjs";
|
|
2
2
|
|
|
3
3
|
//#region src/devtools/browser/NiceActionDevtools.d.ts
|
|
4
4
|
interface INiceActionDevtoolsProps {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as TDevtoolsActionStatus, i as IDevtoolsObservableDomain, n as IActionDevtoolsCoreOptions, o as TDevtoolsListener, r as IDevtoolsActionEntry, s as TDevtoolsPosition, t as ActionDevtoolsCore } from "../../ActionDevtoolsCore-
|
|
1
|
+
import { a as TDevtoolsActionStatus, i as IDevtoolsObservableDomain, n as IActionDevtoolsCoreOptions, o as TDevtoolsListener, r as IDevtoolsActionEntry, s as TDevtoolsPosition, t as ActionDevtoolsCore } from "../../ActionDevtoolsCore-C5XrQI1K.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/devtools/browser/NiceActionDevtools.d.ts
|
|
4
4
|
interface INiceActionDevtoolsProps {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as TDevtoolsActionStatus, i as IDevtoolsObservableDomain, n as IActionDevtoolsCoreOptions, o as TDevtoolsListener, r as IDevtoolsActionEntry, t as ActionDevtoolsCore } from "../../ActionDevtoolsCore-
|
|
1
|
+
import { a as TDevtoolsActionStatus, i as IDevtoolsObservableDomain, n as IActionDevtoolsCoreOptions, o as TDevtoolsListener, r as IDevtoolsActionEntry, t as ActionDevtoolsCore } from "../../ActionDevtoolsCore-Dd1qJAwK.cjs";
|
|
2
2
|
|
|
3
3
|
//#region src/devtools/server/NiceActionServerDevtools.d.ts
|
|
4
4
|
type TServerDevtoolsLogFn = (message: string, data?: Record<string, unknown>) => void;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as TDevtoolsActionStatus, i as IDevtoolsObservableDomain, n as IActionDevtoolsCoreOptions, o as TDevtoolsListener, r as IDevtoolsActionEntry, t as ActionDevtoolsCore } from "../../ActionDevtoolsCore-
|
|
1
|
+
import { a as TDevtoolsActionStatus, i as IDevtoolsObservableDomain, n as IActionDevtoolsCoreOptions, o as TDevtoolsListener, r as IDevtoolsActionEntry, t as ActionDevtoolsCore } from "../../ActionDevtoolsCore-C5XrQI1K.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/devtools/server/NiceActionServerDevtools.d.ts
|
|
4
4
|
type TServerDevtoolsLogFn = (message: string, data?: Record<string, unknown>) => void;
|
package/build/index.cjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_rolldown_runtime = require("./rolldown-runtime-emK7D4bc.cjs");
|
|
3
3
|
const require_RunningAction_types = require("./RunningAction.types-DjCX1xp5.cjs");
|
|
4
|
+
const require_wsAcceptorCarrier = require("./wsAcceptorCarrier-DHRbsY1X.cjs");
|
|
4
5
|
let nanoid = require("nanoid");
|
|
5
6
|
let _nice_code_error = require("@nice-code/error");
|
|
6
7
|
let _nice_code_common_errors = require("@nice-code/common-errors");
|
|
@@ -854,32 +855,6 @@ const err_nice_transport = err_nice_external_client.createChildDomain({
|
|
|
854
855
|
}
|
|
855
856
|
});
|
|
856
857
|
//#endregion
|
|
857
|
-
//#region src/ActionRuntime/Transport/Transport.types.ts
|
|
858
|
-
/**
|
|
859
|
-
* Carrier-shape class identity: the one carrier-invariant trait the selection layer reasons about —
|
|
860
|
-
* whether a carrier can push unsolicited frames (`duplex`: WS/WebRTC/BLE/in-memory) or only answers a
|
|
861
|
-
* request with a single correlated reply (`exchange`: HTTP). The concrete carrier kind ("ws", "webrtc",
|
|
862
|
-
* "http", …) is a free-form {@link ITransportRouteInfo.carrierLabel} for display, not a class tag.
|
|
863
|
-
*/
|
|
864
|
-
let ETransportShape = /* @__PURE__ */ function(ETransportShape) {
|
|
865
|
-
ETransportShape["duplex"] = "duplex";
|
|
866
|
-
ETransportShape["exchange"] = "exchange";
|
|
867
|
-
return ETransportShape;
|
|
868
|
-
}({});
|
|
869
|
-
/**
|
|
870
|
-
*
|
|
871
|
-
* TRANSPORT READINESS RESPONSE
|
|
872
|
-
*
|
|
873
|
-
*/
|
|
874
|
-
let ETransportStatus = /* @__PURE__ */ function(ETransportStatus) {
|
|
875
|
-
ETransportStatus["uninitialized"] = "uninitialized";
|
|
876
|
-
ETransportStatus["unsupported"] = "unsupported";
|
|
877
|
-
ETransportStatus["initializing"] = "initializing";
|
|
878
|
-
ETransportStatus["ready"] = "ready";
|
|
879
|
-
ETransportStatus["failed"] = "failed";
|
|
880
|
-
return ETransportStatus;
|
|
881
|
-
}({});
|
|
882
|
-
//#endregion
|
|
883
858
|
//#region src/ActionRuntime/Transport/ConnectionTransportManager.ts
|
|
884
859
|
var ConnectionTransportManager = class {
|
|
885
860
|
_cache;
|
|
@@ -1199,6 +1174,16 @@ var PeerLinkHandler = class extends ActionHandler {
|
|
|
1199
1174
|
_emitIncoming(json) {
|
|
1200
1175
|
for (const listener of this._incomingActionDataListeners) listener(json);
|
|
1201
1176
|
}
|
|
1177
|
+
/**
|
|
1178
|
+
* Whether this handler currently holds a *live* connection bound to `origin`. The runtime's return-path
|
|
1179
|
+
* dispatch ({@link ActionRuntime.getReturnHandlerForOrigin}) prefers a handler that owns the origin's
|
|
1180
|
+
* connection over a mere coordinate match, so with several duplex acceptors a result/push routes back
|
|
1181
|
+
* over the carrier the client connected on. Defaults to `false`; an acceptor overrides it from its
|
|
1182
|
+
* connection registry.
|
|
1183
|
+
*/
|
|
1184
|
+
ownsLiveConnectionFor(_origin) {
|
|
1185
|
+
return false;
|
|
1186
|
+
}
|
|
1202
1187
|
/** Release any long-lived connections this handler owns (a teardown). No-op by default. */
|
|
1203
1188
|
clearTransportCache() {}
|
|
1204
1189
|
};
|
|
@@ -1509,11 +1494,19 @@ var ActionRuntime = class {
|
|
|
1509
1494
|
* Find the best registered external handler that can reach `originClient` directly.
|
|
1510
1495
|
* Used to locate the return-path channel for dispatching results back to the action origin.
|
|
1511
1496
|
* Returns `undefined` if no handler matches (score > 0 required, i.e. at least id must match).
|
|
1497
|
+
*
|
|
1498
|
+
* A handler that currently holds the origin's *live* connection always wins over a mere coordinate
|
|
1499
|
+
* match — so with several duplex acceptors (e.g. WS + WebRTC) a result/push routes back over the carrier
|
|
1500
|
+
* the client actually connected on, never a same-coordinate sibling that lacks the socket. Only when no
|
|
1501
|
+
* handler owns a live connection do we fall back to the plain best-coordinate-score pick (the
|
|
1502
|
+
* single-acceptor and connector-only cases, unchanged).
|
|
1512
1503
|
*/
|
|
1513
1504
|
getReturnHandlerForOrigin(originClient) {
|
|
1514
1505
|
if (originClient.envId === "_unset_") return void 0;
|
|
1515
1506
|
let bestScore = -1;
|
|
1516
1507
|
let bestHandler;
|
|
1508
|
+
let bestOwnedScore = -1;
|
|
1509
|
+
let bestOwnedHandler;
|
|
1517
1510
|
for (const handler of this._registeredPeerHandlers) {
|
|
1518
1511
|
if (!handler.canPush) continue;
|
|
1519
1512
|
const score = originClient.similarityLevel(handler.peerClient);
|
|
@@ -1521,7 +1514,12 @@ var ActionRuntime = class {
|
|
|
1521
1514
|
bestScore = score;
|
|
1522
1515
|
bestHandler = handler;
|
|
1523
1516
|
}
|
|
1517
|
+
if (score > bestOwnedScore && handler.ownsLiveConnectionFor(originClient)) {
|
|
1518
|
+
bestOwnedScore = score;
|
|
1519
|
+
bestOwnedHandler = handler;
|
|
1520
|
+
}
|
|
1524
1521
|
}
|
|
1522
|
+
if (bestOwnedHandler != null && bestOwnedScore > 0) return bestOwnedHandler;
|
|
1525
1523
|
return bestScore > 0 ? bestHandler : void 0;
|
|
1526
1524
|
}
|
|
1527
1525
|
resetRuntime() {
|
|
@@ -2781,6 +2779,14 @@ var AcceptorHandler = class extends PeerLinkHandler {
|
|
|
2781
2779
|
getConnectionForClient(client) {
|
|
2782
2780
|
return this._connByClient.get(client.stringId);
|
|
2783
2781
|
}
|
|
2782
|
+
/** This acceptor owns the origin's return path when it currently holds a live connection bound to it. */
|
|
2783
|
+
ownsLiveConnectionFor(origin) {
|
|
2784
|
+
return this._connByClient.has(origin.stringId);
|
|
2785
|
+
}
|
|
2786
|
+
/** Whether this acceptor currently tracks `connection` — used to pick the owning handler among several. */
|
|
2787
|
+
hasConnection(connection) {
|
|
2788
|
+
return this._clientByConn.has(connection);
|
|
2789
|
+
}
|
|
2784
2790
|
/**
|
|
2785
2791
|
* Send (and optionally await) a server-initiated action to a specific connected client. Pass the
|
|
2786
2792
|
* connection token directly (e.g. the `ws`) or a client `RuntimeCoordinate` to look one up.
|
|
@@ -2928,7 +2934,7 @@ const createAcceptorHandler = (options) => {
|
|
|
2928
2934
|
//#endregion
|
|
2929
2935
|
//#region src/ActionRuntime/Handler/PeerLink/Acceptor/createSecureActionServer.ts
|
|
2930
2936
|
/** Default accepted set: negotiate per connection to whatever the client picks. */
|
|
2931
|
-
const DEFAULT_SERVER_SECURITY_LEVELS = [
|
|
2937
|
+
const DEFAULT_SERVER_SECURITY_LEVELS$1 = [
|
|
2932
2938
|
"none",
|
|
2933
2939
|
"authenticated",
|
|
2934
2940
|
"encrypted"
|
|
@@ -2943,7 +2949,7 @@ const DEFAULT_SERVER_SECURITY_LEVELS = [
|
|
|
2943
2949
|
* {@link createHibernatableWsServerAdapter} to wire persistence + replay.
|
|
2944
2950
|
*/
|
|
2945
2951
|
function createSecureAcceptorHandler(options) {
|
|
2946
|
-
const link = new _nice_code_util.ClientCryptoKeyLink({ storageAdapter: options.storageAdapter });
|
|
2952
|
+
const link = options.link ?? new _nice_code_util.ClientCryptoKeyLink({ storageAdapter: options.storageAdapter });
|
|
2947
2953
|
return new AcceptorHandler({
|
|
2948
2954
|
clientEnv: options.clientEnv,
|
|
2949
2955
|
createFormatMessage: options.channel.createCodec,
|
|
@@ -2951,7 +2957,7 @@ function createSecureAcceptorHandler(options) {
|
|
|
2951
2957
|
runtime: options.runtime,
|
|
2952
2958
|
defaultTimeout: options.defaultTimeout,
|
|
2953
2959
|
security: {
|
|
2954
|
-
securityLevel: options.securityLevel ?? DEFAULT_SERVER_SECURITY_LEVELS,
|
|
2960
|
+
securityLevel: options.securityLevel ?? DEFAULT_SERVER_SECURITY_LEVELS$1,
|
|
2955
2961
|
link,
|
|
2956
2962
|
localCoordinate: options.runtime.coordinate.toJsonObject(),
|
|
2957
2963
|
dictionaryVersion: options.channel.dictionaryVersion,
|
|
@@ -3023,6 +3029,7 @@ function acceptChannel(runtime, channel, options) {
|
|
|
3023
3029
|
runtime,
|
|
3024
3030
|
clientEnv: options.clientEnv,
|
|
3025
3031
|
storageAdapter: options.storageAdapter,
|
|
3032
|
+
link: options.link,
|
|
3026
3033
|
send: options.send,
|
|
3027
3034
|
securityLevel: options.securityLevel,
|
|
3028
3035
|
verifyKeyResolver: options.verifyKeyResolver,
|
|
@@ -3511,7 +3518,8 @@ function createActionFetchHandler(runtime, options = {}) {
|
|
|
3511
3518
|
return async (request) => {
|
|
3512
3519
|
if (request.method === "OPTIONS") return withCors(new Response(null, { status: 204 }));
|
|
3513
3520
|
const url = new URL(request.url);
|
|
3514
|
-
|
|
3521
|
+
const isWebSocketUpgrade = options.isWebSocketUpgrade ?? ((req, u) => req.headers.get("Upgrade") === "websocket" && isWebSocketPath(u));
|
|
3522
|
+
if (options.onWebSocketUpgrade != null && isWebSocketUpgrade(request, url)) return options.onWebSocketUpgrade(request, url);
|
|
3515
3523
|
if (request.method === "POST" && isActionPath(url)) {
|
|
3516
3524
|
if (exchangeAcceptor != null) {
|
|
3517
3525
|
const reply = await exchangeAcceptor.handlePost(await request.text());
|
|
@@ -3526,6 +3534,151 @@ function createActionFetchHandler(runtime, options = {}) {
|
|
|
3526
3534
|
};
|
|
3527
3535
|
}
|
|
3528
3536
|
//#endregion
|
|
3537
|
+
//#region src/ActionRuntime/Handler/PeerLink/Acceptor/Hibernation/createHibernatableWsServerAdapter.ts
|
|
3538
|
+
/**
|
|
3539
|
+
* Wire the hibernation lifecycle for an acceptor handler on a transport whose connections outlive process
|
|
3540
|
+
* eviction (e.g. a Durable Object's hibernatable WebSockets). It owns persistence end to end:
|
|
3541
|
+
* registers `setAttachment` as the handler's connection-bound callback and immediately replays every
|
|
3542
|
+
* live connection's stored binding via `getAttachment`, so results/pushes still route after a wake.
|
|
3543
|
+
*
|
|
3544
|
+
* Layered on top of the generic {@link AcceptorHandler} — it touches only the handler's neutral
|
|
3545
|
+
* `setOnConnectionBound` / `rehydrateConnection` / `receive` / `dropConnection` surface, so no
|
|
3546
|
+
* hibernation concern leaks into the handler itself.
|
|
3547
|
+
*
|
|
3548
|
+
* Construct it once when the handler is built, then forward connection events:
|
|
3549
|
+
* ```ts
|
|
3550
|
+
* const duplex = createHibernatableWsServerAdapter({ handler, getConnections, getAttachment, setAttachment });
|
|
3551
|
+
* // webSocketMessage(ws, msg) => duplex.receive(ws, msg);
|
|
3552
|
+
* // webSocketClose/Error(ws) => duplex.drop(ws);
|
|
3553
|
+
* ```
|
|
3554
|
+
*/
|
|
3555
|
+
function createHibernatableWsServerAdapter(options) {
|
|
3556
|
+
const { handler, getConnections, getAttachment, setAttachment } = options;
|
|
3557
|
+
handler.setOnConnectionBound(setAttachment);
|
|
3558
|
+
for (const connection of getConnections()) {
|
|
3559
|
+
const binding = getAttachment(connection);
|
|
3560
|
+
if (binding != null) handler.rehydrateConnection(connection, binding);
|
|
3561
|
+
}
|
|
3562
|
+
return {
|
|
3563
|
+
receive: (connection, frame) => handler.receive(connection, frame),
|
|
3564
|
+
drop: (connection) => handler.dropConnection(connection)
|
|
3565
|
+
};
|
|
3566
|
+
}
|
|
3567
|
+
//#endregion
|
|
3568
|
+
//#region src/ActionRuntime/Channel/serveChannel.ts
|
|
3569
|
+
/** Default accepted set, shared by every carrier: negotiate per connection to whatever the client picks. */
|
|
3570
|
+
const DEFAULT_SERVER_SECURITY_LEVELS = [
|
|
3571
|
+
"none",
|
|
3572
|
+
"authenticated",
|
|
3573
|
+
"encrypted"
|
|
3574
|
+
];
|
|
3575
|
+
/**
|
|
3576
|
+
* Serve a secure channel over one or more carriers from a single call — the accept-in dual of
|
|
3577
|
+
* `connectChannel`. It builds the crypto identity (a {@link ClientCryptoKeyLink} + a storage-backed TOFU
|
|
3578
|
+
* resolver) and the security block (coordinate, dictionary version, accepted levels) *once* from
|
|
3579
|
+
* `(runtime, channel)` and fans them across every carrier, so the WebSocket and the secure-HTTP endpoint
|
|
3580
|
+
* can never drift apart. It registers your handlers (plus the duplex acceptor it builds) on the runtime,
|
|
3581
|
+
* wires hibernation when the duplex carrier declares it, and returns a single {@link IChannelServer} whose
|
|
3582
|
+
* `fetch` / `duplex` / `pushToClient` you forward straight to the host:
|
|
3583
|
+
* ```ts
|
|
3584
|
+
* const server = serveChannel(runtime, channel, {
|
|
3585
|
+
* clientEnv, storage,
|
|
3586
|
+
* carriers: [wsAcceptorCarrier({ send, upgrade, hibernation }), httpAcceptorCarrier()],
|
|
3587
|
+
* handlers: [localHandler],
|
|
3588
|
+
* });
|
|
3589
|
+
* // fetch(req) => server.fetch(req)
|
|
3590
|
+
* // webSocketMessage(conn, m) => server.duplex?.receive(conn, m)
|
|
3591
|
+
* // webSocketClose/Error(conn) => server.duplex?.drop(conn)
|
|
3592
|
+
* ```
|
|
3593
|
+
*
|
|
3594
|
+
* `TConn` (the live-connection token a duplex carrier hands back through `send`/`receive`/`drop`) is
|
|
3595
|
+
* inferred from the carriers — `WebSocket` for `wsAcceptorCarrier`, the data-channel type for a WebRTC
|
|
3596
|
+
* carrier, and so on — so it stays carrier-agnostic.
|
|
3597
|
+
*/
|
|
3598
|
+
function serveChannel(runtime, channel, options) {
|
|
3599
|
+
const duplexCarriers = options.carriers.filter((carrier) => !require_wsAcceptorCarrier.isExchangeAcceptorCarrier(carrier));
|
|
3600
|
+
const exchangeCarriers = options.carriers.filter(require_wsAcceptorCarrier.isExchangeAcceptorCarrier);
|
|
3601
|
+
if (exchangeCarriers.length > 1) throw new Error("serveChannel: at most one exchange carrier is supported");
|
|
3602
|
+
const exchangeCarrier = exchangeCarriers[0];
|
|
3603
|
+
const exchangeSecure = exchangeCarrier != null && (exchangeCarrier.secure ?? true);
|
|
3604
|
+
const anyDuplexSecure = duplexCarriers.some((carrier) => carrier.secure ?? true);
|
|
3605
|
+
const securityLevel = options.securityLevel ?? DEFAULT_SERVER_SECURITY_LEVELS;
|
|
3606
|
+
let secure;
|
|
3607
|
+
if (anyDuplexSecure || exchangeSecure) {
|
|
3608
|
+
const storage = options.storage;
|
|
3609
|
+
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.");
|
|
3610
|
+
secure = {
|
|
3611
|
+
storage,
|
|
3612
|
+
link: options.link ?? new _nice_code_util.ClientCryptoKeyLink({ storageAdapter: storage }),
|
|
3613
|
+
verifyKeyResolver: options.verifyKeyResolver ?? createStorageTofuVerifyKeyResolver(storage)
|
|
3614
|
+
};
|
|
3615
|
+
}
|
|
3616
|
+
const handlers = [];
|
|
3617
|
+
for (const carrier of duplexCarriers) {
|
|
3618
|
+
const handler = (carrier.secure ?? true) && secure != null ? acceptChannel(runtime, channel, {
|
|
3619
|
+
clientEnv: options.clientEnv,
|
|
3620
|
+
storageAdapter: secure.storage,
|
|
3621
|
+
link: secure.link,
|
|
3622
|
+
verifyKeyResolver: secure.verifyKeyResolver,
|
|
3623
|
+
securityLevel,
|
|
3624
|
+
send: carrier.send,
|
|
3625
|
+
defaultTimeout: options.defaultTimeout
|
|
3626
|
+
}) : createAcceptorHandler({
|
|
3627
|
+
clientEnv: options.clientEnv,
|
|
3628
|
+
createFormatMessage: channel.createCodec,
|
|
3629
|
+
send: carrier.send,
|
|
3630
|
+
runtime,
|
|
3631
|
+
defaultTimeout: options.defaultTimeout
|
|
3632
|
+
});
|
|
3633
|
+
const router = carrier.hibernation != null ? createHibernatableWsServerAdapter({
|
|
3634
|
+
handler,
|
|
3635
|
+
...carrier.hibernation
|
|
3636
|
+
}) : {
|
|
3637
|
+
receive: (connection, frame) => handler.receive(connection, frame),
|
|
3638
|
+
drop: (connection) => handler.dropConnection(connection)
|
|
3639
|
+
};
|
|
3640
|
+
carrier._activate(router);
|
|
3641
|
+
handlers.push(handler);
|
|
3642
|
+
}
|
|
3643
|
+
runtime.addHandlers([...options.handlers ?? [], ...handlers]);
|
|
3644
|
+
const exchangeSecurity = exchangeSecure && secure != null ? {
|
|
3645
|
+
link: secure.link,
|
|
3646
|
+
verifyKeyResolver: secure.verifyKeyResolver,
|
|
3647
|
+
localCoordinate: runtime.coordinate.toJsonObject(),
|
|
3648
|
+
dictionaryVersion: channel.dictionaryVersion,
|
|
3649
|
+
securityLevel
|
|
3650
|
+
} : void 0;
|
|
3651
|
+
const defaultIsUpgrade = (request) => request.headers.get("Upgrade") === "websocket";
|
|
3652
|
+
const upgraders = [];
|
|
3653
|
+
for (const carrier of duplexCarriers) {
|
|
3654
|
+
if (carrier.upgrade == null) continue;
|
|
3655
|
+
upgraders.push({
|
|
3656
|
+
isUpgrade: carrier.isUpgrade ?? defaultIsUpgrade,
|
|
3657
|
+
upgrade: carrier.upgrade
|
|
3658
|
+
});
|
|
3659
|
+
}
|
|
3660
|
+
const fetch = createActionFetchHandler(runtime, {
|
|
3661
|
+
cors: exchangeCarrier?.cors,
|
|
3662
|
+
onWebSocketUpgrade: upgraders.length === 0 ? void 0 : (request, url) => (upgraders.find((u) => u.isUpgrade(request, url)) ?? upgraders[0]).upgrade(request, url),
|
|
3663
|
+
isWebSocketUpgrade: upgraders.length === 0 ? void 0 : (request, url) => upgraders.some((u) => u.isUpgrade(request, url)),
|
|
3664
|
+
isActionPath: exchangeCarrier != null ? exchangeCarrier.isActionPath ?? (() => true) : () => false,
|
|
3665
|
+
security: exchangeSecurity,
|
|
3666
|
+
useErrorStatus: exchangeCarrier?.useErrorStatus
|
|
3667
|
+
});
|
|
3668
|
+
const duplex = duplexCarriers.length === 1 ? duplexCarriers[0] : void 0;
|
|
3669
|
+
const pushToClient = (target, request, pushOptions) => {
|
|
3670
|
+
const owner = target instanceof RuntimeCoordinate ? handlers.find((handler) => handler.ownsLiveConnectionFor(target)) : handlers.find((handler) => handler.hasConnection(target));
|
|
3671
|
+
if (owner == null) throw new Error("serveChannel: no duplex carrier holds a connection for the push target");
|
|
3672
|
+
return owner.pushToClient(runtime, target, request, pushOptions);
|
|
3673
|
+
};
|
|
3674
|
+
return {
|
|
3675
|
+
handlers,
|
|
3676
|
+
fetch,
|
|
3677
|
+
duplex,
|
|
3678
|
+
pushToClient
|
|
3679
|
+
};
|
|
3680
|
+
}
|
|
3681
|
+
//#endregion
|
|
3529
3682
|
//#region src/ActionRuntime/Handler/PeerLink/Acceptor/Hibernation/ConnectionStateStore.ts
|
|
3530
3683
|
/**
|
|
3531
3684
|
* A typed per-connection state store that co-owns the app state and the acceptor handler's routing
|
|
@@ -3633,37 +3786,6 @@ function createConnectionStateStore(handler, options) {
|
|
|
3633
3786
|
return store;
|
|
3634
3787
|
}
|
|
3635
3788
|
//#endregion
|
|
3636
|
-
//#region src/ActionRuntime/Handler/PeerLink/Acceptor/Hibernation/createHibernatableWsServerAdapter.ts
|
|
3637
|
-
/**
|
|
3638
|
-
* Wire the hibernation lifecycle for an acceptor handler on a transport whose sockets outlive process
|
|
3639
|
-
* eviction (e.g. a Durable Object's hibernatable WebSockets). It owns persistence end to end:
|
|
3640
|
-
* registers `setAttachment` as the handler's connection-bound callback and immediately replays every
|
|
3641
|
-
* live connection's stored binding via `getAttachment`, so results/pushes still route after a wake.
|
|
3642
|
-
*
|
|
3643
|
-
* Layered on top of the generic {@link AcceptorHandler} — it touches only the handler's neutral
|
|
3644
|
-
* `setOnConnectionBound` / `rehydrateConnection` / `receive` / `dropConnection` surface, so no
|
|
3645
|
-
* hibernation concern leaks into the handler itself.
|
|
3646
|
-
*
|
|
3647
|
-
* Construct it once when the handler is built, then forward socket events:
|
|
3648
|
-
* ```ts
|
|
3649
|
-
* const wsServer = createHibernatableWsServerAdapter({ handler, getWebSockets, getAttachment, setAttachment });
|
|
3650
|
-
* // webSocketMessage(ws, msg) => wsServer.receive(ws, msg);
|
|
3651
|
-
* // webSocketClose/Error(ws) => wsServer.drop(ws);
|
|
3652
|
-
* ```
|
|
3653
|
-
*/
|
|
3654
|
-
function createHibernatableWsServerAdapter(options) {
|
|
3655
|
-
const { handler, getWebSockets, getAttachment, setAttachment } = options;
|
|
3656
|
-
handler.setOnConnectionBound(setAttachment);
|
|
3657
|
-
for (const connection of getWebSockets()) {
|
|
3658
|
-
const binding = getAttachment(connection);
|
|
3659
|
-
if (binding != null) handler.rehydrateConnection(connection, binding);
|
|
3660
|
-
}
|
|
3661
|
-
return {
|
|
3662
|
-
receive: (connection, frame) => handler.receive(connection, frame),
|
|
3663
|
-
drop: (connection) => handler.dropConnection(connection)
|
|
3664
|
-
};
|
|
3665
|
-
}
|
|
3666
|
-
//#endregion
|
|
3667
3789
|
//#region src/ActionRuntime/Transport/Carrier/duplex/inMemory/createInMemoryChannel.ts
|
|
3668
3790
|
/**
|
|
3669
3791
|
* Two cross-wired in-process byte channels — a loopback carrier with no socket. The client end is a
|
|
@@ -3821,6 +3943,22 @@ function rtcCarrier(dataChannel, options = {}) {
|
|
|
3821
3943
|
};
|
|
3822
3944
|
}
|
|
3823
3945
|
//#endregion
|
|
3946
|
+
//#region src/ActionRuntime/Transport/Carrier/duplex/ws/err_nice_transport_ws.ts
|
|
3947
|
+
let EErrId_NiceTransport_WebSocket = /* @__PURE__ */ function(EErrId_NiceTransport_WebSocket) {
|
|
3948
|
+
EErrId_NiceTransport_WebSocket["ws_disconnected"] = "ws_disconnected";
|
|
3949
|
+
EErrId_NiceTransport_WebSocket["ws_create_failed"] = "ws_create_failed";
|
|
3950
|
+
EErrId_NiceTransport_WebSocket["ws_error"] = "ws_error";
|
|
3951
|
+
return EErrId_NiceTransport_WebSocket;
|
|
3952
|
+
}({});
|
|
3953
|
+
const err_nice_transport_ws = err_nice_transport.createChildDomain({
|
|
3954
|
+
domain: "ws_transport",
|
|
3955
|
+
schema: {
|
|
3956
|
+
["ws_disconnected"]: (0, _nice_code_error.err)({ message: () => `WebSocket transport disconnected.` }),
|
|
3957
|
+
["ws_create_failed"]: (0, _nice_code_error.err)({ message: ({ originalError }) => `Failed to create WebSocket transport.${originalError ? ` Original error: ${originalError.message}` : ""}` }),
|
|
3958
|
+
["ws_error"]: (0, _nice_code_error.err)({ message: ({ originalError }) => `WebSocket transport error.${originalError ? ` Original error: ${originalError.message}` : ""}` })
|
|
3959
|
+
}
|
|
3960
|
+
});
|
|
3961
|
+
//#endregion
|
|
3824
3962
|
//#region src/ActionRuntime/Transport/Carrier/duplex/ws/ws_util.ts
|
|
3825
3963
|
/**
|
|
3826
3964
|
* Send a text or binary frame over a socket. A binary formatter may hand back a `Uint8Array` whose
|
|
@@ -3933,6 +4071,25 @@ function defaultWebSocket(url) {
|
|
|
3933
4071
|
return ws;
|
|
3934
4072
|
}
|
|
3935
4073
|
//#endregion
|
|
4074
|
+
//#region src/ActionRuntime/Transport/Carrier/exchange/http/httpAcceptorCarrier.ts
|
|
4075
|
+
/**
|
|
4076
|
+
* An HTTP {@link IExchangeAcceptorCarrier}: the accept-in dual of {@link httpCarrier}. It serves the
|
|
4077
|
+
* secure exchange protocol (handshake → token session → encrypted frames) over web-standard
|
|
4078
|
+
* `Request`/`Response`. The crypto identity, runtime coordinate, dictionary version, and accepted security
|
|
4079
|
+
* levels are all supplied centrally by `serveChannel`, so this only needs to say which requests carry an
|
|
4080
|
+
* action envelope and how to answer CORS.
|
|
4081
|
+
*/
|
|
4082
|
+
function httpAcceptorCarrier(options = {}) {
|
|
4083
|
+
return {
|
|
4084
|
+
shape: "exchange",
|
|
4085
|
+
carrierLabel: options.carrierLabel ?? "http",
|
|
4086
|
+
secure: options.secure,
|
|
4087
|
+
isActionPath: options.isActionPath,
|
|
4088
|
+
cors: options.cors,
|
|
4089
|
+
useErrorStatus: options.useErrorStatus
|
|
4090
|
+
};
|
|
4091
|
+
}
|
|
4092
|
+
//#endregion
|
|
3936
4093
|
//#region src/ActionRuntime/Transport/Carrier/exchange/http/httpCarrier.ts
|
|
3937
4094
|
function shortPath(url) {
|
|
3938
4095
|
try {
|
|
@@ -4398,22 +4555,6 @@ var ExchangeTransport = class ExchangeTransport extends Transport {
|
|
|
4398
4555
|
}
|
|
4399
4556
|
};
|
|
4400
4557
|
//#endregion
|
|
4401
|
-
//#region src/ActionRuntime/Transport/Carrier/duplex/ws/err_nice_transport_ws.ts
|
|
4402
|
-
let EErrId_NiceTransport_WebSocket = /* @__PURE__ */ function(EErrId_NiceTransport_WebSocket) {
|
|
4403
|
-
EErrId_NiceTransport_WebSocket["ws_disconnected"] = "ws_disconnected";
|
|
4404
|
-
EErrId_NiceTransport_WebSocket["ws_create_failed"] = "ws_create_failed";
|
|
4405
|
-
EErrId_NiceTransport_WebSocket["ws_error"] = "ws_error";
|
|
4406
|
-
return EErrId_NiceTransport_WebSocket;
|
|
4407
|
-
}({});
|
|
4408
|
-
const err_nice_transport_ws = err_nice_transport.createChildDomain({
|
|
4409
|
-
domain: "ws_transport",
|
|
4410
|
-
schema: {
|
|
4411
|
-
["ws_disconnected"]: (0, _nice_code_error.err)({ message: () => `WebSocket transport disconnected.` }),
|
|
4412
|
-
["ws_create_failed"]: (0, _nice_code_error.err)({ message: ({ originalError }) => `Failed to create WebSocket transport.${originalError ? ` Original error: ${originalError.message}` : ""}` }),
|
|
4413
|
-
["ws_error"]: (0, _nice_code_error.err)({ message: ({ originalError }) => `WebSocket transport error.${originalError ? ` Original error: ${originalError.message}` : ""}` })
|
|
4414
|
-
}
|
|
4415
|
-
});
|
|
4416
|
-
//#endregion
|
|
4417
4558
|
//#region src/ActionRuntime/Transport/helpers/createUnsetTransportResolvers.ts
|
|
4418
4559
|
const createUnsetTransportResolvers = (transportLabel) => ({ onIncomingActionDataJson: (json) => {
|
|
4419
4560
|
console.warn(`Received incoming action JSON [${json.domain}:${json.id}] on Transport [${transportLabel}] but no incoming data listener has been set.`);
|
|
@@ -4741,8 +4882,8 @@ exports.ERunningActionFinishedType = require_RunningAction_types.ERunningActionF
|
|
|
4741
4882
|
exports.ERunningActionState = require_RunningAction_types.ERunningActionState;
|
|
4742
4883
|
exports.ERunningActionUpdateType = require_RunningAction_types.ERunningActionUpdateType;
|
|
4743
4884
|
exports.ESecurityLevel = ESecurityLevel;
|
|
4744
|
-
exports.ETransportShape = ETransportShape;
|
|
4745
|
-
exports.ETransportStatus = ETransportStatus;
|
|
4885
|
+
exports.ETransportShape = require_wsAcceptorCarrier.ETransportShape;
|
|
4886
|
+
exports.ETransportStatus = require_wsAcceptorCarrier.ETransportStatus;
|
|
4746
4887
|
exports.ExchangeAcceptor = ExchangeAcceptor;
|
|
4747
4888
|
exports.ExchangeTransport = ExchangeTransport;
|
|
4748
4889
|
exports.LinkTransport = LinkTransport;
|
|
@@ -4779,16 +4920,20 @@ exports.err_nice_action = err_nice_action;
|
|
|
4779
4920
|
exports.err_nice_external_client = err_nice_external_client;
|
|
4780
4921
|
exports.err_nice_transport = err_nice_transport;
|
|
4781
4922
|
exports.err_nice_transport_ws = err_nice_transport_ws;
|
|
4923
|
+
exports.httpAcceptorCarrier = httpAcceptorCarrier;
|
|
4782
4924
|
exports.httpCarrier = httpCarrier;
|
|
4783
4925
|
exports.inMemoryCarrier = inMemoryCarrier;
|
|
4784
4926
|
exports.isActionPayload_Any_JsonObject = isActionPayload_Any_JsonObject;
|
|
4785
4927
|
exports.isActionPayload_Request_JsonObject = isActionPayload_Request_JsonObject;
|
|
4786
4928
|
exports.isActionPayload_Result_JsonObject = isActionPayload_Result_JsonObject;
|
|
4929
|
+
exports.isExchangeAcceptorCarrier = require_wsAcceptorCarrier.isExchangeAcceptorCarrier;
|
|
4787
4930
|
exports.plainTransport = plainTransport;
|
|
4788
4931
|
exports.rtcCarrier = rtcCarrier;
|
|
4789
4932
|
exports.rtcDataChannelByteChannel = rtcDataChannelByteChannel;
|
|
4790
4933
|
exports.runtimeLinkId = runtimeLinkId;
|
|
4791
4934
|
exports.secureTransport = secureTransport;
|
|
4935
|
+
exports.serveChannel = serveChannel;
|
|
4936
|
+
exports.wsAcceptorCarrier = require_wsAcceptorCarrier.wsAcceptorCarrier;
|
|
4792
4937
|
exports.wsCarrier = wsCarrier;
|
|
4793
4938
|
|
|
4794
4939
|
//# sourceMappingURL=index.cjs.map
|