@xmachines/play-router 2.1.0 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/README.md +270 -11
  2. package/dist/base-path.d.ts +209 -0
  3. package/dist/base-path.d.ts.map +1 -0
  4. package/dist/base-path.js +418 -0
  5. package/dist/base-path.js.map +1 -0
  6. package/dist/base-route-map.d.ts.map +1 -1
  7. package/dist/base-route-map.js +5 -0
  8. package/dist/base-route-map.js.map +1 -1
  9. package/dist/errors.d.ts +87 -4
  10. package/dist/errors.d.ts.map +1 -1
  11. package/dist/errors.js +97 -4
  12. package/dist/errors.js.map +1 -1
  13. package/dist/framework-params.d.ts +144 -0
  14. package/dist/framework-params.d.ts.map +1 -0
  15. package/dist/framework-params.js +291 -0
  16. package/dist/framework-params.js.map +1 -0
  17. package/dist/index.d.ts +7 -2
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +13 -1
  20. package/dist/index.js.map +1 -1
  21. package/dist/provider-lifecycle.d.ts +179 -0
  22. package/dist/provider-lifecycle.d.ts.map +1 -0
  23. package/dist/provider-lifecycle.js +153 -0
  24. package/dist/provider-lifecycle.js.map +1 -0
  25. package/dist/query.d.ts +49 -0
  26. package/dist/query.d.ts.map +1 -1
  27. package/dist/query.js +59 -0
  28. package/dist/query.js.map +1 -1
  29. package/dist/router-bridge-base.d.ts +353 -15
  30. package/dist/router-bridge-base.d.ts.map +1 -1
  31. package/dist/router-bridge-base.js +998 -83
  32. package/dist/router-bridge-base.js.map +1 -1
  33. package/dist/types.d.ts +44 -0
  34. package/dist/types.d.ts.map +1 -1
  35. package/dist/url-pattern-utils.d.ts +0 -30
  36. package/dist/url-pattern-utils.d.ts.map +1 -1
  37. package/dist/url-pattern-utils.js +52 -1
  38. package/dist/url-pattern-utils.js.map +1 -1
  39. package/package.json +4 -4
package/dist/errors.js CHANGED
@@ -153,13 +153,20 @@ export class UnknownStateTypeError extends PlayError {
153
153
  }
154
154
  }
155
155
  /**
156
- * The `RouteMap` constructor throws this error when `URLPattern` cannot compile the
157
- * string of a route pattern. The `pattern` field holds the string in question, and
158
- * `cause` holds the original error of the `URLPattern` constructor.
156
+ * The library throws this error when `URLPattern` cannot compile the string of a route
157
+ * pattern. The `pattern` field holds the string in question, and `cause` holds the
158
+ * original error of the `URLPattern` constructor.
159
+ *
160
+ * Every compilation reports through this error, so `extractRouteParams` raises it for a
161
+ * pattern that no `RouteMap` ever held, and not a bare `TypeError`.
159
162
  *
160
163
  * The common causes:
161
164
  * - A parenthesis or a bracket without its pair in the string of the pattern
162
165
  * - A character that a URL pathname pattern does not permit
166
+ * - Two params of one pattern that land on the same URLPattern group. A name with a
167
+ * hyphen compiles with an underscore, so `:cat-id` and `:cat_id` are one group. The
168
+ * message names the two params and the group, and `cause` is absent: the library
169
+ * refuses the pattern before URLPattern sees it.
163
170
  *
164
171
  * **Error code:** `PLAY_ROUTE_MAP_INVALID_PATTERN`
165
172
  *
@@ -179,10 +186,96 @@ export class UnknownStateTypeError extends PlayError {
179
186
  export class InvalidRoutePatternError extends PlayError {
180
187
  /** The string of the route pattern. URLPattern could not compile it. */
181
188
  pattern;
189
+ /**
190
+ * @param pattern - The route pattern that URLPattern could not compile.
191
+ * @param options - The standard `cause`, and an optional `reason` that says WHY. Give
192
+ * a reason whenever the library knows it: the pattern alone shows a caller nothing
193
+ * when the fault is a rewrite that the library made, and not the text they wrote.
194
+ */
182
195
  constructor(pattern, options) {
183
- super("RouteMap", "PLAY_ROUTE_MAP_INVALID_PATTERN", `Invalid route pattern: "${pattern}"`, options);
196
+ const reason = options?.reason;
197
+ super("RouteMap", "PLAY_ROUTE_MAP_INVALID_PATTERN", reason
198
+ ? `Invalid route pattern: "${pattern}". ${reason}`
199
+ : `Invalid route pattern: "${pattern}"`, options);
184
200
  this.name = "InvalidRoutePatternError";
185
201
  this.pattern = pattern;
186
202
  }
187
203
  }
