@xmachines/play-router 1.0.0-beta.50 → 1.0.0-beta.52
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 +19 -18
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/router-bridge-base.d.ts +39 -17
- package/dist/router-bridge-base.d.ts.map +1 -1
- package/dist/router-bridge-base.js +54 -5
- package/dist/router-bridge-base.js.map +1 -1
- package/dist/types.d.ts +68 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +9 -6
package/README.md
CHANGED
|
@@ -11,13 +11,13 @@ Part of the [xmachines-js monorepo](../../README.md).
|
|
|
11
11
|
## Installation
|
|
12
12
|
|
|
13
13
|
```bash
|
|
14
|
-
npm install xstate@^5.
|
|
14
|
+
npm install xstate@^5.31.0
|
|
15
15
|
npm install @xmachines/play-router
|
|
16
16
|
```
|
|
17
17
|
|
|
18
18
|
**Peer dependencies:**
|
|
19
19
|
|
|
20
|
-
- `xstate` ^5.
|
|
20
|
+
- `xstate` ^5.31.0 — XState v5 state machine runtime
|
|
21
21
|
|
|
22
22
|
**URLPattern polyfill (Node.js < 24 / older browsers):**
|
|
23
23
|
|
|
@@ -126,15 +126,14 @@ Extend `RouterBridgeBase` and implement the three abstract methods for your fram
|
|
|
126
126
|
|
|
127
127
|
```typescript
|
|
128
128
|
import { RouterBridgeBase } from "@xmachines/play-router";
|
|
129
|
-
import type {
|
|
130
|
-
import type { AnyActorLogic } from "xstate";
|
|
129
|
+
import type { RoutableActor } from "@xmachines/play-router";
|
|
131
130
|
|
|
132
131
|
export class MyRouterBridge extends RouterBridgeBase {
|
|
133
132
|
private unsubscribe: (() => void) | null = null;
|
|
134
133
|
|
|
135
134
|
constructor(
|
|
136
135
|
private readonly myRouter: MyRouter,
|
|
137
|
-
actor:
|
|
136
|
+
actor: RoutableActor,
|
|
138
137
|
routeMap: ReturnType<typeof createRouteMap>,
|
|
139
138
|
) {
|
|
140
139
|
super(actor, routeMap);
|
|
@@ -223,18 +222,20 @@ bridge.disconnect();
|
|
|
223
222
|
|
|
224
223
|
### Key Types
|
|
225
224
|
|
|
226
|
-
| Export | Description
|
|
227
|
-
| ---------------------------------- |
|
|
228
|
-
| `RouterBridge` | Interface for `connect()` / `disconnect()` lifecycle
|
|
229
|
-
| `RouteTree` | Hierarchical tree with `root`, `byStateId`, `byPath`, and optional `graph`
|
|
230
|
-
| `RouteNode` | Single node in the tree with `id`, `path`, `fullPath`, `stateId`, `children`, `parent`
|
|
231
|
-
| `RouteInfo` | Flat route descriptor extracted from a state node
|
|
232
|
-
| `PlayRouteEvent` | Routing event `{ type: "play.route", to, params?, query? }`
|
|
233
|
-
| `
|
|
234
|
-
| `
|
|
235
|
-
| `
|
|
236
|
-
| `
|
|
237
|
-
| `
|
|
225
|
+
| Export | Description |
|
|
226
|
+
| ---------------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
|
|
227
|
+
| `RouterBridge` | Interface for `connect()` / `disconnect()` lifecycle |
|
|
228
|
+
| `RouteTree` | Hierarchical tree with `root`, `byStateId`, `byPath`, and optional `graph` |
|
|
229
|
+
| `RouteNode` | Single node in the tree with `id`, `path`, `fullPath`, `stateId`, `children`, `parent` |
|
|
230
|
+
| `RouteInfo` | Flat route descriptor extracted from a state node |
|
|
231
|
+
| `PlayRouteEvent` | Routing event `{ type: "play.route", to, params?, query? }` |
|
|
232
|
+
| `RoutableActor` | Minimal actor interface required by `RouterBridgeBase` — `currentRoute`, `initialRoute`, and `send(PlayRouteEvent)` |
|
|
233
|
+
| `PlayActor` | Full actor interface used by `PlayRouterProvider` — extends `RoutableActor` with `currentView` (`Routable + Viewable`) |
|
|
234
|
+
| `RouteMapping` | `{ stateId, path }` pair used to build a `RouteMap` |
|
|
235
|
+
| `RouteMapping as BaseRouteMapping` | Alias for `RouteMapping` (backwards-compat re-export) |
|
|
236
|
+
| `MachineGraph` | Typed `@statelyai/graph` Graph with `MachineNodeData` / `MachineEdgeData` |
|
|
237
|
+
| `WindowLike` | Injectable minimal `window` interface for SSR / testing |
|
|
238
|
+
| `LocationLike` | Injectable minimal `location` interface for SSR / testing |
|
|
238
239
|
|
|
239
240
|
### Errors (subpath `@xmachines/play-router/errors`)
|
|
240
241
|
|
|
@@ -345,7 +346,7 @@ runBridgeContractTests({
|
|
|
345
346
|
## Related Packages
|
|
346
347
|
|
|
347
348
|
- **[@xmachines/play](../play/README.md)** — Core protocol types (`PlayEvent`, `PlayError`)
|
|
348
|
-
- **[@xmachines/play-actor](../play-actor/README.md)** — Abstract actor base class (`AbstractActor`, `Routable`)
|
|
349
|
+
- **[@xmachines/play-actor](../play-actor/README.md)** — Abstract actor base class (`AbstractActor`, `Routable`); all `AbstractActor` subclasses satisfy `RoutableActor` structurally
|
|
349
350
|
- **[@xmachines/play-signals](../play-signals/README.md)** — TC39 Signals polyfill used for actor route observation
|
|
350
351
|
- **[@xmachines/play-xstate](../play-xstate/README.md)** — XState v5 logic adapter that integrates with route trees
|
|
351
352
|
- **[@xmachines/play-tanstack-react-router](../play-tanstack-react-router/README.md)** — TanStack Router adapter (React)
|
package/dist/index.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ export { extractMachineRoutes } from "./extract-routes.js";
|
|
|
8
8
|
export { getNavigableRoutes, getRoutableRoutes, routeExists, getTransitionReachableRoutes, isRouteReachable, } from "./query.js";
|
|
9
9
|
export { machineToGraph } from "./machine-to-graph.js";
|
|
10
10
|
export type { MachineGraph } from "./machine-to-graph.js";
|
|
11
|
-
export type { RouteInfo, RouteNode, RouteTree, RouteObject, RouteMetadata, PlayRouteEvent, RouterBridge, MachineNodeData, MachineEdgeData, WindowLike, LocationLike, } from "./types.js";
|
|
11
|
+
export type { RouteInfo, RouteNode, RouteTree, RouteObject, RouteMetadata, PlayRouteEvent, RoutableActor, PlayActor, RouterBridge, MachineNodeData, MachineEdgeData, WindowLike, LocationLike, } from "./types.js";
|
|
12
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
14
|
export { createRouteMap } from "./create-route-map.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -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,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"}
|
|
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,aAAa,EACb,SAAS,EACT,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.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;
|
|
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;AAmBvD,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"}
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
* export class MyRouterBridge extends RouterBridgeBase {
|
|
19
19
|
* private unsubscribe: (() => void) | null = null;
|
|
20
20
|
*
|
|
21
|
-
* constructor(private router: MyRouter, actor:
|
|
21
|
+
* constructor(private router: MyRouter, actor: RoutableActor, routeMap: { getStateIdByPath(path: string): string | undefined; getPathByStateId(id: string): string | undefined; }) {
|
|
22
22
|
* super(actor, routeMap);
|
|
23
23
|
* }
|
|
24
24
|
*
|
|
@@ -42,8 +42,7 @@
|
|
|
42
42
|
* @see [Play RFC](../../docs/rfc/play.md) - Invariant INV-04
|
|
43
43
|
*/
|
|
44
44
|
import { Signal } from "@xmachines/play-signals";
|
|
45
|
-
import type {
|
|
46
|
-
import type { AnyActorLogic } from "xstate";
|
|
45
|
+
import type { RoutableActor } from "./types.js";
|
|
47
46
|
import type { RouterBridge } from "./types.js";
|
|
48
47
|
/**
|
|
49
48
|
* Narrow interface for the TC39 Signal watcher used by `RouterBridgeBase` to
|
|
@@ -71,7 +70,7 @@ export interface RouteWatcherHandle {
|
|
|
71
70
|
* between frameworks.
|
|
72
71
|
*/
|
|
73
72
|
export declare abstract class RouterBridgeBase implements RouterBridge {
|
|
74
|
-
protected readonly actor:
|
|
73
|
+
protected readonly actor: RoutableActor;
|
|
75
74
|
protected readonly routeMap: {
|
|
76
75
|
getStateIdByPath(path: string): string | null | undefined;
|
|
77
76
|
getPathByStateId(id: string): string | null | undefined;
|
|
@@ -92,12 +91,12 @@ export declare abstract class RouterBridgeBase implements RouterBridge {
|
|
|
92
91
|
protected isProcessingNavigation: boolean;
|
|
93
92
|
protected routeWatcher: RouteWatcherHandle | null;
|
|
94
93
|
/**
|
|
95
|
-
* @param actor - A `
|
|
94
|
+
* @param actor - A `RoutableActor` exposing `currentRoute`, `initialRoute`, and `send`.
|
|
96
95
|
* @param routeMap - Bidirectional route map for `stateId ↔ path` resolution.
|
|
97
96
|
* Provide `getStateIdByPath` and `getPathByStateId`. Framework adapters
|
|
98
97
|
* typically wrap the result of `createRouteMap(machine)` or an equivalent.
|
|
99
98
|
*/
|
|
100
|
-
constructor(actor:
|
|
99
|
+
constructor(actor: RoutableActor, routeMap: {
|
|
101
100
|
getStateIdByPath(path: string): string | null | undefined;
|
|
102
101
|
getPathByStateId(id: string): string | null | undefined;
|
|
103
102
|
});
|
|
@@ -140,8 +139,18 @@ export declare abstract class RouterBridgeBase implements RouterBridge {
|
|
|
140
139
|
/**
|
|
141
140
|
* Sync actor state when router location changes.
|
|
142
141
|
*
|
|
143
|
-
*
|
|
144
|
-
* Prevents circular updates via
|
|
142
|
+
* **Known path:** sends a `play.route` event to the actor with the matched
|
|
143
|
+
* stateId, params, and query. Prevents circular updates via the
|
|
144
|
+
* `isProcessingNavigation` flag.
|
|
145
|
+
*
|
|
146
|
+
* **Unknown/unmapped path:** does NOT send a `play.route` event (actor state
|
|
147
|
+
* is unchanged). Instead, actively corrects the browser URL by calling
|
|
148
|
+
* `navigateRouter(actor.currentRoute.get())` — keeping the URL in sync with
|
|
149
|
+
* actor state even when the user types an invalid path into the address bar
|
|
150
|
+
* or pushes one programmatically mid-session. `lastSyncedPath` is set to the
|
|
151
|
+
* resolved concrete path before calling `navigateRouter` so the router's own
|
|
152
|
+
* callback for that navigation short-circuits the echo-suppression guard and
|
|
153
|
+
* sends no spurious event.
|
|
145
154
|
*/
|
|
146
155
|
protected syncActorFromRouter(pathname: string, search?: string): void;
|
|
147
156
|
/**
|
|
@@ -183,27 +192,40 @@ export declare abstract class RouterBridgeBase implements RouterBridge {
|
|
|
183
192
|
*/
|
|
184
193
|
protected extractQuery(search: string): Record<string, string>;
|
|
185
194
|
/**
|
|
186
|
-
* Navigate the framework router to the given path.
|
|
187
|
-
*
|
|
188
|
-
* Called when actor's currentRoute signal changes to a new path.
|
|
189
195
|
* Must trigger the framework router's navigation (e.g., router.navigate(path)).
|
|
190
196
|
*/
|
|
191
197
|
protected abstract navigateRouter(path: string): void;
|
|
198
|
+
/**
|
|
199
|
+
* Sanitize and validate a raw URL pathname received from the router.
|
|
200
|
+
*
|
|
201
|
+
* Applies the path-length cap (2048 chars), strips query strings and fragments
|
|
202
|
+
* that may have been included in the pathname segment, and normalises
|
|
203
|
+
* consecutive slashes.
|
|
204
|
+
*
|
|
205
|
+
* Implementations that bypass `syncActorFromRouter()` (e.g. when using
|
|
206
|
+
* framework-native reactive watchers that receive pre-parsed route objects)
|
|
207
|
+
* MUST call this method before passing the path to any route-map lookup.
|
|
208
|
+
* `syncActorFromRouter()` calls this internally, so bridges that delegate
|
|
209
|
+
* to it do not need to call `sanitizePath` themselves.
|
|
210
|
+
*
|
|
211
|
+
* @param pathname - Raw URL pathname from the framework router.
|
|
212
|
+
* @returns Sanitized pathname, or `null` if the path is invalid / too long.
|
|
213
|
+
*/
|
|
214
|
+
protected sanitizePath(pathname: string): string | null;
|
|
192
215
|
/**
|
|
193
216
|
* Start watching for router location changes.
|
|
194
217
|
*
|
|
195
218
|
* Called by connect(). Should set up the framework-specific subscription
|
|
196
219
|
* for location changes and call syncActorFromRouter() on each change.
|
|
197
220
|
*
|
|
198
|
-
* **Implementations that call `syncActorFromRouter`** get
|
|
221
|
+
* **Implementations that call `syncActorFromRouter`** get path sanitization
|
|
199
222
|
* applied automatically — no extra work needed.
|
|
200
223
|
*
|
|
201
224
|
* **Implementations that bypass `syncActorFromRouter`** (e.g. `VueRouterBridge`,
|
|
202
|
-
* which builds the `play.route` event directly from
|
|
203
|
-
*
|
|
204
|
-
* this allows oversized or malformed paths through without the length
|
|
205
|
-
* guards that protect the route-map lookup.
|
|
206
|
-
* `@xmachines/play-router`.
|
|
225
|
+
* which builds the `play.route` event directly from framework-native route params)
|
|
226
|
+
* MUST call `this.sanitizePath(path)` and return early when it returns `null`.
|
|
227
|
+
* Skipping this allows oversized or malformed paths through without the length
|
|
228
|
+
* and content guards that protect the route-map lookup.
|
|
207
229
|
*/
|
|
208
230
|
protected abstract watchRouterChanges(): void;
|
|
209
231
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router-bridge-base.d.ts","sourceRoot":"","sources":["../src/router-bridge-base.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AAEH,OAAO,EAAE,MAAM,EAAe,MAAM,yBAAyB,CAAC;AAE9D,OAAO,KAAK,EAAE,aAAa,EAAE,
|
|
1
|
+
{"version":3,"file":"router-bridge-base.d.ts","sourceRoot":"","sources":["../src/router-bridge-base.ts"],"names":[],"mappings":"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"}
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
* export class MyRouterBridge extends RouterBridgeBase {
|
|
19
19
|
* private unsubscribe: (() => void) | null = null;
|
|
20
20
|
*
|
|
21
|
-
* constructor(private router: MyRouter, actor:
|
|
21
|
+
* constructor(private router: MyRouter, actor: RoutableActor, routeMap: { getStateIdByPath(path: string): string | undefined; getPathByStateId(id: string): string | undefined; }) {
|
|
22
22
|
* super(actor, routeMap);
|
|
23
23
|
* }
|
|
24
24
|
*
|
|
@@ -86,7 +86,7 @@ export class RouterBridgeBase {
|
|
|
86
86
|
isProcessingNavigation = false;
|
|
87
87
|
routeWatcher = null;
|
|
88
88
|
/**
|
|
89
|
-
* @param actor - A `
|
|
89
|
+
* @param actor - A `RoutableActor` exposing `currentRoute`, `initialRoute`, and `send`.
|
|
90
90
|
* @param routeMap - Bidirectional route map for `stateId ↔ path` resolution.
|
|
91
91
|
* Provide `getStateIdByPath` and `getPathByStateId`. Framework adapters
|
|
92
92
|
* typically wrap the result of `createRouteMap(machine)` or an equivalent.
|
|
@@ -260,8 +260,18 @@ export class RouterBridgeBase {
|
|
|
260
260
|
/**
|
|
261
261
|
* Sync actor state when router location changes.
|
|
262
262
|
*
|
|
263
|
-
*
|
|
264
|
-
* Prevents circular updates via
|
|
263
|
+
* **Known path:** sends a `play.route` event to the actor with the matched
|
|
264
|
+
* stateId, params, and query. Prevents circular updates via the
|
|
265
|
+
* `isProcessingNavigation` flag.
|
|
266
|
+
*
|
|
267
|
+
* **Unknown/unmapped path:** does NOT send a `play.route` event (actor state
|
|
268
|
+
* is unchanged). Instead, actively corrects the browser URL by calling
|
|
269
|
+
* `navigateRouter(actor.currentRoute.get())` — keeping the URL in sync with
|
|
270
|
+
* actor state even when the user types an invalid path into the address bar
|
|
271
|
+
* or pushes one programmatically mid-session. `lastSyncedPath` is set to the
|
|
272
|
+
* resolved concrete path before calling `navigateRouter` so the router's own
|
|
273
|
+
* callback for that navigation short-circuits the echo-suppression guard and
|
|
274
|
+
* sends no spurious event.
|
|
265
275
|
*/
|
|
266
276
|
syncActorFromRouter(pathname, search) {
|
|
267
277
|
if (this.hasConnectedOnce && !this.isConnected)
|
|
@@ -283,7 +293,27 @@ export class RouterBridgeBase {
|
|
|
283
293
|
match: (nextPathname) => matchRouteMap(nextPathname, this.routeMap, (resolvedPathname, stateId) => this.extractParams(resolvedPathname, stateId)),
|
|
284
294
|
});
|
|
285
295
|
if (!nextRoute) {
|
|
286
|
-
|
|
296
|
+
// Unknown path — no matching route in the map.
|
|
297
|
+
// Push the actor's current route back to the router so the browser URL
|
|
298
|
+
// stays in sync with actor state (corrects an invalid address-bar entry
|
|
299
|
+
// on cold-load or mid-session navigation to a non-existent path).
|
|
300
|
+
//
|
|
301
|
+
// Call navigateRouter() directly rather than syncRouterFromActor() to
|
|
302
|
+
// avoid the dedup guard (lastSyncedPath is already the actor's route).
|
|
303
|
+
// Set lastSyncedPath to the resolved concrete path first so that the
|
|
304
|
+
// router's own callback for this navigation (hashchange / history event)
|
|
305
|
+
// short-circuits in the sanitized === lastSyncedPath guard and does not
|
|
306
|
+
// send a spurious play.route event to the actor.
|
|
307
|
+
//
|
|
308
|
+
// isProcessingNavigation is left true here; the finally block below
|
|
309
|
+
// clears it after navigateRouter returns, providing a synchronous
|
|
310
|
+
// re-entrancy guard for any router callback that fires inline.
|
|
311
|
+
const currentActorRoute = this.actor.currentRoute.get();
|
|
312
|
+
if (currentActorRoute) {
|
|
313
|
+
const resolved = this.resolveNavigationPath(currentActorRoute);
|
|
314
|
+
this.lastSyncedPath = resolved ?? currentActorRoute;
|
|
315
|
+
this.navigateRouter(currentActorRoute);
|
|
316
|
+
}
|
|
287
317
|
return;
|
|
288
318
|
}
|
|
289
319
|
this.actor.send(nextRoute.event);
|
|
@@ -356,6 +386,25 @@ export class RouterBridgeBase {
|
|
|
356
386
|
extractQuery(search) {
|
|
357
387
|
return extractQuery(search);
|
|
358
388
|
}
|
|
389
|
+
/**
|
|
390
|
+
* Sanitize and validate a raw URL pathname received from the router.
|
|
391
|
+
*
|
|
392
|
+
* Applies the path-length cap (2048 chars), strips query strings and fragments
|
|
393
|
+
* that may have been included in the pathname segment, and normalises
|
|
394
|
+
* consecutive slashes.
|
|
395
|
+
*
|
|
396
|
+
* Implementations that bypass `syncActorFromRouter()` (e.g. when using
|
|
397
|
+
* framework-native reactive watchers that receive pre-parsed route objects)
|
|
398
|
+
* MUST call this method before passing the path to any route-map lookup.
|
|
399
|
+
* `syncActorFromRouter()` calls this internally, so bridges that delegate
|
|
400
|
+
* to it do not need to call `sanitizePath` themselves.
|
|
401
|
+
*
|
|
402
|
+
* @param pathname - Raw URL pathname from the framework router.
|
|
403
|
+
* @returns Sanitized pathname, or `null` if the path is invalid / too long.
|
|
404
|
+
*/
|
|
405
|
+
sanitizePath(pathname) {
|
|
406
|
+
return sanitizePathname(pathname);
|
|
407
|
+
}
|
|
359
408
|
/**
|
|
360
409
|
* Return the router's current pathname at connect() time.
|
|
361
410
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router-bridge-base.js","sourceRoot":"","sources":["../src/router-bridge-base.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AAEH,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"router-bridge-base.js","sourceRoot":"","sources":["../src/router-bridge-base.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AAEH,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEpE,OAAO,EACN,mBAAmB,EACnB,YAAY,EACZ,kBAAkB,EAClB,aAAa,EACb,gBAAgB,GAChB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,0BAA0B,EAAE,MAAM,aAAa,CAAC;AAqBzD;;;;;;;;GAQG;AACH,MAAM,aAAa,GAAG,IAAI,OAAO,EAA4B,CAAC;AAE9D,2DAA2D;AAC3D,SAAS,WAAW,CAAC,EAAU;IAC9B,OAAO,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AAC9C,CAAC;AAED;;;;;;GAMG;AACH,MAAM,OAAgB,gBAAgB;IAyBjB;IACA;IAzBpB,+DAA+D;IACrD,WAAW,GAAY,KAAK,CAAC;IAC7B,gBAAgB,GAAY,KAAK,CAAC;IAClC,cAAc,GAAkB,IAAI,CAAC;IAC/C;;;;;;;;;OASG;IACO,sBAAsB,GAAY,KAAK,CAAC;IACxC,YAAY,GAA8B,IAAI,CAAC;IAEzD;;;;;OAKG;IACH,YACoB,KAAoB,EACpB,QAGlB;QAJkB,UAAK,GAAL,KAAK,CAAe;QACpB,aAAQ,GAAR,QAAQ,CAG1B;QAED,mFAAmF;QACnF,wEAAwE;QACxE,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC;IAC7D,CAAC;IAED,qEAAqE;IAErE;;;;;;;;;;;;;OAaG;IACH,OAAO;QACN,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACtB,OAAO;QACR,CAAC;QAED,4EAA4E;QAC5E,iFAAiF;QACjF,0EAA0E;QAC1E,MAAM,cAAc,GAAG,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACrD,IAAI,cAAc,KAAK,SAAS,IAAI,cAAc,KAAK,IAAI,EAAE,CAAC;YAC7D,MAAM,IAAI,oBAAoB,EAAE,CAAC;QAClC,CAAC;QACD,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QAEpC,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;QACxB,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC;QAE7B,0DAA0D;QAC1D,IAAI,CAAC,YAAY,GAAG,kBAAkB,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,EAAE,CAAC,KAAK,EAAE,EAAE;YACzE,IAAI,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC;QACjC,CAAC,CAAC,CAAC;QAEH,qDAAqD;QACrD,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAE1B,mEAAmE;QACnE,EAAE;QACF,6EAA6E;QAC7E,6EAA6E;QAC7E,4EAA4E;QAC5E,2EAA2E;QAC3E,mBAAmB;QACnB,EAAE;QACF,4EAA4E;QAC5E,8EAA8E;QAC9E,yEAAyE;QACzE,MAAM,iBAAiB,GAAG,IAAI,CAAC,oBAAoB,EAAE,CAAC;QACtD,MAAM,mBAAmB,GAAG,IAAI,CAAC,sBAAsB,EAAE,CAAC;QAC1D,MAAM,iBAAiB,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,GAAG,EAAE,CAAC;QAExD,IAAI,OAAO,iBAAiB,KAAK,QAAQ,EAAE,CAAC;YAC3C,8DAA8D;YAC9D,iFAAiF;YACjF,+EAA+E;YAC/E,iFAAiF;YACjF,MAAM,eAAe,GAAG,IAAI,CAAC,QAAQ,CAAC,gBAAgB,CACrD,gBAAgB,CAAC,iBAAiB,CAAC,IAAI,iBAAiB,CACxD,CAAC;YACF,8EAA8E;YAC9E,oEAAoE;YACpE,oFAAoF;YACpF,MAAM,4BAA4B,GACjC,eAAe,KAAK,IAAI;gBACxB,eAAe,KAAK,SAAS;gBAC7B,CAAC,WAAW,CAAC,eAAe,CAAC,KAAK,WAAW,CAAC,iBAAiB,IAAI,EAAE,CAAC;oBACrE,iBAAiB,KAAK,iBAAiB,CAAC,CAAC;YAE3C,IAAI,CAAC,4BAA4B,EAAE,CAAC;gBACnC,+EAA+E;gBAC/E,EAAE;gBACF,uEAAuE;gBACvE,sEAAsE;gBACtE,EAAE;gBACF,uEAAuE;gBACvE,mDAAmD;gBACnD,6DAA6D;gBAC7D,EAAE;gBACF,0EAA0E;gBAC1E,6DAA6D;gBAC7D,IACC,iBAAiB;oBACjB,iBAAiB,KAAK,IAAI,CAAC,KAAK,CAAC,YAAY;oBAC7C,iBAAiB,KAAK,IAAI,CAAC,KAAK,CAAC,YAAY,EAC5C,CAAC;oBACF,IAAI,CAAC,cAAc,GAAG,iBAAiB,CAAC;oBACxC,IAAI,CAAC,cAAc,CAAC,iBAAiB,CAAC,CAAC;gBACxC,CAAC;qBAAM,CAAC;oBACP,IAAI,CAAC,mBAAmB,CAAC,iBAAiB,EAAE,mBAAmB,CAAC,CAAC;gBAClE,CAAC;YACF,CAAC;QACF,CAAC;aAAM,IAAI,iBAAiB,IAAI,iBAAiB,KAAK,IAAI,EAAE,CAAC;YAC5D,kFAAkF;YAClF,0EAA0E;YAC1E,IAAI,CAAC,cAAc,GAAG,iBAAiB,CAAC;YACxC,IAAI,CAAC,cAAc,CAAC,iBAAiB,CAAC,CAAC;QACxC,CAAC;aAAM,IAAI,iBAAiB,IAAI,iBAAiB,KAAK,IAAI,CAAC,cAAc,EAAE,CAAC;YAC3E,wEAAwE;YACxE,IAAI,CAAC,mBAAmB,CAAC,iBAAiB,CAAC,CAAC;QAC7C,CAAC;IACF,CAAC;IAED;;;;OAIG;IACH,UAAU;QACT,MAAM,eAAe,GAAG,IAAI,CAAC,YAAY,KAAK,IAAI,CAAC;QAEnD,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACvB,IAAI,CAAC;gBACJ,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,CAAC;YAC7B,CAAC;YAAC,MAAM,CAAC;gBACR,gEAAgE;YACjE,CAAC;QACF,CAAC;QACD,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;QACzB,IAAI,IAAI,CAAC,WAAW,IAAI,eAAe,EAAE,CAAC;YACzC,IAAI,CAAC,oBAAoB,EAAE,CAAC;QAC7B,CAAC;QACD,IAAI,CAAC,sBAAsB,GAAG,KAAK,CAAC;QACpC,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC;QAEzB,wEAAwE;QACxE,8EAA8E;QAC9E,4EAA4E;QAC5E,IAAI,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,IAAI,EAAE,CAAC;YAC5C,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAClC,CAAC;IACF,CAAC;IAED,gFAAgF;IAEhF;;;;;;;;;;;;;OAaG;IACO,mBAAmB,CAAC,KAA8B;QAC3D,IAAI,IAAI,CAAC,gBAAgB,IAAI,CAAC,IAAI,CAAC,WAAW;YAAE,OAAO;QACvD,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;YAAE,OAAO;QAChD,IAAI,KAAK,KAAK,IAAI,CAAC,cAAc;YAAE,OAAO;QAE1C,6EAA6E;QAC7E,4EAA4E;QAC5E,gFAAgF;QAChF,2EAA2E;QAC3E,mFAAmF;QACnF,EAAE;QACF,8EAA8E;QAC9E,+EAA+E;QAC/E,4EAA4E;QAC5E,MAAM,QAAQ,GAAG,IAAI,CAAC,qBAAqB,CAAC,KAAK,CAAC,CAAC;QACnD,IAAI,CAAC,cAAc,GAAG,QAAQ,IAAI,KAAK,CAAC;QACxC,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;IAC5B,CAAC;IAED;;;;;;;;;;;;;;;OAeG;IACO,mBAAmB,CAAC,QAAgB,EAAE,MAAe;QAC9D,IAAI,IAAI,CAAC,gBAAgB,IAAI,CAAC,IAAI,CAAC,WAAW;YAAE,OAAO;QACvD,IAAI,OAAO,QAAQ,KAAK,QAAQ;YAAE,OAAO;QAEzC,MAAM,SAAS,GAAG,gBAAgB,CAAC,QAAQ,CAAC,CAAC;QAC7C,IAAI,SAAS,KAAK,IAAI;YAAE,OAAO,CAAC,yBAAyB;QAEzD,IAAI,SAAS,KAAK,IAAI,CAAC,cAAc;YAAE,OAAO;QAC9C,IAAI,IAAI,CAAC,sBAAsB;YAAE,OAAO;QAExC,IAAI,CAAC,sBAAsB,GAAG,IAAI,CAAC;QAEnC,IAAI,CAAC;YACJ,MAAM,SAAS,GAAG,mBAAmB,CAAC;gBACrC,QAAQ;gBACR,MAAM;gBACN,KAAK,EAAE,CAAC,YAAY,EAAE,EAAE,CACvB,aAAa,CAAC,YAAY,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,gBAAgB,EAAE,OAAO,EAAE,EAAE,CACxE,IAAI,CAAC,aAAa,CAAC,gBAAgB,EAAE,OAAO,CAAC,CAC7C;aACF,CAAC,CAAC;YAEH,IAAI,CAAC,SAAS,EAAE,CAAC;gBAChB,+CAA+C;gBAC/C,uEAAuE;gBACvE,wEAAwE;gBACxE,kEAAkE;gBAClE,EAAE;gBACF,sEAAsE;gBACtE,uEAAuE;gBACvE,qEAAqE;gBACrE,yEAAyE;gBACzE,wEAAwE;gBACxE,iDAAiD;gBACjD,EAAE;gBACF,oEAAoE;gBACpE,kEAAkE;gBAClE,+DAA+D;gBAC/D,MAAM,iBAAiB,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,GAAG,EAAE,CAAC;gBACxD,IAAI,iBAAiB,EAAE,CAAC;oBACvB,MAAM,QAAQ,GAAG,IAAI,CAAC,qBAAqB,CAAC,iBAAiB,CAAC,CAAC;oBAC/D,IAAI,CAAC,cAAc,GAAG,QAAQ,IAAI,iBAAiB,CAAC;oBACpD,IAAI,CAAC,cAAc,CAAC,iBAAiB,CAAC,CAAC;gBACxC,CAAC;gBACD,OAAO;YACR,CAAC;YAED,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;YACjC,IAAI,CAAC,cAAc,GAAG,SAAS,CAAC,QAAQ,CAAC;QAC1C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,0EAA0E;YAC1E,6EAA6E;YAC7E,IAAI,KAAK,YAAY,0BAA0B,EAAE,CAAC;gBACjD,MAAM,KAAK,CAAC;YACb,CAAC;YACD,MAAM,IAAI,eAAe,CAAC,kDAAkD,EAAE;gBAC7E,KAAK,EAAE,KAAK;aACZ,CAAC,CAAC;QACJ,CAAC;gBAAS,CAAC;YACV,IAAI,CAAC,sBAAsB,GAAG,KAAK,CAAC;QACrC,CAAC;IACF,CAAC;IAED,iFAAiF;IAEjF;;;;;;;;;;;;OAYG;IACO,aAAa,CAAC,QAAgB,EAAE,OAAe;QACxD,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC;QACxD,IAAI,CAAC,OAAO;YAAE,OAAO,EAAE,CAAC;QACxB,OAAO,kBAAkB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC9C,CAAC;IAED;;;;;;;;;;;;;;;OAeG;IACO,qBAAqB,CAAC,KAAa;QAC5C,MAAM,WAAW,GAAG,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;QACnE,MAAM,MAAM,GACX,IAAI,CAAC,QAAQ,CAAC,gBAAgB,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAC;QACtF,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAC9D,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;YAAE,OAAO,IAAI,CAAC;QACrD,OAAO,IAAI,CAAC;IACb,CAAC;IAED;;;;;OAKG;IACO,YAAY,CAAC,MAAc;QACpC,OAAO,YAAY,CAAC,MAAM,CAAC,CAAC;IAC7B,CAAC;IASD;;;;;;;;;;;;;;;OAeG;IACO,YAAY,CAAC,QAAgB;QACtC,OAAO,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IACnC,CAAC;IA0BD;;;;;;;;;;;;;;;;;OAiBG;IACO,oBAAoB;QAC7B,OAAO,SAAS,CAAC;IAClB,CAAC;IAED;;;;;;;;;;;;OAYG;IACO,sBAAsB;QAC/B,OAAO,SAAS,CAAC;IAClB,CAAC;CACD;AAED,SAAS,WAAW,KAAI,CAAC;AAEzB,SAAS,kBAAkB,CAC1B,MAAsC,EACtC,OAAuC;IAEvC,IAAI,OAAO,GAAe,WAAW,CAAC;IACtC,MAAM,OAAO,GAAuB;QACnC,KAAK,CAAC,UAA0C;YAC/C,OAAO,GAAG,WAAW,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QAC5C,CAAC;QACD,OAAO;YACN,OAAO,EAAE,CAAC;QACX,CAAC;KACD,CAAC;IAEF,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACtB,OAAO,OAAO,CAAC;AAChB,CAAC"}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import type { Graph } from "@statelyai/graph";
|
|
2
|
+
import type { Signal } from "@xmachines/play-signals";
|
|
3
|
+
import type { PlaySpec } from "@xmachines/play-actor";
|
|
2
4
|
/**
|
|
3
5
|
* Data attached to each node in the machine graph representation.
|
|
4
6
|
* Captures the essential state metadata needed for route extraction and queries.
|
|
@@ -219,6 +221,72 @@ export interface PlayRouteEvent {
|
|
|
219
221
|
readonly match?: unknown;
|
|
220
222
|
[key: string]: unknown;
|
|
221
223
|
}
|
|
224
|
+
/**
|
|
225
|
+
* Minimal actor interface required by `RouterBridgeBase` and all framework router
|
|
226
|
+
* adapters.
|
|
227
|
+
*
|
|
228
|
+
* Using this interface instead of `AbstractActor<AnyActorLogic> & Routable` lets
|
|
229
|
+
* `RouterBridgeBase.actor.send` be typed to accept `PlayRouteEvent` directly —
|
|
230
|
+
* eliminating the unsafe `(actor.send as (e: PlayRouteEvent) => void)` cast that
|
|
231
|
+
* existed when the actor was typed with the weaker `EventObject` constraint.
|
|
232
|
+
*
|
|
233
|
+
* All `AbstractActor` subclasses satisfy this interface structurally because:
|
|
234
|
+
* - `AbstractActor` implements `send(event: TEvent): void` where `TEvent` accepts
|
|
235
|
+
* any `EventObject`, so `PlayRouteEvent` (a subtype) is always accepted.
|
|
236
|
+
* - `Routable` provides `currentRoute` and `initialRoute`.
|
|
237
|
+
*
|
|
238
|
+
* @example
|
|
239
|
+
* ```typescript
|
|
240
|
+
* import type { RoutableActor } from "@xmachines/play-router";
|
|
241
|
+
*
|
|
242
|
+
* class MyBridge extends RouterBridgeBase {
|
|
243
|
+
* constructor(actor: RoutableActor, routeMap: RouteMap) {
|
|
244
|
+
* super(actor, routeMap);
|
|
245
|
+
* }
|
|
246
|
+
* }
|
|
247
|
+
* ```
|
|
248
|
+
*/
|
|
249
|
+
export interface RoutableActor {
|
|
250
|
+
/** TC39 Signal exposing the actor's current URL path (or state ID). */
|
|
251
|
+
readonly currentRoute: Signal.Computed<string | null>;
|
|
252
|
+
/**
|
|
253
|
+
* The route derived from the machine's initial state — fixed at construction.
|
|
254
|
+
* Router bridges compare this against the browser URL to distinguish a deep-link
|
|
255
|
+
* (router wins) from a session restore (actor wins).
|
|
256
|
+
*/
|
|
257
|
+
readonly initialRoute: string | null;
|
|
258
|
+
/** Send a route navigation event to the actor. */
|
|
259
|
+
send(event: PlayRouteEvent): void;
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Full actor shape used by `PlayRouterProvider` components across all framework
|
|
263
|
+
* adapters (`play-solid-router`, `play-tanstack-solid-router`, `play-vue-router`,
|
|
264
|
+
* `play-tanstack-react-router`, `play-react-router`).
|
|
265
|
+
*
|
|
266
|
+
* Extends `RoutableActor` with `currentView` — the provider renders the current
|
|
267
|
+
* view spec in addition to synchronizing routes, so it needs both capabilities.
|
|
268
|
+
*
|
|
269
|
+
* - Use `RoutableActor` when only routing is needed (e.g. `RouterBridgeBase` subclasses,
|
|
270
|
+
* `connectRouter`).
|
|
271
|
+
* - Use `PlayActor` when the component also renders the current view spec
|
|
272
|
+
* (e.g. `PlayRouterProvider` renderer callback parameter, `PlayRenderer`).
|
|
273
|
+
*
|
|
274
|
+
* All `AbstractActor` subclasses that implement both `Routable` and `Viewable`
|
|
275
|
+
* satisfy this interface structurally.
|
|
276
|
+
*
|
|
277
|
+
* @example
|
|
278
|
+
* ```typescript
|
|
279
|
+
* import type { PlayActor } from "@xmachines/play-router";
|
|
280
|
+
*
|
|
281
|
+
* function MyRouterProvider({ actor }: { actor: PlayActor }) {
|
|
282
|
+
* // access actor.currentRoute (routing) and actor.currentView (rendering)
|
|
283
|
+
* }
|
|
284
|
+
* ```
|
|
285
|
+
*/
|
|
286
|
+
export interface PlayActor extends RoutableActor {
|
|
287
|
+
/** TC39 Signal exposing the actor's current view spec, or `null` when inactive. */
|
|
288
|
+
readonly currentView: Signal.State<PlaySpec | null>;
|
|
289
|
+
}
|
|
222
290
|
/**
|
|
223
291
|
* RouterBridge interface for runtime infrastructure adapters
|
|
224
292
|
*
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xmachines/play-router",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.52",
|
|
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.12.0",
|
|
50
|
-
"@xmachines/play": "1.0.0-beta.
|
|
51
|
-
"@xmachines/play-actor": "1.0.0-beta.
|
|
52
|
-
"@xmachines/play-signals": "1.0.0-beta.
|
|
50
|
+
"@xmachines/play": "1.0.0-beta.52",
|
|
51
|
+
"@xmachines/play-actor": "1.0.0-beta.52",
|
|
52
|
+
"@xmachines/play-signals": "1.0.0-beta.52",
|
|
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.
|
|
58
|
-
"@xmachines/shared": "1.0.0-beta.
|
|
57
|
+
"@xmachines/play-xstate": "1.0.0-beta.52",
|
|
58
|
+
"@xmachines/shared": "1.0.0-beta.52",
|
|
59
59
|
"oxfmt": "^0.47.0",
|
|
60
60
|
"oxlint": "^1.62.0",
|
|
61
61
|
"typescript": "^5.9.3 || ^6.0.3",
|
|
@@ -72,5 +72,8 @@
|
|
|
72
72
|
"optional": true
|
|
73
73
|
}
|
|
74
74
|
},
|
|
75
|
+
"engines": {
|
|
76
|
+
"node": ">=22.0.0"
|
|
77
|
+
},
|
|
75
78
|
"_devDependencies_note": "xstate appears in both peerDependencies and devDependencies intentionally. devDependencies provides workspace resolution for local builds and tests. peerDependencies declares the consumer version constraint. Both are pinned to ^5.30.0 to prevent drift. urlpattern-polyfill is an optional peer dependency — consumers on Node < 24 or older browsers install it themselves. devDependencies entry ensures workspace test resolution."
|
|
76
79
|
}
|