@nice-code/action 0.20.0 → 0.21.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 +49 -50
- package/build/{ActionDevtoolsCore-D_JvgPmz.d.mts → ActionDevtoolsCore-baIHExfj.d.mts} +2 -2
- package/build/{ActionDevtoolsCore-dV-IVPcP.d.cts → ActionDevtoolsCore-dApyYvTS.d.cts} +2 -2
- package/build/{ActionPayload.types-CnfWlkA1.d.cts → ActionPayload.types-CQM1HRw_.d.cts} +161 -194
- package/build/{ActionPayload.types-D0DM-g65.d.mts → ActionPayload.types-DXGiw1SF.d.mts} +161 -194
- 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 +1763 -1722
- 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 +1764 -1721
- package/build/index.mjs.map +1 -1
- package/build/platform/cloudflare/index.d.cts +1 -1
- package/build/platform/cloudflare/index.d.mts +1 -1
- package/build/react-query/index.d.cts +1 -1
- package/build/react-query/index.d.mts +1 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -33,7 +33,7 @@ The pieces:
|
|
|
33
33
|
| **ActionRuntime** | One per runtime; identifies it and dispatches actions to handlers |
|
|
34
34
|
| **Channel** | The transport-agnostic routing contract between two runtimes, declared *by role* (`toAcceptor` / `toConnector`) — `defineChannel` (plain) or `defineSecureChannel` (binary + encryption) |
|
|
35
35
|
| **Carrier** | How bytes actually move: `wsCarrier` / `httpCarrier` / `inMemoryCarrier` / `rtcCarrier` (connector side), `wsAcceptorCarrier` / `httpAcceptorCarrier` (acceptor side) |
|
|
36
|
-
| **Transport** | A carrier wrapped with a security policy
|
|
36
|
+
| **Transport** | A carrier wrapped with a security policy (handshake + optional encryption, or plain). You don't build these directly — `connectChannel` / `serveChannel` apply the policy to each carrier for you |
|
|
37
37
|
| **RuntimeCoordinate** | Identifies an environment (frontend, backend, worker…) and is how actions are routed |
|
|
38
38
|
|
|
39
39
|
> **One runtime per client.** A client (a frontend, a backend, a worker) has a *single* `ActionRuntime`
|
|
@@ -243,9 +243,12 @@ Key options: `clientEnv` (required), `storage` (required only when a carrier is
|
|
|
243
243
|
|
|
244
244
|
### Connecting — `connectChannel`
|
|
245
245
|
|
|
246
|
-
The connector has one runtime and `connectChannel`s to each acceptor it talks to.
|
|
247
|
-
|
|
248
|
-
|
|
246
|
+
The connector has one runtime and `connectChannel`s to each acceptor it talks to. One call binds the
|
|
247
|
+
shared facts — the channel (its codec + routing), the runtime, and one crypto identity over `storage` —
|
|
248
|
+
into every transport, so you state them *once*. It routes the channel's `toAcceptor` domains out over the
|
|
249
|
+
transports (first = preferred, rest = fallback) and registers local handlers for the `toConnector` pushes
|
|
250
|
+
from `onPush` — all derived from the channel, no restated lists. It's the exact dial-out dual of
|
|
251
|
+
`serveChannel`.
|
|
249
252
|
|
|
250
253
|
```ts
|
|
251
254
|
import {
|
|
@@ -253,39 +256,35 @@ import {
|
|
|
253
256
|
RuntimeCoordinate,
|
|
254
257
|
ESecurityLevel,
|
|
255
258
|
connectChannel,
|
|
256
|
-
secureTransport,
|
|
257
|
-
plainTransport,
|
|
258
259
|
wsCarrier,
|
|
259
260
|
httpCarrier,
|
|
260
261
|
} from "@nice-code/action";
|
|
261
262
|
|
|
262
263
|
export const clientRuntime = new ActionRuntime(RuntimeCoordinate.env("frontend"));
|
|
263
264
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
runtime: clientRuntime, // its coordinate is the authenticated identity in the handshake
|
|
268
|
-
storageAdapter, // persists this client's crypto identity across reloads
|
|
265
|
+
connectChannel(clientRuntime, appChannel, {
|
|
266
|
+
peer: serverCoord,
|
|
267
|
+
storage, // one crypto identity, fanned across every secure transport
|
|
269
268
|
securityLevel: ESecurityLevel.encrypted,
|
|
270
|
-
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
});
|
|
275
|
-
|
|
276
|
-
connectChannel(clientRuntime, serverCoord, {
|
|
277
|
-
channel: appChannel,
|
|
278
|
-
transports: [wsTransport, httpTransport], // secure WS preferred, HTTP fallback
|
|
269
|
+
transports: [
|
|
270
|
+
{ carrier: wsCarrier("wss://api.example.com/resolve_action/ws") }, // secure WS, preferred
|
|
271
|
+
{ carrier: httpCarrier(() => ({ url: "https://api.example.com/resolve_action" })), secure: false }, // plain HTTP fallback
|
|
272
|
+
],
|
|
279
273
|
// onPush: { ... } // handlers for the channel's toConnector pushes (see below)
|
|
280
274
|
});
|
|
281
275
|
```
|
|
282
276
|
|
|
283
|
-
`connectChannel(runtime,
|
|
277
|
+
`connectChannel(runtime, channel, options)` returns the `ConnectorHandler` so you can later
|
|
284
278
|
`handler.clearTransportCache()` (which also closes any live sockets) on teardown. Options:
|
|
285
279
|
|
|
286
|
-
- **`
|
|
287
|
-
- **`transports`** —
|
|
288
|
-
manager falls through on failure.
|
|
280
|
+
- **`peer`** — the acceptor's `RuntimeCoordinate` this connection dials.
|
|
281
|
+
- **`transports`** — declared by *carrier* `{ carrier, secure? }`, in preference order; all carry the
|
|
282
|
+
channel's `toAcceptor` domains and the manager falls through on failure. `secure` defaults to `true`.
|
|
283
|
+
- **`storage`** — one backing store for the connection's crypto identity, fanned across every secure
|
|
284
|
+
transport. Required when any transport is secure; omit for a fully-plain connection. (`link` shares an
|
|
285
|
+
existing identity instead.)
|
|
286
|
+
- **`securityLevel`** — default level for secure transports (`authenticated` if omitted; override per
|
|
287
|
+
transport with `securityLevel` on the descriptor).
|
|
289
288
|
- **`onPush`** — handlers for the channel's `toConnector` pushes (optional; omit for send-only).
|
|
290
289
|
- **`defaultTimeout`** — default per-action timeout.
|
|
291
290
|
|
|
@@ -348,9 +347,10 @@ export const appChannel = defineSecureChannel({
|
|
|
348
347
|
### Connector side — handle pushes with `onPush`
|
|
349
348
|
|
|
350
349
|
```ts
|
|
351
|
-
connectChannel(clientRuntime,
|
|
352
|
-
|
|
353
|
-
|
|
350
|
+
connectChannel(clientRuntime, appChannel, {
|
|
351
|
+
peer: serverCoord,
|
|
352
|
+
storage,
|
|
353
|
+
transports: [{ carrier: wsCarrier(wsUrl) }, { carrier: httpCarrier(httpUrl), secure: false }],
|
|
354
354
|
onPush: {
|
|
355
355
|
// Keyed by the toConnector action id; input + output typed from the channel.
|
|
356
356
|
position_update: async ({ player, x, y }) => {
|
|
@@ -489,7 +489,7 @@ and pushes still route to the right socket after the object wakes from eviction.
|
|
|
489
489
|
|
|
490
490
|
## Security levels
|
|
491
491
|
|
|
492
|
-
`ESecurityLevel` (used by `
|
|
492
|
+
`ESecurityLevel` (used by `connectChannel` and `serveChannel`):
|
|
493
493
|
|
|
494
494
|
- **`none`** — identity self-asserted, no handshake. Fastest; fine for dev/trusted networks.
|
|
495
495
|
- **`authenticated`** — the handshake verifies identity (sign/verify + trust-on-first-use key pin);
|
|
@@ -502,7 +502,7 @@ crypto identity; the server pins client keys trust-on-first-use. Persisting the
|
|
|
502
502
|
hibernatable carrier) lets an `authenticated`/`encrypted` connection resume after eviction without
|
|
503
503
|
re-handshaking.
|
|
504
504
|
|
|
505
|
-
The whole thing rides one channel: the same `
|
|
505
|
+
The whole thing rides one channel: the same secure `{ carrier: wsCarrier(...) }` transport works at any
|
|
506
506
|
level, and `httpCarrier` runs the *same* secure session over HTTP (handshake → token → encrypted frames),
|
|
507
507
|
with the request/reply correlation provided for free by the HTTP transaction. Pair a secure WS with a
|
|
508
508
|
plain HTTP fallback by giving the acceptor a `httpAcceptorCarrier({ secure: false })`.
|
|
@@ -542,17 +542,19 @@ holds, with no reconnect.
|
|
|
542
542
|
|
|
543
543
|
```ts
|
|
544
544
|
// Prefer the secure socket, but only once a session id exists; fall back to HTTP meanwhile.
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
545
|
+
connectChannel(runtime, appChannel, {
|
|
546
|
+
peer: serverCoord,
|
|
547
|
+
storage,
|
|
548
|
+
transports: [
|
|
549
|
+
{
|
|
550
|
+
carrier: wsCarrier(`${url}/ws`, {
|
|
551
|
+
// Only ever called once `available` passes, so no need for a placeholder cache key.
|
|
552
|
+
getTransportCacheKey: () => [sessionId],
|
|
553
|
+
}),
|
|
554
|
+
available: () => sessionId != null, // ws preferred; HTTP serves while ws is gated off
|
|
555
|
+
},
|
|
556
|
+
{ carrier: httpCarrier(httpUrl), secure: false },
|
|
557
|
+
],
|
|
556
558
|
});
|
|
557
559
|
```
|
|
558
560
|
|
|
@@ -656,17 +658,14 @@ try {
|
|
|
656
658
|
|
|
657
659
|
## Lower-level building blocks
|
|
658
660
|
|
|
659
|
-
`connectChannel` and `serveChannel` are
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
— what `connectChannel` desugars to: build a `ConnectorHandler` for a peer, route domains/actions to
|
|
663
|
-
it, register it (plus any local push handlers), and apply — in one call. Use it directly when your
|
|
664
|
-
routing isn't expressed as a single channel.
|
|
661
|
+
`connectChannel` and `serveChannel` are the supported entry points — they bind the channel, runtime, and
|
|
662
|
+
crypto identity for you. The pieces below are what they're built on; reach for them only for the rare
|
|
663
|
+
routing that isn't a single channel.
|
|
665
664
|
|
|
666
665
|
- **Carriers vs transports.** A *carrier* (`wsCarrier`, `httpCarrier`, `inMemoryCarrier`, `rtcCarrier`) is
|
|
667
|
-
raw byte movement; a *transport*
|
|
668
|
-
`
|
|
669
|
-
|
|
666
|
+
raw byte movement; a *transport* wraps one with a security policy. You name carriers in
|
|
667
|
+
`connectChannel`'s `transports` (the `secure` flag picks the policy) and in `serveChannel`'s `carriers`;
|
|
668
|
+
the transport wrapping happens internally, so there's no separate transport-builder to call.
|
|
670
669
|
|
|
671
670
|
- **`acceptChannel(runtime, channel, { clientEnv, storageAdapter, send, ... })`** — build the secure
|
|
672
671
|
`AcceptorHandler` for a channel by hand (the accept-in counterpart to a single transport), when you're
|
|
@@ -695,5 +694,5 @@ try {
|
|
|
695
694
|
same-process peers) with no network.
|
|
696
695
|
|
|
697
696
|
- **Custom carriers** — for any channel nice-action doesn't model natively, implement an
|
|
698
|
-
`IDuplexCarrierSource` / `IExchangeCarrierSource` and
|
|
697
|
+
`IDuplexCarrierSource` / `IExchangeCarrierSource` and name it in `connectChannel`'s `transports`
|
|
699
698
|
(connector) or build an acceptor carrier for `serveChannel`.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Pr as IRuntimeCoordinate, _ as TActionProgress } from "./ActionPayload.types-DXGiw1SF.mjs";
|
|
2
2
|
//#region ../nice-devtools-shared/src/components/PanelChrome.d.ts
|
|
3
3
|
/** Where a devtools panel is docked. */
|
|
4
4
|
type TDevtoolsPosition = "dock-bottom" | "dock-top" | "dock-left" | "dock-right";
|
|
@@ -76,4 +76,4 @@ declare class ActionDevtoolsCore {
|
|
|
76
76
|
}
|
|
77
77
|
//#endregion
|
|
78
78
|
export { TDevtoolsActionStatus as a, IDevtoolsObservableDomain as i, IActionDevtoolsCoreOptions as n, TDevtoolsListener as o, IDevtoolsActionEntry as r, TDevtoolsPosition as s, ActionDevtoolsCore as t };
|
|
79
|
-
//# sourceMappingURL=ActionDevtoolsCore-
|
|
79
|
+
//# sourceMappingURL=ActionDevtoolsCore-baIHExfj.d.mts.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Pr as IRuntimeCoordinate, _ as TActionProgress } from "./ActionPayload.types-CQM1HRw_.cjs";
|
|
2
2
|
//#region ../nice-devtools-shared/src/components/PanelChrome.d.ts
|
|
3
3
|
/** Where a devtools panel is docked. */
|
|
4
4
|
type TDevtoolsPosition = "dock-bottom" | "dock-top" | "dock-left" | "dock-right";
|
|
@@ -76,4 +76,4 @@ declare class ActionDevtoolsCore {
|
|
|
76
76
|
}
|
|
77
77
|
//#endregion
|
|
78
78
|
export { TDevtoolsActionStatus as a, IDevtoolsObservableDomain as i, IActionDevtoolsCoreOptions as n, TDevtoolsListener as o, IDevtoolsActionEntry as r, TDevtoolsPosition as s, ActionDevtoolsCore as t };
|
|
79
|
-
//# sourceMappingURL=ActionDevtoolsCore-
|
|
79
|
+
//# sourceMappingURL=ActionDevtoolsCore-dApyYvTS.d.cts.map
|