@xmachines/play-router 1.0.0-beta.9 → 1.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 (81) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +246 -341
  3. package/dist/base-route-map.d.ts +38 -17
  4. package/dist/base-route-map.d.ts.map +1 -1
  5. package/dist/base-route-map.js +69 -62
  6. package/dist/base-route-map.js.map +1 -1
  7. package/dist/build-tree.d.ts +7 -0
  8. package/dist/build-tree.d.ts.map +1 -1
  9. package/dist/build-tree.js +21 -6
  10. package/dist/build-tree.js.map +1 -1
  11. package/dist/create-route-map-from-tree.d.ts +33 -0
  12. package/dist/create-route-map-from-tree.d.ts.map +1 -0
  13. package/dist/create-route-map-from-tree.js +43 -0
  14. package/dist/create-route-map-from-tree.js.map +1 -0
  15. package/dist/create-route-map.d.ts +26 -50
  16. package/dist/create-route-map.d.ts.map +1 -1
  17. package/dist/create-route-map.js +24 -114
  18. package/dist/create-route-map.js.map +1 -1
  19. package/dist/errors.d.ts +152 -0
  20. package/dist/errors.d.ts.map +1 -0
  21. package/dist/errors.js +186 -0
  22. package/dist/errors.js.map +1 -0
  23. package/dist/extract-routes.d.ts +5 -31
  24. package/dist/extract-routes.d.ts.map +1 -1
  25. package/dist/extract-routes.js +73 -51
  26. package/dist/extract-routes.js.map +1 -1
  27. package/dist/find-route.d.ts +44 -0
  28. package/dist/find-route.d.ts.map +1 -0
  29. package/dist/find-route.js +103 -0
  30. package/dist/find-route.js.map +1 -0
  31. package/dist/index.d.ts +13 -52
  32. package/dist/index.d.ts.map +1 -1
  33. package/dist/index.js +13 -137
  34. package/dist/index.js.map +1 -1
  35. package/dist/machine-to-graph.d.ts +17 -0
  36. package/dist/machine-to-graph.d.ts.map +1 -0
  37. package/dist/machine-to-graph.js +115 -0
  38. package/dist/machine-to-graph.js.map +1 -0
  39. package/dist/query.d.ts +49 -1
  40. package/dist/query.d.ts.map +1 -1
  41. package/dist/query.js +98 -3
  42. package/dist/query.js.map +1 -1
  43. package/dist/router-bridge-base.d.ts +187 -48
  44. package/dist/router-bridge-base.d.ts.map +1 -1
  45. package/dist/router-bridge-base.js +312 -120
  46. package/dist/router-bridge-base.js.map +1 -1
  47. package/dist/router-sync.d.ts +95 -0
  48. package/dist/router-sync.d.ts.map +1 -0
  49. package/dist/router-sync.js +161 -0
  50. package/dist/router-sync.js.map +1 -0
  51. package/dist/types.d.ts +163 -22
  52. package/dist/types.d.ts.map +1 -1
  53. package/dist/url-pattern-utils.d.ts +117 -0
  54. package/dist/url-pattern-utils.d.ts.map +1 -0
  55. package/dist/url-pattern-utils.js +176 -0
  56. package/dist/url-pattern-utils.js.map +1 -0
  57. package/dist/validate-routes.d.ts +32 -14
  58. package/dist/validate-routes.d.ts.map +1 -1
  59. package/dist/validate-routes.js +28 -21
  60. package/dist/validate-routes.js.map +1 -1
  61. package/package.json +34 -14
  62. package/dist/connect-router.d.ts +0 -56
  63. package/dist/connect-router.d.ts.map +0 -1
  64. package/dist/connect-router.js +0 -112
  65. package/dist/connect-router.js.map +0 -1
  66. package/dist/crawl-machine.d.ts +0 -74
  67. package/dist/crawl-machine.d.ts.map +0 -1
  68. package/dist/crawl-machine.js +0 -95
  69. package/dist/crawl-machine.js.map +0 -1
  70. package/dist/create-browser-history.d.ts +0 -93
  71. package/dist/create-browser-history.d.ts.map +0 -1
  72. package/dist/create-browser-history.js +0 -94
  73. package/dist/create-browser-history.js.map +0 -1
  74. package/dist/create-router.d.ts +0 -73
  75. package/dist/create-router.d.ts.map +0 -1
  76. package/dist/create-router.js +0 -63
  77. package/dist/create-router.js.map +0 -1
  78. package/dist/extract-route.d.ts +0 -25
  79. package/dist/extract-route.d.ts.map +0 -1
  80. package/dist/extract-route.js +0 -63
  81. package/dist/extract-route.js.map +0 -1
