@xmachines/play-router 6.1.0 → 7.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.
- package/README.md +73 -16
- package/dist/base-route-map.js +240 -270
- package/dist/base-route-map.js.map +1 -1
- package/dist/build-tree.js +84 -96
- package/dist/build-tree.js.map +1 -1
- package/dist/create-route-map-from-tree.js +50 -47
- package/dist/create-route-map-from-tree.js.map +1 -1
- package/dist/errors.js +124 -133
- package/dist/errors.js.map +1 -1
- package/dist/find-route.js +88 -105
- package/dist/find-route.js.map +1 -1
- package/dist/index.js +10 -28
- package/dist/provider-lifecycle.js +109 -143
- package/dist/provider-lifecycle.js.map +1 -1
- package/dist/router-bridge-base.d.ts +4 -4
- package/dist/router-bridge-base.d.ts.map +1 -1
- package/dist/router-bridge-base.js +1026 -1601
- package/dist/router-bridge-base.js.map +1 -1
- package/dist/router-sync.js +107 -139
- package/dist/router-sync.js.map +1 -1
- package/dist/validate-routes.js +58 -66
- package/dist/validate-routes.js.map +1 -1
- package/dist/xstate/create-route-map.js +36 -35
- package/dist/xstate/create-route-map.js.map +1 -1
- package/dist/xstate/extract-routes.js +66 -83
- package/dist/xstate/extract-routes.js.map +1 -1
- package/dist/xstate/index.js +5 -33
- package/dist/xstate/machine-to-graph.js +98 -109
- package/dist/xstate/machine-to-graph.js.map +1 -1
- package/dist/xstate/query.js +190 -212
- package/dist/xstate/query.js.map +1 -1
- package/package.json +16 -16
- package/dist/index.js.map +0 -1
- package/dist/types.js +0 -2
- package/dist/types.js.map +0 -1
- package/dist/xstate/index.js.map +0 -1
- package/dist/xstate/machine-types.js +0 -2
- package/dist/xstate/machine-types.js.map +0 -1
|
@@ -1,116 +1,105 @@
|
|
|
1
|
+
import { UnknownStateTypeError } from "../errors.js";
|
|
1
2
|
import { toDirectedGraph } from "xstate/graph";
|
|
2
3
|
import { createGraph } from "@statelyai/graph";
|
|
3
|
-
|
|
4
|
+
//#region packages/play-router/src/xstate/machine-to-graph.ts
|
|
4
5
|
/**
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
6
|
+
* Converts an XState v5 state machine into a typed Graph of @statelyai/graph.
|
|
7
|
+
*
|
|
8
|
+
* The pipeline of the conversion is:
|
|
9
|
+
* `XState Machine → toDirectedGraph() → the hierarchy of the DirectedGraphNode objects → createGraph() → Graph`
|
|
10
|
+
*
|
|
11
|
+
* The graph of the result holds three things:
|
|
12
|
+
* - **The hierarchy**: the parentId of a node shows the compound nesting and the parallel nesting of XState
|
|
13
|
+
* - **The edges**: every transition, with its event types and with its optional guard types
|
|
14
|
+
* - **The metadata**: the state type, the meta object, and the route path from the extraction
|
|
15
|
+
*
|
|
16
|
+
* @param machine - The XState v5 state machine, in each shape
|
|
17
|
+
* @returns The typed directed graph, with a MachineNodeData object on each node and a MachineEdgeData object on each edge
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* The conversion of a simple machine, and a query of its routes
|
|
21
|
+
* ```typescript
|
|
22
|
+
* import { createMachine } from "xstate";
|
|
23
|
+
* import { getChildren, getSuccessors } from "@statelyai/graph";
|
|
24
|
+
* import { machineToGraph } from "@xmachines/play-router/xstate";
|
|
25
|
+
*
|
|
26
|
+
* const machine = createMachine({
|
|
27
|
+
* id: "app",
|
|
28
|
+
* initial: "home",
|
|
29
|
+
* states: {
|
|
30
|
+
* home: { meta: { route: "/home" }, on: { GO_ABOUT: "about" } },
|
|
31
|
+
* about: { meta: { route: "/about" } },
|
|
32
|
+
* },
|
|
33
|
+
* });
|
|
34
|
+
*
|
|
35
|
+
* const graph = machineToGraph(machine);
|
|
36
|
+
* const children = getChildren(graph, "app"); // [home, about]
|
|
37
|
+
* const successors = getSuccessors(graph, "app.home"); // [about]
|
|
38
|
+
* ```
|
|
39
|
+
*
|
|
40
|
+
* @see {@link MachineNodeData} for the shape of the data of a node
|
|
41
|
+
* @see {@link MachineEdgeData} for the shape of the data of an edge
|
|
42
|
+
* @see https://github.com/statelyai/graph for the API reference of @statelyai/graph
|
|
43
|
+
*/
|
|
43
44
|
/**
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
45
|
+
* The set of the valid XState state types, for the check at run time.
|
|
46
|
+
* It guards against a later change of XState, and against a machine shape that the
|
|
47
|
+
* package does not expect.
|
|
48
|
+
*/
|
|
49
|
+
var VALID_STATE_TYPES = /* @__PURE__ */ new Set([
|
|
50
|
+
"atomic",
|
|
51
|
+
"compound",
|
|
52
|
+
"parallel",
|
|
53
|
+
"final",
|
|
54
|
+
"history"
|
|
54
55
|
]);
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
data: edgeData,
|
|
101
|
-
});
|
|
102
|
-
}
|
|
103
|
-
// Walk into the children, with this node as their parent
|
|
104
|
-
for (const child of dgNode.children) {
|
|
105
|
-
walk(child, dgNode.id);
|
|
106
|
-
}
|
|
107
|
-
};
|
|
108
|
-
walk(dg);
|
|
109
|
-
return createGraph({
|
|
110
|
-
mode: "directed",
|
|
111
|
-
initialNodeId: dg.id,
|
|
112
|
-
nodes,
|
|
113
|
-
edges,
|
|
114
|
-
});
|
|
56
|
+
var machineToGraph = (machine) => {
|
|
57
|
+
const dg = toDirectedGraph(machine);
|
|
58
|
+
const nodes = [];
|
|
59
|
+
const edges = [];
|
|
60
|
+
let edgeCounter = 0;
|
|
61
|
+
const walk = (dgNode, parentId) => {
|
|
62
|
+
const sn = dgNode.stateNode;
|
|
63
|
+
const meta = sn.meta;
|
|
64
|
+
const metaRoute = meta?.["route"];
|
|
65
|
+
const route = typeof metaRoute === "string" ? metaRoute : typeof metaRoute === "object" && metaRoute !== null && "path" in metaRoute ? metaRoute.path : void 0;
|
|
66
|
+
if (!VALID_STATE_TYPES.has(sn.type)) throw new UnknownStateTypeError(sn.type, sn.id, [...VALID_STATE_TYPES]);
|
|
67
|
+
const nodeData = {
|
|
68
|
+
stateId: sn.id,
|
|
69
|
+
type: sn.type
|
|
70
|
+
};
|
|
71
|
+
if (meta !== void 0) nodeData.meta = meta;
|
|
72
|
+
if (route !== void 0) nodeData.route = route;
|
|
73
|
+
if (parentId !== void 0) nodes.push({
|
|
74
|
+
id: dgNode.id,
|
|
75
|
+
parentId,
|
|
76
|
+
data: nodeData
|
|
77
|
+
});
|
|
78
|
+
else nodes.push({
|
|
79
|
+
id: dgNode.id,
|
|
80
|
+
data: nodeData
|
|
81
|
+
});
|
|
82
|
+
for (const edge of dgNode.edges) {
|
|
83
|
+
const edgeData = { eventType: edge.label.text };
|
|
84
|
+
if (edge.transition.guard) edgeData.guardType = String(edge.transition.guard);
|
|
85
|
+
edges.push({
|
|
86
|
+
id: `e${edgeCounter++}`,
|
|
87
|
+
sourceId: edge.source.id,
|
|
88
|
+
targetId: edge.target.id,
|
|
89
|
+
data: edgeData
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
for (const child of dgNode.children) walk(child, dgNode.id);
|
|
93
|
+
};
|
|
94
|
+
walk(dg);
|
|
95
|
+
return createGraph({
|
|
96
|
+
mode: "directed",
|
|
97
|
+
initialNodeId: dg.id,
|
|
98
|
+
nodes,
|
|
99
|
+
edges
|
|
100
|
+
});
|
|
115
101
|
};
|
|
102
|
+
//#endregion
|
|
103
|
+
export { machineToGraph };
|
|
104
|
+
|
|
116
105
|
//# sourceMappingURL=machine-to-graph.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"machine-to-graph.js","
|
|
1
|
+
{"version":3,"file":"machine-to-graph.js","names":[],"sources":["../../src/xstate/machine-to-graph.ts"],"sourcesContent":["import type { AnyStateMachine } from \"xstate\";\nimport { toDirectedGraph, type DirectedGraphNode } from \"xstate/graph\";\nimport { createGraph, type Graph } from \"@statelyai/graph\";\nimport type { MachineNodeData, MachineEdgeData } from \"./machine-types.js\";\nimport { UnknownStateTypeError } from \"../errors.js\";\n\n/**\n * The typed Graph of @statelyai/graph that represents a state machine.\n * It gives you the queries of the hierarchy, the algorithms of a walk, and the tests\n * of the reachability.\n *\n * @example\n * ```typescript\n * import { getChildren, getSuccessors, hasPath } from \"@statelyai/graph\";\n * const graph: MachineGraph = machineToGraph(machine);\n * const children = getChildren(graph, \"myMachine\");\n * ```\n */\nexport type MachineGraph = Graph<MachineNodeData, MachineEdgeData>;\n\n/**\n * Converts an XState v5 state machine into a typed Graph of @statelyai/graph.\n *\n * The pipeline of the conversion is:\n * `XState Machine → toDirectedGraph() → the hierarchy of the DirectedGraphNode objects → createGraph() → Graph`\n *\n * The graph of the result holds three things:\n * - **The hierarchy**: the parentId of a node shows the compound nesting and the parallel nesting of XState\n * - **The edges**: every transition, with its event types and with its optional guard types\n * - **The metadata**: the state type, the meta object, and the route path from the extraction\n *\n * @param machine - The XState v5 state machine, in each shape\n * @returns The typed directed graph, with a MachineNodeData object on each node and a MachineEdgeData object on each edge\n *\n * @example\n * The conversion of a simple machine, and a query of its routes\n * ```typescript\n * import { createMachine } from \"xstate\";\n * import { getChildren, getSuccessors } from \"@statelyai/graph\";\n * import { machineToGraph } from \"@xmachines/play-router/xstate\";\n *\n * const machine = createMachine({\n * id: \"app\",\n * initial: \"home\",\n * states: {\n * home: { meta: { route: \"/home\" }, on: { GO_ABOUT: \"about\" } },\n * about: { meta: { route: \"/about\" } },\n * },\n * });\n *\n * const graph = machineToGraph(machine);\n * const children = getChildren(graph, \"app\"); // [home, about]\n * const successors = getSuccessors(graph, \"app.home\"); // [about]\n * ```\n *\n * @see {@link MachineNodeData} for the shape of the data of a node\n * @see {@link MachineEdgeData} for the shape of the data of an edge\n * @see https://github.com/statelyai/graph for the API reference of @statelyai/graph\n */\n/**\n * The set of the valid XState state types, for the check at run time.\n * It guards against a later change of XState, and against a machine shape that the\n * package does not expect.\n */\nconst VALID_STATE_TYPES: ReadonlySet<string> = new Set([\n\t\"atomic\",\n\t\"compound\",\n\t\"parallel\",\n\t\"final\",\n\t\"history\",\n]);\n\nexport const machineToGraph = (machine: AnyStateMachine): MachineGraph => {\n\tconst dg = toDirectedGraph(machine);\n\n\t// Convert the hierarchy of the DirectedGraphNode objects into a flat array of nodes and a flat array of edges\n\tconst nodes: Array<{ id: string; parentId?: string; data: MachineNodeData }> = [];\n\tconst edges: Array<{\n\t\tid: string;\n\t\tsourceId: string;\n\t\ttargetId: string;\n\t\tdata: MachineEdgeData;\n\t}> = [];\n\tlet edgeCounter = 0;\n\n\tconst walk = (dgNode: DirectedGraphNode, parentId?: string): void => {\n\t\tconst sn = dgNode.stateNode;\n\t\tconst meta = sn.meta as Record<string, unknown> | undefined;\n\t\tconst metaRoute = meta?.[\"route\"];\n\t\tconst route =\n\t\t\ttypeof metaRoute === \"string\"\n\t\t\t\t? metaRoute\n\t\t\t\t: typeof metaRoute === \"object\" && metaRoute !== null && \"path\" in metaRoute\n\t\t\t\t\t? (metaRoute as { path: string }).path\n\t\t\t\t\t: undefined;\n\n\t\t// An assertion at run time: check the state type before the cast\n\t\tif (!VALID_STATE_TYPES.has(sn.type)) {\n\t\t\tthrow new UnknownStateTypeError(sn.type, sn.id, [...VALID_STATE_TYPES]);\n\t\t}\n\n\t\tconst nodeData: MachineNodeData = {\n\t\t\tstateId: sn.id,\n\t\t\ttype: sn.type as MachineNodeData[\"type\"],\n\t\t};\n\t\tif (meta !== undefined) nodeData.meta = meta;\n\t\tif (route !== undefined) nodeData.route = route;\n\n\t\tif (parentId !== undefined) {\n\t\t\tnodes.push({ id: dgNode.id, parentId, data: nodeData });\n\t\t} else {\n\t\t\tnodes.push({ id: dgNode.id, data: nodeData });\n\t\t}\n\n\t\t// Collect the edges of THIS node. An edge is on its source node, and not on the root of the graph\n\t\tfor (const edge of dgNode.edges) {\n\t\t\tconst edgeData: MachineEdgeData = {\n\t\t\t\teventType: edge.label.text,\n\t\t\t};\n\t\t\tif (edge.transition.guard) {\n\t\t\t\tedgeData.guardType = String(edge.transition.guard);\n\t\t\t}\n\t\t\tedges.push({\n\t\t\t\tid: `e${edgeCounter++}`,\n\t\t\t\tsourceId: edge.source.id,\n\t\t\t\ttargetId: edge.target.id,\n\t\t\t\tdata: edgeData,\n\t\t\t});\n\t\t}\n\n\t\t// Walk into the children, with this node as their parent\n\t\tfor (const child of dgNode.children) {\n\t\t\twalk(child, dgNode.id);\n\t\t}\n\t};\n\n\twalk(dg);\n\n\treturn createGraph({\n\t\tmode: \"directed\",\n\t\tinitialNodeId: dg.id,\n\t\tnodes,\n\t\tedges,\n\t});\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgEA,IAAM,oCAAyC,IAAI,IAAI;CACtD;CACA;CACA;CACA;CACA;AACD,CAAC;AAED,IAAa,kBAAkB,YAA2C;CACzE,MAAM,KAAK,gBAAgB,OAAO;CAGlC,MAAM,QAAyE,CAAC;CAChF,MAAM,QAKD,CAAC;CACN,IAAI,cAAc;CAElB,MAAM,QAAQ,QAA2B,aAA4B;EACpE,MAAM,KAAK,OAAO;EAClB,MAAM,OAAO,GAAG;EAChB,MAAM,YAAY,OAAO;EACzB,MAAM,QACL,OAAO,cAAc,WAClB,YACA,OAAO,cAAc,YAAY,cAAc,QAAQ,UAAU,YAC/D,UAA+B,OAChC,KAAA;EAGL,IAAI,CAAC,kBAAkB,IAAI,GAAG,IAAI,GACjC,MAAM,IAAI,sBAAsB,GAAG,MAAM,GAAG,IAAI,CAAC,GAAG,iBAAiB,CAAC;EAGvE,MAAM,WAA4B;GACjC,SAAS,GAAG;GACZ,MAAM,GAAG;EACV;EACA,IAAI,SAAS,KAAA,GAAW,SAAS,OAAO;EACxC,IAAI,UAAU,KAAA,GAAW,SAAS,QAAQ;EAE1C,IAAI,aAAa,KAAA,GAChB,MAAM,KAAK;GAAE,IAAI,OAAO;GAAI;GAAU,MAAM;EAAS,CAAC;OAEtD,MAAM,KAAK;GAAE,IAAI,OAAO;GAAI,MAAM;EAAS,CAAC;EAI7C,KAAK,MAAM,QAAQ,OAAO,OAAO;GAChC,MAAM,WAA4B,EACjC,WAAW,KAAK,MAAM,KACvB;GACA,IAAI,KAAK,WAAW,OACnB,SAAS,YAAY,OAAO,KAAK,WAAW,KAAK;GAElD,MAAM,KAAK;IACV,IAAI,IAAI;IACR,UAAU,KAAK,OAAO;IACtB,UAAU,KAAK,OAAO;IACtB,MAAM;GACP,CAAC;EACF;EAGA,KAAK,MAAM,SAAS,OAAO,UAC1B,KAAK,OAAO,OAAO,EAAE;CAEvB;CAEA,KAAK,EAAE;CAEP,OAAO,YAAY;EAClB,MAAM;EACN,eAAe,GAAG;EAClB;EACA;CACD,CAAC;AACF"}
|