@xmachines/play-router 2.0.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +93 -76
- package/dist/base-route-map.d.ts +63 -57
- package/dist/base-route-map.d.ts.map +1 -1
- package/dist/base-route-map.js +65 -59
- package/dist/base-route-map.js.map +1 -1
- package/dist/build-tree.d.ts +13 -12
- package/dist/build-tree.d.ts.map +1 -1
- package/dist/build-tree.js +30 -28
- package/dist/build-tree.js.map +1 -1
- package/dist/create-route-map-from-tree.d.ts +15 -15
- package/dist/create-route-map-from-tree.js +15 -15
- package/dist/create-route-map.d.ts +18 -16
- package/dist/create-route-map.d.ts.map +1 -1
- package/dist/create-route-map.js +10 -9
- package/dist/create-route-map.js.map +1 -1
- package/dist/errors.d.ts +40 -38
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +40 -38
- package/dist/errors.js.map +1 -1
- package/dist/extract-routes.d.ts +8 -7
- package/dist/extract-routes.d.ts.map +1 -1
- package/dist/extract-routes.js +31 -27
- package/dist/extract-routes.js.map +1 -1
- package/dist/find-route.d.ts +18 -15
- package/dist/find-route.d.ts.map +1 -1
- package/dist/find-route.js +42 -38
- package/dist/find-route.js.map +1 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -10
- package/dist/index.js.map +1 -1
- package/dist/machine-to-graph.d.ts +3 -2
- package/dist/machine-to-graph.d.ts.map +1 -1
- package/dist/machine-to-graph.js +20 -19
- package/dist/machine-to-graph.js.map +1 -1
- package/dist/query.d.ts +39 -37
- package/dist/query.d.ts.map +1 -1
- package/dist/query.js +62 -57
- package/dist/query.js.map +1 -1
- package/dist/router-bridge-base.d.ts +208 -190
- package/dist/router-bridge-base.d.ts.map +1 -1
- package/dist/router-bridge-base.js +235 -211
- package/dist/router-bridge-base.js.map +1 -1
- package/dist/router-sync.d.ts +41 -35
- package/dist/router-sync.d.ts.map +1 -1
- package/dist/router-sync.js +53 -45
- package/dist/router-sync.js.map +1 -1
- package/dist/types.d.ts +165 -147
- package/dist/types.d.ts.map +1 -1
- package/dist/url-pattern-utils.d.ts +53 -47
- package/dist/url-pattern-utils.d.ts.map +1 -1
- package/dist/url-pattern-utils.js +61 -55
- package/dist/url-pattern-utils.js.map +1 -1
- package/dist/validate-routes.d.ts +32 -31
- package/dist/validate-routes.d.ts.map +1 -1
- package/dist/validate-routes.js +30 -29
- package/dist/validate-routes.js.map +1 -1
- package/package.json +6 -5
package/dist/types.d.ts
CHANGED
|
@@ -2,127 +2,133 @@ import type { Graph } from "@statelyai/graph";
|
|
|
2
2
|
import type { Signal } from "@xmachines/play-signals";
|
|
3
3
|
import type { PlaySpec } from "@xmachines/play-actor";
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
6
|
-
*
|
|
5
|
+
* The data on each node of the graph that represents the machine.
|
|
6
|
+
* It holds the state metadata that the route extraction and the queries need.
|
|
7
7
|
*/
|
|
8
8
|
export interface MachineNodeData {
|
|
9
|
-
/** XState state ID
|
|
9
|
+
/** The XState state ID, for example "test.dashboard.overview" */
|
|
10
10
|
stateId: string;
|
|
11
|
-
/**
|
|
11
|
+
/** The state type of XState */
|
|
12
12
|
type: "atomic" | "compound" | "parallel" | "final" | "history";
|
|
13
|
-
/**
|
|
13
|
+
/** The original meta object of the state */
|
|
14
14
|
meta?: Record<string, unknown>;
|
|
15
|
-
/**
|
|
15
|
+
/** The route path of meta.route, in its string form */
|
|
16
16
|
route?: string;
|
|
17
17
|
}
|
|
18
18
|
/**
|
|
19
|
-
*
|
|
20
|
-
*
|
|
19
|
+
* The data on each edge of the graph that represents the machine.
|
|
20
|
+
* It holds the event of the transition and the information of its guard.
|
|
21
21
|
*/
|
|
22
22
|
export interface MachineEdgeData {
|
|
23
|
-
/** The event type that
|
|
23
|
+
/** The event type that starts this transition */
|
|
24
24
|
eventType: string;
|
|
25
|
-
/**
|
|
25
|
+
/**
|
|
26
|
+
* The guard as a string, when a guard is present
|
|
27
|
+
*
|
|
28
|
+
* @deprecated Will be removed in the next major.
|
|
29
|
+
*/
|
|
26
30
|
guardType?: string;
|
|
27
31
|
}
|
|
28
32
|
/**
|
|
29
|
-
*
|
|
33
|
+
* The type definitions of the routing protocol of @xmachines/play-router
|
|
30
34
|
*
|
|
31
|
-
* PlayRouteEvent, RouterBridge, RouteMetadata, and RouteObject
|
|
32
|
-
*
|
|
35
|
+
* PlayRouteEvent, RouterBridge, RouteMetadata, and RouteObject are here. The routing
|
|
36
|
+
* therefore stays separate from the base event protocol of @xmachines/play.
|
|
33
37
|
*/
|
|
34
38
|
/**
|
|
35
|
-
*
|
|
39
|
+
* A route object, with more metadata.
|
|
36
40
|
*/
|
|
37
41
|
export interface RouteObject {
|
|
38
|
-
/**
|
|
42
|
+
/** The template of the route path, for example '/user/:id' */
|
|
39
43
|
path: string;
|
|
40
|
-
/**
|
|
44
|
+
/** The additional metadata of the route: a title, a breadcrumb, and so on */
|
|
41
45
|
[key: string]: unknown;
|
|
42
46
|
}
|
|
43
47
|
/**
|
|
44
|
-
*
|
|
48
|
+
* The route metadata of the `meta.route` field of a state machine.
|
|
45
49
|
*/
|
|
46
50
|
export type RouteMetadata = string | RouteObject;
|
|
47
51
|
/**
|
|
48
|
-
*
|
|
52
|
+
* The route information of a state node
|
|
49
53
|
*/
|
|
50
54
|
export interface RouteInfo {
|
|
51
|
-
/**
|
|
55
|
+
/** The identifier of the state: node.id, or path.join('.') */
|
|
52
56
|
stateId: string;
|
|
53
|
-
/**
|
|
57
|
+
/** The segments of the state path, from the root */
|
|
54
58
|
statePath: string[];
|
|
55
|
-
/**
|
|
59
|
+
/** The route path of meta.route */
|
|
56
60
|
routePath: string;
|
|
57
|
-
/**
|
|
61
|
+
/** The route pattern with its parameters, for example /profile/:userId, when routePath holds a parameter */
|
|
58
62
|
pattern?: string;
|
|
59
|
-
/**
|
|
63
|
+
/** It tells you if the route path is absolute, which means that it starts with / */
|
|
60
64
|
isAbsolute: boolean;
|
|
61
65
|
/**
|
|
62
|
-
*
|
|
63
|
-
* true = has meta.route, can receive play.route
|
|
66
|
+
* It tells you if this state has a route, which means that it has a meta.route field.
|
|
67
|
+
* true = it has a meta.route field, and it can receive a play.route event
|
|
64
68
|
*/
|
|
65
69
|
routable: boolean;
|
|
66
|
-
/**
|
|
70
|
+
/** The original route metadata */
|
|
67
71
|
metadata: RouteMetadata;
|
|
68
72
|
}
|
|
69
73
|
/**
|
|
70
|
-
*
|
|
74
|
+
* A node of the route tree. It represents one route
|
|
71
75
|
*/
|
|
72
76
|
export interface RouteNode {
|
|
73
|
-
/**
|
|
77
|
+
/** The unique identifier, which is the state ID */
|
|
74
78
|
id: string;
|
|
75
79
|
/**
|
|
76
|
-
* The raw route path
|
|
77
|
-
* or absolute
|
|
80
|
+
* The raw segment of the route path, as `meta.route` declares it. It is relative,
|
|
81
|
+
* for example `"overview"`, or absolute, for example `"/dashboard"`. Never use it for
|
|
82
|
+
* a match of a URL: use `fullPath` for that.
|
|
78
83
|
*/
|
|
79
84
|
path: string;
|
|
80
85
|
/**
|
|
81
|
-
* The
|
|
82
|
-
* Always use `fullPath` for browser URL
|
|
83
|
-
* `createRouteMapFromTree` and `createRouteMap` both use this field.
|
|
86
|
+
* The complete absolute path from the root, for example `"/dashboard/overview"`.
|
|
87
|
+
* Always use `fullPath` for a match of a browser URL and for the construction of a
|
|
88
|
+
* route map. `createRouteMapFromTree` and `createRouteMap` both use this field.
|
|
84
89
|
*/
|
|
85
90
|
fullPath: string;
|
|
86
|
-
/**
|
|
91
|
+
/** The route pattern with its parameters, for example /profile/:userId, when path holds a parameter */
|
|
87
92
|
pattern?: string;
|
|
88
|
-
/** XState state ID this route
|
|
93
|
+
/** The XState state ID of this route */
|
|
89
94
|
stateId: string;
|
|
90
95
|
/**
|
|
91
|
-
*
|
|
92
|
-
*
|
|
96
|
+
* It tells you if this state has a route, which means that it has a meta.route field.
|
|
97
|
+
* A state with a meta.route field can receive a play.route event
|
|
93
98
|
*/
|
|
94
99
|
routable: boolean;
|
|
95
|
-
/**
|
|
100
|
+
/** The child routes */
|
|
96
101
|
children: RouteNode[];
|
|
97
|
-
/**
|
|
102
|
+
/** The parent route. It is null for the root */
|
|
98
103
|
parent: RouteNode | null;
|
|
99
|
-
/**
|
|
104
|
+
/** The original meta.route metadata */
|
|
100
105
|
metadata: RouteMetadata;
|
|
101
106
|
}
|
|
102
107
|
/**
|
|
103
|
-
*
|
|
108
|
+
* The complete route tree, with its lookup maps
|
|
104
109
|
*
|
|
105
|
-
*
|
|
106
|
-
* - byStateId:
|
|
107
|
-
* - byPath:
|
|
110
|
+
* It gives you the map between a state ID and a URL path, in both directions:
|
|
111
|
+
* - byStateId: it maps each state ID to its route node, for the target of a play.route event
|
|
112
|
+
* - byPath: it maps each URL path to its route node, for the browser navigation
|
|
108
113
|
*/
|
|
109
114
|
export interface RouteTree {
|
|
110
|
-
/**
|
|
115
|
+
/** The root node of the routes */
|
|
111
116
|
root: RouteNode;
|
|
112
117
|
/**
|
|
113
|
-
*
|
|
114
|
-
*
|
|
118
|
+
* The map from a state ID to its route node.
|
|
119
|
+
* It gives you the URL path of a state ID, for the update of the browser URL
|
|
115
120
|
*/
|
|
116
121
|
byStateId: Map<string, RouteNode>;
|
|
117
122
|
/**
|
|
118
|
-
*
|
|
119
|
-
*
|
|
123
|
+
* The map from a complete path to its route node.
|
|
124
|
+
* It gives you the state ID of a URL path, for the target of a play.route event
|
|
120
125
|
*/
|
|
121
126
|
byPath: Map<string, RouteNode>;
|
|
122
127
|
/**
|
|
123
|
-
*
|
|
124
|
-
*
|
|
125
|
-
* and
|
|
128
|
+
* The graph of the state machine, for an advanced query.
|
|
129
|
+
* extractMachineRoutes() fills it. Use it for a query of the hierarchy, for a test of
|
|
130
|
+
* the reachability, and for a navigation that knows the transitions, through the
|
|
131
|
+
* algorithms of @statelyai/graph.
|
|
126
132
|
*
|
|
127
133
|
* @example
|
|
128
134
|
* ```typescript
|
|
@@ -133,31 +139,36 @@ export interface RouteTree {
|
|
|
133
139
|
graph?: Graph<MachineNodeData, MachineEdgeData>;
|
|
134
140
|
}
|
|
135
141
|
/**
|
|
136
|
-
*
|
|
137
|
-
*
|
|
138
|
-
*
|
|
139
|
-
* navigation
|
|
140
|
-
*
|
|
141
|
-
*
|
|
142
|
-
*
|
|
143
|
-
*
|
|
144
|
-
*
|
|
145
|
-
*
|
|
146
|
-
*
|
|
147
|
-
*
|
|
148
|
-
*
|
|
149
|
-
*
|
|
150
|
-
*
|
|
151
|
-
*
|
|
152
|
-
*
|
|
153
|
-
* @param
|
|
154
|
-
* @param
|
|
155
|
-
* @param
|
|
156
|
-
*
|
|
157
|
-
*
|
|
142
|
+
* The routing event, with its parameters and its query
|
|
143
|
+
*
|
|
144
|
+
* This is the one routing event of the complete Play architecture. It supports a
|
|
145
|
+
* navigation that knows the parameters, for example `/profile/:userId`, for a dynamic
|
|
146
|
+
* route segment.
|
|
147
|
+
*
|
|
148
|
+
* **Architectural context:** the event implements **Passive Infrastructure
|
|
149
|
+
* (INV-04)**, because it holds the navigation intent of the user, and the Actor then
|
|
150
|
+
* evaluates that intent with its guards. The infrastructure makes a request with a
|
|
151
|
+
* `play.route` event, and the Actor decides with a transition of its state machine.
|
|
152
|
+
*
|
|
153
|
+
* **The flow of a browser navigation:**
|
|
154
|
+
* 1. The browser fires `popstate`
|
|
155
|
+
* 2. The router adapter resolves the URL to a route target
|
|
156
|
+
* 3. The adapter sends a `PlayRouteEvent` to the Actor
|
|
157
|
+
* 4. The Actor checks the transition with the guards of its state machine
|
|
158
|
+
*
|
|
159
|
+
* @param type - The discriminator of the event. It is always "play.route"
|
|
160
|
+
* @param to - The target state ID, with a # prefix, for example '#home' or '#profile'
|
|
161
|
+
* @param params - The route parameters of the path only, from the URL path, for
|
|
162
|
+
* example `{ userId: '123' }` of `/profile/123`. The `query` field holds the query
|
|
163
|
+
* parameters separately.
|
|
164
|
+
* @param query - The query parameters only. They stay separate from the params of the path
|
|
165
|
+
* @param match - The complete match result of URLPattern, for the debug work and for
|
|
166
|
+
* the observability. It is optional
|
|
167
|
+
*
|
|
168
|
+
* @returns Nothing. This interface defines the shape of the event only
|
|
158
169
|
*
|
|
159
170
|
* @example
|
|
160
|
-
*
|
|
171
|
+
* The base event and the routing event together
|
|
161
172
|
* ```typescript
|
|
162
173
|
* import type { PlayEvent } from "@xmachines/play";
|
|
163
174
|
* import type { PlayRouteEvent } from "@xmachines/play-router";
|
|
@@ -166,7 +177,7 @@ export interface RouteTree {
|
|
|
166
177
|
* ```
|
|
167
178
|
*
|
|
168
179
|
* @example
|
|
169
|
-
*
|
|
180
|
+
* A basic navigation to a route
|
|
170
181
|
* ```typescript
|
|
171
182
|
* import type { PlayRouteEvent } from "@xmachines/play-router";
|
|
172
183
|
*
|
|
@@ -178,7 +189,7 @@ export interface RouteTree {
|
|
|
178
189
|
* ```
|
|
179
190
|
*
|
|
180
191
|
* @example
|
|
181
|
-
*
|
|
192
|
+
* A navigation with route parameters
|
|
182
193
|
* ```typescript
|
|
183
194
|
* import type { PlayRouteEvent } from "@xmachines/play-router";
|
|
184
195
|
*
|
|
@@ -188,30 +199,31 @@ export interface RouteTree {
|
|
|
188
199
|
* params: { userId: '123' }
|
|
189
200
|
* };
|
|
190
201
|
* actor.send(event);
|
|
191
|
-
* //
|
|
202
|
+
* // It resolves to the route /profile/123
|
|
192
203
|
* ```
|
|
193
204
|
*
|
|
194
205
|
* @example
|
|
195
|
-
*
|
|
206
|
+
* A navigation with query parameters
|
|
196
207
|
* ```typescript
|
|
197
208
|
* import type { PlayRouteEvent } from "@xmachines/play-router";
|
|
198
209
|
*
|
|
199
210
|
* const event: PlayRouteEvent = {
|
|
200
211
|
* type: 'play.route',
|
|
201
212
|
* to: '#settings',
|
|
202
|
-
* params: { section: 'profile' }, //
|
|
203
|
-
* query: { tab: 'security' } //
|
|
213
|
+
* params: { section: 'profile' }, // a route parameter of the path only
|
|
214
|
+
* query: { tab: 'security' } // the query only
|
|
204
215
|
* };
|
|
205
216
|
* actor.send(event);
|
|
206
|
-
* //
|
|
217
|
+
* // It resolves to the route /settings/profile?tab=security
|
|
207
218
|
* ```
|
|
208
219
|
*
|
|
209
220
|
* @see [Play RFC](../../docs/rfc/play.md)
|
|
210
221
|
*
|
|
211
222
|
* @remarks
|
|
212
|
-
* Use `play.route` when you need
|
|
213
|
-
* config pattern on your state machine
|
|
214
|
-
* URLPatternResult for advanced use
|
|
223
|
+
* Use `play.route` when you need a navigation that knows the parameters, with the
|
|
224
|
+
* `route: {}` config pattern on the nodes of your state machine. The `match` field
|
|
225
|
+
* gives you the complete URLPatternResult, for an advanced use such as a debug or an
|
|
226
|
+
* analysis of the pattern.
|
|
215
227
|
*/
|
|
216
228
|
export interface PlayRouteEvent {
|
|
217
229
|
readonly type: "play.route";
|
|
@@ -222,18 +234,19 @@ export interface PlayRouteEvent {
|
|
|
222
234
|
[key: string]: unknown;
|
|
223
235
|
}
|
|
224
236
|
/**
|
|
225
|
-
*
|
|
226
|
-
*
|
|
237
|
+
* The minimal actor interface that `RouterBridgeBase` and every framework router
|
|
238
|
+
* adapter require.
|
|
227
239
|
*
|
|
228
|
-
*
|
|
229
|
-
* `RouterBridgeBase.actor.send`
|
|
230
|
-
*
|
|
231
|
-
*
|
|
240
|
+
* This interface, and not `AbstractActor<AnyActorLogic> & Routable`, gives
|
|
241
|
+
* `RouterBridgeBase.actor.send` the type that accepts a `PlayRouteEvent` directly.
|
|
242
|
+
* It therefore removes the unsafe cast `(actor.send as (e: PlayRouteEvent) => void)`,
|
|
243
|
+
* which the weaker `EventObject` constraint of the actor type needed before.
|
|
232
244
|
*
|
|
233
|
-
*
|
|
234
|
-
*
|
|
235
|
-
*
|
|
236
|
-
*
|
|
245
|
+
* Every `AbstractActor` subclass satisfies this interface structurally, for two
|
|
246
|
+
* reasons:
|
|
247
|
+
* - `AbstractActor` implements `send(event: TEvent): void`, and `TEvent` accepts each
|
|
248
|
+
* `EventObject`. Therefore it always accepts a `PlayRouteEvent`, which is a subtype.
|
|
249
|
+
* - `Routable` gives `currentRoute` and `initialRoute`.
|
|
237
250
|
*
|
|
238
251
|
* @example
|
|
239
252
|
* ```typescript
|
|
@@ -247,59 +260,63 @@ export interface PlayRouteEvent {
|
|
|
247
260
|
* ```
|
|
248
261
|
*/
|
|
249
262
|
export interface RoutableActor {
|
|
250
|
-
/** TC39 Signal
|
|
263
|
+
/** The TC39 Signal of the current URL path of the actor, or of its state ID. */
|
|
251
264
|
readonly currentRoute: Signal.Computed<string | null>;
|
|
252
265
|
/**
|
|
253
|
-
* The route
|
|
254
|
-
*
|
|
255
|
-
*
|
|
266
|
+
* The route of the initial state of the machine. The constructor fixes it.
|
|
267
|
+
* A router bridge compares it with the browser URL. It therefore separates a deep
|
|
268
|
+
* link, where the router wins, from a restore of a session, where the actor wins.
|
|
256
269
|
*/
|
|
257
270
|
readonly initialRoute: string | null;
|
|
258
|
-
/**
|
|
271
|
+
/** Sends a route navigation event to the actor. */
|
|
259
272
|
send(event: PlayRouteEvent): void;
|
|
260
273
|
}
|
|
261
274
|
/**
|
|
262
|
-
*
|
|
263
|
-
*
|
|
264
|
-
*
|
|
275
|
+
* The complete actor shape of the `PlayRouterProvider` component of each framework
|
|
276
|
+
* adapter: `play-solid-router`, `play-vue-router`, `play-react-router`, and each
|
|
277
|
+
* adapter on the shared framework router bridge bases.
|
|
265
278
|
*
|
|
266
|
-
*
|
|
267
|
-
* view spec
|
|
279
|
+
* The shape extends `RoutableActor` with `currentView`, because the provider renders
|
|
280
|
+
* the current view spec and also keeps the routes in step. It therefore needs both
|
|
281
|
+
* capabilities.
|
|
268
282
|
*
|
|
269
|
-
* - Use `RoutableActor` when
|
|
270
|
-
* `connectRouter
|
|
271
|
-
* - Use `PlayActor` when the component also renders the current view spec
|
|
272
|
-
*
|
|
283
|
+
* - Use `RoutableActor` when you need the routing alone, for example in a
|
|
284
|
+
* `RouterBridgeBase` subclass, or in `connectRouter`.
|
|
285
|
+
* - Use `PlayActor` when the component also renders the current view spec, for
|
|
286
|
+
* example for the renderer callback parameter of `PlayRouterProvider`, and in
|
|
287
|
+
* `PlayRenderer`.
|
|
273
288
|
*
|
|
274
|
-
*
|
|
275
|
-
*
|
|
289
|
+
* Every `AbstractActor` subclass that implements both `Routable` and `Viewable`
|
|
290
|
+
* satisfies this interface structurally.
|
|
276
291
|
*
|
|
277
292
|
* @example
|
|
278
293
|
* ```typescript
|
|
279
294
|
* import type { PlayActor } from "@xmachines/play-router";
|
|
280
295
|
*
|
|
281
296
|
* function MyRouterProvider({ actor }: { actor: PlayActor }) {
|
|
282
|
-
* //
|
|
297
|
+
* // it reads actor.currentRoute for the routing, and actor.currentView for the render
|
|
283
298
|
* }
|
|
284
299
|
* ```
|
|
285
300
|
*/
|
|
286
301
|
export interface PlayActor extends RoutableActor {
|
|
287
|
-
/** TC39 Signal
|
|
302
|
+
/** The TC39 Signal of the current view spec of the actor, or `null` when no view is active. */
|
|
288
303
|
readonly currentView: Signal.State<PlaySpec | null>;
|
|
289
304
|
}
|
|
290
305
|
/**
|
|
291
|
-
* RouterBridge interface
|
|
306
|
+
* The RouterBridge interface of a runtime infrastructure adapter
|
|
292
307
|
*
|
|
293
|
-
*
|
|
294
|
-
*
|
|
295
|
-
*
|
|
308
|
+
* The interface defines the connection of the lifecycle between the infrastructure,
|
|
309
|
+
* for example a framework router, and the Actor. The infrastructure builds a "bridge"
|
|
310
|
+
* to the Actor: it observes the signals of the Actor, and it manages its own
|
|
311
|
+
* lifecycle accordingly.
|
|
296
312
|
*
|
|
297
|
-
* **Architectural
|
|
298
|
-
*
|
|
299
|
-
*
|
|
313
|
+
* **Architectural context:** the interface implements **Passive Infrastructure
|
|
314
|
+
* (INV-04)**, because it gives an observation in one direction. The infrastructure
|
|
315
|
+
* connects to observe the signals of the Actor (currentRoute, currentView, and
|
|
316
|
+
* state), and it reflects each change. It makes no decision about the state.
|
|
300
317
|
*
|
|
301
318
|
* @example
|
|
302
|
-
*
|
|
319
|
+
* The implementation of a framework router bridge
|
|
303
320
|
* ```typescript
|
|
304
321
|
* import type { RouterBridge } from "@xmachines/play-router";
|
|
305
322
|
* import { Signal } from "@xmachines/play-signals";
|
|
@@ -308,7 +325,7 @@ export interface PlayActor extends RoutableActor {
|
|
|
308
325
|
* private watcher: Signal.Watcher | null = null;
|
|
309
326
|
*
|
|
310
327
|
* async connect(): Promise<void> {
|
|
311
|
-
* // Start
|
|
328
|
+
* // Start the observation of the actor.currentRoute signal
|
|
312
329
|
* this.watcher = new Signal.subtle.Watcher(() => {
|
|
313
330
|
* const route = actor.currentRoute.get();
|
|
314
331
|
* if (route) router.navigate(route);
|
|
@@ -317,62 +334,63 @@ export interface PlayActor extends RoutableActor {
|
|
|
317
334
|
* }
|
|
318
335
|
*
|
|
319
336
|
* async disconnect(): Promise<void> {
|
|
320
|
-
* // Stop
|
|
337
|
+
* // Stop the observation, and clean the watchers up
|
|
321
338
|
* this.watcher?.unwatch(actor.currentRoute);
|
|
322
339
|
* this.watcher = null;
|
|
323
340
|
* }
|
|
324
341
|
* }
|
|
325
342
|
* ```
|
|
326
343
|
*
|
|
327
|
-
* @see [Play RFC](../../docs/rfc/play.md) -
|
|
344
|
+
* @see [Play RFC](../../docs/rfc/play.md) - invariant INV-04
|
|
328
345
|
*/
|
|
329
346
|
export interface RouterBridge {
|
|
330
347
|
/**
|
|
331
|
-
*
|
|
348
|
+
* Connects the router bridge to the Actor
|
|
332
349
|
*
|
|
333
|
-
*
|
|
334
|
-
*
|
|
350
|
+
* The infrastructure calls it when it must start the observation of the Actor
|
|
351
|
+
* signals, and when it must bring its own state, for example the browser URL, in line
|
|
352
|
+
* with the Actor state.
|
|
335
353
|
*
|
|
336
|
-
* @returns
|
|
354
|
+
* @returns The promise that resolves after the connection, or void for a synchronous connection
|
|
337
355
|
*
|
|
338
356
|
* @example
|
|
339
357
|
* ```typescript
|
|
340
358
|
* const bridge: RouterBridge = createBridge(actor, router);
|
|
341
359
|
* await bridge.connect();
|
|
342
|
-
* //
|
|
360
|
+
* // The bridge observes the actor.currentRoute signal now
|
|
343
361
|
* ```
|
|
344
362
|
*/
|
|
345
363
|
connect(): void | Promise<void>;
|
|
346
364
|
/**
|
|
347
|
-
*
|
|
365
|
+
* Disconnects the router bridge from the Actor
|
|
348
366
|
*
|
|
349
|
-
*
|
|
350
|
-
*
|
|
367
|
+
* The infrastructure calls it when it must stop the observation and free its
|
|
368
|
+
* resources, for example a signal watcher and an event listener.
|
|
351
369
|
*
|
|
352
|
-
* @returns
|
|
370
|
+
* @returns The promise that resolves after the disconnection, or void for a synchronous disconnection
|
|
353
371
|
*
|
|
354
372
|
* @example
|
|
355
373
|
* ```typescript
|
|
356
374
|
* await bridge.disconnect();
|
|
357
|
-
* //
|
|
375
|
+
* // The bridge stopped its observation, and it freed its resources
|
|
358
376
|
* ```
|
|
359
377
|
*/
|
|
360
378
|
disconnect(): void | Promise<void>;
|
|
361
379
|
}
|
|
362
380
|
/**
|
|
363
|
-
*
|
|
364
|
-
*
|
|
365
|
-
* the global `window` when
|
|
381
|
+
* The minimal window interface of an adapter that subscribes to a DOM event, for
|
|
382
|
+
* example to `hashchange`. You can inject it for SSR and for a test: give a mock in
|
|
383
|
+
* place of the global `window` when no DOM is available.
|
|
366
384
|
*
|
|
367
|
-
*
|
|
368
|
-
* the DOM lib.
|
|
385
|
+
* The definition is structural, and it holds no reference to `Window`. This package
|
|
386
|
+
* therefore compiles without the DOM lib.
|
|
369
387
|
*
|
|
370
388
|
* @example
|
|
371
389
|
* ```typescript
|
|
372
|
-
* //
|
|
390
|
+
* // The normal use — the global window, which is the default
|
|
373
391
|
* connectRouter({ actor, routeMap });
|
|
374
392
|
*
|
|
375
|
-
* // SSR
|
|
393
|
+
* // SSR or a test — an injected mock
|
|
376
394
|
* const mockWin: WindowLike = { addEventListener: vi.fn(), removeEventListener: vi.fn() };
|
|
377
395
|
* connectRouter({ actor, routeMap, window: mockWin });
|
|
378
396
|
* ```
|
|
@@ -382,16 +400,16 @@ export interface WindowLike {
|
|
|
382
400
|
removeEventListener(type: string, listener: (event: Event) => void): void;
|
|
383
401
|
}
|
|
384
402
|
/**
|
|
385
|
-
*
|
|
386
|
-
* `connect()
|
|
387
|
-
* global `location` when
|
|
403
|
+
* The minimal location interface of an adapter that reads the current URL at the
|
|
404
|
+
* moment of `connect()`. You can inject it for SSR and for a test: give a mock in
|
|
405
|
+
* place of the global `location` when no DOM is available.
|
|
388
406
|
*
|
|
389
|
-
*
|
|
390
|
-
* the DOM lib.
|
|
407
|
+
* The definition is structural, and it holds no reference to `Location`. This package
|
|
408
|
+
* therefore compiles without the DOM lib.
|
|
391
409
|
*
|
|
392
410
|
* @example
|
|
393
411
|
* ```typescript
|
|
394
|
-
* // SSR
|
|
412
|
+
* // SSR or a test — an injected mock
|
|
395
413
|
* const mockLoc: LocationLike = { pathname: "/dashboard", search: "?tab=posts" };
|
|
396
414
|
* connectRouter({ actor, routeMap, location: mockLoc });
|
|
397
415
|
* ```
|
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;AAC9C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEtD;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC/B,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|