@@ -1,61 +1,83 @@
1
- import { crawlMachine } from "./crawl-machine.js";
2
- import { extractRoute } from "./extract-route.js";
3
- import { detectDuplicateRoutes } from "./validate-routes.js";
1
+ import { machineToGraph } from "./machine-to-graph.js";
2
+ import { validateRouteFormat, validateStateExists } from "./validate-routes.js";
4
3
  import { buildRouteTree } from "./build-tree.js";
5
4
  /**
6
- * Extract complete route tree from state machine graph
7
- *
8
- * Crawls machine starting from root, visits all state nodes (including nested
9
- * and parallel), extracts meta.route metadata, validates route references,
10
- * and builds hierarchical tree.
5
+ * Build statePath for a graph node by walking the parentId chain.
11
6
  *
12
- * @param machine - XState v5 state machine
13
- * @returns Route tree with root, byStateId map, and byPath map
14
- * @throws {Error} If route references non-existent state
15
- * @throws {Error} If route path is malformed (doesn't start with /)
16
- * @throws {Error} If parallel states define conflicting routes
7
+ * Produces an array of stateId segments from root to this node (excluding root),
8
+ * matching the format expected by buildRouteTree's parent lookup.
17
9
  *
18
- * @example
19
- * ```typescript
20
- * import { createMachine } from 'xstate';
21
- * import { extractMachineRoutes } from '@xmachines/play-router';
10
+ * @param graphNode - The node to build a path for
11
+ * @param graphNodeMap - Map from node id to GraphNode for O(1) parent lookup
12
+ * @returns Array of stateId segments (e.g. ["dashboard", "overview"])
13
+ */
14
+ const buildStatePath = (graphNode, graphNodeMap) => {
15
+ const path = [];
16
+ let current = graphNode;
17
+ while (current && current.parentId !== undefined && current.parentId !== null) {
18
+ path.unshift(current.data.stateId);
19
+ current = graphNodeMap.get(current.parentId);
20
+ }
21
+ return path;
22
+ };
23
+ /**
24
+ * Extract route info from a graph node's MachineNodeData.
25
+ * Returns null if the node has no route (not routable).
26
+ */
27
+ const extractRouteFromNode = (graphNode, stateIds, graphNodeMap) => {
28
+ const { stateId, route, meta } = graphNode.data;
29
+ // Node has no route — not routable
30
+ if (!route)
31
+ return null;
32
+ // Validate format (must start with /)
33
+ validateRouteFormat(route, stateId);
34
+ // Validate state exists in graph (redundant but guards against corruption)
35
+ validateStateExists(stateId, stateIds);
36
+ // Build statePath from parentId chain (works for both explicit IDs and auto-generated)
37
+ const statePath = buildStatePath(graphNode, graphNodeMap);
38
+ const pattern = route.includes(":") ? route : undefined;
39
+ // Reconstruct original metadata shape from graph data
40
+ const metadata = meta && typeof meta === "object" && "route" in meta
41
+ ? meta["route"]
42
+ : route;
43
+ const result = {
44
+ stateId,
45
+ statePath,
46
+ routePath: route,
47
+ isAbsolute: route.startsWith("/"),
48
+ routable: true,
49
+ metadata,
50
+ };
51
+ if (pattern)
52
+ result.pattern = pattern;
53
+ return result;
54
+ };
55
+ /**
56
+ * Extract complete route tree from state machine graph
22
57
  *
23
- * const machine = createMachine({
24
- * initial: 'home',
25
- * states: {
26
- * home: { id: 'home', meta: { route: '/' } },
27
- * dashboard: {
28
- * id: 'dashboard',
29
- * meta: { route: '/dashboard' },
30
- * initial: 'overview',
31
- * states: {
32
- * overview: { id: 'overview', meta: { route: '/overview' } }
33
- * }
34
- * }
35
- * }
36
- * });
58
+ * Converts the XState machine to a @statelyai/graph Graph via machineToGraph(),
59
+ * then walks graph nodes to extract route metadata, validate route references,
60
+ * and build a hierarchical RouteTree. The graph is attached to the returned
61
+ * RouteTree for downstream transition-aware queries.
37
62
  *
38
- * const tree = extractMachineRoutes(machine);
39
- * console.log(tree.byPath.get('/dashboard/overview'));
40
- * ```
63
+ * @param machine - XState v5 state machine
64
+ * @returns Route tree with root, byStateId map, byPath map, and graph
41
65
  */
