@xmachines/play-xstate 3.0.0 → 4.0.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 (75) hide show
  1. package/README.md +148 -57
  2. package/dist/capabilities.d.ts +92 -0
  3. package/dist/capabilities.d.ts.map +1 -0
  4. package/dist/capabilities.js +4 -0
  5. package/dist/capabilities.js.map +1 -0
  6. package/dist/define-player.d.ts +7 -1
  7. package/dist/define-player.d.ts.map +1 -1
  8. package/dist/define-player.js +9 -60
  9. package/dist/define-player.js.map +1 -1
  10. package/dist/errors.d.ts +29 -26
  11. package/dist/errors.d.ts.map +1 -1
  12. package/dist/errors.js +53 -35
  13. package/dist/errors.js.map +1 -1
  14. package/dist/index.d.ts +2 -4
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +9 -4
  17. package/dist/index.js.map +1 -1
  18. package/dist/player-actor.d.ts +52 -117
  19. package/dist/player-actor.d.ts.map +1 -1
  20. package/dist/player-actor.js +72 -228
  21. package/dist/player-actor.js.map +1 -1
  22. package/dist/routing/derive-current-route.d.ts +1 -36
  23. package/dist/routing/derive-current-route.d.ts.map +1 -1
  24. package/dist/routing/derive-current-route.js +2 -76
  25. package/dist/routing/derive-current-route.js.map +1 -1
  26. package/dist/routing/derive-initial-route.d.ts.map +1 -1
  27. package/dist/routing/derive-initial-route.js +11 -0
  28. package/dist/routing/derive-initial-route.js.map +1 -1
  29. package/dist/routing/derive-route.d.ts +81 -2
  30. package/dist/routing/derive-route.d.ts.map +1 -1
  31. package/dist/routing/derive-route.js +97 -3
  32. package/dist/routing/derive-route.js.map +1 -1
  33. package/dist/routing/format-play-route-transitions.d.ts +8 -2
  34. package/dist/routing/format-play-route-transitions.d.ts.map +1 -1
  35. package/dist/routing/format-play-route-transitions.js +170 -43
  36. package/dist/routing/format-play-route-transitions.js.map +1 -1
  37. package/dist/routing/index.d.ts +1 -1
  38. package/dist/routing/index.d.ts.map +1 -1
  39. package/dist/routing/types.d.ts +9 -5
  40. package/dist/routing/types.d.ts.map +1 -1
  41. package/dist/state-meta.d.ts +52 -0
  42. package/dist/state-meta.d.ts.map +1 -0
  43. package/dist/state-meta.js +77 -0
  44. package/dist/state-meta.js.map +1 -0
  45. package/dist/types.d.ts +18 -3
  46. package/dist/types.d.ts.map +1 -1
  47. package/dist/view/derive-current-view.d.ts +1 -1
  48. package/dist/view/derive-current-view.d.ts.map +1 -1
  49. package/dist/view/derive-current-view.js +2 -2
  50. package/dist/view/derive-current-view.js.map +1 -1
  51. package/dist/with-routing.d.ts +45 -0
  52. package/dist/with-routing.d.ts.map +1 -0
  53. package/dist/with-routing.js +78 -0
  54. package/dist/with-routing.js.map +1 -0
  55. package/dist/with-view.d.ts +42 -0
  56. package/dist/with-view.d.ts.map +1 -0
  57. package/dist/with-view.js +150 -0
  58. package/dist/with-view.js.map +1 -0
  59. package/package.json +38 -17
  60. package/dist/guards/compose.d.ts +0 -158
  61. package/dist/guards/compose.d.ts.map +0 -1
  62. package/dist/guards/compose.js +0 -188
  63. package/dist/guards/compose.js.map +0 -1
  64. package/dist/guards/helpers.d.ts +0 -62
  65. package/dist/guards/helpers.d.ts.map +0 -1
  66. package/dist/guards/helpers.js +0 -85
  67. package/dist/guards/helpers.js.map +0 -1
  68. package/dist/guards/index.d.ts +0 -20
  69. package/dist/guards/index.d.ts.map +0 -1
  70. package/dist/guards/index.js +0 -18
  71. package/dist/guards/index.js.map +0 -1
  72. package/dist/guards/types.d.ts +0 -22
  73. package/dist/guards/types.d.ts.map +0 -1
  74. package/dist/guards/types.js +0 -2
  75. package/dist/guards/types.js.map +0 -1
package/README.md CHANGED
@@ -2,15 +2,13 @@
2
2
 
3
3
  > XState v5 adapter for the XMachines Play Architecture. It binds a state machine to the actor base, with signal-driven reactivity and a router integration.
4
4
 
