@nice-code/action 0.22.0 → 0.24.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.
Files changed (40) hide show
  1. package/README.md +22 -25
  2. package/build/{ActionPayload.types-Dx1JPyfs.d.mts → AcceptorHandler-11-QMdx2.d.mts} +977 -1351
  3. package/build/{ActionPayload.types-L9k0LyBd.d.cts → AcceptorHandler-CxD0c1BE.d.cts} +977 -1351
  4. package/build/{ActionDevtoolsCore-CQ0vrvPD.d.cts → ActionDevtoolsCore-37JP4bOG.d.cts} +2 -2
  5. package/build/{ActionDevtoolsCore-CiLBYC3K.d.mts → ActionDevtoolsCore-Cgq-go1R.d.mts} +2 -2
  6. package/build/advanced/index.cjs +115 -0
  7. package/build/advanced/index.cjs.map +1 -0
  8. package/build/advanced/index.d.cts +344 -0
  9. package/build/advanced/index.d.mts +344 -0
  10. package/build/advanced/index.mjs +88 -0
  11. package/build/advanced/index.mjs.map +1 -0
  12. package/build/{httpAcceptorCarrier-OnJxzsAD.cjs → createHibernatableWsServerAdapter-BNi4k9j3.cjs} +258 -470
  13. package/build/createHibernatableWsServerAdapter-BNi4k9j3.cjs.map +1 -0
  14. package/build/{httpAcceptorCarrier-DL8lf0xB.mjs → createHibernatableWsServerAdapter-C07RfUTH.mjs} +233 -421
  15. package/build/createHibernatableWsServerAdapter-C07RfUTH.mjs.map +1 -0
  16. package/build/devtools/browser/index.d.cts +1 -1
  17. package/build/devtools/browser/index.d.mts +1 -1
  18. package/build/devtools/server/index.d.cts +1 -1
  19. package/build/devtools/server/index.d.mts +1 -1
  20. package/build/httpAcceptorCarrier-C3S_bDkL.cjs +454 -0
  21. package/build/httpAcceptorCarrier-C3S_bDkL.cjs.map +1 -0
  22. package/build/httpAcceptorCarrier-DPBEuewS.mjs +401 -0
  23. package/build/httpAcceptorCarrier-DPBEuewS.mjs.map +1 -0
  24. package/build/index.cjs +84 -458
  25. package/build/index.cjs.map +1 -1
  26. package/build/index.d.cts +2 -2
  27. package/build/index.d.mts +2 -2
  28. package/build/index.mjs +28 -374
  29. package/build/index.mjs.map +1 -1
  30. package/build/platform/cloudflare/index.cjs +1 -1
  31. package/build/platform/cloudflare/index.cjs.map +1 -1
  32. package/build/platform/cloudflare/index.d.cts +3 -3
  33. package/build/platform/cloudflare/index.d.mts +3 -3
  34. package/build/platform/cloudflare/index.mjs +1 -1
  35. package/build/platform/cloudflare/index.mjs.map +1 -1
  36. package/build/react-query/index.d.cts +1 -1
  37. package/build/react-query/index.d.mts +1 -1
  38. package/package.json +15 -4
  39. package/build/httpAcceptorCarrier-DL8lf0xB.mjs.map +0 -1
  40. package/build/httpAcceptorCarrier-OnJxzsAD.cjs.map +0 -1
package/README.md CHANGED
@@ -31,7 +31,7 @@ The pieces:
31
31
  | **ActionDomain** | A named group of typed actions (your API surface) |
32
32
  | **ActionSchema** | Input/output schema + declared error types for one action |
33
33
  | **ActionRuntime** | One per runtime; identifies it and dispatches actions to handlers |