42
66
  export const extractMachineRoutes = (machine) => {
43
- // 1. Crawl machine graph to discover all states
44
- const visits = crawlMachine(machine);
45
- // 2. Build state map for validation
46
- const stateMap = new Map();
47
- for (const visit of visits) {
48
- if (visit.node.id) {
49
- stateMap.set(visit.node.id, visit.node);
50
- }
51
- }
52
- // 3. Extract routes with validation
53
- const routes = visits
54
- .map((visit) => extractRoute(visit.node, visit.path, stateMap))
55
- .filter((route) => route !== null);
56
- // 4. Detect duplicate routes
57
- detectDuplicateRoutes(routes);
58
- // 5. Build hierarchical tree
59
- return buildRouteTree(routes);
67
+ // 1. Convert machine to graph
68
+ const graph = machineToGraph(machine);
69
+ // 2. Build state ID set for validation and node map for O(1) parent lookup
70
+ const stateIds = new Set(graph.nodes.map((n) => n.data.stateId));
71
+ const graphNodeMap = new Map(graph.nodes.map((n) => [n.id, n]));
72
+ // 3. Extract routes from graph nodes
73
+ const routes = graph.nodes
74
+ .map((node) => extractRouteFromNode(node, stateIds, graphNodeMap))
75
+ .filter((r) => r !== null);
76
+ // 4. Build hierarchical tree and attach graph.
77
+ // Duplicate-route detection happens inside buildRouteTree, AFTER relative
78
+ // routes are resolved to full paths — raw route strings are not comparable
79
+ // (two relative "settings" routes under different parents are distinct).
80
+ const tree = buildRouteTree(routes);
81
+ return { ...tree, graph };
60
82
  };
61
83
  //# sourceMappingURL=extract-routes.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"extract-routes.js","sourceRoot":"","sources":["../src/extract-routes.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEjD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,OAAwB,EAAa,EAAE;IAC3E,gDAAgD;IAChD,MAAM,MAAM,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;IAErC,oCAAoC;IACpC,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAqB,CAAC;IAC9C,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC5B,IAAI,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;YACnB,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QACzC,CAAC;IACF,CAAC;IAED,oCAAoC;IACpC,MAAM,MAAM,GAAG,MAAM;SACnB,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;SAC9D,MAAM,CAAC,CAAC,KAAK,EAAsC,EAAE,CAAC,KAAK,KAAK,IAAI,CAAC,CAAC;IAExE,6BAA6B;IAC7B,qBAAqB,CAAC,MAAM,CAAC,CAAC;IAE9B,6BAA6B;IAC7B,OAAO,cAAc,CAAC,MAAM,CAAC,CAAC;AAC/B,CAAC,CAAC"}
