@xmachines/play-router 1.0.0-beta.43 → 1.0.0-beta.45

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 CHANGED
@@ -124,7 +124,7 @@ Open http://localhost:5174/ and explore:
124
124
  ```typescript
125
125
  // Extract routes from machine
126
126
  const routeTree = extractMachineRoutes(authMachine);
127
- const routeMatcher = createRouteMap(routeTree);
127
+ const routeMatcher = createRouteMatcher(routeTree);
128
128
 
129
129
  // Actor → URL sync
130
130
  const watcher = new Signal.subtle.Watcher(() => {
@@ -195,7 +195,7 @@ That final step distinguishes:
195
195
  - **deep-link:** browser URL differs from the machine's initial route, so router wins and the actor receives `play.route`
196
196
  - **restore:** browser URL is still at the machine's initial route while the actor was restored elsewhere, so actor wins and the bridge pushes the actor route back into the router
197
197
 
198
- Actor-originated router sync also keeps `isProcessingNavigation` set until the next microtask. That short window intentionally suppresses synchronous router callbacks that echo the same navigation back into the actor.
198
+ Actor-originated router sync suppresses router echoes via `lastSyncedPath`. `syncRouterFromActor` resolves the concrete path and stores it before calling the adapter's navigation method; when the router callback fires with that same path, `syncActorFromRouter` short-circuits at `sanitized === lastSyncedPath` and sends no event.
199
199
 
200
200
  ## Diagnostics
201
201
 
@@ -291,14 +291,14 @@ const successors = getSuccessors(tree.graph!, "myMachine.home");
291
291
  - `eventType: string` — event type triggering this transition
292
292
  - `guardType?: string` — guard name/description (if transition is guarded)
293
293
 
294
- ### createRouteMapFromMachine() / createRouteMapFromTree()
294
+ ### createRouteMap() / createRouteMapFromTree()
295
295
 
296
296
  Both build a `BaseRouteMap` using `node.fullPath` (absolute resolved paths) for browser URL matching.
297
297
 
298
298
  ```typescript
299
299
  // Single-call form — preferred for XState machines:
300
- import { createRouteMapFromMachine } from "@xmachines/play-router";
301
- const routeMap = createRouteMapFromMachine(machine);
300
+ import { createRouteMap } from "@xmachines/play-router";
301
+ const routeMap = createRouteMap(machine);
302
302
 
303
303
  // Two-step form — used by framework adapter packages:
304
304
  import { extractMachineRoutes, createRouteMapFromTree } from "@xmachines/play-router";
@@ -306,7 +306,7 @@ const routeTree = extractMachineRoutes(machine);
306
306
  const routeMap = createRouteMapFromTree(routeTree);
307
307
  ```
308
308
 
309
- Both forms produce identical results. `createRouteMapFromTree` is exposed for framework adapters (React Router, TanStack Router) that need to hold the `RouteTree` separately for other purposes (e.g. graph queries).
309
+ Both forms produce identical `RouteMap` results. `createRouteMapFromTree` is exposed for framework adapters (React Router, TanStack Router) that already hold the `RouteTree` separately for other purposes (e.g. graph queries). `createRouteMatcher(routeTree)` is the distinct API for URL-pattern matching that returns a `RouteMatcher`, not a `RouteMap`.
310
310
 
311
311
  **`node.path` vs `node.fullPath`:** Every `RouteNode` carries both fields. `path` is the raw `meta.route` segment as declared in the machine — it may be relative (e.g. `"overview"`). `fullPath` is the resolved absolute path (e.g. `"/dashboard/overview"`). Route maps always use `fullPath`. Only use `path` if you specifically need the declared segment.
312
312
 
@@ -586,10 +586,10 @@ This package enables **Actor Authority (INV-01)**:
586
586
 
587
587
  ## Related Packages
588
588
 
589
- - **[@xmachines/play-xstate](../play-xstate)** - XState adapter using route extraction
590
- - **[@xmachines/play-tanstack-react-router](../play-tanstack-react-router)** - TanStack Router adapter using route trees
591
- - **[@xmachines/play-react-router](../play-react-router)** - React Router v7 adapter using RouterBridgeBase
592
- - **[@xmachines/play](../play)** - Protocol types
589
+ - **[@xmachines/play-xstate](../play-xstate/README.md)** - XState adapter using route extraction
590
+ - **[@xmachines/play-tanstack-react-router](../play-tanstack-react-router/README.md)** - TanStack Router adapter using route trees
591
+ - **[@xmachines/play-react-router](../play-react-router/README.md)** - React Router v7 adapter using RouterBridgeBase
592
+ - **[@xmachines/play](../play/README.md)** - Protocol types
593
593
 
594
594
  ## License
595
595
 
@@ -6,7 +6,7 @@
6
6
  *
7
7
  * Algorithm: O(1) exact match via Map, then bucket-based O(k) pattern match
8
8
  * where k = routes in the first-segment bucket (typically << total routes).
9
- * Uses URLPattern for parameterized route matching (same engine as createRouteMap).
9
+ * Uses URLPattern for parameterized route matching (same engine as createRouteMatcher).
10
10
  */
11
11
  /**
12
12
  * A single state ID ↔ path mapping entry.
@@ -6,7 +6,7 @@
6
6
  *
7
7
  * Algorithm: O(1) exact match via Map, then bucket-based O(k) pattern match
8
8
  * where k = routes in the first-segment bucket (typically << total routes).
9
- * Uses URLPattern for parameterized route matching (same engine as createRouteMap).
9
+ * Uses URLPattern for parameterized route matching (same engine as createRouteMatcher).
10
10
  */
11
11
  import QuickLRU from "quick-lru";
12
12
  import { getURLPatternCtor, getIndexKey, getCandidates, } from "./url-pattern-utils.js";
@@ -1,31 +1,33 @@
1
1
  import type { RouteTree } from "./types.js";
2
2
  import { RouteMap } from "./base-route-map.js";
3
+ import type { RouteMapOptions } from "./create-route-map.js";
3
4
  /**
4
5
  * Create a `RouteMap` from a `RouteTree` node structure.
5
6
  *
6
7
  * Used by framework-router adapters (React Router, TanStack Router) that pass a
7
8
  * `RouteTree` produced by `extractMachineRoutes()` rather than calling
8
- * `createRouteMapFromMachine()` directly.
9
+ * `createRouteMap()` directly.
9
10
  *
10
11
  * Traverses all nodes collecting `{ stateId: node.id, path: node.fullPath }` pairs.
11
12
  * `node.fullPath` is always the absolute resolved path (e.g. `"/dashboard/overview"`),
12
13
  * which is what `RouteMap` needs for browser URL matching. This matches the
13
- * behaviour of `createRouteMapFromMachine`, which also uses `node.fullPath`.
14
+ * behaviour of `createRouteMap(machine)`, which also uses `node.fullPath`.
14
15
  *
15
16
  * @param routeTree - A `RouteTree` as returned by `extractMachineRoutes()`.
17
+ * @param options - Optional configuration (e.g. `{ cacheSize }` to override the LRU cache size).
16
18
  * @returns A `RouteMap` for use with any `RouterBridgeBase`-based adapter.
17
19
  *
18
20
  * @example
19
21
  * ```typescript
20
22
  * // Preferred — single call for XState machines:
21
- * import { createRouteMapFromMachine } from '@xmachines/play-router';
22
- * const routeMap = createRouteMapFromMachine(machine);
23
+ * import { createRouteMap } from '@xmachines/play-router';
24
+ * const routeMap = createRouteMap(machine); // takes AnyStateMachine
23
25
  *
24
- * // Equivalent two-step form used by framework adapters:
26
+ * // Two-step form used by framework adapters that work with route trees:
25
27
  * import { extractMachineRoutes, createRouteMapFromTree } from '@xmachines/play-router';
26
28
  * const routeTree = extractMachineRoutes(machine);
27
29
  * const routeMap = createRouteMapFromTree(routeTree); // uses node.fullPath (absolute)
28
30
  * ```
29
31
  */
30
- export declare function createRouteMapFromTree(routeTree: RouteTree): RouteMap;
32
+ export declare function createRouteMapFromTree(routeTree: RouteTree, options?: RouteMapOptions): RouteMap;
31
33
  //# sourceMappingURL=create-route-map-from-tree.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"create-route-map-from-tree.d.ts","sourceRoot":"","sources":["../src/create-route-map-from-tree.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAa,MAAM,YAAY,CAAC;AACvD,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAE/C;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,SAAS,GAAG,QAAQ,CAcrE"}
1
+ {"version":3,"file":"create-route-map-from-tree.d.ts","sourceRoot":"","sources":["../src/create-route-map-from-tree.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAa,MAAM,YAAY,CAAC;AACvD,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAE7D;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,QAAQ,CAchG"}
@@ -4,29 +4,30 @@ import { RouteMap } from "./base-route-map.js";
4
4
  *
5
5
  * Used by framework-router adapters (React Router, TanStack Router) that pass a
6
6
  * `RouteTree` produced by `extractMachineRoutes()` rather than calling
7
- * `createRouteMapFromMachine()` directly.
7
+ * `createRouteMap()` directly.
8
8
  *
9
9
  * Traverses all nodes collecting `{ stateId: node.id, path: node.fullPath }` pairs.
10
10
  * `node.fullPath` is always the absolute resolved path (e.g. `"/dashboard/overview"`),
11
11
  * which is what `RouteMap` needs for browser URL matching. This matches the
12
- * behaviour of `createRouteMapFromMachine`, which also uses `node.fullPath`.
12
+ * behaviour of `createRouteMap(machine)`, which also uses `node.fullPath`.
13
13
  *
14
14
  * @param routeTree - A `RouteTree` as returned by `extractMachineRoutes()`.
15
+ * @param options - Optional configuration (e.g. `{ cacheSize }` to override the LRU cache size).
15
16
  * @returns A `RouteMap` for use with any `RouterBridgeBase`-based adapter.
16
17
  *
17
18
  * @example
18
19
  * ```typescript