204
+ /**
205
+ * Thrown when a `basePath` option resolves to one concrete URL prefix never.
206
+ *
207
+ * A bridge writes a real browser URL from its prefix, so every segment must hold
208
+ * exactly one value. A wildcard segment (`*`), an optional segment (`:section?`), a
209
+ * nameless `:` segment, a query string, and a hash fragment each describe a SET of
210
+ * prefixes instead, or no prefix at all. A `$param` segment is the route-param
211
+ * syntax of TanStack Router: a base path writes a param as `:param`, and it takes
212
+ * the value of that param from `basePathParams`.
213
+ *
214
+ * **How to fix it:** mount on the prefix itself, and let the machine own the rest.
215
+ * For the splat route `/$machineId/play/$` of TanStack, the base path is
216
+ * `"/:machineId/play"` with `basePathParams: { machineId }`.
217
+ *
218
+ * **Error code:** `PLAY_ROUTER_INVALID_BASE_PATH`
219
+ *
220
+ * @example
221
+ * ```typescript
222
+ * import { InvalidBasePathError } from "@xmachines/play-router/errors";
223
+ *
224
+ * try {
225
+ * bridge.setBasePath("/:machineId/play/*");
226
+ * } catch (err) {
227
+ * if (err instanceof InvalidBasePathError) {
228
+ * console.error(`Bad base path: "${err.basePath}"`, err.message);
229
+ * }
230
+ * }
231
+ * ```
232
+ */
233
+ export class InvalidBasePathError extends PlayError {
234
+ /** The `basePath` option of the refusal, exactly as the caller gave it. */
235
+ basePath;
236
+ constructor(basePath, reason) {
237
+ super("resolveBasePath", "PLAY_ROUTER_INVALID_BASE_PATH", `Invalid basePath "${basePath}": ${reason}`);
238
+ this.name = "InvalidBasePathError";
239
+ this.basePath = basePath;
240
+ }
241
+ }
242
+ /**
243
+ * Thrown when a `:param` segment of a `basePath` has no value in `basePathParams`.
244
+ *
245
+ * A base path can be a pattern, so a host keeps one string that mirrors its own
246
+ * route config. The bridge must still resolve that pattern to a concrete prefix,
247
+ * because it writes a real browser URL, and it removes a literal prefix from every
248
+ * inbound location. Every `:param` therefore needs a value.
249
+ *
250
+ * **How to fix it:** give the value that the host resolved already — a loader of
251
+ * TanStack, or a `useParams()` call, holds it — as `basePathParams: { machineId }`.
252
+ * An empty string counts as an absent value, because it would collapse the segment.
253
+ *
254
+ * **Error code:** `PLAY_ROUTER_MISSING_BASE_PATH_PARAM`
255
+ *
256
+ * @example
257
+ * ```typescript
258
+ * import { MissingBasePathParamError } from "@xmachines/play-router/errors";
259
+ *
260
+ * try {
261
+ * connectRouter({ actor, router, routeMap, basePath: "/:machineId/play" });
262
+ * } catch (err) {
263
+ * if (err instanceof MissingBasePathParamError) {
264
+ * console.error(`basePath needs a value for :${err.param}`);
265
+ * }
266
+ * }
267
+ * ```
268
+ */
269
+ export class MissingBasePathParamError extends PlayError {
270
+ /** The name of the `:param` segment without a value, and without its `:`. */
271
+ param;
272
+ /** The `basePath` option that declares the param. */
273
+ basePath;
274
+ constructor(param, basePath) {
275
+ super("resolveBasePath", "PLAY_ROUTER_MISSING_BASE_PATH_PARAM", `basePath "${basePath}" declares ":${param}", but basePathParams has no value for it.`);
276
+ this.name = "MissingBasePathParamError";
277
+ this.param = param;
278
+ this.basePath = basePath;
279
+ }
280
+ }
188
281
  //# sourceMappingURL=errors.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,144 @@
