@nice-code/action 0.1.3 → 0.2.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 (104) hide show
  1. package/README.md +1 -410
  2. package/build/index.js +5176 -1970
  3. package/build/react-query/index.js +7 -7
  4. package/build/types/ActionDefinition/Action/Action.combined.types.d.ts +27 -0
  5. package/build/types/ActionDefinition/Action/ActionBase.d.ts +14 -0
  6. package/build/types/ActionDefinition/Action/ActionBase.types.d.ts +24 -0
  7. package/build/types/ActionDefinition/Action/Context/ActionContext.d.ts +26 -0
  8. package/build/types/ActionDefinition/Action/Context/ActionContext.types.d.ts +35 -0
  9. package/build/types/ActionDefinition/Action/Core/ActionCore.d.ts +20 -0
  10. package/build/types/ActionDefinition/Action/Core/ActionCore.types.d.ts +10 -0
  11. package/build/types/ActionDefinition/Action/Payload/ActionPayload.d.ts +14 -0
  12. package/build/types/ActionDefinition/Action/Payload/ActionPayload.types.d.ts +106 -0
  13. package/build/types/ActionDefinition/Action/Payload/ActionPayload_Progress.d.ts +15 -0
  14. package/build/types/ActionDefinition/Action/Payload/ActionPayload_Request.d.ts +24 -0
  15. package/build/types/ActionDefinition/Action/Payload/ActionPayload_Result.d.ts +18 -0
  16. package/build/types/ActionDefinition/Action/RunningAction.d.ts +33 -0
  17. package/build/types/ActionDefinition/Action/RunningAction.types.d.ts +65 -0
  18. package/build/types/ActionDefinition/Domain/ActionDomain.d.ts +30 -0
  19. package/build/types/ActionDefinition/Domain/ActionDomain.types.d.ts +37 -0
  20. package/build/types/ActionDefinition/Domain/ActionDomainBase.d.ts +14 -0
  21. package/build/types/ActionDefinition/Domain/ActionRootDomain.d.ts +23 -0
  22. package/build/types/ActionDefinition/Domain/helpers/createRootActionDomain.d.ts +5 -0
  23. package/build/types/{ActionSchema/NiceActionSchema.d.ts → ActionDefinition/Schema/ActionSchema.d.ts} +10 -29
  24. package/build/types/ActionDefinition/Schema/ActionSchema.types.d.ts +32 -0
  25. package/build/types/ActionRuntime/ActionDomainManager.d.ts +13 -0
  26. package/build/types/ActionRuntime/ActionRuntime.d.ts +48 -0
  27. package/build/types/ActionRuntime/ActionRuntime.types.d.ts +22 -0
  28. package/build/types/ActionRuntime/ActionRuntimeManager.d.ts +19 -0
  29. package/build/types/ActionRuntime/Client/ActionClientSpecifier.d.ts +47 -0
  30. package/build/types/ActionRuntime/Client/utils/clientSpecifierToStringIds.d.ts +2 -0
  31. package/build/types/ActionRuntime/Handler/ActionHandler.d.ts +16 -0
  32. package/build/types/ActionRuntime/Handler/ActionHandler.types.d.ts +68 -0
  33. package/build/types/ActionRuntime/Handler/ExternalClient/ActionExternalClientHandler.d.ts +42 -0
  34. package/build/types/ActionRuntime/Handler/ExternalClient/ActionExternalClientHandler.types.d.ts +7 -0
  35. package/build/types/ActionRuntime/Handler/ExternalClient/Transport/ConnectionTransportManager.d.ts +9 -0
  36. package/build/types/ActionRuntime/Handler/ExternalClient/Transport/Custom/TransportCustom.d.ts +7 -0
  37. package/build/types/ActionRuntime/Handler/ExternalClient/Transport/Custom/TransportCustom.types.d.ts +11 -0
  38. package/build/types/ActionRuntime/Handler/ExternalClient/Transport/Http/TransportHttp.d.ts +8 -0
  39. package/build/types/ActionRuntime/Handler/ExternalClient/Transport/Http/TransportHttp.types.d.ts +17 -0
  40. package/build/types/ActionRuntime/Handler/ExternalClient/Transport/Transport.combined.types.d.ts +4 -0
  41. package/build/types/ActionRuntime/Handler/ExternalClient/Transport/Transport.d.ts +13 -0
  42. package/build/types/ActionRuntime/Handler/ExternalClient/Transport/Transport.types.d.ts +106 -0
  43. package/build/types/ActionRuntime/Handler/ExternalClient/Transport/WebSocket/TransportWebSocket.d.ts +13 -0
  44. package/build/types/ActionRuntime/Handler/ExternalClient/Transport/WebSocket/TransportWebSocket.types.d.ts +13 -0
  45. package/build/types/{ActionRuntimeEnvironment/ActionConnect → ActionRuntime/Handler/ExternalClient}/Transport/err_nice_transport.d.ts +5 -7
  46. package/build/types/ActionRuntime/Handler/ExternalClient/Transport/helpers/addTransportStatusMetadata.d.ts +2 -0
  47. package/build/types/ActionRuntime/Handler/ExternalClient/Transport/helpers/createUnsetTransportResolvers.d.ts +2 -0
  48. package/build/types/ActionRuntime/Handler/ExternalClient/err_nice_external_client.d.ts +5 -0
  49. package/build/types/ActionRuntime/Handler/Local/ActionLocalHandler.d.ts +55 -0
  50. package/build/types/ActionRuntime/Handler/Local/ActionLocalHandler.types.d.ts +6 -0
  51. package/build/types/ActionRuntime/Routing/ActionRouter.d.ts +55 -0
  52. package/build/types/ActionRuntime/Routing/ActionRouter.types.d.ts +20 -0
  53. package/build/types/ActionRuntime/test/helpers/new_action_test_data.d.ts +301 -0
  54. package/build/types/errors/err_nice_action.d.ts +22 -12
  55. package/build/types/index.d.ts +31 -32
  56. package/build/types/nice_action.static.d.ts +3 -0
  57. package/build/types/react-query/index.d.ts +9 -10
  58. package/build/types/utils/assertIsActionJson.d.ts +2 -0
  59. package/build/types/utils/getAssumedRuntimeEnvironment.d.ts +2 -0
  60. package/build/types/utils/isActionPayload_Any_JsonObject.d.ts +2 -0
  61. package/build/types/utils/isActionPayload_Progress_JsonObject.d.ts +2 -0
  62. package/build/types/utils/isActionPayload_Request_JsonObject.d.ts +2 -0
  63. package/build/types/utils/isActionPayload_Result_JsonObject.d.ts +2 -0
  64. package/build/types/utils/isAction_Any_Instance.d.ts +3 -0
  65. package/build/types/utils/isAction_Any_JsonObject.d.ts +2 -0
  66. package/build/types/utils/isAction_Base_JsonObject.d.ts +2 -0
  67. package/build/types/utils/isAction_Context_JsonObject.d.ts +2 -0
  68. package/build/types/utils/isAction_Core_JsonObject.d.ts +2 -0
  69. package/build/types/utils/wait.utils.d.ts +13 -0
  70. package/package.json +3 -3
  71. package/build/types/ActionDomain/NiceActionDomain.d.ts +0 -40
  72. package/build/types/ActionDomain/NiceActionDomain.types.d.ts +0 -37
  73. package/build/types/ActionDomain/NiceActionDomainBase.d.ts +0 -14
  74. package/build/types/ActionDomain/RootDomain/NiceActionRootDomain.d.ts +0 -22
  75. package/build/types/ActionDomain/helpers/createRootActionDomain.d.ts +0 -5
  76. package/build/types/ActionRuntimeEnvironment/ActionConnect/ActionConnect.d.ts +0 -24
  77. package/build/types/ActionRuntimeEnvironment/ActionConnect/ActionConnect.types.d.ts +0 -15
  78. package/build/types/ActionRuntimeEnvironment/ActionConnect/ConnectionConfig/ConnectionConfig.d.ts +0 -12
  79. package/build/types/ActionRuntimeEnvironment/ActionConnect/ConnectionConfig/ConnectionConfig.types.d.ts +0 -6
  80. package/build/types/ActionRuntimeEnvironment/ActionConnect/Transport/Transport.d.ts +0 -19
  81. package/build/types/ActionRuntimeEnvironment/ActionConnect/Transport/Transport.types.d.ts +0 -70
  82. package/build/types/ActionRuntimeEnvironment/ActionConnect/Transport/TransportCustom.d.ts +0 -12
  83. package/build/types/ActionRuntimeEnvironment/ActionConnect/Transport/TransportHttp.d.ts +0 -9
  84. package/build/types/ActionRuntimeEnvironment/ActionConnect/Transport/TransportWebSocket.d.ts +0 -17
  85. package/build/types/ActionRuntimeEnvironment/ActionConnect/err_nice_connect.d.ts +0 -5
  86. package/build/types/ActionRuntimeEnvironment/ActionHandler/ActionHandler.d.ts +0 -80
  87. package/build/types/ActionRuntimeEnvironment/ActionHandler/ActionHandler.types.d.ts +0 -69
  88. package/build/types/ActionRuntimeEnvironment/ActionRuntimeEnvironment.d.ts +0 -32
  89. package/build/types/ActionRuntimeEnvironment/ActionRuntimeEnvironment.types.d.ts +0 -15
  90. package/build/types/ActionRuntimeEnvironment/utils/getAssumedRuntimeEnvironment.d.ts +0 -2
  91. package/build/types/ActionSchema/NiceActionSchema.types.d.ts +0 -32
  92. package/build/types/ActionSchema/action.d.ts +0 -2
  93. package/build/types/NiceAction/MatchAction/MatchAction.d.ts +0 -27
  94. package/build/types/NiceAction/NiceAction.d.ts +0 -64
  95. package/build/types/NiceAction/NiceAction.enums.d.ts +0 -5
  96. package/build/types/NiceAction/NiceAction.types.d.ts +0 -78
  97. package/build/types/NiceAction/NiceActionCombined.types.d.ts +0 -10
  98. package/build/types/NiceAction/NiceActionPrimed.d.ts +0 -43
  99. package/build/types/NiceAction/NiceActionResponse.d.ts +0 -42
  100. package/build/types/NiceAction/utils/isNiceActionInstance.d.ts +0 -3
  101. package/build/types/utils/isActionResponseJsonObject.d.ts +0 -2
  102. package/build/types/utils/isPrimedActionJsonObject.d.ts +0 -2
  103. /package/build/types/{ActionRuntimeEnvironment/ActionConnect → ActionRuntime/Handler/ExternalClient}/Transport/err_nice_transport_ws.d.ts +0 -0
  104. /package/build/types/utils/{maybePromise.d.ts → typescript/MaybePromise.d.ts} +0 -0