19
20
  * // Preferred — single call for XState machines:
20
- * import { createRouteMapFromMachine } from '@xmachines/play-router';
21
- * const routeMap = createRouteMapFromMachine(machine);
21
+ * import { createRouteMap } from '@xmachines/play-router';
22
+ * const routeMap = createRouteMap(machine); // takes AnyStateMachine
22
23
  *
23
- * // Equivalent two-step form used by framework adapters:
24
+ * // Two-step form used by framework adapters that work with route trees:
24
25
  * import { extractMachineRoutes, createRouteMapFromTree } from '@xmachines/play-router';
25
26
  * const routeTree = extractMachineRoutes(machine);
26
27
  * const routeMap = createRouteMapFromTree(routeTree); // uses node.fullPath (absolute)
27
28
  * ```
28
29
  */
29
- export function createRouteMapFromTree(routeTree) {
30
+ export function createRouteMapFromTree(routeTree, options) {
30
31
  const routes = [];
31
32
  function traverse(node) {
32
33
  if (node.id && node.fullPath) {
@@ -37,6 +38,6 @@ export function createRouteMapFromTree(routeTree) {
37
38
  }
38
39
  }
39
40
  traverse(routeTree.root);
40
- return new RouteMap(routes);
41
+ return new RouteMap(routes, options);
41
42
  }
42
43
  //# sourceMappingURL=create-route-map-from-tree.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"create-route-map-from-tree.js","sourceRoot":"","sources":["../src/create-route-map-from-tree.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAE/C;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,UAAU,sBAAsB,CAAC,SAAoB;IAC1D,MAAM,MAAM,GAA6C,EAAE,CAAC;IAE5D,SAAS,QAAQ,CAAC,IAAe;QAChC,IAAI,IAAI,CAAC,EAAE,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC9B,MAAM,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;QACxD,CAAC;QACD,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnB,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACjC,CAAC;IACF,CAAC;IAED,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IACzB,OAAO,IAAI,QAAQ,CAAC,MAAM,CAAC,CAAC;AAC7B,CAAC"}
1
+ {"version":3,"file":"create-route-map-from-tree.js","sourceRoot":"","sources":["../src/create-route-map-from-tree.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAG/C;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAM,UAAU,sBAAsB,CAAC,SAAoB,EAAE,OAAyB;IACrF,MAAM,MAAM,GAA6C,EAAE,CAAC;IAE5D,SAAS,QAAQ,CAAC,IAAe;QAChC,IAAI,IAAI,CAAC,EAAE,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC9B,MAAM,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;QACxD,CAAC;QACD,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnB,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACjC,CAAC;IACF,CAAC;IAED,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IACzB,OAAO,IAAI,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AACtC,CAAC"}
@@ -1,66 +1,42 @@
1
- import type { RouteTree } from "./types.js";
1
+ import type { AnyStateMachine } from "xstate";
2
+ import { RouteMap } from "./base-route-map.js";
2
3
  /**
3
- * URL route matcher interface returned by `createRouteMap()`.
4
- *
5
- * Matches incoming URL paths to state IDs (with `#` prefix) and extracts
6
- * route parameters. Used by `RouterBridgeBase` to translate router navigation
7
- * events into `play.route` actor events.
8
- *
9
- * @see {@link createRouteMap} for the factory function
10
- * @see {@link RouteMap} for direct state ID ↔ path lookups without params extraction
4
+ * Options for `createRouteMap` and `createRouteMapFromTree`.
11
5
  */