34
- | **Channel** | The transport-agnostic routing contract between two runtimes, declared *by role* (`toAcceptor` / `toConnector`) `defineChannel` (plain) or `defineSecureChannel` (binary + encryption) |
34
+ | **Channel** | The transport-agnostic routing contract + binary wire identity between two runtimes, declared *by role* (`toAcceptor` / `toConnector`) with `defineChannel`. Security is a per-transport choice, not a channel one |
35
35
  | **Carrier** | How bytes actually move: `wsCarrier` / `httpCarrier` / `inMemoryCarrier` / `rtcCarrier` (connector side), `wsAcceptorCarrier` / `httpAcceptorCarrier` (acceptor side) |
36
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 |
@@ -130,30 +130,21 @@ Define it once in code shared by both ends:
130
130
  import { defineChannel } from "@nice-code/action";
131
131
 
132
132
  export const appChannel = defineChannel({
133
- toAcceptor: [userDomain], // client → server requests
134
- toConnector: [], // server → client pushes (none here)
133
+ toAcceptor: [userDomain, lobbyDomain], // client → server requests
134
+ toConnector: [lobbyDomain], // server → client pushes (lobbyDomain is bidirectional)
135
135
  });
136
136
  ```
137
137
 
138
- For an authenticated/encrypted binary WebSocket, use **`defineSecureChannel`** insteadsame role-based
139
- shape, plus it bakes in the positional binary wire dictionary and a version derived from the domains, so
140
- the codec and version can never drift between the two ends:
141
-
142
- ```ts
143
- import { defineSecureChannel } from "@nice-code/action";
144
-
145
- export const appChannel = defineSecureChannel({
146
- toAcceptor: [userDomain, lobbyDomain], // requests
147
- toConnector: [lobbyDomain], // pushes (lobbyDomain is bidirectional)
148
- });
149
- ```
138
+ A channel carries both its routing (`toAcceptor` / `toConnector` domains) **and** its wire identity the
139
+ positional binary wire dictionary and a version derived from the domains, so the per-connection codec and
140
+ version can never drift between the two ends. Whether a given transport actually runs encrypted is a
141
+ per-transport choice (`secure` on `connectChannel`'s transports and the acceptor's `securityLevel`), not a
142
+ property of the channel — so this one definition serves both plain and secure transports.
150
143
 
151
144
  > The lists are **positional** for the binary wire dictionary — **add new domains to the end** of their
152
145
  > list. Reordering shifts the version, and a stale peer is then cleanly rejected by the handshake instead
153
146
  > of silently misrouting a frame.
154
147
 
155
- A secure channel is still an ordinary channel, so it works anywhere a channel is expected.
156
-
157
148
  ---
158
149
 
159
150
  ## Runtimes & handlers
@@ -281,7 +272,7 @@ connectChannel(clientRuntime, appChannel, {
281
272
  storage, // one crypto identity, fanned across every secure transport
282
273
  securityLevel: ESecurityLevel.encrypted,
283
274
  transports: [
284
- { carrier: wsCarrier("wss://api.example.com/resolve_action/ws") }, // secure WS, preferred
275
+ { carrier: wsCarrier(() => ({ url: "wss://api.example.com/resolve_action/ws" })) }, // secure WS, preferred
285
276
  { carrier: httpCarrier(() => ({ url: "https://api.example.com/resolve_action" })), secure: false }, // plain HTTP fallback
286
277
  ],
287
278
  // onPush: { ... } // handlers for the channel's toConnector pushes (see below)
@@ -353,7 +344,7 @@ export const lobbyDomain = appRoot.createChildDomain({
353
344
  },
354
345
  });
355
346
 
356
- export const appChannel = defineSecureChannel({
347
+ export const appChannel = defineChannel({
357
348
  toAcceptor: [userDomain, lobbyDomain], // start_feed flows here
358
349
  toConnector: [lobbyDomain], // position_update pushes back here
359
350
  });
@@ -366,7 +357,7 @@ export const appChannel = defineSecureChannel({
366
357
  connectChannel(clientRuntime, appChannel, {
367
358
  peer: serverCoord,
368
359
  storage,
369
- transports: [{ carrier: wsCarrier(wsUrl) }, { carrier: httpCarrier(httpUrl), secure: false }],
360
+ transports: [{ carrier: wsCarrier(() => ({ url: wsUrl })) }, { carrier: httpCarrier(() => ({ url: httpUrl })), secure: false }],
370
361
  onPush: {
371
362
  // Keyed by the toConnector action id; input + output typed from the channel.
372
363
  position_update: async ({ player, x, y }) => {
@@ -579,13 +570,13 @@ connectChannel(runtime, appChannel, {
579
570
  storage,
580
571
  transports: [
581
572
  {
582
- carrier: wsCarrier(`${url}/ws`, {
573
+ carrier: wsCarrier(() => ({ url: `${url}/ws` }), {
583
574
  // Only ever called once `available` passes, so no need for a placeholder cache key.
584
575
  getTransportCacheKey: () => [sessionId],
585
576
  }),
586
577
  available: () => sessionId != null, // ws preferred; HTTP serves while ws is gated off
587
578
  },
588
- { carrier: httpCarrier(httpUrl), secure: false },
579
+ { carrier: httpCarrier(() => ({ url: httpUrl })), secure: false },
589
580
  ],
590
581
  });
591
582
  ```