1
+ /**
2
+ * The params of a framework router, reconciled with the pattern of the machine.
3
+ *
4
+ * A framework that parses the params itself — Vue Router and SolidJS Router both do —
5
+ * lets a bridge keep that parse instead of running URLPattern again. The decision that
6
+ * makes it safe is the same in each of them, and the source of the params is the one
7
+ * thing that differs, so the decision lives here and each bridge supplies its source.
8
+ *
9
+ * @see [Multi-router integration](../../docs/examples/multi-router-integration.md)
10
+ */
11
+ /**
12
+ * Reads the names of every `:param` of a route pattern of the route map.
13
+ *
14
+ * @param pattern - A route pattern, for example `/profile/:userId`.
15
+ * @returns The names, in the order that the pattern declares them. A fresh array, because
16
+ * `readPatternParams` caches the one it holds.
17
+ */
18
+ export declare function getPatternParamNames(pattern: string): string[];
19
+ /**
20
+ * The names of every param the pattern REQUIRES, so `:name?` is left out.
21
+ *
22
+ * An optional segment that did not match has no value, and a framework reports none.
23
+ * That is a complete answer and not a partial one, so a MIXED pattern such as
24
+ * `/profile/:userId/:tab?` keeps the parse of the framework when only `:tab` is absent.
25
+ * A caller that counted that absence as a gap would fall back to the URLPattern
26
+ * extraction, which THROWS on a runtime with no URLPattern — for a route the framework
27
+ * had already answered.
28
+ *
29
+ * A pattern whose params are ALL optional reports nothing at all, which reads the same
30
+ * as "the framework matched another route", so {@link pickOwnParams} falls back for it.
31
+ * {@link resolveFrameworkParams} settles that case from the PATH instead, and it needs
32
+ * no URLPattern to do it.
33
+ *
34
+ * @param pattern - A route pattern, for example `/profile/:userId/:tab?`.
35
+ * @returns The required names, in the order that the pattern declares them. A fresh
36
+ * array, because `readPatternParams` caches the one it holds.
37
+ */
38
+ export declare function getRequiredPatternParamNames(pattern: string): string[];
39
+ /**
40
+ * Keeps the entries of `params` whose name the pattern of the machine declares, and
41
+ * only when the result covers EVERY name of that pattern.
42
+ *
43
+ * A complete pick is an answer, and a partial pick is not: a wrapper route of the host
44
+ * can declare a subset of the params of the machine — a tenant segment, for example,
45
+ * but not the document one — and keeping that subset drops the rest from a route that
46
+ * declares them. The caller falls back to its own extraction for `null`.
47
+ *
48
+ * The result has a null prototype, so a param named `__proto__` stays an own key.
49
+ *
50
+ * An OPTIONAL name of the pattern (`:name?`) is covered whether the framework reports
51
+ * it or not: a segment that did not match has no value, and that is a complete answer.
52
+ * At least one declared name must come back, though — a framework that reports none
53
+ * matched another route, and the path may still hold a value that only the fallback
54
+ * reads. A pattern whose params are ALL optional therefore always answers `null` here
55
+ * when the framework reports nothing; {@link resolveFrameworkParams} then reads the PATH,
56
+ * which settles the question without the framework and without URLPattern.
57
+ *
58
+ * @param params - The params of the framework router. {@link cleanFrameworkParams}
59
+ * removes each empty value already, and one that reaches here anyway counts as
60
+ * absent: an empty value says that the segment did not match, and never that the
61
+ * path carries the empty string.
62
+ * @param names - The names that the pattern of the machine declares.
63
+ * @param requiredNames - The names the pattern REQUIRES. The default treats every name
64
+ * as required, so a two-argument call keeps the strict test.
65
+ * @returns The params of the machine, or `null` when the framework covers them not.
66
+ */
67
+ export declare function pickOwnParams(params: Record<string, string>, names: string[], requiredNames?: string[]): Record<string, string> | null;
68
+ /**
69
+ * The params of a framework router, in the shape that {@link pickOwnParams} reads.
70
+ *
71
+ * Every framework reports a param that its own route DECLARES and that the location
72
+ * did not fill: Vue Router gives `undefined` or `""`, and SolidJS Router does the
73
+ * same. Such an entry is not an answer, and a pick that kept it would send an empty
74
+ * value to the actor as though the path carried one. Drop it here instead, one time,
75
+ * because the rule belongs to the decision of {@link resolveFrameworkParams} and not
76
+ * to a bridge: `VueRouterBridge` and `SolidRouterBridge` held one copy each.
77
+ *
78
+ * A value of an array — the splat of a catch-all route of Vue Router — becomes its
79
+ * `String()` form, exactly as a single value does.
80
+ *
81
+ * The result has a null prototype, for the same reason {@link pickOwnParams} gives: a
82
+ * plain `{}` accumulator turns `cleaned["__proto__"] = value` into a write of the
83
+ * PROTOTYPE setter, which drops a string value in silence. `pickOwnParams` then read
84
+ * `Object.hasOwn(params, "__proto__")` as `false`, called the pick incomplete, and fell
85
+ * back to the URLPattern extraction — which THROWS on a runtime with no URLPattern, for
86
+ * a route the framework had answered already.
87
+ *
88
+ * @param params - The raw params of the framework router.
89
+ * @returns The params with no absent value, each one a string.
90
+ */
91
+ export declare function cleanFrameworkParams(params: Record<string, unknown>): Record<string, string>;
92
+ /** What {@link resolveFrameworkParams} needs from the bridge that calls it. */
93
+ export interface FrameworkParamsSource {
94
+ /** The route pattern of the match, from `routeMap.getPathByStateId`. */
95
+ pattern: string | null | undefined;
96
+ /** The resolved prefix of the mount. `""` means that the machine owns the router. */
97
+ basePath: string;
98
+ /**
99
+ * The machine-side path of the location, with the mount prefix already removed.
100
+ *
101
+ * The field is OPTIONAL, so a caller that was written before it keeps its behaviour:
102
+ * the one branch that reads it falls back without it, exactly as it did.
103
+ */
104
+ pathname?: string;
105
+ /** The params of the framework router, read lazily and cleaned of empty values. */
106
+ frameworkParams(): Record<string, string>;
107
+ /** The URLPattern extraction of the base class, read lazily. */
108
+ fallback(): Record<string, string>;
109
+ }
110
+ /**
111
+ * Decides which params describe the route of the machine.
112
+ *
113
+ * The three branches, in the order that they apply:
114
+ *
115
+ * - **The pattern declares no name** — a static path, a bare `*` wildcard, or an
116
+ * unknown stateId. The answer is `{}`. The params of the framework must NOT travel
117
+ * here: under a catch-all they hold the splat of the host, and that value would reach
118
+ * the actor as a param of the machine. This branch also reaches no URLPattern, which
119
+ * matters: the extraction needs the constructor even for a pattern with no parameter,
120
+ * so a delegation would throw on a runtime without the API.
121
+ * - **The bridge sits under a mount** — the framework matched a route of the HOST by
122
+ * construction, because the machine owns the suffix of the path only. Its params
123
+ * therefore describe this pattern never, whatever they are named, and a name that
124
+ * happens to collide carries the value of the host. Read the params of the machine
125
+ * from its own pattern instead.
126
+ * - **The framework covers every REQUIRED name** — it matched the machine route. Keep
127
+ * its parse, together with its decoding. An optional `:name?` that the framework
128
+ * reports not is covered too: a segment that did not match has no value. A gap in a
129
+ * required name falls back, because keeping it would drop a name the route declares.
130
+ * - **The path IS the bare form of the pattern** — every optional segment is absent, so
131
+ * `{}` is the complete answer. The branch reads the path and trusts the framework with
132
+ * nothing, which is what makes it safe under a catch-all of the host, and it calls
133
+ * URLPattern for a location that needs none.
134
+ *
135
+ * None of this decides whether the APPLICATION needs a URLPattern polyfill. A `RouteMap`
136
+ * that holds one parameterized route compiles it in the CONSTRUCTOR, and it throws a
137
+ * `URLPatternUnavailableError` there when the runtime has no URLPattern. The polyfill
138
+ * question is therefore settled at startup: only a route map of static paths alone
139
+ * escapes it. What these branches decide is whether a NAVIGATION calls URLPattern again.
140
+ *
141
+ * @returns The path parameters of the machine route, or `{}`.
142
+ */
143
+ export declare function resolveFrameworkParams({ pattern, basePath, pathname, frameworkParams, fallback, }: FrameworkParamsSource): Record<string, string>;
144
+ //# sourceMappingURL=framework-params.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"framework-params.d.ts","sourceRoot":"","sources":["../src/framework-params.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAUH;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAE9D;AAqCD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,4BAA4B,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAEtE;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,aAAa,CAC5B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC9B,KAAK,EAAE,MAAM,EAAE,EACf,aAAa,GAAE,MAAM,EAAU,GAC7B,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAoC/B;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAc5F;AAkDD,+EAA+E;AAC/E,MAAM,WAAW,qBAAqB;IACrC,wEAAwE;IACxE,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACnC,qFAAqF;IACrF,QAAQ,EAAE,MAAM,CAAC;IACjB;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mFAAmF;IACnF,eAAe,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1C,gEAAgE;IAChE,QAAQ,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACnC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAgB,sBAAsB,CAAC,EACtC,OAAO,EACP,QAAQ,EACR,QAAQ,EACR,eAAe,EACf,QAAQ,GACR,EAAE,qBAAqB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAqBhD"}
@@ -0,0 +1,291 @@
1
+ /**
2
+ * The params of a framework router, reconciled with the pattern of the machine.
3
+ *
4
+ * A framework that parses the params itself — Vue Router and SolidJS Router both do —
5
+ * lets a bridge keep that parse instead of running URLPattern again. The decision that
6
+ * makes it safe is the same in each of them, and the source of the params is the one
7
+ * thing that differs, so the decision lives here and each bridge supplies its source.
8
+ *
9
+ * @see [Multi-router integration](../../docs/examples/multi-router-integration.md)
10
+ */
11
+ /**
12
+ * The expression reads each NAMED parameter of a route pattern of the route map, for
13
+ * example `userId` of `/profile/:userId`, `section` of `/settings/:section?`, and
14
+ * `cat-id` of `/docs/:cat-id`. A `*` wildcard carries no name, and the expression
15
+ * therefore matches it not.
16
+ */
17
+ const PATTERN_PARAM_NAME_RE = /:([A-Za-z_$][A-Za-z0-9_$-]*)(\?)?/g;
18
+ /**
19
+ * Reads the names of every `:param` of a route pattern of the route map.
20
+ *
21
+ * @param pattern - A route pattern, for example `/profile/:userId`.
22
+ * @returns The names, in the order that the pattern declares them. A fresh array, because
23
+ * `readPatternParams` caches the one it holds.
24
+ */
25
+ export function getPatternParamNames(pattern) {
26
+ return [...readPatternParams(pattern).names];
27
+ }
28
+ /**
29
+ * The names of each pattern that this module has read, kept at the module level.
30
+ *
31
+ * {@link resolveFrameworkParams} runs on EVERY navigation, and the answer for one
32
+ * pattern never changes: a pattern is a static string of the route map. The number of
33
+ * the route patterns of the application therefore bounds this cache, exactly as it
34
+ * bounds the compiled-pattern cache of `url-pattern-utils.ts`.
35
+ */
36
+ const patternParamCache = new Map();
37
+ /**
38
+ * Reads the declared names and the REQUIRED names of a pattern in ONE scan.
39
+ *
40
+ * {@link resolveFrameworkParams} needs both lists for every navigation, and two calls
41
+ * walked the pattern two times and allocated two match arrays for one answer. The two
42
+ * exported readers stay, because each one names what a caller asks for.
43
+ *
44
+ * The result is CACHED, and each caller therefore treats the two arrays as read-only.
45
+ */
46
+ function readPatternParams(pattern) {
47
+ const cached = patternParamCache.get(pattern);
48
+ if (cached)
49
+ return cached;
50
+ const names = [];
51
+ const required = [];
52
+ for (const match of pattern.matchAll(PATTERN_PARAM_NAME_RE)) {
53
+ const name = match[1] ?? "";
54
+ names.push(name);
55
+ if (match[2] === undefined)
56
+ required.push(name);
57
+ }
58
+ const read = { names, required };
59
+ patternParamCache.set(pattern, read);
60
+ return read;
61
+ }
62
+ /**
63
+ * The names of every param the pattern REQUIRES, so `:name?` is left out.
64
+ *
65
+ * An optional segment that did not match has no value, and a framework reports none.
66
+ * That is a complete answer and not a partial one, so a MIXED pattern such as
67
+ * `/profile/:userId/:tab?` keeps the parse of the framework when only `:tab` is absent.
68
+ * A caller that counted that absence as a gap would fall back to the URLPattern
69
+ * extraction, which THROWS on a runtime with no URLPattern — for a route the framework
70
+ * had already answered.
71
+ *
72
+ * A pattern whose params are ALL optional reports nothing at all, which reads the same
73
+ * as "the framework matched another route", so {@link pickOwnParams} falls back for it.
74
+ * {@link resolveFrameworkParams} settles that case from the PATH instead, and it needs
75
+ * no URLPattern to do it.
76
+ *
77
+ * @param pattern - A route pattern, for example `/profile/:userId/:tab?`.
78
+ * @returns The required names, in the order that the pattern declares them. A fresh
79
+ * array, because `readPatternParams` caches the one it holds.
80
+ */
81
+ export function getRequiredPatternParamNames(pattern) {
82
+ return [...readPatternParams(pattern).required];
83
+ }
84
+ /**
85
+ * Keeps the entries of `params` whose name the pattern of the machine declares, and
86
+ * only when the result covers EVERY name of that pattern.
87
+ *
88
+ * A complete pick is an answer, and a partial pick is not: a wrapper route of the host
89
+ * can declare a subset of the params of the machine — a tenant segment, for example,
90
+ * but not the document one — and keeping that subset drops the rest from a route that
91
+ * declares them. The caller falls back to its own extraction for `null`.
92
+ *
93
+ * The result has a null prototype, so a param named `__proto__` stays an own key.
94
+ *
95
+ * An OPTIONAL name of the pattern (`:name?`) is covered whether the framework reports
96
+ * it or not: a segment that did not match has no value, and that is a complete answer.
97
+ * At least one declared name must come back, though — a framework that reports none
98
+ * matched another route, and the path may still hold a value that only the fallback
99
+ * reads. A pattern whose params are ALL optional therefore always answers `null` here
100
+ * when the framework reports nothing; {@link resolveFrameworkParams} then reads the PATH,
101
+ * which settles the question without the framework and without URLPattern.
102
+ *
103
+ * @param params - The params of the framework router. {@link cleanFrameworkParams}
104
+ * removes each empty value already, and one that reaches here anyway counts as
105
+ * absent: an empty value says that the segment did not match, and never that the
106
+ * path carries the empty string.
107
+ * @param names - The names that the pattern of the machine declares.
108
+ * @param requiredNames - The names the pattern REQUIRES. The default treats every name
109
+ * as required, so a two-argument call keeps the strict test.
110
+ * @returns The params of the machine, or `null` when the framework covers them not.
111
+ */
112
+ export function pickOwnParams(params, names, requiredNames = names) {
113
+ const required = new Set(requiredNames);
114
+ const picked = Object.create(null);
115
+ for (const name of names) {
116
+ // `Object.hasOwn` first, and not a bare read: this function is exported, so a
117
+ // caller can hand it a plain object, and `params["constructor"]` then walks the
118
+ // prototype chain and answers with a function for a name that the object holds not.
119
+ const value = Object.hasOwn(params, name)
120
+ ? params[name] // nosemgrep: gitlab.eslint.detect-object-injection
121
+ : undefined;
122
+ // An ABSENT value, and an empty one: {@link cleanFrameworkParams} drops both
123
+ // already, and this function is exported, so a caller of its own reaches here with
124
+ // either. A `?? ""` fallback wrote the empty value into the pick instead — the
125
+ // exact value that cleaning exists to remove — and that entry then counted as "the
126
+ // framework matched this route", so the pick won over the fallback that reads the
127
+ // value the PATH carries.
128
+ if (value === undefined || value === null || value === "") {
129
+ if (required.has(name))
130
+ return null;
131
+ continue;
132
+ }
133
+ picked[name] = value; // nosemgrep: gitlab.eslint.detect-object-injection
134
+ }
135
+ // NONE of the declared names came back, so the framework matched another route — a
136
+ // catch-all, in practice — and it knows nothing about this pattern. An empty pick
137
+ // would then drop a value the PATH carries: `/settings/security` against
138
+ // `/settings/:section?` holds "security", and only the fallback reads it. One name
139
+ // present is what says the framework matched this route, and an optional segment that
140
+ // did not match is genuinely absent.
141
+ if (names.length > 0 && Object.keys(picked).length === 0)
142
+ return null;
143
+ // Spread at the boundary: `event.params` reaches a machine of the user, and it was a
144
+ // plain object before this release. A spread creates OWN properties, so a param named
145
+ // "__proto__" stays a key while the value keeps a prototype — `hasOwnProperty` on it
146
+ // therefore answers instead of throwing.
147
+ return { ...picked };
148
+ }
149
+ /**
150
+ * The params of a framework router, in the shape that {@link pickOwnParams} reads.
151
+ *
152
+ * Every framework reports a param that its own route DECLARES and that the location
153
+ * did not fill: Vue Router gives `undefined` or `""`, and SolidJS Router does the
154
+ * same. Such an entry is not an answer, and a pick that kept it would send an empty
155
+ * value to the actor as though the path carried one. Drop it here instead, one time,
156
+ * because the rule belongs to the decision of {@link resolveFrameworkParams} and not
157
+ * to a bridge: `VueRouterBridge` and `SolidRouterBridge` held one copy each.
158
+ *
159
+ * A value of an array — the splat of a catch-all route of Vue Router — becomes its
160
+ * `String()` form, exactly as a single value does.
161
+ *
162
+ * The result has a null prototype, for the same reason {@link pickOwnParams} gives: a
163
+ * plain `{}` accumulator turns `cleaned["__proto__"] = value` into a write of the
164
+ * PROTOTYPE setter, which drops a string value in silence. `pickOwnParams` then read
165
+ * `Object.hasOwn(params, "__proto__")` as `false`, called the pick incomplete, and fell
166
+ * back to the URLPattern extraction — which THROWS on a runtime with no URLPattern, for
167
+ * a route the framework had answered already.
168
+ *
169
+ * @param params - The raw params of the framework router.
170
+ * @returns The params with no absent value, each one a string.
171
+ */
172
+ export function cleanFrameworkParams(params) {
173
+ const cleaned = Object.create(null);
174
+ for (const [name, value] of Object.entries(params)) {
175
+ if (value === undefined || value === null)
176
+ continue;
177
+ // The test runs on the STRING, and not on the raw value: a repeatable segment that
178
+ // the location did not fill comes back as an EMPTY ARRAY from Vue Router, and `[]`
179
+ // is not `""`. A raw test therefore let it through as `String([])`, which is the
180
+ // empty value this function exists to drop — `pickOwnParams` then picked it and the
181
+ // actor received `{ section: "" }` as though the path carried a value.
182
+ const text = String(value);
183
+ if (text === "")
184
+ continue;
185
+ cleaned[name] = text; // nosemgrep: gitlab.eslint.detect-object-injection
186
+ }
187
+ return cleaned;
188
+ }
189
+ /** A segment that is exactly one optional param, for example `:section?`. */
190
+ const OPTIONAL_SEGMENT_RE = /^:[A-Za-z_$][A-Za-z0-9_$-]*\?$/;
191
+ /**
192
+ * True when the path IS the pattern with every optional segment absent.
193
+ *
194
+ * The test reads the PATH, and it trusts the framework with nothing. A pattern whose
195
+ * trailing segments are all optional has a bare form that holds no `:` and no `*` —
196
+ * `/settings/:section?` has the bare form `/settings` — and a path that equals that
197
+ * form can only match the pattern with every optional group absent. No param has a
198
+ * value, so `{}` is the complete answer whatever route the framework matched, and the
199
+ * URLPattern fallback has nothing to add.
200
+ *
201
+ * The function answers `false` for anything it cannot prove:
202
+ *
203
+ * - An optional segment that is NOT trailing. `/a/:b?/c` matches `/a//c` for URLPattern,
204
+ * because the `/` before the group is a literal of its own, so `/a/c` is no bare form.
205
+ * - A remaining segment that holds a `:` or a `*`. A required param has a value that
206
+ * only the fallback reads, and a wildcard matches a path of any length.
207
+ *
208
+ * @param pathname - The machine-side path, with the mount prefix already removed.
209
+ * @param pattern - The route pattern of the machine.
210
+ */
211
+ function pathIsBareForm(pathname, pattern) {
212
+ const segments = pattern.split("/");
213
+ let end = segments.length;
214
+ while (end > 0 && OPTIONAL_SEGMENT_RE.test(segments.at(end - 1) ?? ""))
215
+ end -= 1;
216
+ // Nothing was optional at the end, so the pattern needs a value somewhere.
217
+ if (end === segments.length)
218
+ return false;
219
+ const kept = segments.slice(0, end);
220
+ if (kept.some((segment) => segment.includes(":") || segment.includes("*")))
221
+ return false;
222
+ return trimPath(kept.join("/")) === trimPath(pathname);
223
+ }
224
+ /**
225
+ * One comparable form for a path: no query, no fragment, and no trailing slash.
226
+ *
227
+ * The root stays `"/"`, because a bare pattern of `/:section?` has the bare form `""`
228
+ * and the path of that page is `"/"`.
229
+ */
230
+ function trimPath(path) {
231
+ const cut = path.split(/[?#]/)[0] ?? "";
232
+ const trimmed = cut.length > 1 && cut.endsWith("/") ? cut.slice(0, -1) : cut;
233
+ return trimmed === "" ? "/" : trimmed;
234
+ }
235
+ /**
236
+ * Decides which params describe the route of the machine.
237
+ *
238
+ * The three branches, in the order that they apply:
239
+ *
240
+ * - **The pattern declares no name** — a static path, a bare `*` wildcard, or an
241
+ * unknown stateId. The answer is `{}`. The params of the framework must NOT travel
242
+ * here: under a catch-all they hold the splat of the host, and that value would reach
243
+ * the actor as a param of the machine. This branch also reaches no URLPattern, which
244
+ * matters: the extraction needs the constructor even for a pattern with no parameter,
245
+ * so a delegation would throw on a runtime without the API.
246
+ * - **The bridge sits under a mount** — the framework matched a route of the HOST by
247
+ * construction, because the machine owns the suffix of the path only. Its params
248
+ * therefore describe this pattern never, whatever they are named, and a name that
249
+ * happens to collide carries the value of the host. Read the params of the machine
250
+ * from its own pattern instead.
251
+ * - **The framework covers every REQUIRED name** — it matched the machine route. Keep
252
+ * its parse, together with its decoding. An optional `:name?` that the framework
253
+ * reports not is covered too: a segment that did not match has no value. A gap in a
254
+ * required name falls back, because keeping it would drop a name the route declares.
255
+ * - **The path IS the bare form of the pattern** — every optional segment is absent, so
256
+ * `{}` is the complete answer. The branch reads the path and trusts the framework with
257
+ * nothing, which is what makes it safe under a catch-all of the host, and it calls
258
+ * URLPattern for a location that needs none.
259
+ *
260
+ * None of this decides whether the APPLICATION needs a URLPattern polyfill. A `RouteMap`
261
+ * that holds one parameterized route compiles it in the CONSTRUCTOR, and it throws a
262
+ * `URLPatternUnavailableError` there when the runtime has no URLPattern. The polyfill
263
+ * question is therefore settled at startup: only a route map of static paths alone
264
+ * escapes it. What these branches decide is whether a NAVIGATION calls URLPattern again.
265
+ *
266
+ * @returns The path parameters of the machine route, or `{}`.
267
+ */
268
+ export function resolveFrameworkParams({ pattern, basePath, pathname, frameworkParams, fallback, }) {
269
+ if (!pattern)
270
+ return {};
271
+ // One scan of the pattern, for both lists: this runs on every navigation.
272
+ const { names, required } = readPatternParams(pattern);
273
+ if (names.length === 0)
274
+ return {};
275
+ if (basePath !== "")
276
+ return fallback();
277
+ const picked = pickOwnParams(frameworkParams(), names, required);
278
+ if (picked !== null)
279
+ return picked;
280
+ // The framework reported none of the names. That is ambiguous on its own — it means
281
+ // "the segment is absent" or "another route matched" — and the PATH settles it
282
+ // without the framework and without URLPattern: a path that is the bare form of the
283
+ // pattern fills no optional segment, so `{}` is the complete answer.
284
+ //
285
+ // Only an all-optional pattern reaches this: `pathIsBareForm` refuses a bare form
286
+ // that still holds a `:`, so a missing REQUIRED name still falls back.
287
+ if (pathname !== undefined && pathIsBareForm(pathname, pattern))
288
+ return {};
289
+ return fallback();
290
+ }
291
+ //# sourceMappingURL=framework-params.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"framework-params.js","sourceRoot":"","sources":["../src/framework-params.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH;;;;;GAKG;AACH,MAAM,qBAAqB,GAAG,oCAAoC,CAAC;AAEnE;;;;;;GAMG;AACH,MAAM,UAAU,oBAAoB,CAAC,OAAe;IACnD,OAAO,CAAC,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC;AAC9C,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,iBAAiB,GAAG,IAAI,GAAG,EAAmD,CAAC;AAErF;;;;;;;;GAQG;AACH,SAAS,iBAAiB,CAAC,OAAe;IACzC,MAAM,MAAM,GAAG,iBAAiB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAC9C,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC;IAE1B,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,KAAK,MAAM,KAAK,IAAI,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAC,EAAE,CAAC;QAC7D,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAC5B,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjB,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,SAAS;YAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACjD,CAAC;IACD,MAAM,IAAI,GAAG,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;IACjC,iBAAiB,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IACrC,OAAO,IAAI,CAAC;AACb,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,4BAA4B,CAAC,OAAe;IAC3D,OAAO,CAAC,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,CAAC;AACjD,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAM,UAAU,aAAa,CAC5B,MAA8B,EAC9B,KAAe,EACf,gBAA0B,KAAK;IAE/B,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,aAAa,CAAC,CAAC;IACxC,MAAM,MAAM,GAA2B,MAAM,CAAC,MAAM,CAAC,IAAI,CAA2B,CAAC;IACrF,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QAC1B,8EAA8E;QAC9E,gFAAgF;QAChF,oFAAoF;QACpF,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC;YACxC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,mDAAmD;YAClE,CAAC,CAAC,SAAS,CAAC;QACb,6EAA6E;QAC7E,mFAAmF;QACnF,+EAA+E;QAC/E,mFAAmF;QACnF,kFAAkF;QAClF,0BAA0B;QAC1B,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,EAAE,EAAE,CAAC;YAC3D,IAAI,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC;gBAAE,OAAO,IAAI,CAAC;YACpC,SAAS;QACV,CAAC;QACD,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,CAAC,mDAAmD;IAC1E,CAAC;IAED,mFAAmF;IACnF,kFAAkF;IAClF,yEAAyE;IACzE,mFAAmF;IACnF,sFAAsF;IACtF,qCAAqC;IACrC,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAEtE,qFAAqF;IACrF,sFAAsF;IACtF,qFAAqF;IACrF,yCAAyC;IACzC,OAAO,EAAE,GAAG,MAAM,EAAE,CAAC;AACtB,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,UAAU,oBAAoB,CAAC,MAA+B;IACnE,MAAM,OAAO,GAA2B,MAAM,CAAC,MAAM,CAAC,IAAI,CAA2B,CAAC;IACtF,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QACpD,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI;YAAE,SAAS;QACpD,mFAAmF;QACnF,mFAAmF;QACnF,iFAAiF;QACjF,oFAAoF;QACpF,uEAAuE;QACvE,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;QAC3B,IAAI,IAAI,KAAK,EAAE;YAAE,SAAS;QAC1B,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC,mDAAmD;IAC1E,CAAC;IACD,OAAO,OAAO,CAAC;AAChB,CAAC;AAED,6EAA6E;AAC7E,MAAM,mBAAmB,GAAG,gCAAgC,CAAC;AAE7D;;;;;;;;;;;;;;;;;;;GAmBG;AACH,SAAS,cAAc,CAAC,QAAgB,EAAE,OAAe;IACxD,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACpC,IAAI,GAAG,GAAG,QAAQ,CAAC,MAAM,CAAC;IAC1B,OAAO,GAAG,GAAG,CAAC,IAAI,mBAAmB,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;QAAE,GAAG,IAAI,CAAC,CAAC;IACjF,2EAA2E;IAC3E,IAAI,GAAG,KAAK,QAAQ,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IAE1C,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IACpC,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IAEzF,OAAO,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,QAAQ,CAAC,QAAQ,CAAC,CAAC;AACxD,CAAC;AAED;;;;;GAKG;AACH,SAAS,QAAQ,CAAC,IAAY;IAC7B,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IACxC,MAAM,OAAO,GAAG,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;IAC7E,OAAO,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC;AACvC,CAAC;AAqBD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,MAAM,UAAU,sBAAsB,CAAC,EACtC,OAAO,EACP,QAAQ,EACR,QAAQ,EACR,eAAe,EACf,QAAQ,GACe;IACvB,IAAI,CAAC,OAAO;QAAE,OAAO,EAAE,CAAC;IAExB,0EAA0E;IAC1E,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC;IACvD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAClC,IAAI,QAAQ,KAAK,EAAE;QAAE,OAAO,QAAQ,EAAE,CAAC;IAEvC,MAAM,MAAM,GAAG,aAAa,CAAC,eAAe,EAAE,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC;IACjE,IAAI,MAAM,KAAK,IAAI;QAAE,OAAO,MAAM,CAAC;IAEnC,oFAAoF;IACpF,+EAA+E;IAC/E,oFAAoF;IACpF,qEAAqE;IACrE,EAAE;IACF,kFAAkF;IAClF,uEAAuE;IACvE,IAAI,QAAQ,KAAK,SAAS,IAAI,cAAc,CAAC,QAAQ,EAAE,OAAO,CAAC;QAAE,OAAO,EAAE,CAAC;IAE3E,OAAO,QAAQ,EAAE,CAAC;AACnB,CAAC"}
package/dist/index.d.ts CHANGED
@@ -7,10 +7,15 @@ export { validateRouteFormat, validateStateExists, detectDuplicateRoutes, } from
7
7
  export type { ResolvedRoutePath } from "./validate-routes.js";
8
8
  export { buildRouteTree } from "./build-tree.js";
9
9
  export { extractMachineRoutes } from "./extract-routes.js";
10
- export { getNavigableRoutes, getRoutableRoutes, routeExists, getTransitionReachableRoutes, isRouteReachable, } from "./query.js";
10
+ export { getNavigableRoutes, getRoutableRoutes, routeExists, getRouteMappings, getTransitionReachableRoutes, isRouteReachable, } from "./query.js";
11
+ export { normalizeBasePath, resolveBasePath, stripBasePath, joinBasePath, NO_BASE_PATH, } from "./base-path.js";
12
+ export type { BasePathOptions, ResolvedBasePath } from "./base-path.js";
13
+ export { cleanFrameworkParams, getPatternParamNames, getRequiredPatternParamNames, pickOwnParams, resolveFrameworkParams, type FrameworkParamsSource, } from "./framework-params.js";
14
+ export { isMountableBridge, mountKey, createRouterConnection, openProviderBridge, repointProviderBridge, } from "./provider-lifecycle.js";
15
+ export type { OpenProviderBridgeArgs, PlayRouterBridgeConstructor, PlayRouterProviderBaseProps, RouterConnection, } from "./provider-lifecycle.js";
11
16
  export { machineToGraph } from "./machine-to-graph.js";
12
17
  export type { MachineGraph } from "./machine-to-graph.js";
13
- export type { RouteInfo, RouteNode, RouteTree, RouteObject, RouteMetadata, PlayRouteEvent, RoutableActor, PlayActor, RouterBridge, MachineNodeData, MachineEdgeData, WindowLike, LocationLike, } from "./types.js";
18
+ export type { RouteInfo, RouteNode, RouteTree, RouteObject, RouteMetadata, PlayRouteEvent, RoutableActor, PlayActor, RouterBridge, MountableRouterBridge, MachineNodeData, MachineEdgeData, WindowLike, LocationLike, } from "./types.js";
14
19
  export { RouteMap, type RouteMapping } from "./base-route-map.js";
15
20
  /**
16
21
  * @deprecated Use {@link RouteMapping}. Will be removed in the next major.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAGxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,YAAY,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAGlE,OAAO,EACN,gBAAgB,EAChB,mBAAmB,EACnB,YAAY,EACZ,kBAAkB,GAClB,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EAAE,UAAU,EAAE,0BAA0B,EAAE,MAAM,kBAAkB,CAAC;AAG/E,OAAO,EACN,mBAAmB,EACnB,mBAAmB,EACnB,qBAAqB,GACrB,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EACN,kBAAkB,EAClB,iBAAiB,EACjB,WAAW,EACX,4BAA4B,EAC5B,gBAAgB,GAChB,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,YAAY,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAE1D,YAAY,EACX,SAAS,EACT,SAAS,EACT,SAAS,EACT,WAAW,EACX,aAAa,EACb,cAAc,EACd,aAAa,EACb,SAAS,EACT,YAAY,EACZ,eAAe,EACf,eAAe,EACf,UAAU,EACV,YAAY,GACZ,MAAM,YAAY,CAAC;AAKpB,OAAO,EAAE,QAAQ,EAAE,KAAK,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAElE;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG,YAAY,CAAC;AAI5C,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":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAGxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,YAAY,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAGlE,OAAO,EACN,gBAAgB,EAChB,mBAAmB,EACnB,YAAY,EACZ,kBAAkB,GAClB,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EAAE,UAAU,EAAE,0BAA0B,EAAE,MAAM,kBAAkB,CAAC;AAG/E,OAAO,EACN,mBAAmB,EACnB,mBAAmB,EACnB,qBAAqB,GACrB,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EACN,kBAAkB,EAClB,iBAAiB,EACjB,WAAW,EACX,gBAAgB,EAChB,4BAA4B,EAC5B,gBAAgB,GAChB,MAAM,YAAY,CAAC;AAMpB,OAAO,EACN,iBAAiB,EACjB,eAAe,EACf,aAAa,EACb,YAAY,EACZ,YAAY,GACZ,MAAM,gBAAgB,CAAC;AACxB,YAAY,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAGxE,OAAO,EACN,oBAAoB,EACpB,oBAAoB,EACpB,4BAA4B,EAC5B,aAAa,EACb,sBAAsB,EACtB,KAAK,qBAAqB,GAC1B,MAAM,uBAAuB,CAAC;AAK/B,OAAO,EACN,iBAAiB,EACjB,QAAQ,EACR,sBAAsB,EACtB,kBAAkB,EAClB,qBAAqB,GACrB,MAAM,yBAAyB,CAAC;AACjC,YAAY,EACX,sBAAsB,EACtB,2BAA2B,EAC3B,2BAA2B,EAC3B,gBAAgB,GAChB,MAAM,yBAAyB,CAAC;AAGjC,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,qBAAqB,EACrB,eAAe,EACf,eAAe,EACf,UAAU,EACV,YAAY,GACZ,MAAM,YAAY,CAAC;AAKpB,OAAO,EAAE,QAAQ,EAAE,KAAK,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAElE;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG,YAAY,CAAC;AAI5C,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
@@ -6,7 +6,19 @@ export { sanitizePathname, buildPlayRouteEvent, extractQuery, extractRouteParams
6
6
  export { validateRouteFormat, validateStateExists, detectDuplicateRoutes, } from "./validate-routes.js";
7
7
  export { buildRouteTree } from "./build-tree.js";
8
8
  export { extractMachineRoutes } from "./extract-routes.js";
9
- export { getNavigableRoutes, getRoutableRoutes, routeExists, getTransitionReachableRoutes, isRouteReachable, } from "./query.js";
9
+ export { getNavigableRoutes, getRoutableRoutes, routeExists, getRouteMappings, getTransitionReachableRoutes, isRouteReachable, } from "./query.js";
10
+ // The base-path mount — it lets a host own a part of the same router as a machine.
11
+ // A consumer normally gives `basePath` to a bridge, to `connectRouter`, or to a
12
+ // `PlayRouterProvider`. These primitives serve an adapter, and a host that builds its
13
+ // own route table.
14
+ export { normalizeBasePath, resolveBasePath, stripBasePath, joinBasePath, NO_BASE_PATH, } from "./base-path.js";
15
+ // The params of a framework router, reconciled with the pattern of the machine. A
16
+ // bridge whose framework parses the params itself calls this, and it keeps that parse.
17
+ export { cleanFrameworkParams, getPatternParamNames, getRequiredPatternParamNames, pickOwnParams, resolveFrameworkParams, } from "./framework-params.js";
18
+ // The framework-free half of a PlayRouterProvider: the props, the constructor shape,
19
+ // and the lifecycle of the bridge. A provider of a framework adds its own effects and
20
+ // nothing else. This entry stays framework-agnostic — nothing here imports one.
21
+ export { isMountableBridge, mountKey, createRouterConnection, openProviderBridge, repointProviderBridge, } from "./provider-lifecycle.js";
10
22
  // The graph adapter — it converts an XState machine into a Graph of @statelyai/graph
11
23
  export { machineToGraph } from "./machine-to-graph.js";
12
24
  // The shared base class of the route map for both directions.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,mEAAmE;AACnE,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAG3D,wHAAwH;AACxH,OAAO,EACN,gBAAgB,EAChB,mBAAmB,EACnB,YAAY,EACZ,kBAAkB,GAClB,MAAM,kBAAkB,CAAC;AAG1B,sBAAsB;AACtB,OAAO,EACN,mBAAmB,EACnB,mBAAmB,EACnB,qBAAqB,GACrB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EACN,kBAAkB,EAClB,iBAAiB,EACjB,WAAW,EACX,4BAA4B,EAC5B,gBAAgB,GAChB,MAAM,YAAY,CAAC;AAEpB,qFAAqF;AACrF,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAmBvD,8DAA8D;AAC9D,qFAAqF;AACrF,qBAAqB;AACrB,OAAO,EAAE,QAAQ,EAAqB,MAAM,qBAAqB,CAAC;AAOlE,kFAAkF;AAClF,iFAAiF;AACjF,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvD,OAAO,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AAEzE,mFAAmF;AACnF,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,mEAAmE;AACnE,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAG3D,wHAAwH;AACxH,OAAO,EACN,gBAAgB,EAChB,mBAAmB,EACnB,YAAY,EACZ,kBAAkB,GAClB,MAAM,kBAAkB,CAAC;AAG1B,sBAAsB;AACtB,OAAO,EACN,mBAAmB,EACnB,mBAAmB,EACnB,qBAAqB,GACrB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EACN,kBAAkB,EAClB,iBAAiB,EACjB,WAAW,EACX,gBAAgB,EAChB,4BAA4B,EAC5B,gBAAgB,GAChB,MAAM,YAAY,CAAC;AAEpB,mFAAmF;AACnF,gFAAgF;AAChF,sFAAsF;AACtF,mBAAmB;AACnB,OAAO,EACN,iBAAiB,EACjB,eAAe,EACf,aAAa,EACb,YAAY,EACZ,YAAY,GACZ,MAAM,gBAAgB,CAAC;AAExB,kFAAkF;AAClF,uFAAuF;AACvF,OAAO,EACN,oBAAoB,EACpB,oBAAoB,EACpB,4BAA4B,EAC5B,aAAa,EACb,sBAAsB,GAEtB,MAAM,uBAAuB,CAAC;AAE/B,qFAAqF;AACrF,sFAAsF;AACtF,gFAAgF;AAChF,OAAO,EACN,iBAAiB,EACjB,QAAQ,EACR,sBAAsB,EACtB,kBAAkB,EAClB,qBAAqB,GACrB,MAAM,yBAAyB,CAAC;AAQjC,qFAAqF;AACrF,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAoBvD,8DAA8D;AAC9D,qFAAqF;AACrF,qBAAqB;AACrB,OAAO,EAAE,QAAQ,EAAqB,MAAM,qBAAqB,CAAC;AAOlE,kFAAkF;AAClF,iFAAiF;AACjF,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvD,OAAO,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AAEzE,mFAAmF;AACnF,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC"}