@xmachines/play-xstate 1.0.0 → 2.0.0-alpha.1
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 +77 -24
- package/dist/define-player.d.ts +3 -3
- package/dist/define-player.js +3 -3
- package/dist/define-player.typecheck.js +10 -10
- package/dist/define-player.typecheck.js.map +1 -1
- package/dist/errors.d.ts +38 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +45 -0
- package/dist/errors.js.map +1 -1
- package/dist/guards/compose.d.ts +59 -41
- package/dist/guards/compose.d.ts.map +1 -1
- package/dist/guards/compose.js +97 -69
- package/dist/guards/compose.js.map +1 -1
- package/dist/guards/compose.typecheck.d.ts +2 -0
- package/dist/guards/compose.typecheck.d.ts.map +1 -0
- package/dist/guards/compose.typecheck.js +22 -0
- package/dist/guards/compose.typecheck.js.map +1 -0
- package/dist/index.d.ts +4 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/player-actor.d.ts +3 -3
- package/dist/player-actor.d.ts.map +1 -1
- package/dist/player-actor.js +15 -9
- package/dist/player-actor.js.map +1 -1
- package/dist/player-actor.typecheck.js +8 -5
- package/dist/player-actor.typecheck.js.map +1 -1
- package/dist/routing/create-routed-machine.d.ts +71 -0
- package/dist/routing/create-routed-machine.d.ts.map +1 -0
- package/dist/routing/create-routed-machine.js +71 -0
- package/dist/routing/create-routed-machine.js.map +1 -0
- package/dist/routing/derive-initial-route.d.ts +1 -1
- package/dist/routing/derive-initial-route.js +1 -1
- package/dist/routing/format-play-route-transitions.d.ts +54 -11
- package/dist/routing/format-play-route-transitions.d.ts.map +1 -1
- package/dist/routing/format-play-route-transitions.js +125 -52
- package/dist/routing/format-play-route-transitions.js.map +1 -1
- package/dist/routing/index.d.ts +4 -0
- package/dist/routing/index.d.ts.map +1 -1
- package/dist/routing/index.js +2 -0
- package/dist/routing/index.js.map +1 -1
- package/dist/routing/play-route-event.typecheck.d.ts +2 -0
- package/dist/routing/play-route-event.typecheck.d.ts.map +1 -0
- package/dist/routing/play-route-event.typecheck.js +43 -0
- package/dist/routing/play-route-event.typecheck.js.map +1 -0
- package/dist/routing/schemas.d.ts +99 -0
- package/dist/routing/schemas.d.ts.map +1 -0
- package/dist/routing/schemas.js +30 -0
- package/dist/routing/schemas.js.map +1 -0
- package/dist/schemas.d.ts +28 -0
- package/dist/schemas.d.ts.map +1 -0
- package/dist/schemas.js +29 -0
- package/dist/schemas.js.map +1 -0
- package/dist/types.d.ts +1 -1
- package/package.json +9 -9
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { formatPlayRouteTransitions, } from "./format-play-route-transitions.js";
|
|
2
|
+
/**
|
|
3
|
+
* Returns a `createMachine` that routes: identical signature to the setup's
|
|
4
|
+
* own `createMachine`, with {@link formatPlayRouteTransitions} applied to the
|
|
5
|
+
* config at runtime.
|
|
6
|
+
*
|
|
7
|
+
* ### Why this exists
|
|
8
|
+
*
|
|
9
|
+
* `formatPlayRouteTransitions(config)` accepts a loosely-typed config. A config
|
|
10
|
+
* authored as a standalone value loses inline transition-function parameter
|
|
11
|
+
* inference entirely (implicit-any under strict mode), and even the inline
|
|
12
|
+
* `setup().createMachine(formatPlayRouteTransitions({ ... }))` form depends on
|
|
13
|
+
* TypeScript threading contextual typing through two generic calls.
|
|
14
|
+
*
|
|
15
|
+
* This wrapper removes the question: it is typed as the setup's own
|
|
16
|
+
* `createMachine`, so the config is contextually typed exactly as if passed to
|
|
17
|
+
* `setup().createMachine(...)` directly — transition-function args infer from
|
|
18
|
+
* the setup's schemas, sibling targets are validated, and the returned machine
|
|
19
|
+
* keeps its full literal state-value typing.
|
|
20
|
+
*
|
|
21
|
+
* Typing is *identical to native* — including its current gaps: as of xstate
|
|
22
|
+
* 6.0.0-alpha.20, `event` and `context` reads in transition args are fully
|
|
23
|
+
* typed, while returned context patches are property-typed but still carry a
|
|
24
|
+
* loose index signature in the alpha itself. Expect that to tighten upstream
|
|
25
|
+
* without changes here.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```typescript
|
|
29
|
+
* import { setup, types } from "xstate";
|
|
30
|
+
* import { createRoutedMachine, playMetaSchema, playRouteEventSchema } from "@xmachines/play-xstate";
|
|
31
|
+
*
|
|
32
|
+
* const authSetup = setup({
|
|
33
|
+
* schemas: {
|
|
34
|
+
* context: types<{ isAuthenticated: boolean }>(),
|
|
35
|
+
* events: { "play.route": playRouteEventSchema },
|
|
36
|
+
* meta: playMetaSchema,
|
|
37
|
+
* },
|
|
38
|
+
* });
|
|
39
|
+
*
|
|
40
|
+
* const machine = createRoutedMachine(authSetup)({
|
|
41
|
+
* initial: "home",
|
|
42
|
+
* context: { isAuthenticated: false },
|
|
43
|
+
* states: {
|
|
44
|
+
* home: { id: "home", meta: { route: "/" } },
|
|
45
|
+
* login: { id: "login", meta: { route: "/login" } },
|
|
46
|
+
* },
|
|
47
|
+
* });
|
|
48
|
+
* // ({ context }) params in transitions infer from the setup schemas —
|
|
49
|
+
* // no explicit annotations needed.
|
|
50
|
+
* ```
|
|
51
|
+
*
|
|
52
|
+
* Note: routes are injected at runtime, so the machine's static type does not
|
|
53
|
+
* gain an `xstate.route` event for them — `play.route` (declared in the
|
|
54
|
+
* setup's event schemas) remains the typed public API; native `xstate.route`
|
|
55
|
+
* interop is runtime-only.
|
|
56
|
+
*
|
|
57
|
+
* @param s - A `setup(...)` return value (anything with `createMachine`).
|
|
58
|
+
* @returns A function with the same signature as `s.createMachine` that
|
|
59
|
+
* applies {@link formatPlayRouteTransitions} before creating the machine.
|
|
60
|
+
*
|
|
61
|
+
* @see {@link formatPlayRouteTransitions} for the routing transform itself
|
|
62
|
+
*/
|
|
63
|
+
export const createRoutedMachine = (s) =>
|
|
64
|
+
// The runtime transform only ADDS behavior (native route configs + the
|
|
65
|
+
// play.route forwarder) and preserves the config's own shape, so exposing
|
|
66
|
+
// the setup's exact createMachine signature keeps native config typing.
|
|
67
|
+
((config) =>
|
|
68
|
+
// One internal widening cast: the `never[]` constraint that keeps
|
|
69
|
+
// SetupLike any-free also makes the parameter uncallable directly.
|
|
70
|
+
s.createMachine(formatPlayRouteTransitions(config)));
|
|
71
|
+
//# sourceMappingURL=create-routed-machine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-routed-machine.js","sourceRoot":"","sources":["../../src/routing/create-routed-machine.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,0BAA0B,GAE1B,MAAM,oCAAoC,CAAC;AAa5C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4DG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAA2B,CAAS,EAA2B,EAAE;AACnG,uEAAuE;AACvE,0EAA0E;AAC1E,wEAAwE;AACxE,CAAC,CAAC,MAA0B,EAAE,EAAE;AAC/B,kEAAkE;AAClE,mEAAmE;AAClE,CAAC,CAAC,aAA8C,CAChD,0BAA0B,CAAC,MAAM,CAAC,CAClC,CAA4B,CAAC"}
|
|
@@ -17,7 +17,7 @@ import { type AnyStateMachine } from "xstate";
|
|
|
17
17
|
* a different restored route → actor wins). Because the derivation never consults a
|
|
18
18
|
* restored snapshot, it always yields the machine's **default** initial route.
|
|
19
19
|
*
|
|
20
|
-
* @param machine - XState
|
|
20
|
+
* @param machine - XState v6 state machine definition.
|
|
21
21
|
* @param input - Actor input, applied to the machine's context factory exactly as
|
|
22
22
|
* `createActor(machine, { input })` would.
|
|
23
23
|
* @returns Resolved initial URL string, or `null` if the initial state has no
|
|
@@ -18,7 +18,7 @@ import { deriveCurrentRoute } from "./derive-current-route.js";
|
|
|
18
18
|
* a different restored route → actor wins). Because the derivation never consults a
|
|
19
19
|
* restored snapshot, it always yields the machine's **default** initial route.
|
|
20
20
|
*
|
|
21
|
-
* @param machine - XState
|
|
21
|
+
* @param machine - XState v6 state machine definition.
|
|
22
22
|
* @param input - Actor input, applied to the machine's context factory exactly as
|
|
23
23
|
* `createActor(machine, { input })` would.
|
|
24
24
|
* @returns Resolved initial URL string, or `null` if the initial state has no
|
|
@@ -18,6 +18,8 @@ export type RouteStateNode = {
|
|
|
18
18
|
*/
|
|
19
19
|
route?: RouteMetadata;
|
|
20
20
|
};
|
|
21
|
+
/** XState v6 native route config; injected as `{}` when absent. */
|
|
22
|
+
route?: unknown;
|
|
21
23
|
/** Nested child states, recursively crawled for additional route declarations. */
|
|
22
24
|
states?: Record<string, RouteStateNode>;
|
|
23
25
|
[key: string]: unknown;
|
|
@@ -30,8 +32,15 @@ export type RouteStateNode = {
|
|
|
30
32
|
* config object and the stricter `setup().createMachine` config without requiring
|
|
31
33
|
* any type casts at the call site. The generic `T extends RouteMachineConfig`
|
|
32
34
|
* parameter on `formatPlayRouteTransitions` preserves the original concrete type
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
+
* of the RETURN value, so it remains directly usable by `setup().createMachine()`.
|
|
36
|
+
*
|
|
37
|
+
* Known limitation: a config authored as a STANDALONE value
|
|
38
|
+
* (`const config = formatPlayRouteTransitions({...})`) is typed against this
|
|
39
|
+
* loose shape only, so inline transition functions lose parameter inference
|
|
40
|
+
* (implicit-any under strict mode). Written inline inside a
|
|
41
|
+
* `setup().createMachine(formatPlayRouteTransitions({...}))` call, contextual
|
|
42
|
+
* typing still flows. {@link createRoutedMachine} is the recommended entry
|
|
43
|
+
* point either way — it keeps the setup's exact `createMachine` signature.
|
|
35
44
|
*/
|
|
36
45
|
export type RouteMachineConfig = {
|
|
37
46
|
context?: unknown;
|
|
@@ -40,12 +49,18 @@ export type RouteMachineConfig = {
|
|
|
40
49
|
[key: string]: unknown;
|
|
41
50
|
};
|
|
42
51
|
/**
|
|
43
|
-
* Formats play.route
|
|
52
|
+
* Formats play.route routing from declarative route configs.
|
|
44
53
|
*
|
|
45
|
-
* Crawls machine states looking for states with meta.route and
|
|
46
|
-
*
|
|
54
|
+
* Crawls machine states looking for states with `meta.route` and wires them to
|
|
55
|
+
* XState v6's **native routing machinery**:
|
|
47
56
|
*
|
|
48
|
-
*
|
|
57
|
+
* - every routed state gets a native `route: {}` config (unless it already
|
|
58
|
+
* declares its own `route`), making it targetable via the built-in
|
|
59
|
+
* `{ type: "xstate.route", to: "#id" }` event (Stately tooling interop and
|
|
60
|
+
* statically-known graph edges), and
|
|
61
|
+
* - one root-level `play.route` forwarder performs the navigation for those
|
|
62
|
+
* targets as ONE atomic transition: target + re-entry + a shallow
|
|
63
|
+
* `params`/`query` context patch.
|
|
49
64
|
*
|
|
50
65
|
* @example
|
|
51
66
|
* ```typescript
|
|
@@ -60,13 +75,41 @@ export type RouteMachineConfig = {
|
|
|
60
75
|
* const machine = createMachine(formatPlayRouteTransitions(machineConfig));
|
|
61
76
|
* ```
|
|
62
77
|
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
78
|
+
* Because the injected `route` configs are static (object form), the machine's
|
|
79
|
+
* route transitions keep **statically-known targets** — `toDirectedGraph()` /
|
|
80
|
+
* `machineToGraph()` edges point at the actual routed states, so graph
|
|
81
|
+
* reachability queries work. (Function-form transition candidates would have
|
|
82
|
+
* dynamic targets, opaque to static analysis.)
|
|
83
|
+
*
|
|
84
|
+
* The `play.route` public API and its v5 semantics are preserved:
|
|
85
|
+
* - `send({ type: "play.route", to: "#home", params, query })` navigates and
|
|
86
|
+
* patches `context.params`/`context.query` in the SAME transition — exit
|
|
87
|
+
* actions of the departing state observe the OLD params, entry actions of
|
|
88
|
+
* the target observe the NEW ones, `always` transitions never see a
|
|
89
|
+
* half-navigated intermediate state, and entry/exit actions receive the
|
|
90
|
+
* original `play.route` event;
|
|
91
|
+
* - user-defined `play.route` transitions (e.g. a hand-written 404 fallback)
|
|
92
|
+
* are preserved AFTER the forwarder: for unknown targets the forwarder
|
|
93
|
+
* returns `undefined`, so evaluation falls through to them;
|
|
94
|
+
* - `params`/`query` are only patched when the forwarder navigates — unknown
|
|
95
|
+
* and blocked targets leave context untouched.
|
|
96
|
+
*
|
|
97
|
+
* When a state declares its OWN `route` config (which wins over the injected
|
|
98
|
+
* default), the forwarder re-raises the event as `xstate.route` instead of
|
|
99
|
+
* navigating, so the user's resolver decides — including blocking. The
|
|
100
|
+
* forwarder does NOT patch `params`/`query` for such targets (a blocking
|
|
101
|
+
* resolver would otherwise leave context describing a route that was never
|
|
102
|
+
* entered); the user's function-form resolver owns any context patch, and
|
|
103
|
+
* that navigation microstep runs under the `xstate.route` event.
|
|
104
|
+
*
|
|
105
|
+
* Native `xstate.route` events also work directly (Stately ecosystem tooling),
|
|
106
|
+
* but bypass the forwarder — no `params`/`query` context patch is applied, so
|
|
107
|
+
* stale values from earlier `play.route` events linger in context (and a
|
|
108
|
+
* router bridge deriving the URL from context would interpolate those stale
|
|
109
|
+
* params).
|
|
67
110
|
*
|
|
68
111
|
* @param machineConfig - XState machine config (before createMachine). Must extend `RouteMachineConfig`.
|
|
69
|
-
* @returns The
|
|
112
|
+
* @returns The machine config with native `route` configs and the `play.route` forwarder merged in, preserving the original type `T`.
|
|
70
113
|
*/
|
|
71
114
|
export declare function formatPlayRouteTransitions<T extends RouteMachineConfig>(machineConfig: T): T;
|
|
72
115
|
//# sourceMappingURL=format-play-route-transitions.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"format-play-route-transitions.d.ts","sourceRoot":"","sources":["../../src/routing/format-play-route-transitions.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"format-play-route-transitions.d.ts","sourceRoot":"","sources":["../../src/routing/format-play-route-transitions.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD;;;;;;;GAOG;AACH,MAAM,MAAM,cAAc,GAAG;IAC5B,iHAAiH;IACjH,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,iEAAiE;IACjE,IAAI,CAAC,EAAE;QACN;;;WAGG;QACH,KAAK,CAAC,EAAE,aAAa,CAAC;KACtB,CAAC;IACF,mEAAmE;IACnE,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,kFAAkF;IAClF,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IACxC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACvB,CAAC;AA4BF;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,MAAM,kBAAkB,GAAG;IAChC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;IAC7C,EAAE,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;IACzC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACvB,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8DG;AACH,wBAAgB,0BAA0B,CAAC,CAAC,SAAS,kBAAkB,EAAE,aAAa,EAAE,CAAC,GAAG,CAAC,CAyH5F"}
|
|
@@ -1,13 +1,18 @@
|
|
|
1
|
-
import { assign } from "xstate";
|
|
2
1
|
import { MissingStateIdError } from "../errors.js";
|
|
3
2
|
import { normalizeRoute } from "./derive-route.js";
|
|
4
3
|
/**
|
|
5
|
-
* Formats play.route
|
|
4
|
+
* Formats play.route routing from declarative route configs.
|
|
6
5
|
*
|
|
7
|
-
* Crawls machine states looking for states with meta.route and
|
|
8
|
-
*
|
|
6
|
+
* Crawls machine states looking for states with `meta.route` and wires them to
|
|
7
|
+
* XState v6's **native routing machinery**:
|
|
9
8
|
*
|
|
10
|
-
*
|
|
9
|
+
* - every routed state gets a native `route: {}` config (unless it already
|
|
10
|
+
* declares its own `route`), making it targetable via the built-in
|
|
11
|
+
* `{ type: "xstate.route", to: "#id" }` event (Stately tooling interop and
|
|
12
|
+
* statically-known graph edges), and
|
|
13
|
+
* - one root-level `play.route` forwarder performs the navigation for those
|
|
14
|
+
* targets as ONE atomic transition: target + re-entry + a shallow
|
|
15
|
+
* `params`/`query` context patch.
|
|
11
16
|
*
|
|
12
17
|
* @example
|
|
13
18
|
* ```typescript
|
|
@@ -22,21 +27,58 @@ import { normalizeRoute } from "./derive-route.js";
|
|
|
22
27
|
* const machine = createMachine(formatPlayRouteTransitions(machineConfig));
|
|
23
28
|
* ```
|
|
24
29
|
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
30
|
+
* Because the injected `route` configs are static (object form), the machine's
|
|
31
|
+
* route transitions keep **statically-known targets** — `toDirectedGraph()` /
|
|
32
|
+
* `machineToGraph()` edges point at the actual routed states, so graph
|
|
33
|
+
* reachability queries work. (Function-form transition candidates would have
|
|
34
|
+
* dynamic targets, opaque to static analysis.)
|
|
35
|
+
*
|
|
36
|
+
* The `play.route` public API and its v5 semantics are preserved:
|
|
37
|
+
* - `send({ type: "play.route", to: "#home", params, query })` navigates and
|
|
38
|
+
* patches `context.params`/`context.query` in the SAME transition — exit
|
|
39
|
+
* actions of the departing state observe the OLD params, entry actions of
|
|
40
|
+
* the target observe the NEW ones, `always` transitions never see a
|
|
41
|
+
* half-navigated intermediate state, and entry/exit actions receive the
|
|
42
|
+
* original `play.route` event;
|
|
43
|
+
* - user-defined `play.route` transitions (e.g. a hand-written 404 fallback)
|
|
44
|
+
* are preserved AFTER the forwarder: for unknown targets the forwarder
|
|
45
|
+
* returns `undefined`, so evaluation falls through to them;
|
|
46
|
+
* - `params`/`query` are only patched when the forwarder navigates — unknown
|
|
47
|
+
* and blocked targets leave context untouched.
|
|
48
|
+
*
|
|
49
|
+
* When a state declares its OWN `route` config (which wins over the injected
|
|
50
|
+
* default), the forwarder re-raises the event as `xstate.route` instead of
|
|
51
|
+
* navigating, so the user's resolver decides — including blocking. The
|
|
52
|
+
* forwarder does NOT patch `params`/`query` for such targets (a blocking
|
|
53
|
+
* resolver would otherwise leave context describing a route that was never
|
|
54
|
+
* entered); the user's function-form resolver owns any context patch, and
|
|
55
|
+
* that navigation microstep runs under the `xstate.route` event.
|
|
56
|
+
*
|
|
57
|
+
* Native `xstate.route` events also work directly (Stately ecosystem tooling),
|
|
58
|
+
* but bypass the forwarder — no `params`/`query` context patch is applied, so
|
|
59
|
+
* stale values from earlier `play.route` events linger in context (and a
|
|
60
|
+
* router bridge deriving the URL from context would interpolate those stale
|
|
61
|
+
* params).
|
|
29
62
|
*
|
|
30
63
|
* @param machineConfig - XState machine config (before createMachine). Must extend `RouteMachineConfig`.
|
|
31
|
-
* @returns The
|
|
64
|
+
* @returns The machine config with native `route` configs and the `play.route` forwarder merged in, preserving the original type `T`.
|
|
32
65
|
*/
|
|
33
66
|
export function formatPlayRouteTransitions(machineConfig) {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
67
|
+
/**
|
|
68
|
+
* Routing table: `#id` -> the state's key path (e.g. `.dashboard.stats`)
|
|
69
|
+
* for targets whose `route` config was injected by this transform, or
|
|
70
|
+
* `null` for targets with a USER-declared `route` config (the user's
|
|
71
|
+
* resolver decides those — the forwarder re-raises instead of navigating).
|
|
72
|
+
*/
|
|
73
|
+
const routeTargets = new Map();
|
|
74
|
+
/**
|
|
75
|
+
* Rebuild the states tree, injecting a native `route` config into routed
|
|
76
|
+
* nodes. The input config is never mutated — every node is shallow-copied.
|
|
77
|
+
*/
|
|
78
|
+
const injectRoutes = (states, parentPath = "") => {
|
|
79
|
+
const next = {};
|
|
80
|
+
for (const [key, stateConfig] of Object.entries(states)) {
|
|
81
|
+
const node = { ...stateConfig };
|
|
40
82
|
const statePath = parentPath ? `${parentPath}.${key}` : key;
|
|
41
83
|
// Validates the metadata (malformed object routes throw
|
|
42
84
|
// InvalidRouteMetadataError) and normalizes to the path string. Both
|
|
@@ -48,48 +90,79 @@ export function formatPlayRouteTransitions(machineConfig) {
|
|
|
48
90
|
if (routePath && !node.id) {
|
|
49
91
|
throw new MissingStateIdError(key, routePath);
|
|
50
92
|
}
|
|
51
|
-
if (routePath && node.id) {
|
|
52
|
-
const transition = {
|
|
53
|
-
target: `.${statePath}`,
|
|
54
|
-
guard: ({ event }) => event.to === `#${node.id}`,
|
|
55
|
-
reenter: true,
|
|
56
|
-
actions: assign({
|
|
57
|
-
params: ({ event }) => event.params || {},
|
|
58
|
-
query: ({ event }) => event.query || {},
|
|
59
|
-
}),
|
|
60
|
-
};
|
|
61
|
-
routeTransitions.push(transition);
|
|
62
|
-
}
|
|
63
93
|
if (node.states) {
|
|
64
|
-
|
|
94
|
+
node.states = injectRoutes(node.states, statePath);
|
|
95
|
+
}
|
|
96
|
+
if (routePath && node.id) {
|
|
97
|
+
if (node.route === undefined) {
|
|
98
|
+
// Native object-form route config: statically-targeted transition,
|
|
99
|
+
// visible to graph tooling. The play.route forwarder navigates these
|
|
100
|
+
// targets DIRECTLY (atomically); the native config exists for
|
|
101
|
+
// xstate.route interop (Stately tooling, devtools).
|
|
102
|
+
node.route = {};
|
|
103
|
+
routeTargets.set(`#${node.id}`, `.${statePath}`);
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
// A user-declared route config wins: the forwarder re-raises
|
|
107
|
+
// xstate.route so the user's resolver decides (and owns any
|
|
108
|
+
// context patch).
|
|
109
|
+
routeTargets.set(`#${node.id}`, null);
|
|
110
|
+
}
|
|
65
111
|
}
|
|
66
|
-
|
|
112
|
+
next[key] = node;
|
|
113
|
+
}
|
|
114
|
+
return next;
|
|
67
115
|
};
|
|
68
116
|
const machineStates = machineConfig.states;
|
|
69
|
-
|
|
70
|
-
|
|
117
|
+
const injectedStates = machineStates ? injectRoutes(machineStates) : machineStates;
|
|
118
|
+
if (routeTargets.size === 0) {
|
|
119
|
+
return machineConfig;
|
|
71
120
|
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
"
|
|
87
|
-
|
|
121
|
+
// Root play.route forwarder. For injected-route targets it returns ONE
|
|
122
|
+
// atomic transition (target + reenter + params/query patch): exit actions
|
|
123
|
+
// see the OLD params, `always` transitions never observe a half-navigated
|
|
124
|
+
// intermediate state, and entry/exit actions receive the original
|
|
125
|
+
// play.route event. For user-routed targets it re-raises xstate.route
|
|
126
|
+
// WITHOUT patching (the user's resolver owns the patch — otherwise a
|
|
127
|
+
// blocking resolver would leave context describing a route that was never
|
|
128
|
+
// entered). Unknown targets return undefined so user fallback candidates
|
|
129
|
+
// below are evaluated.
|
|
130
|
+
const forwarder = ({ event }, enq) => {
|
|
131
|
+
const target = routeTargets.get(event.to);
|
|
132
|
+
if (target === undefined)
|
|
133
|
+
return undefined;
|
|
134
|
+
if (target === null) {
|
|
135
|
+
enq.raise({ ...event, type: "xstate.route" });
|
|
136
|
+
return {};
|
|
137
|
+
}
|
|
88
138
|
return {
|
|
89
|
-
|
|
90
|
-
|
|
139
|
+
target,
|
|
140
|
+
reenter: true,
|
|
141
|
+
// Shallow context patch — v6's replacement for assign().
|
|
142
|
+
context: {
|
|
143
|
+
params: event.params || {},
|
|
144
|
+
query: event.query || {},
|
|
145
|
+
},
|
|
91
146
|
};
|
|
92
|
-
}
|
|
93
|
-
|
|
147
|
+
};
|
|
148
|
+
// Preserve user-defined play.route transitions (e.g. a hand-written 404
|
|
149
|
+
// fallback) by appending them AFTER the forwarder: XState evaluates
|
|
150
|
+
// candidate transitions in order, so the forwarder wins for known targets
|
|
151
|
+
// and the user's transitions act as fallbacks otherwise.
|
|
152
|
+
const existingOn = machineConfig.on || {};
|
|
153
|
+
const userRouteTransitions = existingOn["play.route"];
|
|
154
|
+
const normalizedUserTransitions = userRouteTransitions === undefined
|
|
155
|
+
? []
|
|
156
|
+
: Array.isArray(userRouteTransitions)
|
|
157
|
+
? userRouteTransitions
|
|
158
|
+
: [userRouteTransitions];
|
|
159
|
+
return {
|
|
160
|
+
...machineConfig,
|
|
161
|
+
states: injectedStates,
|
|
162
|
+
on: {
|
|
163
|
+
...existingOn,
|
|
164
|
+
"play.route": [forwarder, ...normalizedUserTransitions],
|
|
165
|
+
},
|
|
166
|
+
};
|
|
94
167
|
}
|
|
95
168
|
//# sourceMappingURL=format-play-route-transitions.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"format-play-route-transitions.js","sourceRoot":"","sources":["../../src/routing/format-play-route-transitions.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"format-play-route-transitions.js","sourceRoot":"","sources":["../../src/routing/format-play-route-transitions.ts"],"names":[],"mappings":"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"}
|
package/dist/routing/index.d.ts
CHANGED
|
@@ -11,6 +11,10 @@ export { deriveCurrentRoute } from "./derive-current-route.js";
|
|
|
11
11
|
export { deriveInitialRoute } from "./derive-initial-route.js";
|
|
12
12
|
export { buildRouteUrl } from "./build-url.js";
|
|
13
13
|
export { formatPlayRouteTransitions } from "./format-play-route-transitions.js";
|
|
14
|
+
export { playMetaSchema, playRouteEventSchema } from "./schemas.js";
|
|
15
|
+
export type { PlayRoutePayload, WithOptional } from "./schemas.js";
|
|
16
|
+
export type { SetupLike } from "./create-routed-machine.js";
|
|
17
|
+
export { createRoutedMachine } from "./create-routed-machine.js";
|
|
14
18
|
export type { RouteMachineConfig, RouteStateNode } from "./format-play-route-transitions.js";
|
|
15
19
|
export type { RouteContext, RouteObject, RouteMetadata } from "./types.js";
|
|
16
20
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/routing/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,0BAA0B,EAAE,MAAM,oCAAoC,CAAC;AAChF,YAAY,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAC7F,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/routing/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,0BAA0B,EAAE,MAAM,oCAAoC,CAAC;AAChF,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACpE,YAAY,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACnE,YAAY,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,YAAY,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAC7F,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/routing/index.js
CHANGED
|
@@ -11,4 +11,6 @@ export { deriveCurrentRoute } from "./derive-current-route.js";
|
|
|
11
11
|
export { deriveInitialRoute } from "./derive-initial-route.js";
|
|
12
12
|
export { buildRouteUrl } from "./build-url.js";
|
|
13
13
|
export { formatPlayRouteTransitions } from "./format-play-route-transitions.js";
|
|
14
|
+
export { playMetaSchema, playRouteEventSchema } from "./schemas.js";
|
|
15
|
+
export { createRoutedMachine } from "./create-routed-machine.js";
|
|
14
16
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/routing/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,0BAA0B,EAAE,MAAM,oCAAoC,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/routing/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,0BAA0B,EAAE,MAAM,oCAAoC,CAAC;AAChF,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAGpE,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"play-route-event.typecheck.d.ts","sourceRoot":"","sources":["../../src/routing/play-route-event.typecheck.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type-level contract for the play.route event payload as machines receive it
|
|
3
|
+
* through playRouteEventSchema. Pins the requirements the hand-written v5
|
|
4
|
+
* union enforced: `to` is required and string-typed; params/query/match are
|
|
5
|
+
* omittable; values constructed as PlayRouteEvent (router bridges) remain
|
|
6
|
+
* assignable.
|
|
7
|
+
*/
|
|
8
|
+
import { setup } from "xstate";
|
|
9
|
+
import { playRouteEventSchema } from "./schemas.js";
|
|
10
|
+
const s = setup({
|
|
11
|
+
schemas: {
|
|
12
|
+
events: { "play.route": playRouteEventSchema },
|
|
13
|
+
},
|
|
14
|
+
});
|
|
15
|
+
const m = s.createMachine({ initial: "a", states: { a: {} } });
|
|
16
|
+
// Minimal send: optional payload fields are omittable.
|
|
17
|
+
const minimal = { type: "play.route", to: "#home" };
|
|
18
|
+
// Full send: every documented field accepted.
|
|
19
|
+
const full = {
|
|
20
|
+
type: "play.route",
|
|
21
|
+
to: "#profile",
|
|
22
|
+
params: { username: "alice" },
|
|
23
|
+
query: { tab: "posts" },
|
|
24
|
+
match: {},
|
|
25
|
+
};
|
|
26
|
+
// @ts-expect-error `to` is required — a routeless play.route must not compile
|
|
27
|
+
const missingTo = { type: "play.route" };
|
|
28
|
+
// @ts-expect-error `to` must be a string
|
|
29
|
+
const badTo = { type: "play.route", to: 123 };
|
|
30
|
+
const badParams = {
|
|
31
|
+
type: "play.route",
|
|
32
|
+
to: "#p",
|
|
33
|
+
// @ts-expect-error `params` values must be strings
|
|
34
|
+
params: { n: 42 },
|
|
35
|
+
};
|
|
36
|
+
const fromBridge = bridgeEvent;
|
|
37
|
+
void fromBridge;
|
|
38
|
+
void minimal;
|
|
39
|
+
void full;
|
|
40
|
+
void missingTo;
|
|
41
|
+
void badTo;
|
|
42
|
+
void badParams;
|
|
43
|
+
//# sourceMappingURL=play-route-event.typecheck.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"play-route-event.typecheck.js","sourceRoot":"","sources":["../../src/routing/play-route-event.typecheck.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,KAAK,EAAuB,MAAM,QAAQ,CAAC;AAEpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAEpD,MAAM,CAAC,GAAG,KAAK,CAAC;IACf,OAAO,EAAE;QACR,MAAM,EAAE,EAAE,YAAY,EAAE,oBAAoB,EAAE;KAC9C;CACD,CAAC,CAAC;AACH,MAAM,CAAC,GAAG,CAAC,CAAC,aAAa,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;AAG/D,uDAAuD;AACvD,MAAM,OAAO,GAAyB,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC;AAE1E,8CAA8C;AAC9C,MAAM,IAAI,GAAyB;IAClC,IAAI,EAAE,YAAY;IAClB,EAAE,EAAE,UAAU;IACd,MAAM,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE;IAC7B,KAAK,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE;IACvB,KAAK,EAAE,EAAE;CACT,CAAC;AAEF,8EAA8E;AAC9E,MAAM,SAAS,GAAyB,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC;AAE/D,yCAAyC;AACzC,MAAM,KAAK,GAAyB,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC;AAEpE,MAAM,SAAS,GAAyB;IACvC,IAAI,EAAE,YAAY;IAClB,EAAE,EAAE,IAAI;IACR,mDAAmD;IACnD,MAAM,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE;CACjB,CAAC;AAKF,MAAM,UAAU,GAAyB,WAAW,CAAC;AAErD,KAAK,UAAU,CAAC;AAChB,KAAK,OAAO,CAAC;AACb,KAAK,IAAI,CAAC;AACV,KAAK,SAAS,CAAC;AACf,KAAK,KAAK,CAAC;AACX,KAAK,SAAS,CAAC"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import type { PlayRouteEvent } from "@xmachines/play-router";
|
|
2
|
+
import type { PlaySpec } from "@xmachines/play-actor";
|
|
3
|
+
import type { RouteMetadata } from "./types.js";
|
|
4
|
+
/**
|
|
5
|
+
* Event schema for the `play.route` navigation event, for use in an XState v6
|
|
6
|
+
* `schemas.events` map.
|
|
7
|
+
*
|
|
8
|
+
* XState v6 declares machine events as a map of event type to payload schema
|
|
9
|
+
* (payloads exclude the `type` field). Every Play machine handles `play.route`,
|
|
10
|
+
* so this constant is the single source of truth for its payload shape —
|
|
11
|
+
* declare it instead of re-deriving the payload shape per machine. The payload
|
|
12
|
+
* is authored explicitly (not `Omit<PlayRouteEvent, "type">`): `Omit` over
|
|
13
|
+
* PlayRouteEvent's index signature collapses the named props and would erase
|
|
14
|
+
* all payload checking.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```typescript
|
|
18
|
+
* import { setup } from "xstate";
|
|
19
|
+
* import {
|
|
20
|
+
* emptyEventSchema,
|
|
21
|
+
* playMetaSchema,
|
|
22
|
+
* playRouteEventSchema,
|
|
23
|
+
* } from "@xmachines/play-xstate";
|
|
24
|
+
*
|
|
25
|
+
* const authSetup = setup({
|
|
26
|
+
* schemas: {
|
|
27
|
+
* events: {
|
|
28
|
+
* "play.route": playRouteEventSchema,
|
|
29
|
+
* "auth.logout": emptyEventSchema,
|
|
30
|
+
* },
|
|
31
|
+
* meta: playMetaSchema,
|
|
32
|
+
* },
|
|
33
|
+
* });
|
|
34
|
+
* ```
|
|
35
|
+
*
|
|
36
|
+
* @see {@link playMetaSchema} for the companion state-meta schema
|
|
37
|
+
*/
|
|
38
|
+
/**
|
|
39
|
+
* Adds `TExtra` as an optional-by-union extension of `TBase`.
|
|
40
|
+
*
|
|
41
|
+
* XState v6's `InferEvents` wraps every event payload in `Required<>` (to
|
|
42
|
+
* undo Zod-style optional inference), which would make `?`-marked fields
|
|
43
|
+
* mandatory on every send. Encoding optionality as a union sidesteps that:
|
|
44
|
+
* `Required<>` distributes over the members, each of which is already fully
|
|
45
|
+
* required. Use it for your own event payload schemas with optional fields.
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* ```typescript
|
|
49
|
+
* type SavePayload = WithOptional<{ id: string }, { draft: boolean }>;
|
|
50
|
+
* // accepts { id } and { id, draft } — and survives InferEvents' Required<>
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
53
|
+
export type WithOptional<TBase, TExtra> = TBase | (TBase & TExtra);
|
|
54
|
+
/**
|
|
55
|
+
* The `play.route` event payload as machines receive it: `to` required;
|
|
56
|
+
* `params`/`query`/`match` encoded as optional-by-union so they stay omittable
|
|
57
|
+
* through XState v6's `Required<>` event inference.
|
|
58
|
+
*/
|
|
59
|
+
export type PlayRoutePayload = WithOptional<WithOptional<WithOptional<{
|
|
60
|
+
to: PlayRouteEvent["to"];
|
|
61
|
+
}, {
|
|
62
|
+
params: Record<string, string>;
|
|
63
|
+
}>, {
|
|
64
|
+
query: Record<string, string>;
|
|
65
|
+
}>, {
|
|
66
|
+
match: unknown;
|
|
67
|
+
}>;
|
|
68
|
+
export declare const playRouteEventSchema: import("xstate").TypeSchema<PlayRoutePayload>;
|
|
69
|
+
/**
|
|
70
|
+
* State meta schema for Play's routing/view metadata, for use as an XState v6
|
|
71
|
+
* `schemas.meta` declaration.
|
|
72
|
+
*
|
|
73
|
+
* XState v6 types state `meta` as `never` unless a meta schema is declared, so
|
|
74
|
+
* every machine that carries `meta.route` templates or `meta.view` specs needs
|
|
75
|
+
* this schema. `route` accepts both the string template form
|
|
76
|
+
* (`"/profile/:username"`) and the object form (`{ path, title }` — see
|
|
77
|
+
* {@link RouteMetadata}); `view` is a Play view {@link PlaySpec}.
|
|
78
|
+
*
|
|
79
|
+
* @example
|
|
80
|
+
* ```typescript
|
|
81
|
+
* import { createMachine } from "xstate";
|
|
82
|
+
* import { playMetaSchema } from "@xmachines/play-xstate";
|
|
83
|
+
*
|
|
84
|
+
* const machine = createMachine({
|
|
85
|
+
* schemas: { meta: playMetaSchema },
|
|
86
|
+
* initial: "home",
|
|
87
|
+
* states: {
|
|
88
|
+
* home: { id: "home", meta: { route: "/" } },
|
|
89
|
+
* },
|
|
90
|
+
* });
|
|
91
|
+
* ```
|
|
92
|
+
*
|
|
93
|
+
* @see {@link playRouteEventSchema} for the companion `play.route` event schema
|
|
94
|
+
*/
|
|
95
|
+
export declare const playMetaSchema: import("xstate").TypeSchema<{
|
|
96
|
+
route?: RouteMetadata;
|
|
97
|
+
view?: PlaySpec;
|
|
98
|
+
}>;
|
|
99
|
+
//# sourceMappingURL=schemas.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../../src/routing/schemas.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH;;;;;;;;;;;;;;GAcG;AACH,MAAM,MAAM,YAAY,CAAC,KAAK,EAAE,MAAM,IAAI,KAAK,GAAG,CAAC,KAAK,GAAG,MAAM,CAAC,CAAC;AAEnE;;;;GAIG;AACH,MAAM,MAAM,gBAAgB,GAAG,YAAY,CAC1C,YAAY,CACX,YAAY,CAAC;IAAE,EAAE,EAAE,cAAc,CAAC,IAAI,CAAC,CAAA;CAAE,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,CAAC,EAC9E;IAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,CACjC,EACD;IAAE,KAAK,EAAE,OAAO,CAAA;CAAE,CAClB,CAAC;AAEF,eAAO,MAAM,oBAAoB,+CAA4B,CAAC;AAE9D;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,eAAO,MAAM,cAAc;YAAmB,aAAa;WAAS,QAAQ;EAAK,CAAC"}
|