12
- export interface RouteMatcher {
6
+ export interface RouteMapOptions {
13
7
  /**
14
- * Match a URL path to a state ID and params.
15
- *
16
- * @param path - URL pathname (e.g., "/settings/account")
17
- * @returns Object with `to` (state ID with # prefix) and `params`
8
+ * Maximum number of resolved parameterized path lookups to cache.
18
9
  *
19
- * Example:
20
- * ```typescript
21
- * const { to, params } = routeMatcher.match('/settings/account');
22
- * // { to: "#settings", params: { section: "account" } }
10
+ * `RouteMap.getStateIdByPath()` resolves parameterized patterns (e.g.
11
+ * `/profile/:userId`) via URLPattern on every call. Frequently visited
12
+ * paths are cached in an LRU so subsequent lookups are O(1).
23
13
  *
24
- * if (to) {
25
- * actor.send({ type: 'play.route', to, params });
26
- * }
27
- * ```
14
+ * Increase this value for applications with large parameterized route sets
15
+ * or high navigation frequency. Default: `500`.
28
16
  */
29
- match(path: string): {
30
- to: string | null;
31
- params: Record<string, string>;
32
- };
17
+ cacheSize?: number;
33
18
  }
34
19
  /**
35
- * Create a route matcher from a RouteTree for efficient path lookups.
20
+ * Create a `RouteMap` from an XState state machine.
36
21
  *
37
- * Architecture:
38
- * - Pure function - no side effects
39
- * - O(1) lookups for exact matches via Map
40
- * - O(k) bucket-indexed pattern matching with URLPattern, where k = routes in the
41
- * first-segment bucket (typically << total routes)
42
- * - Returns formatted state IDs (with # prefix)
43
- * - Extracts params from matched patterns
22
+ * Extracts all routable states (those with `meta.route`) and builds a bidirectional
23
+ * path stateId lookup structure. The returned map is used by `RouterBridgeBase`
24
+ * subclasses to translate browser URL changes into `play.route` actor events and
25
+ * vice-versa.
44
26
  *
45
- * **URLPattern requirement:** Dynamic route pattern matching requires `URLPattern`
46
- * to be available on `globalThis`. On Node.js < 24 and older browsers, load a polyfill
47
- * before calling this function:
48
- * ```typescript
49
- * import "urlpattern-polyfill"; // before importing @xmachines/play-router
50
- * ```
51
- * If `URLPattern` is unavailable, a `URLPatternUnavailableError` is thrown.
52
- * Static (exact) routes are unaffected by URLPattern availability.
27
+ * @param machine - XState v5 state machine with `meta.route` annotations on states.
28
+ * @param options - Optional configuration. Pass `{ cacheSize }` to override the
29
+ * default LRU cache size for parameterized path lookups.
30
+ * @returns A `RouteMap` for passing to any `RouterBridgeBase`-based adapter.
53
31
  *
54
- * Usage:
32
+ * @example
55
33
  * ```typescript
56
- * const routeTree = extractMachineRoutes(machine);
57
- * const routeMatcher = createRouteMap(routeTree);
34
+ * import { createRouteMap } from '@xmachines/play-router';
35
+ * import { connectRouter } from '@xmachines/play-dom-router';
58
36
  *
59
- * const { to, params } = routeMatcher.match('/settings/account');
60
- * if (to) {
61
- * actor.send({ type: 'play.route', to, params });
62
- * }
37
+ * const routeMap = createRouteMap(myMachine);
38
+ * const disconnect = connectRouter({ actor, router, routeMap });
63
39
  * ```
64
40
  */
65
- export declare function createRouteMap(routeTree: RouteTree): RouteMatcher;
41
+ export declare function createRouteMap(machine: AnyStateMachine, options?: RouteMapOptions): RouteMap;
66
42
  //# sourceMappingURL=create-route-map.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"create-route-map.d.ts","sourceRoot":"","sources":["../src/create-route-map.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAa,MAAM,YAAY,CAAC;AASvD;;;;;;;;;GASG;AACH,MAAM,WAAW,YAAY;IAC5B;;;;;;;;;;;;;;;OAeG;IACH,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG;QACpB,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;QAClB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KAC/B,CAAC;CACF;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,SAAS,GAAG,YAAY,CAuDjE"}
1
+ {"version":3,"file":"create-route-map.d.ts","sourceRoot":"","sources":["../src/create-route-map.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,QAAQ,CAAC;AAG9C,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAE/C;;GAEG;AACH,MAAM,WAAW,eAAe;IAC/B;;;;;;;;;OASG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,eAAe,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,QAAQ,CAU5F"}
@@ -1,83 +1,34 @@
1
- import { URLPatternUnavailableError, InvalidRoutePatternError } from "./errors.js";
2
- import { getURLPatternCtor, getIndexKey, getCandidates, } from "./url-pattern-utils.js";
1
+ import { extractMachineRoutes } from "./extract-routes.js";
2
+ import { getRoutableRoutes } from "./query.js";
3
+ import { RouteMap } from "./base-route-map.js";
3
4
  /**
4
- * Create a route matcher from a RouteTree for efficient path lookups.
5
+ * Create a `RouteMap` from an XState state machine.
5
6
  *
6
- * Architecture:
7
- * - Pure function - no side effects
8
- * - O(1) lookups for exact matches via Map
9
- * - O(k) bucket-indexed pattern matching with URLPattern, where k = routes in the
10
- * first-segment bucket (typically << total routes)
11
- * - Returns formatted state IDs (with # prefix)
12
- * - Extracts params from matched patterns
7
+ * Extracts all routable states (those with `meta.route`) and builds a bidirectional
8
+ * path stateId lookup structure. The returned map is used by `RouterBridgeBase`
9
+ * subclasses to translate browser URL changes into `play.route` actor events and
10
+ * vice-versa.
13
11
  *
14
- * **URLPattern requirement:** Dynamic route pattern matching requires `URLPattern`
15
- * to be available on `globalThis`. On Node.js < 24 and older browsers, load a polyfill
16
- * before calling this function:
17
- * ```typescript
18
- * import "urlpattern-polyfill"; // before importing @xmachines/play-router
19
- * ```
20
- * If `URLPattern` is unavailable, a `URLPatternUnavailableError` is thrown.
21
- * Static (exact) routes are unaffected by URLPattern availability.
12
+ * @param machine - XState v5 state machine with `meta.route` annotations on states.
13
+ * @param options - Optional configuration. Pass `{ cacheSize }` to override the
14
+ * default LRU cache size for parameterized path lookups.
15
+ * @returns A `RouteMap` for passing to any `RouterBridgeBase`-based adapter.
22
16
  *
23
- * Usage:
17
+ * @example
24
18
  * ```typescript
25
- * const routeTree = extractMachineRoutes(machine);
26
- * const routeMatcher = createRouteMap(routeTree);
19
+ * import { createRouteMap } from '@xmachines/play-router';
20
+ * import { connectRouter } from '@xmachines/play-dom-router';
27
21
  *
28
- * const { to, params } = routeMatcher.match('/settings/account');
29
- * if (to) {
30
- * actor.send({ type: 'play.route', to, params });
31
- * }
22
+ * const routeMap = createRouteMap(myMachine);
23
+ * const disconnect = connectRouter({ actor, router, routeMap });
32
24
  * ```
33
25
  */
34
- export function createRouteMap(routeTree) {
35
- // Build bucket-indexed pattern matchers for routes with dynamic segments
36
- const patternBuckets = new Map();
37
- let patternOrder = 0;
38
- const URLPatternCtor = getURLPatternCtor();
39
- function collectPatterns(node) {
40
- if (node.routable && node.pattern) {
41
- if (!URLPatternCtor) {
42
- throw new URLPatternUnavailableError();
43
- }
44
- try {
45
- const urlPattern = new URLPatternCtor({ pathname: node.pattern });
46
- const bucketKey = getIndexKey(node.pattern);
47
- const bucket = patternBuckets.get(bucketKey) ?? [];
48
- bucket.push({ pattern: urlPattern, node, order: patternOrder++ });
49
- patternBuckets.set(bucketKey, bucket);
50
- }
51
- catch (err) {
52
- throw new InvalidRoutePatternError(node.pattern, { cause: err });
53
- }
54
- }
55
- for (const child of node.children) {
56
- collectPatterns(child);
57
- }
58
- }
59
- collectPatterns(routeTree.root);
60
- return {
61
- match(path) {
62
- // O(1) exact match via routeTree.byPath Map (unchanged)
63
- const exactMatch = routeTree.byPath.get(path);
64
- if (exactMatch?.routable) {
65
- return { to: `#${exactMatch.id}`, params: {} };
66
- }
67
- // Bucket-indexed pattern match: only scan candidates for this path's first segment
68
- const candidates = getCandidates(patternBuckets, getIndexKey(path));
69
- for (const { pattern, node } of candidates) {
70
- const match = pattern.exec({ pathname: path });
71
- if (match) {
72
- const params = {};
73
- if (match.pathname.groups) {
74
- Object.assign(params, match.pathname.groups);
75
- }
76
- return { to: `#${node.id}`, params };
77
- }
78
- }
79
- return { to: null, params: {} };
80
- },
81
- };
26
+ export function createRouteMap(machine, options) {
27
+ const routeTree = extractMachineRoutes(machine);
28
+ const routes = getRoutableRoutes(routeTree);
29
+ return new RouteMap(routes.map((node) => ({
30
+ stateId: node.stateId,
31
+ path: node.fullPath,
32
+ })), options);
82
33
  }
83
34
  //# sourceMappingURL=create-route-map.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"create-route-map.js","sourceRoot":"","sources":["../src/create-route-map.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,0BAA0B,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AACnF,OAAO,EAEN,iBAAiB,EACjB,WAAW,EACX,aAAa,GACb,MAAM,wBAAwB,CAAC;AAmChC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,MAAM,UAAU,cAAc,CAAC,SAAoB;IAClD,yEAAyE;IACzE,MAAM,cAAc,GAAG,IAAI,GAAG,EAG3B,CAAC;IACJ,IAAI,YAAY,GAAG,CAAC,CAAC;IACrB,MAAM,cAAc,GAAG,iBAAiB,EAAE,CAAC;IAE3C,SAAS,eAAe,CAAC,IAAe;QACvC,IAAI,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACnC,IAAI,CAAC,cAAc,EAAE,CAAC;gBACrB,MAAM,IAAI,0BAA0B,EAAE,CAAC;YACxC,CAAC;YACD,IAAI,CAAC;gBACJ,MAAM,UAAU,GAAG,IAAI,cAAc,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;gBAClE,MAAM,SAAS,GAAG,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBAC5C,MAAM,MAAM,GAAG,cAAc,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;gBACnD,MAAM,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,KAAK,EAAE,YAAY,EAAE,EAAE,CAAC,CAAC;gBAClE,cAAc,CAAC,GAAG,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;YACvC,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACd,MAAM,IAAI,wBAAwB,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;YAClE,CAAC;QACF,CAAC;QACD,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnC,eAAe,CAAC,KAAK,CAAC,CAAC;QACxB,CAAC;IACF,CAAC;IAED,eAAe,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IAEhC,OAAO;QACN,KAAK,CAAC,IAAY;YACjB,wDAAwD;YACxD,MAAM,UAAU,GAAG,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAC9C,IAAI,UAAU,EAAE,QAAQ,EAAE,CAAC;gBAC1B,OAAO,EAAE,EAAE,EAAE,IAAI,UAAU,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;YAChD,CAAC;YAED,mFAAmF;YACnF,MAAM,UAAU,GAAG,aAAa,CAAC,cAAc,EAAE,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC;YACpE,KAAK,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,UAAU,EAAE,CAAC;gBAC5C,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;gBAC/C,IAAI,KAAK,EAAE,CAAC;oBACX,MAAM,MAAM,GAA2B,EAAE,CAAC;oBAC1C,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;wBAC3B,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;oBAC9C,CAAC;oBACD,OAAO,EAAE,EAAE,EAAE,IAAI,IAAI,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC;gBACtC,CAAC;YACF,CAAC;YAED,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;QACjC,CAAC;KACD,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"create-route-map.js","sourceRoot":"","sources":["../src/create-route-map.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAmB/C;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,UAAU,cAAc,CAAC,OAAwB,EAAE,OAAyB;IACjF,MAAM,SAAS,GAAG,oBAAoB,CAAC,OAAO,CAAC,CAAC;IAChD,MAAM,MAAM,GAAG,iBAAiB,CAAC,SAAS,CAAC,CAAC;IAC5C,OAAO,IAAI,QAAQ,CAClB,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QACrB,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,IAAI,EAAE,IAAI,CAAC,QAAQ;KACnB,CAAC,CAAC,EACH,OAAO,CACP,CAAC;AACH,CAAC"}
@@ -0,0 +1,66 @@
1
+ import type { RouteTree } from "./types.js";
2
+ /**
3
+ * URL route matcher interface returned by `createRouteMatcher()`.
4
+ *
5
+ * Matches incoming URL paths to state IDs (with `#` prefix) and extracts
6
+ * route parameters. Used by `RouterBridgeBase` to translate router navigation
7
+ * events into `play.route` actor events.
8
+ *
9
+ * @see {@link createRouteMatcher} for the factory function
10
+ * @see {@link RouteMap} for direct state ID ↔ path lookups without params extraction
11
+ */
12
+ export interface RouteMatcher {
13
+ /**
14
+ * Match a URL path to a state ID and params.
15
+ *
16
+ * @param path - URL pathname (e.g., "/settings/account")
17
+ * @returns Object with `to` (state ID with # prefix) and `params`
18
+ *
19
+ * Example:
20
+ * ```typescript
21
+ * const { to, params } = routeMatcher.match('/settings/account');
22
+ * // { to: "#settings", params: { section: "account" } }
23
+ *
24
+ * if (to) {
25
+ * actor.send({ type: 'play.route', to, params });
26
+ * }
27
+ * ```
28
+ */
29
+ match(path: string): {
30
+ to: string | null;
31
+ params: Record<string, string>;
32
+ };
33
+ }
34
+ /**
35
+ * Create a URL pattern matcher from a RouteTree for efficient path lookups.
36
+ *
37
+ * Architecture:
38
+ * - Pure function - no side effects
39
+ * - O(1) lookups for exact matches via Map
40
+ * - O(k) bucket-indexed pattern matching with URLPattern, where k = routes in the
41
+ * first-segment bucket (typically << total routes)
42
+ * - Returns formatted state IDs (with # prefix)
43
+ * - Extracts params from matched patterns
44
+ *
45
+ * **URLPattern requirement:** Dynamic route pattern matching requires `URLPattern`
46
+ * to be available on `globalThis`. On Node.js < 24 and older browsers, load a polyfill
47
+ * before calling this function:
48
+ * ```typescript
49
+ * import "urlpattern-polyfill"; // before importing @xmachines/play-router
50
+ * ```
51
+ * If `URLPattern` is unavailable, a `URLPatternUnavailableError` is thrown.
52
+ * Static (exact) routes are unaffected by URLPattern availability.
53
+ *
54
+ * Usage:
55
+ * ```typescript
56
+ * const routeTree = extractMachineRoutes(machine);
57
+ * const routeMatcher = createRouteMatcher(routeTree);
58
+ *
59
+ * const { to, params } = routeMatcher.match('/settings/account');
60
+ * if (to) {
61
+ * actor.send({ type: 'play.route', to, params });
62
+ * }
63
+ * ```
64
+ */
65
+ export declare function createRouteMatcher(routeTree: RouteTree): RouteMatcher;
66
+ //# sourceMappingURL=create-route-matcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-route-matcher.d.ts","sourceRoot":"","sources":["../src/create-route-matcher.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAa,MAAM,YAAY,CAAC;AASvD;;;;;;;;;GASG;AACH,MAAM,WAAW,YAAY;IAC5B;;;;;;;;;;;;;;;OAeG;IACH,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG;QACpB,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;QAClB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KAC/B,CAAC;CACF;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,SAAS,GAAG,YAAY,CAuDrE"}
@@ -0,0 +1,83 @@
1
+ import { URLPatternUnavailableError, InvalidRoutePatternError } from "./errors.js";
2
+ import { getURLPatternCtor, getIndexKey, getCandidates, } from "./url-pattern-utils.js";
3
+ /**
4
+ * Create a URL pattern matcher from a RouteTree for efficient path lookups.
5
+ *
6
+ * Architecture:
7
+ * - Pure function - no side effects
8
+ * - O(1) lookups for exact matches via Map
9
+ * - O(k) bucket-indexed pattern matching with URLPattern, where k = routes in the
10
+ * first-segment bucket (typically << total routes)
11
+ * - Returns formatted state IDs (with # prefix)
12
+ * - Extracts params from matched patterns
13
+ *
14
+ * **URLPattern requirement:** Dynamic route pattern matching requires `URLPattern`
15
+ * to be available on `globalThis`. On Node.js < 24 and older browsers, load a polyfill
16
+ * before calling this function:
17
+ * ```typescript
18
+ * import "urlpattern-polyfill"; // before importing @xmachines/play-router
19
+ * ```
20
+ * If `URLPattern` is unavailable, a `URLPatternUnavailableError` is thrown.
21
+ * Static (exact) routes are unaffected by URLPattern availability.
22
+ *
23
+ * Usage:
24
+ * ```typescript
25
+ * const routeTree = extractMachineRoutes(machine);
26
+ * const routeMatcher = createRouteMatcher(routeTree);
27
+ *
28
+ * const { to, params } = routeMatcher.match('/settings/account');
29
+ * if (to) {
30
+ * actor.send({ type: 'play.route', to, params });
31
+ * }
32
+ * ```
33
+ */
34
+ export function createRouteMatcher(routeTree) {
35
+ // Build bucket-indexed pattern matchers for routes with dynamic segments
36
+ const patternBuckets = new Map();
37
+ let patternOrder = 0;
38
+ const URLPatternCtor = getURLPatternCtor();
39
+ function collectPatterns(node) {
40
+ if (node.routable && node.pattern) {
41
+ if (!URLPatternCtor) {
42
+ throw new URLPatternUnavailableError();
43
+ }
44
+ try {
45
+ const urlPattern = new URLPatternCtor({ pathname: node.pattern });
46
+ const bucketKey = getIndexKey(node.pattern);
47
+ const bucket = patternBuckets.get(bucketKey) ?? [];
48
+ bucket.push({ pattern: urlPattern, node, order: patternOrder++ });
49
+ patternBuckets.set(bucketKey, bucket);
50
+ }
51
+ catch (err) {
52
+ throw new InvalidRoutePatternError(node.pattern, { cause: err });
53
+ }
54
+ }
55
+ for (const child of node.children) {
56
+ collectPatterns(child);
57
+ }
58
+ }
59
+ collectPatterns(routeTree.root);
60
+ return {
61
+ match(path) {
62
+ // O(1) exact match via routeTree.byPath Map (unchanged)
63
+ const exactMatch = routeTree.byPath.get(path);
64
+ if (exactMatch?.routable) {
65
+ return { to: `#${exactMatch.id}`, params: {} };
66
+ }
67
+ // Bucket-indexed pattern match: only scan candidates for this path's first segment
68
+ const candidates = getCandidates(patternBuckets, getIndexKey(path));
69
+ for (const { pattern, node } of candidates) {
70
+ const match = pattern.exec({ pathname: path });
71
+ if (match) {
72
+ const params = {};
73
+ if (match.pathname.groups) {
74
+ Object.assign(params, match.pathname.groups);
75
+ }
76
+ return { to: `#${node.id}`, params };
77
+ }
78
+ }
79
+ return { to: null, params: {} };
80
+ },
81
+ };
82
+ }
83
+ //# sourceMappingURL=create-route-matcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-route-matcher.js","sourceRoot":"","sources":["../src/create-route-matcher.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,0BAA0B,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AACnF,OAAO,EAEN,iBAAiB,EACjB,WAAW,EACX,aAAa,GACb,MAAM,wBAAwB,CAAC;AAmChC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,MAAM,UAAU,kBAAkB,CAAC,SAAoB;IACtD,yEAAyE;IACzE,MAAM,cAAc,GAAG,IAAI,GAAG,EAG3B,CAAC;IACJ,IAAI,YAAY,GAAG,CAAC,CAAC;IACrB,MAAM,cAAc,GAAG,iBAAiB,EAAE,CAAC;IAE3C,SAAS,eAAe,CAAC,IAAe;QACvC,IAAI,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACnC,IAAI,CAAC,cAAc,EAAE,CAAC;gBACrB,MAAM,IAAI,0BAA0B,EAAE,CAAC;YACxC,CAAC;YACD,IAAI,CAAC;gBACJ,MAAM,UAAU,GAAG,IAAI,cAAc,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;gBAClE,MAAM,SAAS,GAAG,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBAC5C,MAAM,MAAM,GAAG,cAAc,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;gBACnD,MAAM,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,KAAK,EAAE,YAAY,EAAE,EAAE,CAAC,CAAC;gBAClE,cAAc,CAAC,GAAG,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;YACvC,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACd,MAAM,IAAI,wBAAwB,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;YAClE,CAAC;QACF,CAAC;QACD,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnC,eAAe,CAAC,KAAK,CAAC,CAAC;QACxB,CAAC;IACF,CAAC;IAED,eAAe,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IAEhC,OAAO;QACN,KAAK,CAAC,IAAY;YACjB,wDAAwD;YACxD,MAAM,UAAU,GAAG,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAC9C,IAAI,UAAU,EAAE,QAAQ,EAAE,CAAC;gBAC1B,OAAO,EAAE,EAAE,EAAE,IAAI,UAAU,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;YAChD,CAAC;YAED,mFAAmF;YACnF,MAAM,UAAU,GAAG,aAAa,CAAC,cAAc,EAAE,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC;YACpE,KAAK,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,UAAU,EAAE,CAAC;gBAC5C,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;gBAC/C,IAAI,KAAK,EAAE,CAAC;oBACX,MAAM,MAAM,GAA2B,EAAE,CAAC;oBAC1C,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;wBAC3B,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;oBAC9C,CAAC;oBACD,OAAO,EAAE,EAAE,EAAE,IAAI,IAAI,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC;gBACtC,CAAC;YACF,CAAC;YAED,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;QACjC,CAAC;KACD,CAAC;AACH,CAAC"}
package/dist/errors.d.ts CHANGED
@@ -24,7 +24,38 @@ export declare class RouterSyncError extends PlayError {
24
24
  constructor(message: string, options?: ErrorOptions);
25
25
  }
26
26
  /**
27
- * Thrown by `createRouteMap()` when the `URLPattern` API is not available in the
27
+ * Thrown by `RouterBridgeBase.connect()` when a second bridge tries to connect
28
+ * to an actor that already has an active bridge connection.
29
+ *
30
+ * One actor may only be connected to one router bridge at a time. Two bridges
31
+ * sharing the same actor would both receive and process every router navigation
32
+ * event, sending duplicate `play.route` events to the actor and producing
33
+ * conflicting echo-suppression state via `lastSyncedPath`.
34
+ *
35
+ * **How to fix:** Call `bridge.disconnect()` on the first bridge before
36
+ * connecting a second one, or ensure only one `connectRouter()` call is active
37
+ * per actor at any given time.
38
+ *
39
+ * **Error code:** `PLAY_ROUTER_DUPLICATE_BRIDGE`
40
+ *
41
+ * @example
42
+ * ```typescript
43
+ * import { DuplicateBridgeError } from "@xmachines/play-router/errors";
44
+ *
45
+ * try {
46
+ * bridge.connect();
47
+ * } catch (err) {
48
+ * if (err instanceof DuplicateBridgeError) {
49
+ * console.error("Actor already has an active router bridge — disconnect first.");
50
+ * }
51
+ * }
52
+ * ```
53
+ */
54
+ export declare class DuplicateBridgeError extends PlayError {
55
+ constructor();
56
+ }
57
+ /**
58
+ * Thrown by `createRouteMatcher()` when the `URLPattern` API is not available in the
28
59
  * current runtime environment and no polyfill has been loaded.
29
60
  *
30
61
  * **How to fix:** Load `urlpattern-polyfill` at your application entry point, before
@@ -44,7 +75,7 @@ export declare class URLPatternUnavailableError extends PlayError {
44
75
  constructor();
45
76
  }
46
77
  /**
47
- * Thrown by `createRouteMap()` when a route pattern string cannot be compiled by
78
+ * Thrown by `createRouteMatcher()` when a route pattern string cannot be compiled by
48
79
  * `URLPattern`. The `pattern` field contains the rejected string; `cause` wraps the
49
80
  * original `URLPattern` constructor error.
50
81
  *
@@ -59,7 +90,7 @@ export declare class URLPatternUnavailableError extends PlayError {
59
90
  * import { InvalidRoutePatternError } from "@xmachines/play-router/errors";
60
91
  *
61
92
  * try {
62
- * const routeMatcher = createRouteMap(tree);
93
+ * const routeMatcher = createRouteMatcher(tree);
63
94
  * } catch (err) {
64
95
  * if (err instanceof InvalidRoutePatternError) {
65
96
  * console.error(`Bad route pattern: "${err.pattern}"`, err.cause);
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,eAAgB,SAAQ,SAAS;gBACjC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY;CAInD;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,0BAA2B,SAAQ,SAAS;;CASxD;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH;;;;;GAKG;AACH,qBAAa,mBAAoB,SAAQ,SAAS;IACjD,8CAA8C;IAC9C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;gBAEb,OAAO,EAAE,MAAM;CAS3B;AAED;;;;;GAKG;AACH,qBAAa,mBAAoB,SAAQ,SAAS;IACjD,sDAAsD;IACtD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;gBAEb,OAAO,EAAE,MAAM;CAS3B;AAED;;;;GAIG;AACH,qBAAa,uBAAwB,SAAQ,SAAS;IACrD,mEAAmE;IACnE,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,CAAC;gBAElB,UAAU,EAAE,MAAM,EAAE;CAWhC;AAED;;;;;GAKG;AACH,qBAAa,qBAAsB,SAAQ,SAAS;IACnD,0CAA0C;IAC1C,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,sDAAsD;IACtD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;gBAEZ,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE;CAWnE;AAED,qBAAa,wBAAyB,SAAQ,SAAS;IACtD,yEAAyE;IACzE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;gBAEb,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY;CAUnD"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,eAAgB,SAAQ,SAAS;gBACjC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY;CAInD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,qBAAa,oBAAqB,SAAQ,SAAS;;CAUlD;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,0BAA2B,SAAQ,SAAS;;CASxD;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH;;;;;GAKG;AACH,qBAAa,mBAAoB,SAAQ,SAAS;IACjD,8CAA8C;IAC9C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;gBAEb,OAAO,EAAE,MAAM;CAS3B;AAED;;;;;GAKG;AACH,qBAAa,mBAAoB,SAAQ,SAAS;IACjD,sDAAsD;IACtD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;gBAEb,OAAO,EAAE,MAAM;CAS3B;AAED;;;;GAIG;AACH,qBAAa,uBAAwB,SAAQ,SAAS;IACrD,mEAAmE;IACnE,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,CAAC;gBAElB,UAAU,EAAE,MAAM,EAAE;CAWhC;AAED;;;;;GAKG;AACH,qBAAa,qBAAsB,SAAQ,SAAS;IACnD,0CAA0C;IAC1C,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,sDAAsD;IACtD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;gBAEZ,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE;CAWnE;AAED,qBAAa,wBAAyB,SAAQ,SAAS;IACtD,yEAAyE;IACzE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;gBAEb,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY;CAUnD"}
package/dist/errors.js CHANGED
@@ -27,7 +27,42 @@ export class RouterSyncError extends PlayError {
27
27
  }
28
28
  }
29
29
  /**
30
- * Thrown by `createRouteMap()` when the `URLPattern` API is not available in the
30
+ * Thrown by `RouterBridgeBase.connect()` when a second bridge tries to connect
31
+ * to an actor that already has an active bridge connection.
32
+ *
33
+ * One actor may only be connected to one router bridge at a time. Two bridges
34
+ * sharing the same actor would both receive and process every router navigation
35
+ * event, sending duplicate `play.route` events to the actor and producing
36
+ * conflicting echo-suppression state via `lastSyncedPath`.
37
+ *
38
+ * **How to fix:** Call `bridge.disconnect()` on the first bridge before
39
+ * connecting a second one, or ensure only one `connectRouter()` call is active
40
+ * per actor at any given time.
41
+ *
42
+ * **Error code:** `PLAY_ROUTER_DUPLICATE_BRIDGE`
43
+ *
44
+ * @example
45
+ * ```typescript
46
+ * import { DuplicateBridgeError } from "@xmachines/play-router/errors";
47
+ *
48
+ * try {
49
+ * bridge.connect();
50
+ * } catch (err) {
51
+ * if (err instanceof DuplicateBridgeError) {
52
+ * console.error("Actor already has an active router bridge — disconnect first.");
53
+ * }
54
+ * }
55
+ * ```
56
+ */
57
+ export class DuplicateBridgeError extends PlayError {
58
+ constructor() {
59
+ super("RouterBridgeBase", "PLAY_ROUTER_DUPLICATE_BRIDGE", "An actor can only be connected to one router bridge at a time. " +
60
+ "Call disconnect() on the existing bridge before connecting a new one.");
61
+ this.name = "DuplicateBridgeError";
62
+ }
63
+ }
64
+ /**
65
+ * Thrown by `createRouteMatcher()` when the `URLPattern` API is not available in the
31
66
  * current runtime environment and no polyfill has been loaded.
32
67
  *
33
68
  * **How to fix:** Load `urlpattern-polyfill` at your application entry point, before
@@ -50,7 +85,7 @@ export class URLPatternUnavailableError extends PlayError {
50
85
  }
51
86
  }
52
87
  /**
53
- * Thrown by `createRouteMap()` when a route pattern string cannot be compiled by
88
+ * Thrown by `createRouteMatcher()` when a route pattern string cannot be compiled by
54
89
  * `URLPattern`. The `pattern` field contains the rejected string; `cause` wraps the
55
90
  * original `URLPattern` constructor error.
56
91
  *
@@ -65,7 +100,7 @@ export class URLPatternUnavailableError extends PlayError {
65
100
  * import { InvalidRoutePatternError } from "@xmachines/play-router/errors";
66
101
  *
67
102
  * try {
68
- * const routeMatcher = createRouteMap(tree);
103
+ * const routeMatcher = createRouteMatcher(tree);
69
104
  * } catch (err) {
70
105
  * if (err instanceof InvalidRoutePatternError) {
71
106
  * console.error(`Bad route pattern: "${err.pattern}"`, err.cause);
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,OAAO,eAAgB,SAAQ,SAAS;IAC7C,YAAY,OAAe,EAAE,OAAsB;QAClD,KAAK,CAAC,kBAAkB,EAAE,yBAAyB,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QACvE,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;IAC/B,CAAC;CACD;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,OAAO,0BAA2B,SAAQ,SAAS;IACxD;QACC,KAAK,CACJ,UAAU,EACV,uCAAuC,EACvC,6IAA6I,CAC7I,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,4BAA4B,CAAC;IAC1C,CAAC;CACD;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH;;;;;GAKG;AACH,MAAM,OAAO,mBAAoB,SAAQ,SAAS;IACjD,8CAA8C;IACrC,OAAO,CAAS;IAEzB,YAAY,OAAe;QAC1B,KAAK,CACJ,UAAU,EACV,uBAAuB,EACvB,8BAA8B,OAAO,sCAAsC,CAC3E,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;QAClC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACxB,CAAC;CACD;AAED;;;;;GAKG;AACH,MAAM,OAAO,mBAAoB,SAAQ,SAAS;IACjD,sDAAsD;IAC7C,OAAO,CAAS;IAEzB,YAAY,OAAe;QAC1B,KAAK,CACJ,UAAU,EACV,6BAA6B,EAC7B,2CAA2C,OAAO,EAAE,CACpD,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;QAClC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACxB,CAAC;CACD;AAED;;;;GAIG;AACH,MAAM,OAAO,uBAAwB,SAAQ,SAAS;IACrD,mEAAmE;IAC1D,UAAU,CAAW;IAE9B,YAAY,UAAoB;QAC/B,KAAK,CACJ,UAAU,EACV,2BAA2B,EAC3B,oCAAoC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM;YAC9D,kDAAkD;YAClD,6FAA6F,CAC9F,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,yBAAyB,CAAC;QACtC,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IAC9B,CAAC;CACD;AAED;;;;;GAKG;AACH,MAAM,OAAO,qBAAsB,SAAQ,SAAS;IACnD,0CAA0C;IACjC,SAAS,CAAS;IAC3B,sDAAsD;IAC7C,MAAM,CAAS;IAExB,YAAY,SAAiB,EAAE,MAAc,EAAE,UAAoB;QAClE,KAAK,CACJ,gBAAgB,EAChB,+BAA+B,EAC/B,8BAA8B,SAAS,cAAc,MAAM,KAAK;YAC/D,oBAAoB,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAC7C,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAC;QACpC,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAC3B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACtB,CAAC;CACD;AAED,MAAM,OAAO,wBAAyB,SAAQ,SAAS;IACtD,yEAAyE;IAChE,OAAO,CAAS;IAEzB,YAAY,OAAe,EAAE,OAAsB;QAClD,KAAK,CACJ,UAAU,EACV,gCAAgC,EAChC,2BAA2B,OAAO,GAAG,EACrC,OAAO,CACP,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,0BAA0B,CAAC;QACvC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACxB,CAAC;CACD"}
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,OAAO,eAAgB,SAAQ,SAAS;IAC7C,YAAY,OAAe,EAAE,OAAsB;QAClD,KAAK,CAAC,kBAAkB,EAAE,yBAAyB,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QACvE,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;IAC/B,CAAC;CACD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAM,OAAO,oBAAqB,SAAQ,SAAS;IAClD;QACC,KAAK,CACJ,kBAAkB,EAClB,8BAA8B,EAC9B,iEAAiE;YAChE,uEAAuE,CACxE,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC;IACpC,CAAC;CACD;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,OAAO,0BAA2B,SAAQ,SAAS;IACxD;QACC,KAAK,CACJ,UAAU,EACV,uCAAuC,EACvC,6IAA6I,CAC7I,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,4BAA4B,CAAC;IAC1C,CAAC;CACD;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH;;;;;GAKG;AACH,MAAM,OAAO,mBAAoB,SAAQ,SAAS;IACjD,8CAA8C;IACrC,OAAO,CAAS;IAEzB,YAAY,OAAe;QAC1B,KAAK,CACJ,UAAU,EACV,uBAAuB,EACvB,8BAA8B,OAAO,sCAAsC,CAC3E,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;QAClC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACxB,CAAC;CACD;AAED;;;;;GAKG;AACH,MAAM,OAAO,mBAAoB,SAAQ,SAAS;IACjD,sDAAsD;IAC7C,OAAO,CAAS;IAEzB,YAAY,OAAe;QAC1B,KAAK,CACJ,UAAU,EACV,6BAA6B,EAC7B,2CAA2C,OAAO,EAAE,CACpD,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;QAClC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACxB,CAAC;CACD;AAED;;;;GAIG;AACH,MAAM,OAAO,uBAAwB,SAAQ,SAAS;IACrD,mEAAmE;IAC1D,UAAU,CAAW;IAE9B,YAAY,UAAoB;QAC/B,KAAK,CACJ,UAAU,EACV,2BAA2B,EAC3B,oCAAoC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM;YAC9D,kDAAkD;YAClD,6FAA6F,CAC9F,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,yBAAyB,CAAC;QACtC,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IAC9B,CAAC;CACD;AAED;;;;;GAKG;AACH,MAAM,OAAO,qBAAsB,SAAQ,SAAS;IACnD,0CAA0C;IACjC,SAAS,CAAS;IAC3B,sDAAsD;IAC7C,MAAM,CAAS;IAExB,YAAY,SAAiB,EAAE,MAAc,EAAE,UAAoB;QAClE,KAAK,CACJ,gBAAgB,EAChB,+BAA+B,EAC/B,8BAA8B,SAAS,cAAc,MAAM,KAAK;YAC/D,oBAAoB,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAC7C,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAC;QACpC,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAC3B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACtB,CAAC;CACD;AAED,MAAM,OAAO,wBAAyB,SAAQ,SAAS;IACtD,yEAAyE;IAChE,OAAO,CAAS;IAEzB,YAAY,OAAe,EAAE,OAAsB;QAClD,KAAK,CACJ,UAAU,EACV,gCAAgC,EAChC,2BAA2B,OAAO,GAAG,EACrC,OAAO,CACP,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,0BAA0B,CAAC;QACvC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACxB,CAAC;CACD"}
package/dist/index.d.ts CHANGED
@@ -9,9 +9,10 @@ export { getNavigableRoutes, getRoutableRoutes, routeExists, getTransitionReacha
9
9
  export { machineToGraph } from "./machine-to-graph.js";
10
10
  export type { MachineGraph } from "./machine-to-graph.js";
11
11
  export type { RouteInfo, RouteNode, RouteTree, RouteObject, RouteMetadata, PlayRouteEvent, RouterBridge, MachineNodeData, MachineEdgeData, WindowLike, LocationLike, } from "./types.js";
12
- export { createRouteMap, type RouteMatcher } from "./create-route-map.js";
12
+ export { createRouteMatcher, type RouteMatcher } from "./create-route-matcher.js";
13
13
  export { RouteMap, type RouteMapping, type RouteMapping as BaseRouteMapping, } from "./base-route-map.js";
14
- export { createRouteMapFromMachine } from "./create-route-map-from-machine.js";
14
+ export { createRouteMap } from "./create-route-map.js";
15
+ export type { RouteMapOptions } from "./create-route-map.js";
15
16
  export { createRouteMapFromTree } from "./create-route-map-from-tree.js";
16
17
  export { findRouteById, findRouteByPath } from "./find-route.js";
17
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;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,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,YAAY,EACZ,eAAe,EACf,eAAe,EACf,UAAU,EACV,YAAY,GACZ,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,cAAc,EAAE,KAAK,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAI1E,OAAO,EACN,QAAQ,EACR,KAAK,YAAY,EACjB,KAAK,YAAY,IAAI,gBAAgB,GACrC,MAAM,qBAAqB,CAAC;AAI7B,OAAO,EAAE,yBAAyB,EAAE,MAAM,oCAAoC,CAAC;AAC/E,OAAO,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AAGzE,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,iBAAiB,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,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,YAAY,EACZ,eAAe,EACf,eAAe,EACf,UAAU,EACV,YAAY,GACZ,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,kBAAkB,EAAE,KAAK,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAIlF,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
@@ -9,14 +9,14 @@ export { extractMachineRoutes } from "./extract-routes.js";
9
9
  export { getNavigableRoutes, getRoutableRoutes, routeExists, getTransitionReachableRoutes, isRouteReachable, } from "./query.js";
10
10
  // Graph adapter — converts XState machines to @statelyai/graph Graph
11
11
  export { machineToGraph } from "./machine-to-graph.js";
12
- // URL-pattern-based matcher (createRouteMap / RouteMatcher interface)
13
- export { createRouteMap } from "./create-route-map.js";
12
+ // URL-pattern-based matcher (createRouteMatcher / RouteMatcher interface)
13
+ export { createRouteMatcher } from "./create-route-matcher.js";
14
14
  // Shared bidirectional route mapping base class.
15
15
  // RouteMapping is exported directly; BaseRouteMapping kept as alias for compatibility.
16
16
  export { RouteMap, } from "./base-route-map.js";
17
17
  // Factories: create a RouteMap from a machine or a route tree.
18
18
  // All RouterBridgeBase adapters use these instead of rolling their own factories.
19
- export { createRouteMapFromMachine } from "./create-route-map-from-machine.js";
19
+ export { createRouteMap } from "./create-route-map.js";
20
20
  export { createRouteMapFromTree } from "./create-route-map-from-tree.js";
21
21
  // Route lookup helpers — matchesPattern is private within find-route.ts
22
22
  export { findRouteById, findRouteByPath } from "./find-route.js";
package/dist/index.js.map CHANGED
@@ -1 +1 @@
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;AAC9B,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;AAiBvD,sEAAsE;AACtE,OAAO,EAAE,cAAc,EAAqB,MAAM,uBAAuB,CAAC;AAE1E,iDAAiD;AACjD,uFAAuF;AACvF,OAAO,EACN,QAAQ,GAGR,MAAM,qBAAqB,CAAC;AAE7B,+DAA+D;AAC/D,kFAAkF;AAClF,OAAO,EAAE,yBAAyB,EAAE,MAAM,oCAAoC,CAAC;AAC/E,OAAO,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AAEzE,wEAAwE;AACxE,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC"}
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;AAC9B,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;AAiBvD,0EAA0E;AAC1E,OAAO,EAAE,kBAAkB,EAAqB,MAAM,2BAA2B,CAAC;AAElF,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"}
@@ -3,8 +3,9 @@
3
3
  *
4
4
  * Captures the 90% identical logic from all existing router bridges:
5
5
  * - TC39 Signal watcher for actor → router direction
6
- * - isProcessingNavigation flag for circular update prevention
7
- * - syncRouterFromActor / syncActorFromRouter with URL parameter extraction
6
+ * - `lastSyncedPath` for echo suppression in the actor→router direction
7
+ * - `isProcessingNavigation` flag for guard-redirect loop prevention in `syncActorFromRouter` only
8
+ * - `syncRouterFromActor` / `syncActorFromRouter` with URL parameter extraction
8
9
  * - connect / disconnect lifecycle matching the RouterBridge protocol
9
10
  *
10
11
  * Subclasses implement only the 3 framework-specific abstract methods:
@@ -78,13 +79,23 @@ export declare abstract class RouterBridgeBase implements RouterBridge {
78
79
  protected isConnected: boolean;
79
80
  protected hasConnectedOnce: boolean;
80
81
  protected lastSyncedPath: string | null;
82
+ /**
83
+ * Guards `syncActorFromRouter` against re-entrant calls triggered by the
84
+ * actor's own guard redirects (router→actor send → signal fires → actor→router
85
+ * push → another syncActorFromRouter before the first one returns).
86
+ *
87
+ * NOT used for actor→router echo suppression — that is handled exclusively by
88
+ * `lastSyncedPath`, which is updated before `navigateRouter()` is called so
89
+ * any router callback for the same path short-circuits at the
90
+ * `sanitized === lastSyncedPath` check in `syncActorFromRouter`.
91
+ */
81
92
  protected isProcessingNavigation: boolean;
82
93
  protected routeWatcher: RouteWatcherHandle | null;
83
94
  /**
84
95
  * @param actor - A `Routable` actor exposing `currentRoute` and `send`.
85
96
  * @param routeMap - Bidirectional route map for `stateId ↔ path` resolution.
86
97
  * Provide `getStateIdByPath` and `getPathByStateId`. Framework adapters
87
- * typically wrap the result of `createRouteMap()` or an equivalent.
98
+ * typically wrap the result of `createRouteMap(machine)` or an equivalent.
88
99
  */
89
100
  constructor(actor: AbstractActor<AnyActorLogic> & Routable, routeMap: {
90
101
  getStateIdByPath(path: string): string | null | undefined;
@@ -115,11 +126,15 @@ export declare abstract class RouterBridgeBase implements RouterBridge {
115
126
  * Sync router location when actor route signal changes.
116
127
  *
117
128
  * Calls navigateRouter() for framework-specific navigation.
118
- * Prevents circular updates via isProcessingNavigation flag.
119
129
  *
120
- * `lastSyncedPath` is updated before `navigateRouter()` and the processing flag is
121
- * released in a microtask so synchronous router callbacks triggered by navigation are
122
- * suppressed as circular echoes.
130
+ * Echo suppression preventing the router's own callback from re-driving the
131
+ * actor is handled entirely by `lastSyncedPath`: it is set to `route` before
132
+ * `navigateRouter()` is called, so any `syncActorFromRouter` invocation for the
133
+ * same path short-circuits at the `sanitized === lastSyncedPath` check and sends
134
+ * no event regardless of whether the callback fires synchronously or asynchronously.
135
+ *
136
+ * `isProcessingNavigation` is NOT set here — it is only used inside
137
+ * `syncActorFromRouter` to guard against re-entrant guard-redirect loops.
123
138
  */
124
139
  protected syncRouterFromActor(route: string | null | unknown): void;
125
140
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"router-bridge-base.d.ts","sourceRoot":"","sources":["../src/router-bridge-base.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"router-bridge-base.d.ts","sourceRoot":"","sources":["../src/router-bridge-base.ts"],"names":[],"mappings":"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"}
@@ -3,8 +3,9 @@
3
3
  *
4
4
  * Captures the 90% identical logic from all existing router bridges:
5
5
  * - TC39 Signal watcher for actor → router direction
6
- * - isProcessingNavigation flag for circular update prevention
7
- * - syncRouterFromActor / syncActorFromRouter with URL parameter extraction
6
+ * - `lastSyncedPath` for echo suppression in the actor→router direction
7
+ * - `isProcessingNavigation` flag for guard-redirect loop prevention in `syncActorFromRouter` only
8
+ * - `syncRouterFromActor` / `syncActorFromRouter` with URL parameter extraction
8
9
  * - connect / disconnect lifecycle matching the RouterBridge protocol
9
10
  *
10
11
  * Subclasses implement only the 3 framework-specific abstract methods:
@@ -41,9 +42,19 @@
41
42
  * @see [Play RFC](../../docs/rfc/play.md) - Invariant INV-04
42
43
  */
43
44
  import { Signal, watchSignal } from "@xmachines/play-signals";
44
- import { RouterSyncError } from "./errors.js";
45
+ import { DuplicateBridgeError, RouterSyncError } from "./errors.js";
45
46
  import { buildPlayRouteEvent, extractQuery, extractRouteParams, matchRouteMap, sanitizePathname, } from "./router-sync.js";
46
47
  import { URLPatternUnavailableError } from "./errors.js";
48
+ /**
49
+ * Module-level registry of actors that currently have an active bridge connection.
50
+ *
51
+ * Keyed on the actor instance (WeakMap — no reference retention). Used to detect and
52
+ * reject duplicate `connect()` calls for the same actor, which would produce duplicate
53
+ * `play.route` events and conflicting `lastSyncedPath` echo-suppression state.
54
+ *
55
+ * @internal
56
+ */
57
+ const activeBridges = new WeakMap();
47
58
  /** Strip leading '#' for normalized stateId comparison. */
48
59
  function normalizeId(id) {
49
60
  return id.startsWith("#") ? id.slice(1) : id;
@@ -62,13 +73,23 @@ export class RouterBridgeBase {
62
73
  isConnected = false;
63
74
  hasConnectedOnce = false;
64
75
  lastSyncedPath = null;
76
+ /**
77
+ * Guards `syncActorFromRouter` against re-entrant calls triggered by the
78
+ * actor's own guard redirects (router→actor send → signal fires → actor→router
79
+ * push → another syncActorFromRouter before the first one returns).
80
+ *
81
+ * NOT used for actor→router echo suppression — that is handled exclusively by
82
+ * `lastSyncedPath`, which is updated before `navigateRouter()` is called so
83
+ * any router callback for the same path short-circuits at the
84
+ * `sanitized === lastSyncedPath` check in `syncActorFromRouter`.
85
+ */
65
86
  isProcessingNavigation = false;
66
87
  routeWatcher = null;
67
88
  /**
68
89
  * @param actor - A `Routable` actor exposing `currentRoute` and `send`.
69
90
  * @param routeMap - Bidirectional route map for `stateId ↔ path` resolution.
70
91
  * Provide `getStateIdByPath` and `getPathByStateId`. Framework adapters
71
- * typically wrap the result of `createRouteMap()` or an equivalent.
92
+ * typically wrap the result of `createRouteMap(machine)` or an equivalent.
72
93
  */
73
94
  constructor(actor, routeMap) {
74
95
  this.actor = actor;
@@ -96,6 +117,14 @@ export class RouterBridgeBase {
96
117
  if (this.isConnected) {
97
118
  return;
98
119
  }
120
+ // Enforce single-bridge-per-actor: two connected bridges for the same actor
121
+ // would both receive every router navigation event, sending duplicate play.route
122
+ // events and producing conflicting lastSyncedPath echo-suppression state.
123
+ const existingBridge = activeBridges.get(this.actor);
124
+ if (existingBridge !== undefined && existingBridge !== this) {
125
+ throw new DuplicateBridgeError();
126
+ }
127
+ activeBridges.set(this.actor, this);
99
128
  this.isConnected = true;
100
129
  this.hasConnectedOnce = true;
101
130
  // Set up TC39 Signal watcher for actor → router direction
@@ -186,17 +215,27 @@ export class RouterBridgeBase {
186
215
  }
187
216
  this.isProcessingNavigation = false;
188
217
  this.isConnected = false;
218
+ // Release the actor slot so a new bridge can connect to the same actor.
219
+ // Only clear if this bridge is the currently registered one — a second bridge
220
+ // that was rejected at connect() time must not evict the legitimate bridge.
221
+ if (activeBridges.get(this.actor) === this) {
222
+ activeBridges.delete(this.actor);
223
+ }
189
224
  }
190
225
  // ── Sync methods (protected, overridable if subclass needs custom behavior) ──
191
226
  /**
192
227
  * Sync router location when actor route signal changes.
193
228
  *
194
229
  * Calls navigateRouter() for framework-specific navigation.
195
- * Prevents circular updates via isProcessingNavigation flag.
196
230
  *
197
- * `lastSyncedPath` is updated before `navigateRouter()` and the processing flag is
198
- * released in a microtask so synchronous router callbacks triggered by navigation are
199
- * suppressed as circular echoes.
231
+ * Echo suppression preventing the router's own callback from re-driving the
232
+ * actor is handled entirely by `lastSyncedPath`: it is set to `route` before
233
+ * `navigateRouter()` is called, so any `syncActorFromRouter` invocation for the
234
+ * same path short-circuits at the `sanitized === lastSyncedPath` check and sends
235
+ * no event regardless of whether the callback fires synchronously or asynchronously.
236
+ *
237
+ * `isProcessingNavigation` is NOT set here — it is only used inside
238
+ * `syncActorFromRouter` to guard against re-entrant guard-redirect loops.
200
239
  */
201
240
  syncRouterFromActor(route) {
202
241
  if (this.hasConnectedOnce && !this.isConnected)
@@ -205,14 +244,18 @@ export class RouterBridgeBase {
205
244
  return;
206
245
  if (route === this.lastSyncedPath)
207
246
  return;
208
- if (this.isProcessingNavigation)
209
- return;
210
- this.lastSyncedPath = route;
211
- this.isProcessingNavigation = true;
247
+ // Resolve the raw actor route (stateId or concrete path) to the concrete URL
248
+ // path that will actually be pushed. lastSyncedPath must store the concrete
249
+ // path so that the router callback (which fires with the concrete path) matches
250
+ // and short-circuits in syncActorFromRouter. Storing the raw stateId (e.g.
251
+ // "#home") would cause a mismatch against the sanitized path ("/") in the watcher.
252
+ //
253
+ // When resolveNavigationPath returns null (parameterized pattern, unknown id)
254
+ // navigateRouter will skip the push — set lastSyncedPath to route as before so
255
+ // the dedup guard still fires correctly on the next identical signal value.
256
+ const resolved = this.resolveNavigationPath(route);
257
+ this.lastSyncedPath = resolved ?? route;
212
258
  this.navigateRouter(route);
213
- queueMicrotask(() => {
214
- this.isProcessingNavigation = false;
215
- });
216
259
  }
217
260
  /**
218
261
  * Sync actor state when router location changes.
@@ -1 +1 @@
1
- {"version":3,"file":"router-bridge-base.js","sourceRoot":"","sources":["../src/router-bridge-base.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"router-bridge-base.js","sourceRoot":"","sources":["../src/router-bridge-base.ts"],"names":[],"mappings":"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"}
package/dist/types.d.ts CHANGED
@@ -78,7 +78,7 @@ export interface RouteNode {
78
78
  /**
79
79
  * The fully resolved absolute path from the root (e.g. `"/dashboard/overview"`).
80
80
  * Always use `fullPath` for browser URL matching and route map construction.
81
- * `createRouteMapFromTree` and `createRouteMapFromMachine` both use this field.
81
+ * `createRouteMapFromTree` and `createRouteMap` both use this field.
82
82
  */
83
83
  fullPath: string;
84
84
  /** Route pattern with parameters (e.g., /profile/:userId) if path contains params */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xmachines/play-router",
3
- "version": "1.0.0-beta.43",
3
+ "version": "1.0.0-beta.45",
4
4
  "description": "Route tree extraction from XState v5 state machines. Part of @xmachines/play Universal Player Architecture.",
5
5
  "keywords": [
6
6
  "routing",
@@ -47,15 +47,15 @@
47
47
  },
48
48
  "dependencies": {
49
49
  "@statelyai/graph": "^0.11.0",
50
- "@xmachines/play": "1.0.0-beta.43",
51
- "@xmachines/play-actor": "1.0.0-beta.43",
52
- "@xmachines/play-signals": "1.0.0-beta.43",
50
+ "@xmachines/play": "1.0.0-beta.45",
51
+ "@xmachines/play-actor": "1.0.0-beta.45",
52
+ "@xmachines/play-signals": "1.0.0-beta.45",
53
53
  "quick-lru": "^7.3.0"
54
54
  },
55
55
  "devDependencies": {
56
56
  "@types/node": "^25.6.0",
57
- "@xmachines/play-xstate": "1.0.0-beta.43",
58
- "@xmachines/shared": "1.0.0-beta.43",
57
+ "@xmachines/play-xstate": "1.0.0-beta.45",
58
+ "@xmachines/shared": "1.0.0-beta.45",
59
59
  "oxfmt": "^0.45.0",
60
60
  "oxlint": "^1.60.0",
61
61
  "typescript": "^5.9.3 || ^6.0.3",
@@ -1,24 +0,0 @@
1
- import type { AnyStateMachine } from "xstate";
2
- import { RouteMap } from "./base-route-map.js";
3
- /**
4
- * Create a `RouteMap` from an XState state machine.
5
- *
6
- * Extracts all routable states (those with `meta.route`) and builds a bidirectional
7
- * path ↔ stateId lookup structure. The returned map is used by `RouterBridgeBase`
8
- * subclasses to translate browser URL changes into `play.route` actor events and
9
- * vice-versa.
10
- *
11
- * @param machine - XState v5 state machine with `meta.route` annotations on states.
12
- * @returns A `RouteMap` for passing to any `RouterBridgeBase`-based adapter.
13
- *
14
- * @example
15
- * ```typescript
16
- * import { createRouteMapFromMachine } from '@xmachines/play-router';
17
- * import { connectRouter } from '@xmachines/play-dom-router';
18
- *
19
- * const routeMap = createRouteMapFromMachine(myMachine);
20
- * const disconnect = connectRouter({ actor, router, routeMap });
21
- * ```
22
- */
23
- export declare function createRouteMapFromMachine(machine: AnyStateMachine): RouteMap;
24
- //# sourceMappingURL=create-route-map-from-machine.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"create-route-map-from-machine.d.ts","sourceRoot":"","sources":["../src/create-route-map-from-machine.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,QAAQ,CAAC;AAG9C,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAE/C;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,eAAe,GAAG,QAAQ,CAS5E"}
@@ -1,32 +0,0 @@
1
- import { extractMachineRoutes } from "./extract-routes.js";
2
- import { getRoutableRoutes } from "./query.js";
3
- import { RouteMap } from "./base-route-map.js";
4
- /**
5
- * Create a `RouteMap` from an XState state machine.
6
- *
7
- * Extracts all routable states (those with `meta.route`) and builds a bidirectional
8
- * path ↔ stateId lookup structure. The returned map is used by `RouterBridgeBase`
9
- * subclasses to translate browser URL changes into `play.route` actor events and
10
- * vice-versa.
11
- *
12
- * @param machine - XState v5 state machine with `meta.route` annotations on states.
13
- * @returns A `RouteMap` for passing to any `RouterBridgeBase`-based adapter.
14
- *
15
- * @example
16
- * ```typescript
17
- * import { createRouteMapFromMachine } from '@xmachines/play-router';
18
- * import { connectRouter } from '@xmachines/play-dom-router';
19
- *
20
- * const routeMap = createRouteMapFromMachine(myMachine);
21
- * const disconnect = connectRouter({ actor, router, routeMap });
22
- * ```
23
- */
24
- export function createRouteMapFromMachine(machine) {
25
- const routeTree = extractMachineRoutes(machine);
26
- const routes = getRoutableRoutes(routeTree);
27
- return new RouteMap(routes.map((node) => ({
28
- stateId: node.stateId,
29
- path: node.fullPath,
30
- })));
31
- }
32
- //# sourceMappingURL=create-route-map-from-machine.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"create-route-map-from-machine.js","sourceRoot":"","sources":["../src/create-route-map-from-machine.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAE/C;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,yBAAyB,CAAC,OAAwB;IACjE,MAAM,SAAS,GAAG,oBAAoB,CAAC,OAAO,CAAC,CAAC;IAChD,MAAM,MAAM,GAAG,iBAAiB,CAAC,SAAS,CAAC,CAAC;IAC5C,OAAO,IAAI,QAAQ,CAClB,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QACrB,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,IAAI,EAAE,IAAI,CAAC,QAAQ;KACnB,CAAC,CAAC,CACH,CAAC;AACH,CAAC"}