package/README.md CHANGED
@@ -1,410 +1 @@
1
- # @nice-code/action
2
-
3
- A fully-typed action-based RPC framework for TypeScript. Define actions once, execute them locally or over HTTP/WebSocket — same code, same types, everywhere.
4
-
5
- ## Why?
6
-
7
- Modern apps split logic across server, client, and workers. Typed RPC frameworks help, but most still require separate client/server type definitions, custom serialization glue, and ad-hoc error handling. `@nice-code/action` solves this with:
8
-
9
- - **One definition, every environment** — same action works locally, over HTTP, or WebSocket
10
- - **Custom serialization baked in** — `Date`, `Map`, `Buffer` — define it once, it works across the wire automatically
11
- - **Typed error unions** — declare which errors an action throws; TypeScript enforces handling them
12
- - **Observable** — attach listeners for logging, analytics, or tracing with zero boilerplate
13
-
14
- ---
15
-
16
- ## Install
17
-
18
- ```bash
19
- bun add @nice-code/action @nice-code/error valibot
20
- ```
21
-
22
- ---
23
-
24
- ## Core Concepts
25
-
26
- Actions flow through three states:
27
-
28
- ```
29
- NiceAction (definition) → NiceActionPrimed (input attached) → NiceActionResponse (result)
30
- ```
31
-
32
- You mostly work with `NiceAction` and let the framework handle the rest.
33
-
34
- ---
35
-
36
- ## Quick Start
37
-
38
- ### 1. Define a domain and its actions
39
-
40
- ```typescript
41
- import { createActionRootDomain, action } from "@nice-code/action";
42
- import * as v from "valibot";
43
-
44
- const root = createActionRootDomain({ domain: "app" });
45
-
46
- const orderDomain = root.createChildDomain({
47
- domain: "order",
48
- actions: {
49
- placeOrder: action()
50
- .input({ schema: v.object({ items: v.array(v.string()), total: v.number() }) })
51
- .output({ schema: v.object({ orderId: v.string(), estimatedDelivery: v.string() }) }),
52
-
53
- cancelOrder: action()
54
- .input({ schema: v.object({ orderId: v.string(), reason: v.string() }) })
55
- .output({ schema: v.object({ refundAmount: v.number() }) }),
56
- },
57
- });
58
- ```
59
-
60
- ### 2. Register handlers
61
-
62
- ```typescript
63
- import { ActionHandler, createActionRuntime } from "@nice-code/action";
64
-
65
- const handler = new ActionHandler()
66
- .forAction(orderDomain, "placeOrder", {
67
- execution: async (primed) => {
68
- const { items, total } = primed.input; // fully typed
69
- const order = await db.orders.create({ items, total });
70
- return primed.setResponse({
71
- orderId: order.id,
72
- estimatedDelivery: "2-3 business days",
73
- });
74
- },
75
- })
76
- .forAction(orderDomain, "cancelOrder", {
77
- execution: async (primed) => {
78
- const refund = await payments.refund(primed.input.orderId);
79
- return primed.setResponse({ refundAmount: refund.amount });
80
- },
81
- });
82
-
83
- root.setRuntimeEnvironment(
84
- createActionRuntime({ envId: "server" }).addHandlers([handler])
85
- );
86
- ```
87
-
88
- ### 3. Execute
89
-
90
- ```typescript
91
- const result = await orderDomain.action("placeOrder").execute({
92
- items: ["SKU-001", "SKU-002"],
93
- total: 49.99,
94
- });
95
- // result: { orderId: "ord_abc123", estimatedDelivery: "2-3 business days" }
96
- ```
97
-
98
- ---
99
-
100
- ## Typed Error Handling
101
-
102
- Declare errors your action can throw — TypeScript tracks them through `executeSafe()`.
103
-
104
- ```typescript
105
- import { err_auth, err_payment } from "@nice-code/common-errors";
106
-
107
- const checkoutDomain = root.createChildDomain({
108
- domain: "checkout",
109
- actions: {
110
- pay: action()
111
- .input({ schema: v.object({ cartId: v.string(), cardToken: v.string() }) })
112
- .output({ schema: v.object({ receiptId: v.string() }) })
113
- .throws(err_auth, ["unauthenticated"]) // only this error from auth domain
114
- .throws(err_payment), // all payment errors
115
- },
116
- });
117
- ```
118
-
119
- ```typescript
120
- const result = await checkoutDomain.action("pay").executeSafe({
121
- cartId: "cart_xyz",
122
- cardToken: "tok_...",
123
- });
124
-
125
- if (!result.ok) {
126
- // result.error is a fully typed NiceError union
127
- result.error.handleWithSync([
128
- forId(err_auth, "unauthenticated", () => res.status(401).json({ error: "Login required" })),
129
- forId(err_payment, "card_declined", (err) => {
130
- const { last4 } = err.getContext();
131
- res.status(402).json({ error: `Card ending in ${last4} was declined` });
132
- }),
133
- forDomain(err_payment, () => res.status(402).json({ error: "Payment failed" })),
134
- ]);
135
- return;
136
- }
137
-
138
- // result.output: { receiptId: string }
139
- res.json({ receiptId: result.output.receiptId });
140
- ```
141
-
142
- ---
143
-
144
- ## Custom Serialization
145
-
146
- Non-JSON types — `Date`, `Map`, binary — need serialization for transport. Define it once on the schema; the framework handles it on both ends.
147
-
148
- ```typescript
149
- const eventDomain = root.createChildDomain({
150
- domain: "event",
151
- actions: {
152
- schedule: action()
153
- .input(
154
- { schema: v.object({ name: v.string(), scheduledAt: v.date() }) },
155
- // serialize: Date → ISO string for the wire
156
- ({ name, scheduledAt }) => ({ name, iso: scheduledAt.toISOString() }),
157
- // deserialize: ISO string → Date on the other end
158
- ({ name, iso }) => ({ name, scheduledAt: new Date(iso) })
159
- )
160
- .output({ schema: v.object({ eventId: v.string() }) }),
161
- },
162
- });
163
- ```
164
-
165
- ```typescript
166
- // Client sends this:
167
- await eventDomain.action("schedule").execute({
168
- name: "Team meeting",
169
- scheduledAt: new Date("2025-03-15T14:00:00Z"), // ← native Date
170
- });
171
-
172
- // Wire format (what actually travels over HTTP):
173
- // { name: "Team meeting", iso: "2025-03-15T14:00:00.000Z" }
174
-
175
- // Server receives native Date automatically — no manual parsing
176
- handler.forAction(eventDomain, "schedule", {
177
- execution: async (primed) => {
178
- console.log(primed.input.scheduledAt instanceof Date); // true
179
- await calendar.create(primed.input.scheduledAt);
180
- return primed.setResponse({ eventId: "evt_..." });
181
- },
182
- });
183
- ```
184
-
185
- ---
186
-
187
- ## Same Actions, Different Environments
188
-
189
- The same domain definition works on both server (with handlers) and client (with remote transport). No code duplication.
190
-
191
- ### Server
192
-
193
- ```typescript
194
- // server.ts
195
- const handler = new ActionHandler().forDomain(orderDomain, {
196
- execution: async (primed) => {
197
- /* ... real DB logic ... */
198
- },
199
- });
200
-
201
- root.setRuntimeEnvironment(
202
- createActionRuntime({ envId: "server" }).addHandlers([handler])
203
- );
204
-
205
- // One endpoint handles all actions
206
- app.post("/actions", async (req, res) => {
207
- const result = await handler.handleWire(req.body);
208
- if (!result.handled) return res.status(404).end();
209
- res.json(result.response.toJsonObject());
210
- });
211
- ```
212
-
213
- ### Client
214
-
215
- ```typescript
216
- // client.ts — exact same domain, different runtime
217
- import { ActionConnect, ConnectionConfig, createActionRuntime } from "@nice-code/action";
218
-
219
- const connect = new ActionConnect(
220
- [new ConnectionConfig({ transports: [{ type: "http", url: "/actions" }] })],
221
- { requestTimeout: 30_000 }
222
- ).routeDomain(orderDomain);
223
-
224
- root.setRuntimeEnvironment(
225
- createActionRuntime({ envId: "browser" }).addHandlers([connect])
226
- );
227
-
228
- // Works exactly like local execution — goes over HTTP transparently
229
- const result = await orderDomain.action("placeOrder").execute({
230
- items: ["SKU-001"],
231
- total: 29.99,
232
- });
233
- ```
234
-
235
- ### WebSocket for real-time
236
-
237
- ```typescript
238
- new ConnectionConfig({
239
- transports: [
240
- { type: "ws", url: "wss://api.example.com/ws" }, // persistent connection, no reconnect overhead
241
- { type: "http", url: "/actions" }, // fallback
242
- ],
243
- })
244
- ```
245
-
246
- ---
247
-
248
- ## Observability
249
-
250
- Attach listeners to any domain — fire for every action without modifying handlers.
251
-
252
- ```typescript
253
- const unsubscribe = orderDomain.addActionListener({
254
- execution: (primed, { runtime }) => {
255
- logger.info(`[${runtime.name}] → ${primed.domain}::${primed.id}`, primed.input);
256
- },
257
- response: (response, { runtime }) => {
258
- const { result } = response;
259
- if (result.ok) {
260
- metrics.increment(`action.success`, { action: response.id });
261
- } else {
262
- metrics.increment(`action.error`, { action: response.id, error: result.error.id });
263
- }
264
- },
265
- });
266
-
267
- // Clean up when done
268
- unsubscribe();
269
- ```
270
-
271
- ---
272
-
273
- ## Pattern Matching
274
-
275
- When you receive an action and need to branch on its identity:
276
-
277
- ```typescript
278
- import { matchAction } from "@nice-code/action";
279
-
280
- await matchAction(incomingAction)
281
- .with({
282
- domain: orderDomain,
283
- id: "placeOrder",
284
- handler: async (action) => {
285
- // action narrowed to NiceAction<OrderDomain, "placeOrder">
286
- await notifyWarehouse(action.input);
287
- },
288
- })
289
- .with({
290
- domain: orderDomain,
291
- id: "cancelOrder",
292
- handler: async (action) => {
293
- await notifyCustomer(action.input.orderId);
294
- },
295
- })
296
- .otherwise(async (action) => {
297
- logger.warn(`Unhandled action: ${action.domain}::${action.id}`);
298
- })
299
- .runAsync();
300
- ```
301
-
302
- ---
303
-
304
- ## Wire Format
305
-
306
- Every action state serializes to JSON — useful for logging, queuing, or replay:
307
-
308
- ```typescript
309
- const primed = orderDomain.action("placeOrder").prime({ items: ["SKU-001"], total: 29.99 });
310
-
311
- const wire = primed.toJsonObject();
312
- // {
313
- // type: "primed",
314
- // domain: "order",
315
- // allDomains: ["order", "app"],
316
- // id: "placeOrder",
317
- // cuid: "abc123...",
318
- // timeCreated: 1704067200000,
319
- // timePrimed: 1704067201000,
320
- // input: { items: ["SKU-001"], total: 29.99 }
321
- // }
322
-
323
- // Reconstruct anywhere
324
- const rehydrated = orderDomain.hydratePrimed(wire);
325
- await rehydrated.execute(); // executes with original input
326
- ```
327
-
328
- Store actions in a queue, ship them to a worker, execute on the other side — full round-trip with validation.
329
-
330
- ---
331
-
332
- ## Named Handlers (Tags)
333
-
334
- Route different action types to different handlers — useful for auth tiers, feature flags, or test overrides.
335
-
336
- ```typescript
337
- const adminHandler = new ActionHandler({ tag: "admin" })
338
- .forAction(userDomain, "deleteUser", {
339
- execution: async (primed) => { /* admin-only logic */ },
340
- });
341
-
342
- const publicHandler = new ActionHandler()
343
- .forDomain(userDomain, { execution: handlePublicActions });
344
-
345
- root.setRuntimeEnvironment(
346
- createActionRuntime({ envId: "server" })
347
- .addHandlers([adminHandler, publicHandler])
348
- );
349
-
350
- // Use the tagged handler explicitly
351
- await userDomain.action("deleteUser").execute(input, { tag: "admin" });
352
- ```
353
-
354
- ---
355
-
356
- ## API Reference
357
-
358
- ### Domain
359
-
360
- | Method | Description |
361
- |---|---|
362
- | `createActionRootDomain({ domain })` | Create root domain |
363
- | `root.createChildDomain({ domain, actions })` | Create child domain |
364
- | `domain.action(id)` | Get action definition |
365
- | `domain.addActionListener({ execution?, response? })` | Observe all actions; returns unsubscribe fn |
366
- | `domain.hydratePrimed(wire)` | Reconstruct primed action from JSON |
367
- | `domain.hydrateResponse(wire)` | Reconstruct response from JSON |
368
-
369
- ### Action
370
-
371
- | Method | Description |
372
- |---|---|
373
- | `action.execute(input, meta?)` | Execute; throws on error |
374
- | `action.executeSafe(input, meta?)` | Execute; returns `{ ok, output }` or `{ ok, error }` |
375
- | `action.prime(input)` | Attach and validate input |
376
- | `action.is(other)` | Type guard — check if action matches this definition |
377
-
378
- ### Schema Builder (`action()`)
379
-
380
- | Method | Description |
381
- |---|---|
382
- | `.input({ schema }, serialize?, deserialize?)` | Declare input schema + optional serde |
383
- | `.output({ schema }, serialize?, deserialize?)` | Declare output schema + optional serde |
384
- | `.throws(errorDomain, [ids]?)` | Declare throwable errors (all or subset) |
385
-
386
- ### Handlers
387
-
388
- | Class | Use case |
389
- |---|---|
390
- | `ActionHandler` | Local/same-process execution |
391
- | `ActionConnect` | Remote execution over HTTP or WebSocket |
392
-
393
- ### ActionHandler
394
-
395
- | Method | Description |
396
- |---|---|
397
- | `.forAction(domain, id, { execution, response? })` | Handle one action |
398
- | `.forActionIds(domain, ids, { execution, response? })` | Handle a subset |
399
- | `.forDomain(domain, { execution, response? })` | Handle all actions in domain |
400
- | `.forDomainActionCases(domain, cases)` | Handle actions via case map |
401
- | `.handleWire(body)` | Parse and dispatch raw JSON (for HTTP endpoints) |
402
-
403
- ### ActionConnect
404
-
405
- | Method | Description |
406
- |---|---|
407
- | `.routeDomain(domain, route?)` | Route all domain actions remotely |
408
- | `.routeAction(domain, id, route?)` | Route one action remotely |
409
- | `.routeActionIds(domain, ids, route?)` | Route a subset remotely |
410
- | `.disconnect()` | Close connections |
1
+ # @nice-code/action-test