1
+ {"version":3,"file":"extract-routes.js","sourceRoot":"","sources":["../src/extract-routes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ import type { RouteTree, RouteNode } from "./types.js";
2
+ /**
3
+ * Find route node by state ID
4
+ *
5
+ * Looks up route node using the state's ID property. Used to get URL path
6
+ * from state ID for browser URL sync after play.route transitions.
7
+ *
8
+ * @param tree - Route tree from extractMachineRoutes
9
+ * @param id - State ID (e.g., 'dashboard', 'settings.profile')
10
+ * @returns Route node if found, undefined otherwise
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * const tree = extractMachineRoutes(machine);
15
+ * const node = findRouteById(tree, 'dashboard');
16
+ * if (node) {
17
+ * console.log(node.fullPath); // '/dashboard'
18
+ * }
19
+ * ```
20
+ */
21
+ export declare const findRouteById: (tree: RouteTree, id: string) => RouteNode | undefined;
22
+ /**
23
+ * Find route node by URL path
24
+ *
25
+ * Looks up route node using the URL path. Used to get state ID from browser
26
+ * URL for sending play.route events on navigation.
27
+ *
28
+ * When multiple states share the same path (e.g., root and a state both at "/"),
29
+ * prefers routable nodes (with meta.route) over non-routable nodes.
30
+ *
31
+ * Supports pattern matching for dynamic routes (e.g., '/settings/:section?').
32
+ *
33
+ * @param tree - Route tree from extractMachineRoutes
34
+ * @param path - URL path (e.g., '/dashboard', '/settings/profile')
35
+ * @returns Route node if found, undefined otherwise
36
+ *
37
+ * @example
38
+ * ```typescript
39
+ * const tree = extractMachineRoutes(machine);
40
+ * const node = findRouteByPath(tree, '/dashboard');
41
+ * ```
42
+ */
43
+ export declare const findRouteByPath: (tree: RouteTree, path: string) => RouteNode | undefined;
44
+ //# sourceMappingURL=find-route.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"find-route.d.ts","sourceRoot":"","sources":["../src/find-route.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAqCvD;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,aAAa,GAAI,MAAM,SAAS,EAAE,IAAI,MAAM,KAAG,SAAS,GAAG,SAEvE,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,eAAe,GAAI,MAAM,SAAS,EAAE,MAAM,MAAM,KAAG,SAAS,GAAG,SAyB3E,CAAC"}
@@ -0,0 +1,103 @@
1
+ import { getURLPatternCtor, getCompiledPattern } from "./url-pattern-utils.js";
2
+ import { URLPatternUnavailableError, InvalidRoutePatternError } from "./errors.js";
3
+ /**
4
+ * Check if a URL path matches a route pattern using URLPattern.
5
+ *
6
+ * For static patterns (no `:param`) falls back to a direct equality check so
7
+ * URLPattern is never required for polyfill-free environments that only use
8
+ * static routes.
9
+ *
10
+ * Uses the shared module-level compiled-pattern cache (`getCompiledPattern`)
11
+ * so repeated lookups never recompile the same pattern, and hyphenated param
12
+ * names (`:cat-id`) are normalized exactly as `RouteMap` does — the same single
13
+ * matching engine underneath.
14
+ *
15
+ * Throws `URLPatternUnavailableError` when a parameterised pattern is tested
16
+ * and URLPattern is not available on `globalThis`.
17
+ * Throws `InvalidRoutePatternError` when URLPattern cannot compile the pattern.
18
+ *
19
+ * Private — not exported from the package public API.
20
+ *
21
+ * @param path - URL path (e.g., '/settings', '/settings/billing')
22
+ * @param pattern - Route pattern (e.g., '/settings/:section?')
23
+ * @returns True if path matches pattern
24
+ */
25
+ function matchesPattern(path, pattern) {
26
+ if (!pattern.includes(":"))
27
+ return path === pattern;
28
+ const Ctor = getURLPatternCtor();
29
+ if (!Ctor)
30
+ throw new URLPatternUnavailableError();
31
+ try {
32
+ return getCompiledPattern(pattern, Ctor).test({ pathname: path });
33
+ }
34
+ catch (err) {
35
+ throw new InvalidRoutePatternError(pattern, { cause: err });
36
+ }
37
+ }
38
+ /**
39
+ * Find route node by state ID
40
+ *
41
+ * Looks up route node using the state's ID property. Used to get URL path
42
+ * from state ID for browser URL sync after play.route transitions.
43
+ *
44
+ * @param tree - Route tree from extractMachineRoutes
45
+ * @param id - State ID (e.g., 'dashboard', 'settings.profile')
46
+ * @returns Route node if found, undefined otherwise
47
+ *
48
+ * @example
49
+ * ```typescript
50
+ * const tree = extractMachineRoutes(machine);
51
+ * const node = findRouteById(tree, 'dashboard');
52
+ * if (node) {
53
+ * console.log(node.fullPath); // '/dashboard'
54
+ * }
55
+ * ```
56
+ */
57
+ export const findRouteById = (tree, id) => {
58
+ return tree.byStateId.get(id);
59
+ };
60
+ /**
61
+ * Find route node by URL path
62
+ *
63
+ * Looks up route node using the URL path. Used to get state ID from browser
64
+ * URL for sending play.route events on navigation.
65
+ *
66
+ * When multiple states share the same path (e.g., root and a state both at "/"),
67
+ * prefers routable nodes (with meta.route) over non-routable nodes.
68
+ *
69
+ * Supports pattern matching for dynamic routes (e.g., '/settings/:section?').
70
+ *
71
+ * @param tree - Route tree from extractMachineRoutes
72
+ * @param path - URL path (e.g., '/dashboard', '/settings/profile')
73
+ * @returns Route node if found, undefined otherwise
74
+ *
75
+ * @example
76
+ * ```typescript
77
+ * const tree = extractMachineRoutes(machine);
78
+ * const node = findRouteByPath(tree, '/dashboard');
79
+ * ```
80
+ */
81
+ export const findRouteByPath = (tree, path) => {
82
+ // 1. Try exact match first (fast path for static routes)
83
+ const node = tree.byPath.get(path);
84
+ if (node?.routable) {
85
+ return node;
86
+ }
87
+ // 2. If exact match not found or non-routable, try pattern matching
88
+ // This handles:
89
+ // - Routes with parameters (e.g., '/settings/:section?')
90
+ // - Multiple states sharing same path (prefer routable)
91
+ for (const candidate of tree.byStateId.values()) {
92
+ if (!candidate.routable) {
93
+ continue; // Skip non-routable nodes
94
+ }
95
+ // Check if path matches this node's pattern
96
+ if (matchesPattern(path, candidate.fullPath)) {
97
+ return candidate;
98
+ }
99
+ }
100
+ // 3. Fallback: if we had a non-routable exact match, return it
101
+ return node;
102
+ };
103
+ //# sourceMappingURL=find-route.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"find-route.js","sourceRoot":"","sources":["../src/find-route.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC/E,OAAO,EAAE,0BAA0B,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AAEnF;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,SAAS,cAAc,CAAC,IAAY,EAAE,OAAe;IACpD,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,KAAK,OAAO,CAAC;IACpD,MAAM,IAAI,GAAG,iBAAiB,EAAE,CAAC;IACjC,IAAI,CAAC,IAAI;QAAE,MAAM,IAAI,0BAA0B,EAAE,CAAC;IAClD,IAAI,CAAC;QACJ,OAAO,kBAAkB,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;IACnE,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACd,MAAM,IAAI,wBAAwB,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;IAC7D,CAAC;AACF,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,IAAe,EAAE,EAAU,EAAyB,EAAE;IACnF,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AAC/B,CAAC,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,IAAe,EAAE,IAAY,EAAyB,EAAE;IACvF,yDAAyD;IACzD,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAEnC,IAAI,IAAI,EAAE,QAAQ,EAAE,CAAC;QACpB,OAAO,IAAI,CAAC;IACb,CAAC;IAED,oEAAoE;IACpE,gBAAgB;IAChB,yDAAyD;IACzD,wDAAwD;IACxD,KAAK,MAAM,SAAS,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,CAAC;QACjD,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,CAAC;YACzB,SAAS,CAAC,0BAA0B;QACrC,CAAC;QAED,4CAA4C;QAC5C,IAAI,cAAc,CAAC,IAAI,EAAE,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC9C,OAAO,SAAS,CAAC;QAClB,CAAC;IACF,CAAC;IAED,+DAA+D;IAC/D,OAAO,IAAI,CAAC;AACb,CAAC,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,57 +1,18 @@
1
1
  export { RouterBridgeBase } from "./router-bridge-base.js";
2
- export { crawlMachine } from "./crawl-machine.js";
3
- export { extractRoute } from "./extract-route.js";
2
+ export type { RouteWatcherHandle } from "./router-bridge-base.js";
3
+ export { sanitizePathname, buildPlayRouteEvent, extractQuery, extractRouteParams, } from "./router-sync.js";
4
+ export type { RouteMatch, BuildPlayRouteEventOptions } from "./router-sync.js";
4
5
  export { validateRouteFormat, validateStateExists, detectDuplicateRoutes, } from "./validate-routes.js";
6
+ export type { ResolvedRoutePath } from "./validate-routes.js";
5
7
  export { buildRouteTree } from "./build-tree.js";
6
8
  export { extractMachineRoutes } from "./extract-routes.js";
7
- export { getNavigableRoutes, getRoutableRoutes, routeExists } from "./query.js";
8
- export type { StateVisit, RouteInfo, RouteNode, RouteTree, RouteObject, RouteMetadata, PlayRouteEvent, RouterBridge, } from "./types.js";
9
- export { createRouteMap, type RouteMap } from "./create-route-map.js";
10
- export { BaseRouteMap, type RouteMapping as BaseRouteMapping } from "./base-route-map.js";
11
- export { createBrowserHistory, type BrowserHistory } from "./create-browser-history.js";
12
- export { createRouter, type VanillaRouter } from "./create-router.js";
13
- export { connectRouter, type ConnectRouterOptions } from "./connect-router.js";
14
- import type { RouteTree, RouteNode } from "./types.js";
15
- /**
16
- * Find route node by state ID
17
- *
18
- * Looks up route node using the state's ID property. Used to get URL path
19
- * from state ID for browser URL sync after play.route transitions.
20
- *
21
- * @param tree - Route tree from extractMachineRoutes
22
- * @param id - State ID (e.g., 'dashboard', 'settings.profile')
23
- * @returns Route node if found, undefined otherwise
24
- *
25
- * @example
26
- * ```typescript
27
- * const tree = extractMachineRoutes(machine);
28
- * const node = findRouteById(tree, 'dashboard');
29
- * if (node) {
30
- * console.log(node.fullPath); // '/dashboard'
31
- * }
32
- * ```
33
- */
34
- export declare const findRouteById: (tree: RouteTree, id: string) => RouteNode | undefined;
35
- /**
36
- * Find route node by URL path
37
- *
38
- * Looks up route node using the URL path. Used to get state ID from browser
39
- * URL for sending play.route events on navigation.
40
- *
41
- * When multiple states share the same path (e.g., root and a state both at "/"),
42
- * prefers routable nodes (with meta.route) over non-routable nodes.
43
- *
44
- * Supports pattern matching for dynamic routes (e.g., '/settings/:section?').
45
- *
46
- * @param tree - Route tree from extractMachineRoutes
47
- * @param path - URL path (e.g., '/dashboard', '/settings/profile')
48
- * @returns Route node if found, undefined otherwise
49
- *
50
- * @example
51
- * ```typescript
52
- * const tree = extractMachineRoutes(machine);
53
- * const node = findRouteByPath(tree, '/dashboard');
54
- * ```
55
- */
56
- export declare const findRouteByPath: (tree: RouteTree, path: string) => RouteNode | undefined;
9
+ export { getNavigableRoutes, getRoutableRoutes, routeExists, getTransitionReachableRoutes, isRouteReachable, } from "./query.js";
10
+ export { machineToGraph } from "./machine-to-graph.js";
11
+ export type { MachineGraph } from "./machine-to-graph.js";
12
+ export type { RouteInfo, RouteNode, RouteTree, RouteObject, RouteMetadata, PlayRouteEvent, RoutableActor, PlayActor, RouterBridge, MachineNodeData, MachineEdgeData, WindowLike, LocationLike, } from "./types.js";
13
+ export { RouteMap, type RouteMapping, type RouteMapping as BaseRouteMapping, } from "./base-route-map.js";
14
+ export { createRouteMap } from "./create-route-map.js";
15
+ export type { RouteMapOptions } from "./create-route-map.js";
16
+ export { createRouteMapFromTree } from "./create-route-map-from-tree.js";
17
+ export { findRouteById, findRouteByPath } from "./find-route.js";
57
18
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAG3D,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EACN,mBAAmB,EACnB,mBAAmB,EACnB,qBAAqB,GACrB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEhF,YAAY,EACX,UAAU,EACV,SAAS,EACT,SAAS,EACT,SAAS,EACT,WAAW,EACX,aAAa,EACb,cAAc,EACd,YAAY,GACZ,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,cAAc,EAAE,KAAK,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAKtE,OAAO,EAAE,YAAY,EAAE,KAAK,YAAY,IAAI,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAG1F,OAAO,EAAE,oBAAoB,EAAE,KAAK,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAGxF,OAAO,EAAE,YAAY,EAAE,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAGtE,OAAO,EAAE,aAAa,EAAE,KAAK,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAE/E,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvD;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,aAAa,GAAI,MAAM,SAAS,EAAE,IAAI,MAAM,KAAG,SAAS,GAAG,SAEvE,CAAC;AAqEF;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,eAAe,GAAI,MAAM,SAAS,EAAE,MAAM,MAAM,KAAG,SAAS,GAAG,SAyB3E,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,YAAY,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAGlE,OAAO,EACN,gBAAgB,EAChB,mBAAmB,EACnB,YAAY,EACZ,kBAAkB,GAClB,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EAAE,UAAU,EAAE,0BAA0B,EAAE,MAAM,kBAAkB,CAAC;AAG/E,OAAO,EACN,mBAAmB,EACnB,mBAAmB,EACnB,qBAAqB,GACrB,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EACN,kBAAkB,EAClB,iBAAiB,EACjB,WAAW,EACX,4BAA4B,EAC5B,gBAAgB,GAChB,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,YAAY,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAE1D,YAAY,EACX,SAAS,EACT,SAAS,EACT,SAAS,EACT,WAAW,EACX,aAAa,EACb,cAAc,EACd,aAAa,EACb,SAAS,EACT,YAAY,EACZ,eAAe,EACf,eAAe,EACf,UAAU,EACV,YAAY,GACZ,MAAM,YAAY,CAAC;AAIpB,OAAO,EACN,QAAQ,EACR,KAAK,YAAY,EACjB,KAAK,YAAY,IAAI,gBAAgB,GACrC,MAAM,qBAAqB,CAAC;AAI7B,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,YAAY,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AAGzE,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC"}
package/dist/index.js CHANGED
@@ -1,145 +1,21 @@
1
1
  // RouterBridgeBase — public API for community adapters
2
2
  export { RouterBridgeBase } from "./router-bridge-base.js";
3
+ // Router sync utilities — used by play-dom-router and adapters that bypass syncActorFromRouter()
4
+ export { sanitizePathname, buildPlayRouteEvent, extractQuery, extractRouteParams, } from "./router-sync.js";
3
5
  // Route utilities (existing)
4
- export { crawlMachine } from "./crawl-machine.js";
5
- export { extractRoute } from "./extract-route.js";
6
6
  export { validateRouteFormat, validateStateExists, detectDuplicateRoutes, } from "./validate-routes.js";
7
7
  export { buildRouteTree } from "./build-tree.js";
8
8
  export { extractMachineRoutes } from "./extract-routes.js";
9
- export { getNavigableRoutes, getRoutableRoutes, routeExists } from "./query.js";
10
- // Route map for path → state ID resolution (createRouteMap / RouteMap interface)
11
- export { createRouteMap } from "./create-route-map.js";
9
+ export { getNavigableRoutes, getRoutableRoutes, routeExists, getTransitionReachableRoutes, isRouteReachable, } from "./query.js";
10
+ // Graph adapter — converts XState machines to @statelyai/graph Graph
11
+ export { machineToGraph } from "./machine-to-graph.js";
12
12
  // Shared bidirectional route mapping base class.
13
- // Re-exported as `BaseRouteMapping` (not `RouteMapping`) so adapter packages can
14
- // define their own local `RouteMapping` type without a name collision.
15
- export { BaseRouteMap } from "./base-route-map.js";
16
- // Browser history abstraction (aligned with TanStack Router)
17
- export { createBrowserHistory } from "./create-browser-history.js";
18
- // Vanilla router (framework-agnostic)
19
- export { createRouter } from "./create-router.js";
20
- // Pure browser integration (low-level API)
21
- export { connectRouter } from "./connect-router.js";
22
- /**
23
- * Find route node by state ID
24
- *
25
- * Looks up route node using the state's ID property. Used to get URL path
26
- * from state ID for browser URL sync after play.route transitions.
27
- *
28
- * @param tree - Route tree from extractMachineRoutes
29
- * @param id - State ID (e.g., 'dashboard', 'settings.profile')
30
- * @returns Route node if found, undefined otherwise
31
- *
32
- * @example
33
- * ```typescript
34
- * const tree = extractMachineRoutes(machine);
35
- * const node = findRouteById(tree, 'dashboard');
36
- * if (node) {
37
- * console.log(node.fullPath); // '/dashboard'
38
- * }
39
- * ```
40
- */
41
- export const findRouteById = (tree, id) => {
42
- return tree.byStateId.get(id);
43
- };
44
- /**
45
- * Check if a URL path matches a route pattern
46
- *
47
- * Handles parameter patterns including optional parameters (:param?).
48
- * Used to match incoming URLs against route patterns with dynamic segments.
49
- *
50
- * @param path - URL path (e.g., '/settings', '/settings/billing')
51
- * @param pattern - Route pattern (e.g., '/settings/:section?')
52
- * @returns True if path matches pattern
53
- *
54
- * @example
55
- * ```typescript
56
- * matchesPattern('/settings', '/settings/:section?') // true
57
- * matchesPattern('/settings/billing', '/settings/:section?') // true
58
- * matchesPattern('/profile/123', '/profile/:userId') // true
59
- * matchesPattern('/profile', '/profile/:userId') // false (required param missing)
60
- * ```
61
- */
62
- const matchesPattern = (path, pattern) => {
63
- // No parameters - exact match required
64
- if (!pattern.includes(":")) {
65
- return path === pattern;
66
- }
67
- const patternSegments = pattern.split("/").filter(Boolean);
68
- const pathSegments = path.split("/").filter(Boolean);
69
- // Check each segment
70
- for (let i = 0; i < patternSegments.length; i++) {
71
- const patternSegment = patternSegments[i];
72
- const pathSegment = pathSegments[i];
73
- // Static segment - must match exactly
74
- if (!patternSegment.startsWith(":")) {
75
- if (patternSegment !== pathSegment) {
76
- return false;
77
- }
78
- continue;
79
- }
80
- // Parameter segment
81
- const isOptional = patternSegment.endsWith("?");
82
- // Optional parameter - can be missing
83
- if (isOptional && pathSegment === undefined) {
84
- // Check if there are more path segments after this - if so, no match
85
- if (i < pathSegments.length) {
86
- return false;
87
- }
88
- continue;
89
- }
90
- // Required parameter - must exist
91
- if (!isOptional && pathSegment === undefined) {
92
- return false;
93
- }
94
- }
95
- // If path has more segments than pattern, no match
96
- // (unless all remaining pattern segments are optional - but we don't support that)
97
- if (pathSegments.length > patternSegments.length) {
98
- return false;
99
- }
100
- return true;
101
- };
102
- /**
103
- * Find route node by URL path
104
- *
105
- * Looks up route node using the URL path. Used to get state ID from browser
106
- * URL for sending play.route events on navigation.
107
- *
108
- * When multiple states share the same path (e.g., root and a state both at "/"),
109
- * prefers routable nodes (with meta.route) over non-routable nodes.
110
- *
111
- * Supports pattern matching for dynamic routes (e.g., '/settings/:section?').
112
- *
113
- * @param tree - Route tree from extractMachineRoutes
114
- * @param path - URL path (e.g., '/dashboard', '/settings/profile')
115
- * @returns Route node if found, undefined otherwise
116
- *
117
- * @example
118
- * ```typescript
119
- * const tree = extractMachineRoutes(machine);
120
- * const node = findRouteByPath(tree, '/dashboard');
121
- * ```
122
- */
123
- export const findRouteByPath = (tree, path) => {
124
- // 1. Try exact match first (fast path for static routes)
125
- const node = tree.byPath.get(path);
126
- if (node?.routable) {
127
- return node;
128
- }
129
- // 2. If exact match not found or non-routable, try pattern matching
130
- // This handles:
131
- // - Routes with parameters (e.g., '/settings/:section?')
132
- // - Multiple states sharing same path (prefer routable)
133
- for (const candidate of tree.byStateId.values()) {
134
- if (!candidate.routable) {
135
- continue; // Skip non-routable nodes
136
- }
137
- // Check if path matches this node's pattern
138
- if (matchesPattern(path, candidate.fullPath)) {
139
- return candidate;
140
- }
141
- }
142
- // 3. Fallback: if we had a non-routable exact match, return it
143
- return node;
144
- };
13
+ // RouteMapping is exported directly; BaseRouteMapping kept as alias for compatibility.
14
+ export { RouteMap, } from "./base-route-map.js";
15
+ // Factories: create a RouteMap from a machine or a route tree.
16
+ // All RouterBridgeBase adapters use these instead of rolling their own factories.
17
+ export { createRouteMap } from "./create-route-map.js";
18
+ export { createRouteMapFromTree } from "./create-route-map-from-tree.js";
19
+ // Route lookup helpers — matchesPattern is private within find-route.ts
20
+ export { findRouteById, findRouteByPath } from "./find-route.js";
145
21
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,uDAAuD;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAG3D,iGAAiG;AACjG,OAAO,EACN,gBAAgB,EAChB,mBAAmB,EACnB,YAAY,EACZ,kBAAkB,GAClB,MAAM,kBAAkB,CAAC;AAG1B,6BAA6B;AAC7B,OAAO,EACN,mBAAmB,EACnB,mBAAmB,EACnB,qBAAqB,GACrB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EACN,kBAAkB,EAClB,iBAAiB,EACjB,WAAW,EACX,4BAA4B,EAC5B,gBAAgB,GAChB,MAAM,YAAY,CAAC;AAEpB,qEAAqE;AACrE,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAmBvD,iDAAiD;AACjD,uFAAuF;AACvF,OAAO,EACN,QAAQ,GAGR,MAAM,qBAAqB,CAAC;AAE7B,+DAA+D;AAC/D,kFAAkF;AAClF,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvD,OAAO,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AAEzE,wEAAwE;AACxE,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,17 @@
1
+ import type { AnyStateMachine } from "xstate";
2
+ import { type Graph } from "@statelyai/graph";
3
+ import type { MachineNodeData, MachineEdgeData } from "./types.js";
4
+ /**
5
+ * Typed @statelyai/graph Graph representing a state machine.
6
+ * Provides hierarchy queries, traversal algorithms, and reachability checks.
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * import { getChildren, getSuccessors, hasPath } from "@statelyai/graph";
11
+ * const graph: MachineGraph = machineToGraph(machine);
12
+ * const children = getChildren(graph, "myMachine");
13
+ * ```
14
+ */
15
+ export type MachineGraph = Graph<MachineNodeData, MachineEdgeData>;
16
+ export declare const machineToGraph: (machine: AnyStateMachine) => MachineGraph;
17
+ //# sourceMappingURL=machine-to-graph.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"machine-to-graph.d.ts","sourceRoot":"","sources":["../src/machine-to-graph.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,QAAQ,CAAC;AAE9C,OAAO,EAAe,KAAK,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAGnE;;;;;;;;;;GAUG;AACH,MAAM,MAAM,YAAY,GAAG,KAAK,CAAC,eAAe,EAAE,eAAe,CAAC,CAAC;AAqDnE,eAAO,MAAM,cAAc,GAAI,SAAS,eAAe,KAAG,YAwEzD,CAAC"}