@nice-code/action 0.18.0 → 0.20.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 +699 -637
- package/build/{ActionDevtoolsCore-C5XrQI1K.d.mts → ActionDevtoolsCore-D_JvgPmz.d.mts} +2 -2
- package/build/{ActionDevtoolsCore-Dd1qJAwK.d.cts → ActionDevtoolsCore-dV-IVPcP.d.cts} +2 -2
- package/build/{ActionPayload.types-BchJrBIX.d.mts → ActionPayload.types-CnfWlkA1.d.cts} +252 -106
- package/build/{ActionPayload.types-snDlSIF-.d.cts → ActionPayload.types-D0DM-g65.d.mts} +252 -106
- 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 +169 -138
- 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 +167 -139
- package/build/index.mjs.map +1 -1
- package/build/platform/cloudflare/index.cjs +8 -4
- package/build/platform/cloudflare/index.cjs.map +1 -1
- package/build/platform/cloudflare/index.d.cts +8 -3
- package/build/platform/cloudflare/index.d.mts +8 -3
- package/build/platform/cloudflare/index.mjs +8 -4
- 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/build/{wsAcceptorCarrier-DHRbsY1X.cjs → wsAcceptorCarrier-BDJRIPfu.cjs} +2 -2
- package/build/wsAcceptorCarrier-BDJRIPfu.cjs.map +1 -0
- package/build/{wsAcceptorCarrier-CXGlQU_f.mjs → wsAcceptorCarrier-CW2qX25W.mjs} +2 -2
- package/build/wsAcceptorCarrier-CW2qX25W.mjs.map +1 -0
- package/package.json +4 -4
- package/build/wsAcceptorCarrier-CXGlQU_f.mjs.map +0 -1
- package/build/wsAcceptorCarrier-DHRbsY1X.cjs.map +0 -1
package/build/index.cjs
CHANGED
|
@@ -1,7 +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-
|
|
4
|
+
const require_wsAcceptorCarrier = require("./wsAcceptorCarrier-BDJRIPfu.cjs");
|
|
5
5
|
let nanoid = require("nanoid");
|
|
6
6
|
let _nice_code_error = require("@nice-code/error");
|
|
7
7
|
let _nice_code_common_errors = require("@nice-code/common-errors");
|
|
@@ -879,6 +879,10 @@ var ConnectionTransportManager = class {
|
|
|
879
879
|
const candidates = [];
|
|
880
880
|
const unavailableTransports = [];
|
|
881
881
|
for (const transport of this._transports) {
|
|
882
|
+
if (!transport.isAvailable(routeActionParams)) {
|
|
883
|
+
unavailableTransports.push(transport);
|
|
884
|
+
continue;
|
|
885
|
+
}
|
|
882
886
|
const cacheKey = transport.getCacheKey(routeActionParams);
|
|
883
887
|
if (cacheKey != null) {
|
|
884
888
|
const cached = this._cache.get(cacheKey);
|
|
@@ -3534,6 +3538,113 @@ function createActionFetchHandler(runtime, options = {}) {
|
|
|
3534
3538
|
};
|
|
3535
3539
|
}
|
|
3536
3540
|
//#endregion
|
|
3541
|
+
//#region src/ActionRuntime/Handler/PeerLink/Acceptor/Hibernation/ConnectionStateStore.ts
|
|
3542
|
+
/**
|
|
3543
|
+
* A typed per-connection state store that co-owns the app state and the acceptor handler's routing
|
|
3544
|
+
* binding in one attachment, so neither the consumer nor the handler has to hand-merge the two. Create
|
|
3545
|
+
* it through {@link createConnectionStateStore} (which also wires binding persistence and replays
|
|
3546
|
+
* surviving connections after a wake), then `get`/`set`/`clearApp` the app state directly.
|
|
3547
|
+
*
|
|
3548
|
+
* The mechanism is carrier-neutral — it only needs read/write/enumerate callbacks for the connection's
|
|
3549
|
+
* attachment — but it pays off on transports whose connections outlive process eviction (e.g. a
|
|
3550
|
+
* Durable Object's hibernatable WebSockets), which is why it lives beside the hibernation adapter.
|
|
3551
|
+
*
|
|
3552
|
+
* ```ts
|
|
3553
|
+
* const players = createConnectionStateStore(serverHandler, {
|
|
3554
|
+
* schema: vs_player,
|
|
3555
|
+
* read: (ws) => ws.deserializeAttachment(),
|
|
3556
|
+
* write: (ws, v) => ws.serializeAttachment(v),
|
|
3557
|
+
* getConnections: () => ctx.getWebSockets(),
|
|
3558
|
+
* });
|
|
3559
|
+
* players.set(ws, player); // binding is preserved automatically
|
|
3560
|
+
* const player = players.get(ws);
|
|
3561
|
+
* ```
|
|
3562
|
+
*/
|
|
3563
|
+
var ConnectionStateStore = class {
|
|
3564
|
+
options;
|
|
3565
|
+
constructor(options) {
|
|
3566
|
+
this.options = options;
|
|
3567
|
+
}
|
|
3568
|
+
/** The validated app state for a connection, or `null` if unset / invalid. */
|
|
3569
|
+
get(connection) {
|
|
3570
|
+
return this._readAttachment(connection).app ?? null;
|
|
3571
|
+
}
|
|
3572
|
+
/** Set the app state, preserving the runtime binding already pinned to the connection. */
|
|
3573
|
+
set(connection, app) {
|
|
3574
|
+
const existing = this._readAttachment(connection);
|
|
3575
|
+
this.options.write(connection, {
|
|
3576
|
+
app,
|
|
3577
|
+
binding: existing.binding
|
|
3578
|
+
});
|
|
3579
|
+
}
|
|
3580
|
+
/** Clear the app state but keep the binding (e.g. a spectator that stopped watching). */
|
|
3581
|
+
clearApp(connection) {
|
|
3582
|
+
const existing = this._readAttachment(connection);
|
|
3583
|
+
this.options.write(connection, { binding: existing.binding });
|
|
3584
|
+
}
|
|
3585
|
+
/** Every live connection paired with its (validated) app state — for rebuilding in-memory state after a wake. */
|
|
3586
|
+
entries() {
|
|
3587
|
+
return this.options.getConnections().map((connection) => [connection, this._readAttachment(connection).app ?? null]);
|
|
3588
|
+
}
|
|
3589
|
+
/** @internal Persist a freshly-bound connection's binding, preserving any app state already stored. */
|
|
3590
|
+
_persistBinding(connection, binding) {
|
|
3591
|
+
const existing = this._readAttachment(connection);
|
|
3592
|
+
this.options.write(connection, {
|
|
3593
|
+
app: existing.app,
|
|
3594
|
+
binding
|
|
3595
|
+
});
|
|
3596
|
+
}
|
|
3597
|
+
/** @internal The persisted binding for a connection, if any (used to replay routing after a wake). */
|
|
3598
|
+
_readBinding(connection) {
|
|
3599
|
+
return this._readAttachment(connection).binding;
|
|
3600
|
+
}
|
|
3601
|
+
_readAttachment(connection) {
|
|
3602
|
+
try {
|
|
3603
|
+
const raw = this.options.read(connection);
|
|
3604
|
+
if (typeof raw !== "object" || raw === null) return {};
|
|
3605
|
+
const attachment = raw;
|
|
3606
|
+
const result = {};
|
|
3607
|
+
if (attachment.binding != null) result.binding = attachment.binding;
|
|
3608
|
+
if (attachment.app !== void 0) {
|
|
3609
|
+
const app = this._validateApp(attachment.app);
|
|
3610
|
+
if (app !== void 0) result.app = app;
|
|
3611
|
+
}
|
|
3612
|
+
return result;
|
|
3613
|
+
} catch {
|
|
3614
|
+
return {};
|
|
3615
|
+
}
|
|
3616
|
+
}
|
|
3617
|
+
_validateApp(value) {
|
|
3618
|
+
const schema = this.options.schema;
|
|
3619
|
+
if (schema == null) return value;
|
|
3620
|
+
const result = schema["~standard"].validate(value);
|
|
3621
|
+
if (result instanceof Promise) return void 0;
|
|
3622
|
+
if (result.issues != null) return void 0;
|
|
3623
|
+
return result.value;
|
|
3624
|
+
}
|
|
3625
|
+
};
|
|
3626
|
+
/**
|
|
3627
|
+
* Build a per-connection {@link ConnectionStateStore} bound to an {@link AcceptorHandler}: it registers
|
|
3628
|
+
* itself as the handler's connection-bound persistence callback (so bindings are written without
|
|
3629
|
+
* overwriting app state) and immediately replays every live connection's stored binding via
|
|
3630
|
+
* {@link AcceptorHandler.rehydrateConnection} — so on a transport that resumes after eviction (e.g. a
|
|
3631
|
+
* Durable Object waking from hibernation) both the app identity and the action routing come back from a
|
|
3632
|
+
* single attachment, with no storage reads and no hand-rolled merge.
|
|
3633
|
+
*
|
|
3634
|
+
* Lives outside the handler so the generic {@link AcceptorHandler} stays free of any attachment/
|
|
3635
|
+
* hibernation concern — it exposes only the neutral `setOnConnectionBound` + `rehydrateConnection`
|
|
3636
|
+
* hooks this builder drives.
|
|
3637
|
+
*/
|
|
3638
|
+
function createConnectionStateStore(handler, options) {
|
|
3639
|
+
const store = new ConnectionStateStore(options);
|
|
3640
|
+
handler.setOnConnectionBound((connection, binding) => store._persistBinding(connection, binding));
|
|
3641
|
+
for (const connection of options.getConnections()) {
|
|
3642
|
+
const binding = store._readBinding(connection);
|
|
3643
|
+
if (binding != null) handler.rehydrateConnection(connection, binding);
|
|
3644
|
+
}
|
|
3645
|
+
return store;
|
|
3646
|
+
}
|
|
3647
|
+
//#endregion
|
|
3537
3648
|
//#region src/ActionRuntime/Handler/PeerLink/Acceptor/Hibernation/createHibernatableWsServerAdapter.ts
|
|
3538
3649
|
/**
|
|
3539
3650
|
* Wire the hibernation lifecycle for an acceptor handler on a transport whose connections outlive process
|
|
@@ -3572,34 +3683,14 @@ const DEFAULT_SERVER_SECURITY_LEVELS = [
|
|
|
3572
3683
|
"authenticated",
|
|
3573
3684
|
"encrypted"
|
|
3574
3685
|
];
|
|
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
3686
|
function serveChannel(runtime, channel, options) {
|
|
3599
3687
|
const duplexCarriers = options.carriers.filter((carrier) => !require_wsAcceptorCarrier.isExchangeAcceptorCarrier(carrier));
|
|
3600
3688
|
const exchangeCarriers = options.carriers.filter(require_wsAcceptorCarrier.isExchangeAcceptorCarrier);
|
|
3601
3689
|
if (exchangeCarriers.length > 1) throw new Error("serveChannel: at most one exchange carrier is supported");
|
|
3602
3690
|
const exchangeCarrier = exchangeCarriers[0];
|
|
3691
|
+
const singleDuplex = duplexCarriers.length === 1;
|
|
3692
|
+
if (options.connectionState != null && !singleDuplex) throw new Error("serveChannel: `connectionState` requires exactly one duplex carrier");
|
|
3693
|
+
if (options.channelCases != null && !singleDuplex) throw new Error("serveChannel: `channelCases` requires exactly one duplex carrier");
|
|
3603
3694
|
const exchangeSecure = exchangeCarrier != null && (exchangeCarrier.secure ?? true);
|
|
3604
3695
|
const anyDuplexSecure = duplexCarriers.some((carrier) => carrier.secure ?? true);
|
|
3605
3696
|
const securityLevel = options.securityLevel ?? DEFAULT_SERVER_SECURITY_LEVELS;
|
|
@@ -3613,7 +3704,13 @@ function serveChannel(runtime, channel, options) {
|
|
|
3613
3704
|
verifyKeyResolver: options.verifyKeyResolver ?? createStorageTofuVerifyKeyResolver(storage)
|
|
3614
3705
|
};
|
|
3615
3706
|
}
|
|
3707
|
+
const plainRouter = (handler) => ({
|
|
3708
|
+
receive: (connection, frame) => handler.receive(connection, frame),
|
|
3709
|
+
drop: (connection) => handler.dropConnection(connection)
|
|
3710
|
+
});
|
|
3711
|
+
const asObject = (value) => typeof value === "object" && value != null ? value : {};
|
|
3616
3712
|
const handlers = [];
|
|
3713
|
+
let connections;
|
|
3617
3714
|
for (const carrier of duplexCarriers) {
|
|
3618
3715
|
const handler = (carrier.secure ?? true) && secure != null ? acceptChannel(runtime, channel, {
|
|
3619
3716
|
clientEnv: options.clientEnv,
|
|
@@ -3630,17 +3727,31 @@ function serveChannel(runtime, channel, options) {
|
|
|
3630
3727
|
runtime,
|
|
3631
3728
|
defaultTimeout: options.defaultTimeout
|
|
3632
3729
|
});
|
|
3633
|
-
const
|
|
3730
|
+
const attach = carrier.attachmentStore;
|
|
3731
|
+
let router;
|
|
3732
|
+
if (attach == null) router = plainRouter(handler);
|
|
3733
|
+
else if (options.connectionState != null) {
|
|
3734
|
+
connections = createConnectionStateStore(handler, {
|
|
3735
|
+
schema: options.connectionState.schema,
|
|
3736
|
+
getConnections: attach.getConnections,
|
|
3737
|
+
read: attach.read,
|
|
3738
|
+
write: attach.write
|
|
3739
|
+
});
|
|
3740
|
+
router = plainRouter(handler);
|
|
3741
|
+
} else router = createHibernatableWsServerAdapter({
|
|
3634
3742
|
handler,
|
|
3635
|
-
|
|
3636
|
-
|
|
3637
|
-
|
|
3638
|
-
|
|
3639
|
-
|
|
3743
|
+
getConnections: attach.getConnections,
|
|
3744
|
+
getAttachment: (connection) => attach.read(connection)?.binding,
|
|
3745
|
+
setAttachment: (connection, binding) => attach.write(connection, {
|
|
3746
|
+
...asObject(attach.read(connection)),
|
|
3747
|
+
binding
|
|
3748
|
+
})
|
|
3749
|
+
});
|
|
3640
3750
|
carrier._activate(router);
|
|
3641
3751
|
handlers.push(handler);
|
|
3642
3752
|
}
|
|
3643
3753
|
runtime.addHandlers([...options.handlers ?? [], ...handlers]);
|
|
3754
|
+
if (options.channelCases != null) runtime.addHandlers([acceptChannelConnections(handlers[0], channel, options.channelCases)]);
|
|
3644
3755
|
const exchangeSecurity = exchangeSecure && secure != null ? {
|
|
3645
3756
|
link: secure.link,
|
|
3646
3757
|
verifyKeyResolver: secure.verifyKeyResolver,
|
|
@@ -3671,121 +3782,23 @@ function serveChannel(runtime, channel, options) {
|
|
|
3671
3782
|
if (owner == null) throw new Error("serveChannel: no duplex carrier holds a connection for the push target");
|
|
3672
3783
|
return owner.pushToClient(runtime, target, request, pushOptions);
|
|
3673
3784
|
};
|
|
3785
|
+
const broadcast = (makeRequest, broadcastOptions) => {
|
|
3786
|
+
if (!singleDuplex) throw new Error("serveChannel: broadcast requires exactly one duplex carrier — broadcast over a specific handlers[i] instead");
|
|
3787
|
+
handlers[0].broadcast(makeRequest, {
|
|
3788
|
+
runtime,
|
|
3789
|
+
...broadcastOptions
|
|
3790
|
+
});
|
|
3791
|
+
};
|
|
3674
3792
|
return {
|
|
3675
3793
|
handlers,
|
|
3676
3794
|
fetch,
|
|
3677
3795
|
duplex,
|
|
3678
|
-
pushToClient
|
|
3796
|
+
pushToClient,
|
|
3797
|
+
broadcast,
|
|
3798
|
+
connections
|
|
3679
3799
|
};
|
|
3680
3800
|
}
|
|
3681
3801
|
//#endregion
|
|
3682
|
-
//#region src/ActionRuntime/Handler/PeerLink/Acceptor/Hibernation/ConnectionStateStore.ts
|
|
3683
|
-
/**
|
|
3684
|
-
* A typed per-connection state store that co-owns the app state and the acceptor handler's routing
|
|
3685
|
-
* binding in one attachment, so neither the consumer nor the handler has to hand-merge the two. Create
|
|
3686
|
-
* it through {@link createConnectionStateStore} (which also wires binding persistence and replays
|
|
3687
|
-
* surviving connections after a wake), then `get`/`set`/`clearApp` the app state directly.
|
|
3688
|
-
*
|
|
3689
|
-
* The mechanism is carrier-neutral — it only needs read/write/enumerate callbacks for the connection's
|
|
3690
|
-
* attachment — but it pays off on transports whose connections outlive process eviction (e.g. a
|
|
3691
|
-
* Durable Object's hibernatable WebSockets), which is why it lives beside the hibernation adapter.
|
|
3692
|
-
*
|
|
3693
|
-
* ```ts
|
|
3694
|
-
* const players = createConnectionStateStore(serverHandler, {
|
|
3695
|
-
* schema: vs_player,
|
|
3696
|
-
* read: (ws) => ws.deserializeAttachment(),
|
|
3697
|
-
* write: (ws, v) => ws.serializeAttachment(v),
|
|
3698
|
-
* getConnections: () => ctx.getWebSockets(),
|
|
3699
|
-
* });
|
|
3700
|
-
* players.set(ws, player); // binding is preserved automatically
|
|
3701
|
-
* const player = players.get(ws);
|
|
3702
|
-
* ```
|
|
3703
|
-
*/
|
|
3704
|
-
var ConnectionStateStore = class {
|
|
3705
|
-
options;
|
|
3706
|
-
constructor(options) {
|
|
3707
|
-
this.options = options;
|
|
3708
|
-
}
|
|
3709
|
-
/** The validated app state for a connection, or `null` if unset / invalid. */
|
|
3710
|
-
get(connection) {
|
|
3711
|
-
return this._readAttachment(connection).app ?? null;
|
|
3712
|
-
}
|
|
3713
|
-
/** Set the app state, preserving the runtime binding already pinned to the connection. */
|
|
3714
|
-
set(connection, app) {
|
|
3715
|
-
const existing = this._readAttachment(connection);
|
|
3716
|
-
this.options.write(connection, {
|
|
3717
|
-
app,
|
|
3718
|
-
binding: existing.binding
|
|
3719
|
-
});
|
|
3720
|
-
}
|
|
3721
|
-
/** Clear the app state but keep the binding (e.g. a spectator that stopped watching). */
|
|
3722
|
-
clearApp(connection) {
|
|
3723
|
-
const existing = this._readAttachment(connection);
|
|
3724
|
-
this.options.write(connection, { binding: existing.binding });
|
|
3725
|
-
}
|
|
3726
|
-
/** Every live connection paired with its (validated) app state — for rebuilding in-memory state after a wake. */
|
|
3727
|
-
entries() {
|
|
3728
|
-
return this.options.getConnections().map((connection) => [connection, this._readAttachment(connection).app ?? null]);
|
|
3729
|
-
}
|
|
3730
|
-
/** @internal Persist a freshly-bound connection's binding, preserving any app state already stored. */
|
|
3731
|
-
_persistBinding(connection, binding) {
|
|
3732
|
-
const existing = this._readAttachment(connection);
|
|
3733
|
-
this.options.write(connection, {
|
|
3734
|
-
app: existing.app,
|
|
3735
|
-
binding
|
|
3736
|
-
});
|
|
3737
|
-
}
|
|
3738
|
-
/** @internal The persisted binding for a connection, if any (used to replay routing after a wake). */
|
|
3739
|
-
_readBinding(connection) {
|
|
3740
|
-
return this._readAttachment(connection).binding;
|
|
3741
|
-
}
|
|
3742
|
-
_readAttachment(connection) {
|
|
3743
|
-
try {
|
|
3744
|
-
const raw = this.options.read(connection);
|
|
3745
|
-
if (typeof raw !== "object" || raw === null) return {};
|
|
3746
|
-
const attachment = raw;
|
|
3747
|
-
const result = {};
|
|
3748
|
-
if (attachment.binding != null) result.binding = attachment.binding;
|
|
3749
|
-
if (attachment.app !== void 0) {
|
|
3750
|
-
const app = this._validateApp(attachment.app);
|
|
3751
|
-
if (app !== void 0) result.app = app;
|
|
3752
|
-
}
|
|
3753
|
-
return result;
|
|
3754
|
-
} catch {
|
|
3755
|
-
return {};
|
|
3756
|
-
}
|
|
3757
|
-
}
|
|
3758
|
-
_validateApp(value) {
|
|
3759
|
-
const schema = this.options.schema;
|
|
3760
|
-
if (schema == null) return value;
|
|
3761
|
-
const result = schema["~standard"].validate(value);
|
|
3762
|
-
if (result instanceof Promise) return void 0;
|
|
3763
|
-
if (result.issues != null) return void 0;
|
|
3764
|
-
return result.value;
|
|
3765
|
-
}
|
|
3766
|
-
};
|
|
3767
|
-
/**
|
|
3768
|
-
* Build a per-connection {@link ConnectionStateStore} bound to an {@link AcceptorHandler}: it registers
|
|
3769
|
-
* itself as the handler's connection-bound persistence callback (so bindings are written without
|
|
3770
|
-
* overwriting app state) and immediately replays every live connection's stored binding via
|
|
3771
|
-
* {@link AcceptorHandler.rehydrateConnection} — so on a transport that resumes after eviction (e.g. a
|
|
3772
|
-
* Durable Object waking from hibernation) both the app identity and the action routing come back from a
|
|
3773
|
-
* single attachment, with no storage reads and no hand-rolled merge.
|
|
3774
|
-
*
|
|
3775
|
-
* Lives outside the handler so the generic {@link AcceptorHandler} stays free of any attachment/
|
|
3776
|
-
* hibernation concern — it exposes only the neutral `setOnConnectionBound` + `rehydrateConnection`
|
|
3777
|
-
* hooks this builder drives.
|
|
3778
|
-
*/
|
|
3779
|
-
function createConnectionStateStore(handler, options) {
|
|
3780
|
-
const store = new ConnectionStateStore(options);
|
|
3781
|
-
handler.setOnConnectionBound((connection, binding) => store._persistBinding(connection, binding));
|
|
3782
|
-
for (const connection of options.getConnections()) {
|
|
3783
|
-
const binding = store._readBinding(connection);
|
|
3784
|
-
if (binding != null) handler.rehydrateConnection(connection, binding);
|
|
3785
|
-
}
|
|
3786
|
-
return store;
|
|
3787
|
-
}
|
|
3788
|
-
//#endregion
|
|
3789
3802
|
//#region src/ActionRuntime/Transport/Carrier/duplex/inMemory/createInMemoryChannel.ts
|
|
3790
3803
|
/**
|
|
3791
3804
|
* Two cross-wired in-process byte channels — a loopback carrier with no socket. The client end is a
|
|
@@ -4440,6 +4453,15 @@ var TransportConnection = class {
|
|
|
4440
4453
|
if (inner == null) return null;
|
|
4441
4454
|
return `${this.transOrd}:${inner}`;
|
|
4442
4455
|
}
|
|
4456
|
+
/**
|
|
4457
|
+
* Whether this transport can serve the given action right now. Consulted by the manager before
|
|
4458
|
+
* cache-key resolution and `getTransport`; a `false` result skips this transport (treated as
|
|
4459
|
+
* `unsupported`) and the manager falls through to the next in preference order. Defaults to `true`
|
|
4460
|
+
* when the transport declares no gate.
|
|
4461
|
+
*/
|
|
4462
|
+
isAvailable(input) {
|
|
4463
|
+
return this.initialized.isAvailable?.(input) ?? true;
|
|
4464
|
+
}
|
|
4443
4465
|
getTransport(input) {
|
|
4444
4466
|
return this._processTransportStatus(input);
|
|
4445
4467
|
}
|
|
@@ -4536,6 +4558,7 @@ var ExchangeTransport = class ExchangeTransport extends Transport {
|
|
|
4536
4558
|
const options = this.options;
|
|
4537
4559
|
return new ExchangeConnection({ initialize: () => ({
|
|
4538
4560
|
getTransportCacheKey: options.getTransportCacheKey,
|
|
4561
|
+
isAvailable: options.available,
|
|
4539
4562
|
getTransport: (input) => ({
|
|
4540
4563
|
status: "ready",
|
|
4541
4564
|
readyData: {
|
|
@@ -4784,6 +4807,7 @@ var LinkTransport = class LinkTransport extends Transport {
|
|
|
4784
4807
|
const options = this.options;
|
|
4785
4808
|
return new LinkConnection({ initialize: () => ({
|
|
4786
4809
|
getTransportCacheKey: options.getTransportCacheKey,
|
|
4810
|
+
isAvailable: options.available,
|
|
4787
4811
|
getTransport: (input) => ({
|
|
4788
4812
|
status: "ready",
|
|
4789
4813
|
readyData: {
|
|
@@ -4820,6 +4844,7 @@ function plainTransport(options) {
|
|
|
4820
4844
|
if (isExchangeCarrierSource(carrier)) return ExchangeTransport.create({
|
|
4821
4845
|
openCarrier: carrier.open,
|
|
4822
4846
|
getTransportCacheKey: carrier.getCacheKey,
|
|
4847
|
+
available: options.available,
|
|
4823
4848
|
getRouteInfo: carrier.getRouteInfo,
|
|
4824
4849
|
label: options.label ?? carrier.carrierLabel,
|
|
4825
4850
|
updateRunConfig: options.updateRunConfig
|
|
@@ -4829,6 +4854,7 @@ function plainTransport(options) {
|
|
|
4829
4854
|
formatMessage: options.formatMessage,
|
|
4830
4855
|
createFormatMessage: options.createFormatMessage,
|
|
4831
4856
|
getTransportCacheKey: carrier.getCacheKey,
|
|
4857
|
+
available: options.available,
|
|
4832
4858
|
getRouteInfo: carrier.getRouteInfo,
|
|
4833
4859
|
label: options.label ?? carrier.carrierLabel,
|
|
4834
4860
|
updateRunConfig: options.updateRunConfig
|
|
@@ -4848,6 +4874,7 @@ function secureTransport(options) {
|
|
|
4848
4874
|
if (isExchangeCarrierSource(carrier)) return ExchangeTransport.create({
|
|
4849
4875
|
openCarrier: carrier.open,
|
|
4850
4876
|
getTransportCacheKey: carrier.getCacheKey,
|
|
4877
|
+
available: options.available,
|
|
4851
4878
|
getRouteInfo: carrier.getRouteInfo,
|
|
4852
4879
|
label: carrier.carrierLabel,
|
|
4853
4880
|
security
|
|
@@ -4856,6 +4883,7 @@ function secureTransport(options) {
|
|
|
4856
4883
|
openChannel: carrier.open,
|
|
4857
4884
|
createFormatMessage: options.channel.createCodec,
|
|
4858
4885
|
getTransportCacheKey: carrier.getCacheKey,
|
|
4886
|
+
available: options.available,
|
|
4859
4887
|
getRouteInfo: carrier.getRouteInfo,
|
|
4860
4888
|
label: carrier.carrierLabel,
|
|
4861
4889
|
security
|
|
@@ -4912,9 +4940,12 @@ exports.createSecureAcceptorHandler = createSecureAcceptorHandler;
|
|
|
4912
4940
|
exports.createServerHandshake = createServerHandshake;
|
|
4913
4941
|
exports.createStorageTofuVerifyKeyResolver = createStorageTofuVerifyKeyResolver;
|
|
4914
4942
|
exports.decodeActionFrame = decodeActionFrame;
|
|
4943
|
+
exports.decodeExchangeReply = decodeExchangeReply;
|
|
4944
|
+
exports.decodeExchangeRequest = decodeExchangeRequest;
|
|
4915
4945
|
exports.decodeHandshakeMessage = decodeHandshakeMessage;
|
|
4916
4946
|
exports.defineChannel = defineChannel;
|
|
4917
4947
|
exports.defineSecureChannel = defineSecureChannel;
|
|
4948
|
+
exports.encodeExchange = encodeExchange;
|
|
4918
4949
|
exports.encodeHandshakeMessage = encodeHandshakeMessage;
|
|
4919
4950
|
exports.err_nice_action = err_nice_action;
|
|
4920
4951
|
exports.err_nice_external_client = err_nice_external_client;
|