@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
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* RouterBridgeBase —
|
|
2
|
+
* RouterBridgeBase — the abstract base class of every framework router adapter
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* -
|
|
7
|
-
* - `
|
|
8
|
-
* - `
|
|
9
|
-
* -
|
|
4
|
+
* The class holds the logic that each router bridge shares, and that is 90% of the
|
|
5
|
+
* code of every bridge:
|
|
6
|
+
* - The TC39 Signal watcher of the direction from the actor to the router
|
|
7
|
+
* - `lastSyncedPath`, for the echo suppression in the direction from the actor to the router
|
|
8
|
+
* - The `isProcessingNavigation` flag, which stops a loop of a guard redirect in `syncActorFromRouter` only
|
|
9
|
+
* - `syncRouterFromActor` and `syncActorFromRouter`, with the read of each URL parameter
|
|
10
|
+
* - The connect and disconnect lifecycle of the RouterBridge protocol
|
|
10
11
|
*
|
|
11
|
-
*
|
|
12
|
-
* - navigateRouter(path):
|
|
13
|
-
* - watchRouterChanges():
|
|
14
|
-
* - unwatchRouterChanges():
|
|
12
|
+
* A subclass implements the 3 abstract methods of its framework only:
|
|
13
|
+
* - navigateRouter(path): how the bridge tells the framework router to navigate
|
|
14
|
+
* - watchRouterChanges(): how the bridge subscribes to each location change of the router
|
|
15
|
+
* - unwatchRouterChanges(): how the bridge cancels that subscription
|
|
15
16
|
*
|
|
16
17
|
* @example
|
|
17
18
|
* ```typescript
|
|
@@ -39,35 +40,35 @@
|
|
|
39
40
|
* }
|
|
40
41
|
* ```
|
|
41
42
|
*
|
|
42
|
-
* @see [Play RFC](../../docs/rfc/play.md) -
|
|
43
|
+
* @see [Play RFC](../../docs/rfc/play.md) - invariant INV-04
|
|
43
44
|
*/
|
|
44
45
|
import { Signal } from "@xmachines/play-signals";
|
|
45
46
|
import type { RoutableActor } from "./types.js";
|
|
46
47
|
import type { RouterBridge } from "./types.js";
|
|
47
48
|
/**
|
|
48
|
-
*
|
|
49
|
-
*
|
|
49
|
+
* The narrow interface of the TC39 Signal watcher. `RouterBridgeBase` uses it to
|
|
50
|
+
* observe each change of `actor.currentRoute`.
|
|
50
51
|
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
* - `watch(signal)` —
|
|
54
|
-
* - `unwatch()` —
|
|
52
|
+
* The interface hides the complete `Signal.subtle.Watcher` surface. It exposes the
|
|
53
|
+
* two operations that `RouterBridgeBase` needs:
|
|
54
|
+
* - `watch(signal)` — it arms the watcher on one signal
|
|
55
|
+
* - `unwatch()` — it stops the watch and frees the resources
|
|
55
56
|
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
57
|
+
* A framework adapter subclass touches this handle never. `RouterBridgeBase` makes
|
|
58
|
+
* it and manages it internally.
|
|
58
59
|
*/
|
|
59
60
|
export interface RouteWatcherHandle {
|
|
60
|
-
/**
|
|
61
|
+
/** Arms the watcher on the given signal. */
|
|
61
62
|
watch(signal: Signal.Computed<string | null>): void;
|
|
62
|
-
/**
|
|
63
|
+
/** Stops the observation and frees the watcher. */
|
|
63
64
|
unwatch(): void;
|
|
64
65
|
}
|
|
65
66
|
/**
|
|
66
|
-
*
|
|
67
|
+
* The abstract base class of every router adapter bridge of `@xmachines`.
|
|
67
68
|
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
69
|
+
* The class implements the RouterBridge protocol, and it holds every part of the
|
|
70
|
+
* bridge logic that the adapters share. A subclass implements the 3 abstract methods
|
|
71
|
+
* that are different in each framework, and it implements nothing more.
|
|
71
72
|
*/
|
|
72
73
|
export declare abstract class RouterBridgeBase implements RouterBridge {
|
|
73
74
|
protected readonly actor: RoutableActor;
|
|
@@ -79,237 +80,254 @@ export declare abstract class RouterBridgeBase implements RouterBridge {
|
|
|
79
80
|
protected hasConnectedOnce: boolean;
|
|
80
81
|
protected lastSyncedPath: string | null;
|
|
81
82
|
/**
|
|
82
|
-
*
|
|
83
|
-
* actor
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
* `
|
|
83
|
+
* The flag guards `syncActorFromRouter` against a re-entrant call from a guard
|
|
84
|
+
* redirect of the actor itself. Such a call has this sequence: the bridge sends to
|
|
85
|
+
* the actor, the signal fires, the bridge pushes to the router, and a second
|
|
86
|
+
* `syncActorFromRouter` call starts before the first one returns.
|
|
87
|
+
*
|
|
88
|
+
* The flag is NOT the echo suppression of the direction from the actor to the
|
|
89
|
+
* router. `lastSyncedPath` does that work alone: the bridge writes it before the
|
|
90
|
+
* `navigateRouter()` call. Therefore each router callback of the same path stops at
|
|
91
|
+
* the `sanitized === lastSyncedPath` test in `syncActorFromRouter`.
|
|
90
92
|
*/
|
|
91
93
|
protected isProcessingNavigation: boolean;
|
|
92
94
|
protected routeWatcher: RouteWatcherHandle | null;
|
|
93
95
|
/**
|
|
94
|
-
* @param actor - A `RoutableActor
|
|
95
|
-
* @param routeMap -
|
|
96
|
-
*
|
|
97
|
-
*
|
|
98
|
-
*
|
|
99
|
-
* `"stateId"
|
|
100
|
-
*
|
|
96
|
+
* @param actor - A `RoutableActor`, with `currentRoute`, `initialRoute`, and `send`.
|
|
97
|
+
* @param routeMap - The route map of both directions, for the resolution between a
|
|
98
|
+
* `stateId` and a `path`. Give `getStateIdByPath` and `getPathByStateId`. A
|
|
99
|
+
* framework adapter usually wraps the result of `createRouteMap(machine)`, or an
|
|
100
|
+
* equivalent value. The key of `getPathByStateId` is the form `"#stateId"` or the
|
|
101
|
+
* bare form `"stateId"`. The bridge tries both forms. Therefore an implementation
|
|
102
|
+
* of your own, for example a plain test object, handles one form only.
|
|
101
103
|
*/
|
|
102
104
|
constructor(actor: RoutableActor, routeMap: {
|
|
103
105
|
getStateIdByPath(path: string): string | null | undefined;
|
|
104
106
|
getPathByStateId(id: string): string | null | undefined;
|
|
105
107
|
});
|
|
106
108
|
/**
|
|
107
|
-
*
|
|
109
|
+
* Connects the router bridge to the Actor.
|
|
108
110
|
*
|
|
109
|
-
*
|
|
110
|
-
* starts
|
|
111
|
+
* The method installs the TC39 Signal watcher of the direction from the actor to the
|
|
112
|
+
* router. It then starts the watch of the router changes, which each framework does
|
|
113
|
+
* in its own way.
|
|
111
114
|
*
|
|
112
|
-
*
|
|
113
|
-
* - `lastSyncedPath`
|
|
114
|
-
* - the actor watcher
|
|
115
|
-
* -
|
|
115
|
+
* The order of these steps is part of the contract of the bridge:
|
|
116
|
+
* - The constructor seeds `lastSyncedPath` from `actor.currentRoute`
|
|
117
|
+
* - The method installs the actor watcher before the router subscriptions of the adapter
|
|
118
|
+
* - The first synchronization then separates a deep link from a restore, with `actor.initialRoute`
|
|
116
119
|
*
|
|
117
|
-
*
|
|
118
|
-
* `getInitialRouterPath()
|
|
120
|
+
* An adapter that needs a different behavior of the first synchronization overrides
|
|
121
|
+
* `getInitialRouterPath()`. It does not change the order of the steps of
|
|
122
|
+
* `connect()`.
|
|
119
123
|
*/
|
|
120
124
|
connect(): void;
|
|
121
125
|
/**
|
|
122
|
-
*
|
|
126
|
+
* Disconnects the router bridge from the Actor.
|
|
123
127
|
*
|
|
124
|
-
*
|
|
128
|
+
* The method stops the watch of the signal, and it removes the router listener of the
|
|
129
|
+
* framework.
|
|
125
130
|
*/
|
|
126
131
|
disconnect(): void;
|
|
127
132
|
/**
|
|
128
|
-
*
|
|
129
|
-
*
|
|
130
|
-
*
|
|
131
|
-
* for
|
|
132
|
-
*
|
|
133
|
-
*
|
|
134
|
-
* or pattern.
|
|
135
|
-
*
|
|
136
|
-
*
|
|
137
|
-
*
|
|
138
|
-
*
|
|
139
|
-
*
|
|
140
|
-
* `sanitized === lastSyncedPath`
|
|
141
|
-
*
|
|
142
|
-
*
|
|
143
|
-
*
|
|
144
|
-
* `syncActorFromRouter
|
|
133
|
+
* Writes the location of the router when the route signal of the actor changes.
|
|
134
|
+
*
|
|
135
|
+
* The method resolves the actor route to a concrete URL path, then it calls
|
|
136
|
+
* navigateRouter() for the navigation of the framework. When it cannot resolve the
|
|
137
|
+
* route, which happens for an unknown stateId and for a parameterized pattern
|
|
138
|
+
* without concrete values, it skips the push completely: `navigateRouter` receives a
|
|
139
|
+
* raw stateId or a pattern never.
|
|
140
|
+
*
|
|
141
|
+
* `lastSyncedPath` does the complete echo suppression, which stops the callback of
|
|
142
|
+
* the router from a send to the actor: the method writes the resolved path to
|
|
143
|
+
* `lastSyncedPath` before the `navigateRouter()` call. Therefore each
|
|
144
|
+
* `syncActorFromRouter` call of the same path stops at the
|
|
145
|
+
* `sanitized === lastSyncedPath` test, and it sends no event. This is correct for a
|
|
146
|
+
* synchronous callback and for an asynchronous callback.
|
|
147
|
+
*
|
|
148
|
+
* The method does NOT set `isProcessingNavigation`. That flag lives inside
|
|
149
|
+
* `syncActorFromRouter`, and it guards against a re-entrant loop of a guard
|
|
150
|
+
* redirect.
|
|
145
151
|
*/
|
|
146
152
|
protected syncRouterFromActor(route: string | null | unknown): void;
|
|
147
153
|
/**
|
|
148
|
-
*
|
|
149
|
-
*
|
|
150
|
-
*
|
|
151
|
-
*
|
|
152
|
-
*
|
|
153
|
-
*
|
|
154
|
-
*
|
|
155
|
-
*
|
|
156
|
-
*
|
|
157
|
-
*
|
|
158
|
-
*
|
|
159
|
-
*
|
|
154
|
+
* Resolves an actor route to its concrete URL path, and pushes that path to the
|
|
155
|
+
* router.
|
|
156
|
+
*
|
|
157
|
+
* lastSyncedPath must hold the concrete path, because the callback of the router
|
|
158
|
+
* fires with the concrete path. The two values therefore match, and
|
|
159
|
+
* syncActorFromRouter stops. A raw stateId in that field, for example "#home", does
|
|
160
|
+
* not match the sanitized path ("/") in the watcher.
|
|
161
|
+
*
|
|
162
|
+
* When resolveNavigationPath returns null, which happens for a parameterized
|
|
163
|
+
* pattern, for a wildcard pattern, and for an unknown id, the method skips the push
|
|
164
|
+
* completely: a push of the raw value writes a stateId, a `:param` pattern, or a
|
|
165
|
+
* literal `*` into the browser URL. The method still writes the raw route to
|
|
166
|
+
* lastSyncedPath. Therefore the dedup guard fires correctly on the next identical
|
|
167
|
+
* value of the signal.
|
|
160
168
|
*/
|
|
161
169
|
private pushResolvedRoute;
|
|
162
170
|
/**
|
|
163
|
-
*
|
|
164
|
-
*
|
|
165
|
-
* **
|
|
166
|
-
* stateId, params, and query.
|
|
167
|
-
*
|
|
168
|
-
*
|
|
169
|
-
* **
|
|
170
|
-
*
|
|
171
|
-
* `navigateRouter(actor.currentRoute.get())`
|
|
172
|
-
* actor state
|
|
173
|
-
* or pushes
|
|
174
|
-
* resolved concrete path
|
|
175
|
-
* callback for that navigation
|
|
176
|
-
* sends no
|
|
171
|
+
* Writes the actor state when the location of the router changes.
|
|
172
|
+
*
|
|
173
|
+
* **A known path:** the method sends a `play.route` event to the actor, with the
|
|
174
|
+
* stateId of the match, the params, and the query. The `isProcessingNavigation` flag
|
|
175
|
+
* stops a circular update.
|
|
176
|
+
*
|
|
177
|
+
* **An unknown path, or a path with no entry in the map:** the method sends NO
|
|
178
|
+
* `play.route` event, and the actor state stays as it is. It corrects the browser URL
|
|
179
|
+
* instead, with a `navigateRouter(actor.currentRoute.get())` call. The URL therefore
|
|
180
|
+
* follows the actor state, also when the user types an invalid path in the address
|
|
181
|
+
* bar, or when the code pushes such a path during a session. The method writes the
|
|
182
|
+
* resolved concrete path to `lastSyncedPath` before the `navigateRouter` call.
|
|
183
|
+
* Therefore the callback of the router for that navigation stops at the guard of the
|
|
184
|
+
* echo suppression, and it sends no false event.
|
|
177
185
|
*/
|
|
178
186
|
protected syncActorFromRouter(pathname: string, search?: string): void;
|
|
179
187
|
/**
|
|
180
|
-
*
|
|
181
|
-
*
|
|
182
|
-
*
|
|
183
|
-
*
|
|
184
|
-
*
|
|
185
|
-
*
|
|
186
|
-
*
|
|
187
|
-
*
|
|
188
|
-
* @param
|
|
189
|
-
* @
|
|
190
|
-
* @
|
|
188
|
+
* Reads the path parameters of a URL, with the URLPattern API.
|
|
189
|
+
*
|
|
190
|
+
* The method reads `globalThis.URLPattern` at run time, because this library imports
|
|
191
|
+
* no polyfill. When `URLPattern` is absent and the route of the match holds a
|
|
192
|
+
* parameterized segment, the method throws a `URLPatternUnavailableError`. A caller
|
|
193
|
+
* must therefore give a polyfill in an environment without the native URLPattern:
|
|
194
|
+
* Node.js < 24, and an older browser.
|
|
195
|
+
*
|
|
196
|
+
* @param pathname - The real URL path, for example '/profile/john'
|
|
197
|
+
* @param stateId - The stateId of the match, for the lookup of the route pattern
|
|
198
|
+
* @returns The path parameters of the read, or an empty object when nothing matches
|
|
199
|
+
* @throws {URLPatternUnavailableError} When URLPattern is absent and the route holds a parameter
|
|
191
200
|
*/
|
|
192
201
|
protected extractParams(pathname: string, stateId: string): Record<string, string>;
|
|
193
202
|
/**
|
|
194
|
-
*
|
|
195
|
-
*
|
|
196
|
-
*
|
|
197
|
-
*
|
|
198
|
-
*
|
|
199
|
-
* - unknown stateId with no route map
|
|
200
|
-
* - parameterized or wildcard pattern
|
|
201
|
-
* concrete
|
|
202
|
-
* -
|
|
203
|
-
*
|
|
204
|
-
*
|
|
205
|
-
*
|
|
206
|
-
* only
|
|
207
|
-
*
|
|
208
|
-
* @param route -
|
|
209
|
-
* @returns
|
|
203
|
+
* Resolves a value of an actor route to a concrete URL path for a navigation.
|
|
204
|
+
*
|
|
205
|
+
* A bridge that receives a raw `actor.currentRoute` value in `navigateRouter` calls
|
|
206
|
+
* this method to convert a stateId, with a `#` prefix or without one, into a path.
|
|
207
|
+
* The method returns `null` when a navigation is not possible:
|
|
208
|
+
* - an unknown stateId, with no entry in the route map
|
|
209
|
+
* - a parameterized pattern or a wildcard pattern, for example `/profile/:id` or
|
|
210
|
+
* `/docs/*`, because no concrete value is available for a real URL
|
|
211
|
+
* - a string that is no path and no known stateId
|
|
212
|
+
*
|
|
213
|
+
* A lookup of a stateId tries the form `"#stateId"` and the bare form `"stateId"`,
|
|
214
|
+
* through `lookupPathByStateId`. Therefore a route map of your own that holds one
|
|
215
|
+
* form only still resolves the path.
|
|
216
|
+
*
|
|
217
|
+
* @param route - The raw value of the actor route: a stateId, a stateId with a `#`, or a concrete path
|
|
218
|
+
* @returns The concrete URL path, or `null` when the bridge must skip the navigation
|
|
210
219
|
*/
|
|
211
220
|
protected resolveNavigationPath(route: string): string | null;
|
|
212
221
|
/**
|
|
213
|
-
*
|
|
214
|
-
*
|
|
215
|
-
*
|
|
216
|
-
* `"stateId"`
|
|
217
|
-
*
|
|
218
|
-
*
|
|
219
|
-
*
|
|
220
|
-
*
|
|
221
|
-
*
|
|
222
|
-
*
|
|
223
|
-
*
|
|
222
|
+
* Returns the path of the route map for a value of an actor route, and it tries both
|
|
223
|
+
* forms of a stateId.
|
|
224
|
+
*
|
|
225
|
+
* The actor can emit `"#stateId"` while a route map of your own holds the bare form
|
|
226
|
+
* `"stateId"`, and also the opposite. `RouteMap` makes the canonical form
|
|
227
|
+
* internally, but the constructor accepts every structural
|
|
228
|
+
* `{ getStateIdByPath, getPathByStateId }` object: a plain test object and a map of
|
|
229
|
+
* one adapter are legal, and the documentation says so. Therefore this method tries
|
|
230
|
+
* both forms: the raw form first, then the form without the `#`, then the form with
|
|
231
|
+
* the `#`.
|
|
232
|
+
*
|
|
233
|
+
* @param route - The raw value of the actor route: a stateId, with a `#` prefix or without one
|
|
234
|
+
* @returns The path of the map, or `null` or `undefined` when no form is registered
|
|
224
235
|
*/
|
|
225
236
|
private lookupPathByStateId;
|
|
226
237
|
/**
|
|
227
|
-
*
|
|
238
|
+
* Reads the query parameters of a URL search string.
|
|
228
239
|
*
|
|
229
|
-
* @param search - URL search string
|
|
230
|
-
* @returns
|
|
240
|
+
* @param search - The URL search string, for example '?tab=security&page=1'
|
|
241
|
+
* @returns The query parameters of the read, or an empty object
|
|
231
242
|
*/
|
|
232
243
|
protected extractQuery(search: string): Record<string, string>;
|
|
233
244
|
/**
|
|
234
|
-
*
|
|
235
|
-
*
|
|
236
|
-
*
|
|
237
|
-
* The
|
|
238
|
-
*
|
|
239
|
-
*
|
|
240
|
-
*
|
|
245
|
+
* The method must start the navigation of the framework router, for example with a
|
|
246
|
+
* router.navigate(path) call.
|
|
247
|
+
*
|
|
248
|
+
* The contract: `path` is always a RESOLVED concrete URL path, for example
|
|
249
|
+
* `"/home"`. The base class resolves each value of an actor route, which includes a
|
|
250
|
+
* stateId such as `"#home"` and a parameterized pattern, with
|
|
251
|
+
* `resolveNavigationPath()` before this call. It skips the push completely when the
|
|
252
|
+
* resolution fails. Therefore an implementation must NOT resolve the value again,
|
|
253
|
+
* and it pushes the value without a change.
|
|
241
254
|
*/
|
|
242
255
|
protected abstract navigateRouter(path: string): void;
|
|
243
256
|
/**
|
|
244
|
-
*
|
|
257
|
+
* Cleans a raw URL pathname of the router, and checks it.
|
|
245
258
|
*
|
|
246
|
-
*
|
|
247
|
-
*
|
|
248
|
-
*
|
|
259
|
+
* The method applies the limit of the path length, which is 2048 characters. It
|
|
260
|
+
* removes a query string and a fragment from the segment of the pathname, and it
|
|
261
|
+
* normalizes each sequence of slashes.
|
|
249
262
|
*
|
|
250
|
-
*
|
|
251
|
-
*
|
|
252
|
-
* MUST call this method before
|
|
253
|
-
* `syncActorFromRouter()` calls
|
|
254
|
-
*
|
|
263
|
+
* An implementation that passes around `syncActorFromRouter()`, for example with a
|
|
264
|
+
* reactive watcher of its framework that receives a route object of a parse before,
|
|
265
|
+
* MUST call this method before it gives the path to a lookup in the route map.
|
|
266
|
+
* `syncActorFromRouter()` calls the method internally. Therefore a bridge that uses
|
|
267
|
+
* that method calls `sanitizePath` never itself.
|
|
255
268
|
*
|
|
256
|
-
* @param pathname -
|
|
257
|
-
* @returns
|
|
269
|
+
* @param pathname - The raw URL pathname of the framework router.
|
|
270
|
+
* @returns The clean pathname, or `null` when the path is invalid or too long.
|
|
258
271
|
*/
|
|
259
272
|
protected sanitizePath(pathname: string): string | null;
|
|
260
273
|
/**
|
|
261
|
-
*
|
|
274
|
+
* Starts the watch of the location changes of the router.
|
|
262
275
|
*
|
|
263
|
-
*
|
|
264
|
-
* for location
|
|
276
|
+
* `connect()` calls this method. The method installs the subscription of the
|
|
277
|
+
* framework for each location change, and it calls syncActorFromRouter() on each
|
|
278
|
+
* change.
|
|
265
279
|
*
|
|
266
|
-
* **
|
|
267
|
-
*
|
|
280
|
+
* **An implementation that calls `syncActorFromRouter`** receives the clean path
|
|
281
|
+
* automatically, and it needs no more work.
|
|
268
282
|
*
|
|
269
|
-
* **
|
|
270
|
-
* which builds the `play.route` event
|
|
271
|
-
* MUST call `this.sanitizePath(path)` and return
|
|
272
|
-
*
|
|
273
|
-
*
|
|
283
|
+
* **An implementation that passes around `syncActorFromRouter`**, for example
|
|
284
|
+
* `VueRouterBridge`, which builds the `play.route` event from the route params of its
|
|
285
|
+
* framework, MUST call `this.sanitizePath(path)` and return at once when that
|
|
286
|
+
* method returns `null`. Without this call, a path that is too long or malformed
|
|
287
|
+
* passes the guards of the length and of the contents, and those guards protect the
|
|
288
|
+
* lookup in the route map.
|
|
274
289
|
*/
|
|
275
290
|
protected abstract watchRouterChanges(): void;
|
|
276
291
|
/**
|
|
277
|
-
*
|
|
292
|
+
* Stops the watch of the location changes of the router.
|
|
278
293
|
*
|
|
279
|
-
*
|
|
294
|
+
* `disconnect()` calls this method. The method removes the subscription of the
|
|
295
|
+
* framework.
|
|
280
296
|
*/
|
|
281
297
|
protected abstract unwatchRouterChanges(): void;
|
|
282
298
|
/**
|
|
283
|
-
*
|
|
284
|
-
*
|
|
285
|
-
*
|
|
286
|
-
* router.subscribe()
|
|
287
|
-
*
|
|
288
|
-
* current location synchronously
|
|
289
|
-
*
|
|
290
|
-
* actor to the correct state
|
|
291
|
-
*
|
|
292
|
-
*
|
|
293
|
-
*
|
|
294
|
-
* - `
|
|
295
|
-
* - `
|
|
296
|
-
*
|
|
297
|
-
*
|
|
298
|
-
*
|
|
299
|
+
* Returns the current pathname of the router at the moment of `connect()`.
|
|
300
|
+
*
|
|
301
|
+
* `connect()` calls this method one time, for the first synchronization from the URL
|
|
302
|
+
* to the actor. router.subscribe() fires on a *later* navigation event only. It does
|
|
303
|
+
* not repeat the location that the router loaded before. A subclass that can read the
|
|
304
|
+
* current location of its router synchronously, for example with
|
|
305
|
+
* `router.state.location.pathname`, overrides this method. A deep link and a direct
|
|
306
|
+
* URL then drive the actor to the correct state, and they leave it not at the default
|
|
307
|
+
* of its machine.
|
|
308
|
+
*
|
|
309
|
+
* The meaning of each return value:
|
|
310
|
+
* - `string` → the router has a current path, and the base `connect()` writes the actor state from the router
|
|
311
|
+
* - `null` → the router is active, but it has no current path yet, and the base `connect()` writes the router from the actor
|
|
312
|
+
* - `undefined` → the adapter does the first synchronization itself, and the base `connect()` does nothing
|
|
313
|
+
*
|
|
314
|
+
* The default value is `undefined`. Therefore a bridge without this hook keeps its
|
|
315
|
+
* earlier behavior.
|
|
299
316
|
*/
|
|
300
317
|
protected getInitialRouterPath(): string | null | undefined;
|
|
301
318
|
/**
|
|
302
|
-
*
|
|
319
|
+
* Returns the current search string of the router at the moment of `connect()`.
|
|
303
320
|
*
|
|
304
|
-
*
|
|
305
|
-
*
|
|
306
|
-
*
|
|
307
|
-
*
|
|
321
|
+
* This method is the pair of `getInitialRouterPath()`. `connect()` calls it one time,
|
|
322
|
+
* to give the query string of the first URL to `syncActorFromRouter()`. It returns
|
|
323
|
+
* `undefined` when the current URL of the router has no search string, and also when
|
|
324
|
+
* the subclass overrides the method not. `syncActorFromRouter` then makes an empty
|
|
325
|
+
* `query: {}` in the event.
|
|
308
326
|
*
|
|
309
|
-
*
|
|
310
|
-
*
|
|
327
|
+
* A subclass that overrides `getInitialRouterPath()` and has a query string
|
|
328
|
+
* overrides this method too.
|
|
311
329
|
*
|
|
312
|
-
* @returns URL search string
|
|
330
|
+
* @returns The URL search string, for example `"?tab=security"`, or `undefined` when it is not available.
|
|
313
331
|
*/
|
|
314
332
|
protected getInitialRouterSearch(): string | undefined;
|
|
315
333
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router-bridge-base.d.ts","sourceRoot":"","sources":["../src/router-bridge-base.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"router-bridge-base.d.ts","sourceRoot":"","sources":["../src/router-bridge-base.ts"],"names":[],"mappings":"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"}
|