5
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![Version](https://img.shields.io/badge/version-3.0.0-blue)](https://www.npmjs.com/package/@xmachines/play-xstate)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![Version](https://img.shields.io/badge/version-4.0.0-blue)](https://www.npmjs.com/package/@xmachines/play-xstate)
6
6
 
7
7
  ---
8
8
 
9
9
  > **Browser floor: Chrome 110, Firefox 115, Safari 16.4.** This package calls the ES2023
10
10
  > change-by-copy array methods, so a browser below that floor throws
11
- > `TypeError: ... is not a function`. Vite 8 resolves its default
12
- > `baseline-widely-available` target to Firefox 114, which is below it — raise
13
- > `build.target` when you bundle for the browser. The root README carries the table.
11
+ > `TypeError: ... is not a function`. The root README carries the table.
14
12
 
15
13
  ## Installation
16
14
 
@@ -18,7 +16,7 @@
18
16
  pnpm add @xmachines/play-xstate xstate
19
17
  ```
20
18
 
21
- `xstate ^5.31.0` is a peer dependency. Install it with this package.
19
+ `xstate ^5.33.0` is a peer dependency. Install it with this package.
22
20
 
23
21
  ---
24
22
 
@@ -26,7 +24,8 @@ pnpm add @xmachines/play-xstate xstate
26
24
 
27
25
  ```typescript
28
26
  import { setup } from "xstate";
29
- import { definePlayer } from "@xmachines/play-xstate";
27
+ import { definePlayer, compose, PlayerActor } from "@xmachines/play-xstate";
28
+ import { withRouting } from "@xmachines/play-xstate/routing";
30
29
 
31
30
  // 1. Define your XState v5 machine
32
31
  const machine = setup({}).createMachine({
@@ -38,7 +37,7 @@ const machine = setup({}).createMachine({
38
37
  });
39
38
 
40
39
  // 2. Create a player factory
41
- const createPlayer = definePlayer({ machine });
40
+ const createPlayer = definePlayer({ machine, actor: compose(PlayerActor, withRouting) });
42
41
 
43
42
  // 3. Instantiate and start an actor
44
43
  const actor = createPlayer();
@@ -133,16 +132,75 @@ console.log(restored.currentRoute.get()); // same route as when saved
133
132
 
134
133
  ### `PlayerActor<TMachine>`
135
134
 
136
- This concrete actor class is an XState v5 actor that also exposes reactive TC39 Signals. It implements both the `Routable` interface and the `Viewable` interface from `@xmachines/play-actor`.
135
+ This concrete actor class is an XState v5 actor that exposes reactive TC39 Signals. It holds the protocol of `PlayActor` and nothing else: `state` and `send`.
137
136
 
138
137
  #### Signals
139
138
 
140
- | Signal | Type | Description |
141
- | -------------- | -------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
142
- | `state` | `Signal.State<SnapshotFrom<TMachine>>` | The current XState snapshot. The actor updates it on every active transition |
143
- | `currentRoute` | `Signal.Computed<string \| null>` | The URL that comes from the `meta.route` template of the active state and from the context |
144
- | `currentView` | `Signal.State<PlaySpec \| null>` | The view spec from the `meta.view` metadata of the active state, with the context params added |
145
- | `initialRoute` | `readonly string \| null` | The route of the initial state of the machine. The constructor fixes it, and a router bridge uses it to detect a deep link or a restore |
139
+ | Signal | Type | Description |
140
+ | ------- | -------------------------------------- | ---------------------------------------------------------------------------- |
141
+ | `state` | `Signal.State<SnapshotFrom<TMachine>>` | The current XState snapshot. The actor updates it on every active transition |
142
+
143
+ ### The capabilities
144
+
145
+ Routing and the view are OPTIONAL, and each one is a mixin behind its own entry point. An application that declares no route loads no routing code, and an application that renders no view loads no view code and installs no json-render.
146
+
147
+ Each capability package is an OPTIONAL peer dependency. Install the one that you compose:
148
+
149
+ ```bash
150
+ pnpm add @xmachines/play-router # for @xmachines/play-xstate/routing
151
+ pnpm add @xmachines/play-view # for @xmachines/play-xstate/view
152
+ ```
153
+
154
+ The main entry point of this package names neither. `@xmachines/play-xstate/routing` also
155
+ carries the route utilities — `deriveRoute`, `isAbsoluteRoute`, `buildRouteUrl`,
156
+ `formatPlayRouteTransitions` and the route types — because each one names
157
+ `@xmachines/play-router` in its own types.
158
+
159
+ | Capability | Entry point | Adds | Interface |
160
+ | ---------- | -------------------------------- | ------------------------------ | -------------------------------------- |
161
+ | Routing | `@xmachines/play-xstate/routing` | `currentRoute`, `initialRoute` | `Routable` of `@xmachines/play-router` |
162
+ | View | `@xmachines/play-xstate/view` | `currentView` | `Viewable` of `@xmachines/play-view` |
163
+
164
+ `compose` applies each capability from left to right:
165
+
166
+ ```typescript
167
+ import { definePlayer, PlayerActor, compose } from "@xmachines/play-xstate";
168
+ import { withRouting } from "@xmachines/play-xstate/routing";
169
+ import { withView } from "@xmachines/play-xstate/view";
170
+
171
+ // Both capabilities
172
+ const createPlayer = definePlayer({
173
+ machine,
174
+ actor: compose(PlayerActor, withRouting, withView),
175
+ });
176
+
177
+ // Routing alone: `currentView` is a compile error on this actor
178
+ const createRouted = definePlayer({ machine, actor: compose(PlayerActor, withRouting) });
179
+
180
+ // Neither: `state` and `send`
181
+ const createBare = definePlayer({ machine });
182
+ ```
183
+
184
+ **Compose `withView` after `withRouting`.** An override calls `super.onSnapshot()` first, so the composition order decides the derivation order: the route holds its new value before the view derives from the same transition. A router bridge therefore sees a guard redirect before a renderer sees the view of the state that the guard refused.
185
+
186
+ **A lifecycle hook receives the bare actor.** `PlayerOptions` is typed before the class is composed, so it cannot name the capabilities, and a narrower hook parameter is refused under `strictFunctionTypes`. A hook that reads `currentRoute` or `currentView` reads them through a binding of the composed type:
187
+
188
+ ```typescript
189
+ let composed: PlayerActor<typeof machine> & Routable & Viewable;
190
+
191
+ const actor = definePlayer({
192
+ machine,
193
+ options: { onStateChange: () => console.log(composed.currentRoute.get()) },
194
+ actor: compose(PlayerActor, withRouting, withView),
195
+ })();
196
+ composed = actor;
197
+ ```
198
+
199
+ | Signal | Type | Capability | Description |
200
+ | -------------- | --------------------------------- | ---------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
201
+ | `currentRoute` | `Signal.Computed<string \| null>` | routing | The URL that comes from the `meta.route` template of the active state and from the context |
202
+ | `initialRoute` | `readonly string \| null` | routing | The route of the initial state of the machine. The construction fixes it, and a router bridge uses it to detect a deep link or a restore |
203
+ | `currentView` | `Signal.State<PlaySpec \| null>` | view | The view spec from the `meta.view` metadata of the active state, with the context params added |
146
204
 
147
205
  #### Methods
148
206
 
@@ -153,7 +211,6 @@ This concrete actor class is an XState v5 actor that also exposes reactive TC39
153
211
  | `send(event)` | Sends a typed event to the machine and calls the `onTransition` hook |
154
212
  | `can(event)` | Returns `true` when the current state accepts the given event |
155
213
  | `getSnapshot()` | Returns the current XState snapshot |
156
- | `dispose()` | The alias of `stop()`. Deprecated — call `stop()`, or write `using` |
157
214
  | `[DISPOSE]()` | Stops the actor at the end of a `using` scope. The release is `stop()` |
158
215
 
159
216
  #### Signal usage example
@@ -173,39 +230,26 @@ actor.start();
173
230
 
174
231
  ---
175
232
 
176
- ### Guard utilities
233
+ ### Guards
177
234
 
178
- > **Deprecated:** these guard helpers wrap the `and()`, `or()`, and `not()`
179
- > combinators of XState, but they do not compose with a guard slot that
180
- > `setup()` types. Use the combinators of XState directly. The next major
181
- > version removes this module.
182
-
183
- These composable guard helpers wrap the `and()`, `or()`, and `not()` functions of XState. Use them in a machine `setup({ guards })` definition.
235
+ This package gives no guard utility. Compose a guard with the `and()`, `or()` and `not()` combinators of XState:
184
236
 
185
237
  ```typescript
186
- import { setup } from "xstate";
187
- import {
188
- composeGuards, // AND logic: all guards must pass
189
- composeGuardsOr, // OR logic: at least one guard must pass
190
- negateGuard, // NOT logic: inverts a guard
191
- hasContext, // guard: context field is present and non-null
192
- eventMatches, // guard: event type matches a string
193
- contextFieldMatches, // guard: context field equals a value
194
- } from "@xmachines/play-xstate";
238
+ import { and, not, setup } from "xstate";
195
239
 
196
240
  const machine = setup({
197
241
  guards: {
198
- isLoggedIn: ({ context }) => !!context.userId,
242
+ isLoggedIn: ({ context }) => context.userId !== "",
199
243
  hasAdminRole: ({ context }) => context.role === "admin",
200
244
  },
201
245
  }).createMachine({
202
246
  on: {
203
247
  accessAdmin: {
204
- guard: composeGuards(["isLoggedIn", "hasAdminRole"]),
248
+ guard: and(["isLoggedIn", "hasAdminRole"]),
205
249
  target: "adminPanel",
206
250
  },
207
251
  accessLogin: {
208
- guard: negateGuard("isLoggedIn"),
252
+ guard: not("isLoggedIn"),
209
253
  target: "login",
210
254
  },
211
255
  },
@@ -213,6 +257,10 @@ const machine = setup({
213
257
  });
214
258
  ```
215
259
 
260
+ A combinator resolves each name against the `guards` of `setup()`. A name that the map does not hold therefore fails to compile, and it names the fault: `Type '"typoGuardName"' is not assignable to type '"isLoggedIn"'`.
261
+
262
+ `composeGuards`, `composeGuardsOr`, `negateGuard`, `hasContext`, `eventMatches` and `contextFieldMatches` stood here before. They closed two gaps of the types of XState 5.28. The peer floor of this package is `^5.33.0`, and 5.33 holds neither gap. The helpers also fitted a guard slot that `setup()` types never: the example of this package reached them through an `as never` cast. Write the combinator instead, and write a plain predicate in place of each helper.
263
+
216
264
  ---
217
265
 
218
266
  ### Routing utilities
@@ -225,7 +273,7 @@ This function reads each machine state that has a `meta.route` field. It then ge
225
273
 
226
274
  ```typescript
227
275
  import { setup } from "xstate";
228
- import { formatPlayRouteTransitions } from "@xmachines/play-xstate";
276
+ import { formatPlayRouteTransitions } from "@xmachines/play-xstate/routing";
229
277
 
230
278
  const config = formatPlayRouteTransitions({
231
279
  id: "app",
@@ -309,17 +357,75 @@ import type {
309
357
  PlayerOptions, // Lifecycle hooks (onStart, onStop, onTransition, onStateChange, onError) + inspect
310
358
  PlayerFactory, // Factory function returned by definePlayer()
311
359
  PlayerFactoryResumeOptions, // { snapshot? } for restoring actor state
312
- Guard, // deprecated with the guard utilities — removed in the next major
313
- GuardArray, // deprecated with the guard utilities — removed in the next major
314
- ComposedGuard, // deprecated with the guard utilities — removed in the next major
360
+ } from "@xmachines/play-xstate";
361
+
362
+ import type {
315
363
  RouteMachineConfig, // Minimal machine config accepted by formatPlayRouteTransitions
316
364
  RouteStateNode, // Single state node shape used during route crawling
317
365
  RouteContext, // Context shape expected by buildRouteUrl ({ params?, query?, basePath?, hash? })
318
- RouteObject, // Route metadata object shape: { path: string }
366
+ RouteObject, // Route metadata object shape: { path, reenter?, handler?, data? }
319
367
  RouteMetadata, // Union: string | RouteObject
320
- } from "@xmachines/play-xstate";
368
+ RouteData, // The resolved extra data of a route: Record<string, unknown>
369
+ RouteDataResolver, // The function form of RouteObject.data
370
+ } from "@xmachines/play-xstate/routing";
321
371
  ```
322
372
 
373
+ `RouteObject`, `RouteMetadata`, `RouteData`, and `RouteDataResolver` have one
374
+ definition, and it lives in `@xmachines/play-router`. `@xmachines/play-xstate/routing`
375
+ re-exports them, so either import path gives you the same type. The MAIN entry point of
376
+ this package re-exports them no longer: it would name an optional peer in the types of
377
+ every consumer, including one that composes no routing.
378
+
379
+ ### The object form of `meta.route`
380
+
381
+ The string form declares the path only. The object form declares the path and the
382
+ behaviour of the generated `play.route` transition:
383
+
384
+ ```typescript
385
+ meta: {
386
+ route: {
387
+ path: "/doc/:docId",
388
+ // Where the generated transition sits. The default is "root", which is what
389
+ // XState does: every route transition sits on the root of the machine.
390
+ // "root" — one transition on the root. A route from any state arrives.
391
+ // "local" — one transition on the PARENT. The parent keeps its entry action,
392
+ // and a route from outside the parent arrives NOWHERE.
393
+ // "both" — one in each place. The parent keeps its entry action, and a route
394
+ // from outside the parent still arrives.
395
+ handler: "both",
396
+ // Whether the transition re-enters its OWN DOMAIN. The default is false, which
397
+ // is the default of XState. Under `handler: "root"` the domain is the root of
398
+ // the machine, so `false` spares the root alone: each ancestor between the root
399
+ // and the target still runs its exit and its entry actions. `handler` is the
400
+ // field that spares those intermediate ancestors.
401
+ reenter: false,
402
+ // The extra data of the route. The generated transition assigns it to
403
+ // `context.data`. A literal value, or a function of { context, event }.
404
+ data: { titleKey: "doc.view" },
405
+ },
406
+ }
407
+ ```
408
+
409
+ An unknown `handler` value throws `InvalidRouteHandlerError` at the format time.
410
+
411
+ > **Upgrading from 3.x: the `reenter` default changed, and a machine that relies on it
412
+ > goes quiet.** An earlier release wrote `reenter: true` on EVERY generated transition,
413
+ > so every routed state re-entered its own domain on each navigation and ran its `entry`
414
+ > actions again. The flag is now what `meta.route` declares, and the default is `false` —
415
+ > which is the default of XState. A state whose `entry` action must run on each
416
+ > navigation has to declare `reenter: true` for itself. Nothing throws, and the action
417
+ > simply stops running.
418
+
419
+ The `data` field follows the `WithDynamicParams` shape of XState, so the function form
420
+ reads the context and the event:
421
+
422
+ ```typescript
423
+ data: ({ context, event }) => ({ title: `Document ${event.params?.docId}` });
424
+ ```
425
+
426
+ A function does not survive `JSON.stringify`. Use the literal form for a machine that
427
+ Stately Studio reads, or that a process sends over a wire.
428
+
323
429
  ---
324
430
 
325
431
  ## Error Classes
@@ -329,31 +435,16 @@ The `@xmachines/play-xstate/errors` subpath exports the error classes. The main
329
435
  ```typescript
330
436
  import {
331
437
  MissingRouteParamError, // Required :param absent from context when resolving currentRoute
332
- MissingQueryContextError, // deprecated: no longer thrown
333
438
  MissingStateIdError, // meta.route declared without a state id field
334
439
  InvalidMachineError, // PlayerActor constructed with a non-object machine
335
440
  InvalidEventError, // actor.send() called with null/undefined/non-object
336
441
  ActorThrewNonErrorError, // actor failed with a thrown value that is not an Error
337
442
  InvalidRouteMetadataError, // meta.route is neither a string nor { path: string }
338
- EmptyGuardArrayError, // composeGuards/composeGuardsOr called with empty array
443
+ InvalidRouteHandlerError, // meta.route.handler is not "root", "local", or "both"
339
444
  } from "@xmachines/play-xstate/errors";
340
445
  ```
341
446
 
342
- Every error class extends `PlayError` from `@xmachines/play`. Each class also carries typed detail fields, such as `param`, `template`, and `combinator`. Your code therefore reads the details of an error, and it does not parse the message.
343
-
344
- ---
345
-
346
- ## Testing
347
-
348
- ```bash
349
- # Run tests for this package in isolation
350
- pnpm --filter @xmachines/play-xstate test
351
-
352
- # Watch mode
353
- pnpm --filter @xmachines/play-xstate run test:watch
354
- ```
355
-
356
- The tests use [Vitest](https://vitest.dev/). They are in `packages/play-xstate/test/`.
447
+ Every error class extends `PlayError` from `@xmachines/play/errors`. Each class also carries typed detail fields, such as `param`, `template`, and `handler`. Your code therefore reads the details of an error, and it does not parse the message.
357
448
 
358
449
  ---
359
450
 
@@ -0,0 +1,92 @@
1
+ /**
2
+ * The composition of the optional capabilities of an actor.
3
+ *
4
+ * `PlayerActor` gives the protocol of `PlayActor` and nothing else: `state` and
5
+ * `send`. Routing and the view are capabilities, each one a MIXIN in a module that the
6
+ * core imports never. An application that renders no view therefore loads no view code,
7
+ * and an application that declares no route loads no routing code.
8
+ *
9
+ * {@link compose} applies each capability from left to right, so the LAST one is the
10
+ * outermost class. That is also the order in which `onSnapshot` derives: an override calls
11
+ * `super.onSnapshot()` first, so `compose(PlayerActor, withRouting, withView)` gives the
12
+ * route its new value before the view reads it.
13
+ *
14
+ * ## Why the types read this way
15
+ *
16
+ * A capability is typed by the INSTANCE that it extends, and not by a type parameter for
17
+ * the class. That one decision removes three problems at once:
18
+ *
19
+ * - A class that extends a TYPE PARAMETER must constrain it to `new (...args: any[])`, and
20
+ * TypeScript reports TS2545 for every other spelling. A concrete constructor type needs
21
+ * no `any`.
22
+ * - A mixin that INFERS its return type emits no declaration: `Actor` of XState carries
23
+ * private members such as `_actorScope`, and an anonymous class that holds one is not
24
+ * nameable (TS4094).
25
+ * - A conditional return type cannot be checked against the class that a mixin builds, so
26
+ * it forces `as unknown as` at the return. Nothing here asserts anything.
27
+ *
28
+ * `TCapabilities` carries what the base already added, so a composed constructor names
29
+ * every capability on its instance. {@link compose} is what accumulates them:
30
+ * `compose(PlayerActor, withRouting, withView)` answers an actor that is `Routable` AND
31
+ * `Viewable`. Each capability declares a FIXED return type, so the nested form
32
+ * `withView(withRouting(PlayerActor))` answers `Viewable` alone.
33
+ */
34
+ import type { ActorOptions, AnyStateMachine, InputFrom } from "xstate";
35
+ import type { PlayerActor } from "./player-actor.js";
36
+ import type { PlayerOptions } from "./types.js";
37
+ /**
38
+ * The constructor of a `PlayerActor`, with every capability that it carries already.
39
+ *
40
+ * The argument list is the one that `PlayerActor` declares, so `definePlayer` builds an
41
+ * actor with the arguments checked, whatever the composition added to the instance.
42
+ *
43
+ * @typeParam TMachine - The machine of the actor.
44
+ * @typeParam TCapabilities - What the capabilities added, for example `Routable & Viewable`.
45
+ */
46
+ export type PlayerConstructor<TMachine extends AnyStateMachine, TCapabilities extends object = object> = new (machine: TMachine, options: PlayerOptions<TMachine>, input?: InputFrom<TMachine>, restoredSnapshot?: ActorOptions<TMachine>["snapshot"]) => PlayerActor<TMachine> & TCapabilities;
47
+ /**
48
+ * One capability of an actor: a function that takes an actor class and answers the same
49
+ * class with `TAdded` on the instance.
50
+ *
51
+ * `withRouting` of `@xmachines/play-xstate/routing` and `withView` of
52
+ * `@xmachines/play-xstate/view` are the two that this package ships. Write your own with
53
+ * the same shape, and {@link compose} takes it beside them.
54
+ *
55
+ * @typeParam TMachine - The machine of the actor.
56
+ * @typeParam TAdded - What the capability adds to the instance, for example `Routable`.
57
+ */
58
+ export type Capability<TMachine extends AnyStateMachine, TAdded extends object> = (Base: PlayerConstructor<TMachine>) => PlayerConstructor<TMachine, TAdded>;
59
+ /**
60
+ * Builds an actor class from a base and a list of capabilities.
61
+ *
62
+ * It applies each capability from left to right, so the LAST one is the outermost class,
63
+ * and the return type accumulates what each one adds:
64
+ * `compose(PlayerActor, withRouting, withView)` is `Routable` AND `Viewable`.
65
+ *
66
+ * Use this form, and not the nested one. Each capability declares a FIXED return type, so
67
+ * `withView(withRouting(PlayerActor))` builds the same class at run time and answers
68
+ * `Viewable` alone at the type level — a router bridge then refuses the actor with
69
+ * TS2739. The overloads below are what carries `Routable` through.
70
+ *
71
+ * @example
72
+ * ```typescript
73
+ * import { definePlayer, PlayerActor, compose } from "@xmachines/play-xstate";
74
+ * import { withRouting } from "@xmachines/play-xstate/routing";
75
+ * import { withView } from "@xmachines/play-xstate/view";
76
+ *
77
+ * const createPlayer = definePlayer({
78
+ * machine,
79
+ * actor: compose(PlayerActor, withRouting, withView),
80
+ * });
81
+ * ```
82
+ *
83
+ * Each overload takes the capabilities as separate arguments, `c1` to `c3`, and it
84
+ * applies them from left to right.
85
+ *
86
+ * @param Base - The actor class to build on, normally `PlayerActor`.
87
+ */
88
+ export declare function compose<TMachine extends AnyStateMachine>(Base: PlayerConstructor<TMachine>): PlayerConstructor<TMachine>;
89
+ export declare function compose<TMachine extends AnyStateMachine, TC1 extends object>(Base: PlayerConstructor<TMachine>, c1: Capability<TMachine, TC1>): PlayerConstructor<TMachine, TC1>;
90
+ export declare function compose<TMachine extends AnyStateMachine, TC1 extends object, TC2 extends object>(Base: PlayerConstructor<TMachine>, c1: Capability<TMachine, TC1>, c2: Capability<TMachine, TC2>): PlayerConstructor<TMachine, TC1 & TC2>;
91
+ export declare function compose<TMachine extends AnyStateMachine, TC1 extends object, TC2 extends object, TC3 extends object>(Base: PlayerConstructor<TMachine>, c1: Capability<TMachine, TC1>, c2: Capability<TMachine, TC2>, c3: Capability<TMachine, TC3>): PlayerConstructor<TMachine, TC1 & TC2 & TC3>;
92
+ //# sourceMappingURL=capabilities.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capabilities.d.ts","sourceRoot":"","sources":["../src/capabilities.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAEvE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD;;;;;;;;GAQG;AACH,MAAM,MAAM,iBAAiB,CAC5B,QAAQ,SAAS,eAAe,EAChC,aAAa,SAAS,MAAM,GAAG,MAAM,IAClC,KACH,OAAO,EAAE,QAAQ,EACjB,OAAO,EAAE,aAAa,CAAC,QAAQ,CAAC,EAChC,KAAK,CAAC,EAAE,SAAS,CAAC,QAAQ,CAAC,EAC3B,gBAAgB,CAAC,EAAE,YAAY,CAAC,QAAQ,CAAC,CAAC,UAAU,CAAC,KACjD,WAAW,CAAC,QAAQ,CAAC,GAAG,aAAa,CAAC;AAE3C;;;;;;;;;;GAUG;AACH,MAAM,MAAM,UAAU,CAAC,QAAQ,SAAS,eAAe,EAAE,MAAM,SAAS,MAAM,IAAI,CACjF,IAAI,EAAE,iBAAiB,CAAC,QAAQ,CAAC,KAC7B,iBAAiB,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;AAEzC;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,OAAO,CAAC,QAAQ,SAAS,eAAe,EACvD,IAAI,EAAE,iBAAiB,CAAC,QAAQ,CAAC,GAC/B,iBAAiB,CAAC,QAAQ,CAAC,CAAC;AAC/B,wBAAgB,OAAO,CAAC,QAAQ,SAAS,eAAe,EAAE,GAAG,SAAS,MAAM,EAC3E,IAAI,EAAE,iBAAiB,CAAC,QAAQ,CAAC,EACjC,EAAE,EAAE,UAAU,CAAC,QAAQ,EAAE,GAAG,CAAC,GAC3B,iBAAiB,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;AACpC,wBAAgB,OAAO,CAAC,QAAQ,SAAS,eAAe,EAAE,GAAG,SAAS,MAAM,EAAE,GAAG,SAAS,MAAM,EAC/F,IAAI,EAAE,iBAAiB,CAAC,QAAQ,CAAC,EACjC,EAAE,EAAE,UAAU,CAAC,QAAQ,EAAE,GAAG,CAAC,EAC7B,EAAE,EAAE,UAAU,CAAC,QAAQ,EAAE,GAAG,CAAC,GAC3B,iBAAiB,CAAC,QAAQ,EAAE,GAAG,GAAG,GAAG,CAAC,CAAC;AAC1C,wBAAgB,OAAO,CACtB,QAAQ,SAAS,eAAe,EAChC,GAAG,SAAS,MAAM,EAClB,GAAG,SAAS,MAAM,EAClB,GAAG,SAAS,MAAM,EAElB,IAAI,EAAE,iBAAiB,CAAC,QAAQ,CAAC,EACjC,EAAE,EAAE,UAAU,CAAC,QAAQ,EAAE,GAAG,CAAC,EAC7B,EAAE,EAAE,UAAU,CAAC,QAAQ,EAAE,GAAG,CAAC,EAC7B,EAAE,EAAE,UAAU,CAAC,QAAQ,EAAE,GAAG,CAAC,GAC3B,iBAAiB,CAAC,QAAQ,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC"}
@@ -0,0 +1,4 @@
1
+ export function compose(Base, ...capabilities) {
2
+ return capabilities.reduce((actor, capability) => capability(actor), Base);
3
+ }
4
+ //# sourceMappingURL=capabilities.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capabilities.js","sourceRoot":"","sources":["../src/capabilities.ts"],"names":[],"mappings":"AA4HA,MAAM,UAAU,OAAO,CACtB,IAAiC,EACjC,GAAG,YAEF;IAED,OAAO,YAAY,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,CAAC;AAC5E,CAAC"}
@@ -1,5 +1,6 @@
1
1
  import type { AnyStateMachine } from "xstate";
2
2
  import type { PlayerConfig, PlayerFactory } from "./types.js";
3
+ import type { PlayerConstructor } from "./capabilities.js";
3
4
  /**
4
5
  * Creates a player factory from an XState machine
5
6
  *
@@ -56,5 +57,10 @@ import type { PlayerConfig, PlayerFactory } from "./types.js";
56
57
  * @see {@link PlayerConfig} for the configuration options
57
58
  * @see {@link PlayerFactory} for the signature of the factory function
58
59
  */
59
- export declare const definePlayer: <TMachine extends AnyStateMachine>(config: PlayerConfig<TMachine>) => PlayerFactory<TMachine>;
60
+ export declare function definePlayer<TMachine extends AnyStateMachine>(config: PlayerConfig<TMachine> & {
61
+ actor?: undefined;
62
+ }): PlayerFactory<TMachine>;
63
+ export declare function definePlayer<TMachine extends AnyStateMachine, TCapabilities extends object>(config: PlayerConfig<TMachine, TCapabilities> & {
64
+ actor: PlayerConstructor<TMachine, TCapabilities>;
65
+ }): PlayerFactory<TMachine, TCapabilities>;
60
66
  //# sourceMappingURL=define-player.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"define-player.d.ts","sourceRoot":"","sources":["../src/define-player.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAa,MAAM,QAAQ,CAAC;AACzD,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAA8B,MAAM,YAAY,CAAC;AAG1F;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuDG;AACH,eAAO,MAAM,YAAY,GAAI,QAAQ,SAAS,eAAe,EAC5D,QAAQ,YAAY,CAAC,QAAQ,CAAC,KAC5B,aAAa,CAAC,QAAQ,CAKxB,CAAC"}
1
+ {"version":3,"file":"define-player.d.ts","sourceRoot":"","sources":["../src/define-player.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAa,MAAM,QAAQ,CAAC;AACzD,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAA8B,MAAM,YAAY,CAAC;AAC1F,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAG3D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuDG;AACH,wBAAgB,YAAY,CAAC,QAAQ,SAAS,eAAe,EAC5D,MAAM,EAAE,YAAY,CAAC,QAAQ,CAAC,GAAG;IAAE,KAAK,CAAC,EAAE,SAAS,CAAA;CAAE,GACpD,aAAa,CAAC,QAAQ,CAAC,CAAC;AAC3B,wBAAgB,YAAY,CAAC,QAAQ,SAAS,eAAe,EAAE,aAAa,SAAS,MAAM,EAC1F,MAAM,EAAE,YAAY,CAAC,QAAQ,EAAE,aAAa,CAAC,GAAG;IAC/C,KAAK,EAAE,iBAAiB,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;CAClD,GACC,aAAa,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC"}
@@ -1,62 +1,11 @@
1
1
  import { PlayerActor } from "./player-actor.js";
2
- /**
3
- * Creates a player factory from an XState machine
4
- *
5
- * This factory function accepts an XState v5 machine. It returns a function that
6
- * makes {@link PlayerActor} instances. One configuration can therefore make more
7
- * than one actor instance, and this helps with a test, with an application of
8
- * several instances, and with a render on the server.
9
- *
10
- * @typeParam TMachine - The type of the XState v5 state machine
11
- *
12
- * @param config - The configuration object of the player
13
- * @param config.machine - The XState v5 state machine
14
- * @param config.options - The optional lifecycle hooks: onStart, onTransition, and the others
15
- *
16
- * @returns The factory function. It makes an actor instance, with an optional input context
17
- *
18
- * @example
19
- * A basic player factory
20
- * ```typescript
21
- * import { setup } from "xstate";
22
- * import { definePlayer } from "@xmachines/play-xstate";
23
- *
24
- * const machine = setup({}).createMachine({
25
- * initial: 'idle',
26
- * states: {
27
- * idle: { meta: { route: '/' } },
28
- * active: { meta: { route: '/active' } }
29
- * }
30
- * });
31
- *
32
- * const createPlayer = definePlayer({ machine });
33
- * const actor = createPlayer();
34
- * actor.start();
35
- * ```
36
- *
37
- * @example
38
- * More than one actor instance from one factory
39
- * ```typescript
40
- * const createPlayer = definePlayer({ machine });
41
- *
42
- * // Create an actor for each user
43
- * const alice = createPlayer({ userId: 'alice' });
44
- * const bob = createPlayer({ userId: 'bob' });
45
- *
46
- * alice.start();
47
- * bob.start();
48
- *
49
- * // The two state machines are independent
50
- * console.log(alice.state.get() !== bob.state.get());
51
- * ```
52
- *
53
- * @see [Play RFC](../../docs/rfc/play.md)
54
- * @see {@link PlayerActor} for the concrete actor implementation
55
- * @see {@link PlayerConfig} for the configuration options
56
- * @see {@link PlayerFactory} for the signature of the factory function
57
- */
58
- export const definePlayer = (config) => {
59
- const { machine, options } = config;
60
- return (input, restore) => new PlayerActor(machine, options ?? {}, input, restore?.snapshot);
61
- };
2
+ export function definePlayer(config) {
3
+ const { machine, options, actor } = config;
4
+ // `PlayerActor` is the default, and it carries no capability. A consumer that routes or
5
+ // renders passes a composed class, and this module imports neither capability. The two
6
+ // overloads above are what keeps the answer exact: the default one answers a bare
7
+ // player, and the other answers the player with everything that the composition added.
8
+ const ActorClass = actor ?? PlayerActor;
9
+ return (input, restore) => new ActorClass(machine, options ?? {}, input, restore?.snapshot);
10
+ }
62
11
  //# sourceMappingURL=define-player.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"define-player.js","sourceRoot":"","sources":["../src/define-player.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuDG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAC3B,MAA8B,EACJ,EAAE;IAC5B,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC;IAEpC,OAAO,CAAC,KAA2B,EAAE,OAA8C,EAAE,EAAE,CACtF,IAAI,WAAW,CAAC,OAAO,EAAE,OAAO,IAAI,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;AACpE,CAAC,CAAC"}
1
+ {"version":3,"file":"define-player.js","sourceRoot":"","sources":["../src/define-player.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAkEhD,MAAM,UAAU,YAAY,CAC3B,MAA6C;IAE7C,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,MAAM,CAAC;IAC3C,wFAAwF;IACxF,uFAAuF;IACvF,kFAAkF;IAClF,uFAAuF;IACvF,MAAM,UAAU,GAAG,KAAK,IAAI,WAAW,CAAC;IAExC,OAAO,CAAC,KAA2B,EAAE,OAA8C,EAAE,EAAE,CACtF,IAAI,UAAU,CAAC,OAAO,EAAE,OAAO,IAAI,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;AACnE,CAAC"}
package/dist/errors.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { PlayError } from "@xmachines/play";
1
+ import { PlayError } from "@xmachines/play/errors";
2
2
  /**
3
3
  * `buildRouteUrl()` throws this error when the context of the actor does not hold a
4
4
  * necessary route parameter.
@@ -14,7 +14,7 @@ import { PlayError } from "@xmachines/play";
14
14
  *
15
15
  * @example
16
16
  * ```typescript
17
- * import { buildRouteUrl } from "@xmachines/play-xstate";
17
+ * import { buildRouteUrl } from "@xmachines/play-xstate/routing";
18
18
  * import { MissingRouteParamError } from "@xmachines/play-xstate/errors";
19
19
  *
20
20
  * try {
@@ -35,23 +35,6 @@ export declare class MissingRouteParamError extends PlayError {
35
35
  readonly template: string;
36
36
  constructor(param: string, template: string);
37
37
  }
38
- /**
39
- * @deprecated Nothing throws this error now. `buildRouteUrl` reads an absent `query`
40
- * field as `query: {}`. The generated `play.route` transitions assign `query` on
41
- * every navigation, and the loss that this error guarded against therefore cannot
42
- * happen through the route derivation. A machine that handles `play.route` itself
43
- * and wants the query must assign `event.query` to its context itself. This class
44
- * stays in the exports, so that an `instanceof` handler that exists now still
45
- * compiles. Remove such a handler when you have the time.
46
- *
47
- * `buildRouteUrl()` threw this error before, when the context had a `params` field,
48
- * which means a context that knows the routing, but no `query` field.
49
- *
50
- * **Error code:** `PLAY_XSTATE_MISSING_QUERY_CONTEXT`
51
- */
52
- export declare class MissingQueryContextError extends PlayError {
53
- constructor();
54
- }
55
38
  /**
56
39
  * `formatPlayRouteTransitions()` throws this error when a state node declares a
57
40
  * `meta.route` field but no explicit `id` field.
@@ -112,15 +95,35 @@ export declare class InvalidRouteMetadataError extends PlayError {
112
95
  constructor(route: unknown, source?: string);
113
96
  }
114
97
  /**
115
- * `composeGuards()` and `composeGuardsOr()` throw this error for an empty array of
116
- * guards. A composition of zero guards has no meaning.
98
+ * `formatPlayRouteTransitions()` throws this error for a `meta.route` object whose
99
+ * `handler` field holds a value that the routing layer does not know.
117
100
  *
118
- * **Error code:** `PLAY_XSTATE_EMPTY_GUARD_ARRAY`
101
+ * The field decides WHERE the generated `play.route` transition sits, and each value
102
+ * produces a different reachability. `"local"` in particular makes a state reachable
103
+ * only while its parent is active. A typo such as `"locale"` would therefore fall back
104
+ * to a placement that the author did not ask for, and the route would behave correctly
105
+ * in the test that the author wrote and wrongly everywhere else. The error refuses the
106
+ * value instead.
107
+ *
108
+ * **Error code:** `PLAY_XSTATE_INVALID_ROUTE_HANDLER`
109
+ *
110
+ * @example
111
+ * ```typescript
112
+ * import { InvalidRouteHandlerError } from "@xmachines/play-xstate/errors";
113
+ *
114
+ * try {
115
+ * formatPlayRouteTransitions(config);
116
+ * } catch (error) {
117
+ * if (error instanceof InvalidRouteHandlerError) {
118
+ * console.error(error.handler); // the value that the config declared
119
+ * }
120
+ * }
121
+ * ```
119
122
  */
120
- export declare class EmptyGuardArrayError extends PlayError {
121
- /** The combinator of the call with the empty array: `"and"` or `"or"`. */
122
- readonly combinator: "and" | "or";
123
- constructor(combinator: "and" | "or");
123
+ export declare class InvalidRouteHandlerError extends PlayError {
124
+ /** The value that the config declared, as a string, for the debug work. */
125
+ readonly handler: string;
126
+ constructor(handler: unknown, source?: string);
124
127
  }
125
128
  /**
126
129
  * `PlayerActor.send()` throws this error when the event argument is not a plain
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAsB5C;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,qBAAa,sBAAuB,SAAQ,SAAS;IACpD,+EAA+E;IAC/E,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAEvB,4FAA4F;IAC5F,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;gBAEd,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;CAU3C;AAED;;;;;;;;;;;;;GAaG;AACH,qBAAa,wBAAyB,SAAQ,SAAS;;CAWtD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,qBAAa,mBAAoB,SAAQ,SAAS;IACjD,sGAAsG;IACtG,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,2EAA2E;IAC3E,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;gBAEX,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;CAW3C;AAED;;;;;;GAMG;AACH,qBAAa,mBAAoB,SAAQ,SAAS;;CASjD;AAED;;;;;GAKG;AACH,qBAAa,yBAA0B,SAAQ,SAAS;IACvD,gEAAgE;IAChE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;gBAEZ,KAAK,EAAE,OAAO,EAAE,MAAM,SAAgB;CAUlD;AAED;;;;;GAKG;AACH,qBAAa,oBAAqB,SAAQ,SAAS;IAClD,0EAA0E;IAC1E,QAAQ,CAAC,UAAU,EAAE,KAAK,GAAG,IAAI,CAAC;gBAEtB,UAAU,EAAE,KAAK,GAAG,IAAI;CASpC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,qBAAa,iBAAkB,SAAQ,SAAS;IAC/C,qDAAqD;IACrD,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;gBAEb,MAAM,EAAE,OAAO;CAS3B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,qBAAa,uBAAwB,SAAQ,SAAS;gBACzC,KAAK,EAAE,OAAO;CAS1B"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAsBnD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,qBAAa,sBAAuB,SAAQ,SAAS;IACpD,+EAA+E;IAC/E,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAEvB,4FAA4F;IAC5F,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;gBAEd,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;CAU3C;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,qBAAa,mBAAoB,SAAQ,SAAS;IACjD,sGAAsG;IACtG,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,2EAA2E;IAC3E,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;gBAEX,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;CAW3C;AAED;;;;;;GAMG;AACH,qBAAa,mBAAoB,SAAQ,SAAS;;CASjD;AAqBD;;;;;GAKG;AACH,qBAAa,yBAA0B,SAAQ,SAAS;IACvD,gEAAgE;IAChE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;gBAEZ,KAAK,EAAE,OAAO,EAAE,MAAM,SAAgB;CAUlD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,qBAAa,wBAAyB,SAAQ,SAAS;IACtD,2EAA2E;IAC3E,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;gBAEb,OAAO,EAAE,OAAO,EAAE,MAAM,SAA+B;CAUnE;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,qBAAa,iBAAkB,SAAQ,SAAS;IAC/C,qDAAqD;IACrD,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;gBAEb,MAAM,EAAE,OAAO;CAS3B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,qBAAa,uBAAwB,SAAQ,SAAS;gBACzC,KAAK,EAAE,OAAO;CAS1B"}