@@ -694,18 +685,24 @@ try {
694
685
  crypto identity for you. The pieces below are what they're built on; reach for them only for the rare
695
686
  routing that isn't a single channel.
696
687
 
688
+ > Most of these live under the **`@nice-code/action/advanced`** subpath, not the main entry — the default
689
+ > `@nice-code/action` export stays focused on the high-level API (`acceptChannel` /
690
+ > `acceptChannelConnections` and the carriers remain on the main entry). Import the raw handler classes
691
+ > (`AcceptorHandler`, `ConnectorHandler`, …), the transport classes/codec, and the handshake primitives
692
+ > from `@nice-code/action/advanced`.
693
+
697
694
  - **Carriers vs transports.** A *carrier* (`wsCarrier`, `httpCarrier`, `inMemoryCarrier`, `rtcCarrier`) is
698
695
  raw byte movement; a *transport* wraps one with a security policy. You name carriers in
699
696
  `connectChannel`'s `transports` (the `secure` flag picks the policy) and in `serveChannel`'s `carriers`;
700
697
  the transport wrapping happens internally, so there's no separate transport-builder to call.
701
698
 
702
- - **`acceptChannel(runtime, channel, { clientEnv, storageAdapter, send, ... })`** — build the secure
699
+ - **`acceptChannel(runtime, channel, { clientEnv, storage, send, ... })`** — build the secure
703
700
  `AcceptorHandler` for a channel by hand (the accept-in counterpart to a single transport), when you're
704
701
  not using `serveChannel`. Pair it with **`acceptChannelConnections(handler, channel, cases)`** to
705
702
  register connection-aware execution — each case receives the request *and* the originating connection:
706
703
 
707
704
  ```ts
708
- const acceptor = acceptChannel(runtime, appChannel, { clientEnv, storageAdapter, send });
705
+ const acceptor = acceptChannel(runtime, appChannel, { clientEnv, storage, send });
709
706
  const cases = acceptChannelConnections(acceptor, appChannel, {
710
707
  join: ({ input }, conn) => { if (conn != null) rooms.add(input.roomId, conn); return { ok: true }; },
711
708
  });
@@ -720,7 +717,7 @@ routing that isn't a single channel.
720
717
  `AcceptorHandler`.
721
718
 
722
719
  - **`createBinaryWireAdapter(domains)`** / **`createBinaryWireSessionFactory(domains)`** — the positional
723
- binary codecs `defineSecureChannel` builds for you; useful for custom carriers.
720
+ binary codecs `defineChannel` builds for you; useful for custom carriers.
724
721
 
725
722
  - **`createInMemoryChannelPair()` / `inMemoryCarrier`** — wire two runtimes together in-process (tests,
726
723
  same-process peers) with no network.