@xmachines/play-router 4.0.0 → 5.0.1
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 +25 -14
- package/dist/base-route-map.d.ts +17 -12
- package/dist/base-route-map.d.ts.map +1 -1
- package/dist/base-route-map.js +101 -25
- package/dist/base-route-map.js.map +1 -1
- package/dist/create-route-map-from-tree.d.ts +1 -1
- package/dist/create-route-map-from-tree.js +1 -1
- package/dist/errors.js +3 -3
- package/dist/errors.js.map +1 -1
- package/dist/find-route.d.ts +13 -1
- package/dist/find-route.d.ts.map +1 -1
- package/dist/find-route.js +22 -10
- package/dist/find-route.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/provider-lifecycle.d.ts +13 -5
- package/dist/provider-lifecycle.d.ts.map +1 -1
- package/dist/provider-lifecycle.js +9 -4
- package/dist/provider-lifecycle.js.map +1 -1
- package/dist/router-bridge-base.d.ts +36 -20
- package/dist/router-bridge-base.d.ts.map +1 -1
- package/dist/router-bridge-base.js +79 -72
- package/dist/router-bridge-base.js.map +1 -1
- package/dist/router-sync.d.ts +2 -26
- package/dist/router-sync.d.ts.map +1 -1
- package/dist/router-sync.js +8 -41
- package/dist/router-sync.js.map +1 -1
- package/dist/types.d.ts +31 -26
- package/dist/types.d.ts.map +1 -1
- package/dist/xstate/create-route-map.d.ts +2 -2
- package/dist/xstate/create-route-map.d.ts.map +1 -1
- package/dist/xstate/create-route-map.js +6 -3
- package/dist/xstate/create-route-map.js.map +1 -1
- package/dist/xstate/extract-routes.d.ts +2 -1
- package/dist/xstate/extract-routes.d.ts.map +1 -1
- package/dist/xstate/extract-routes.js +5 -5
- package/dist/xstate/extract-routes.js.map +1 -1
- package/package.json +15 -12
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Route tree extraction from XState v5 state machines. Part of [@xmachines/play](../play/README.md) Universal Player Architecture.
|
|
4
4
|
|
|
5
|
-
[](https://opensource.org/licenses/MIT) [](https://opensource.org/licenses/MIT) [](https://www.npmjs.com/package/@xmachines/play-router)
|
|
6
6
|
|
|
7
7
|
This package extracts the routes from a machine graph and looks them up in both directions. The Actor therefore keeps the authority over the navigation.
|
|
8
8
|
|
|
@@ -14,15 +14,26 @@ This package extracts the routes from a machine graph and looks them up in both
|
|
|
14
14
|
## Installation
|
|
15
15
|
|
|
16
16
|
```bash
|
|
17
|
-
pnpm add
|
|
18
|
-
pnpm add @xmachines/play-router
|
|
17
|
+
pnpm add @xmachines/play-router @xmachines/play @xmachines/play-atom
|
|
19
18
|
```
|
|
20
19
|
|
|
21
|
-
**Peer dependencies
|
|
20
|
+
**Peer dependencies.** Install them with the package:
|
|
22
21
|
|
|
23
|
-
- `
|
|
22
|
+
- [`@xmachines/play`](../play/README.md) — the core protocol. This package reads `asCleanup` and `DISPOSE` from it, and the error classes from its `errors` subpath.
|
|
23
|
+
- [`@xmachines/play-atom`](../play-atom/README.md) — the atom primitives. The bridge reads the route of the actor with `watchAtom`.
|
|
24
24
|
|
|
25
|
-
**
|
|
25
|
+
**Optional peers.** The `@xmachines/play-router/xstate` subpath alone reads them. Install them when you read that subpath, and not before:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
pnpm add xstate@^5.33.0 @statelyai/graph@^2.4.0
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
- `xstate` ^5.33.0 — the XState v5 runtime.
|
|
32
|
+
- `@statelyai/graph` ^2.4.0 — the graph of the machine that `extractMachineRoutes` walks.
|
|
33
|
+
|
|
34
|
+
A consumer of the root barrel installs neither one. `@statelyai/graph` was an ordinary dependency until this release, so every consumer of the root carried it; it now follows the same rule as `xstate`, which the same files read.
|
|
35
|
+
|
|
36
|
+
**URLPattern:** this package matches each route with the [URLPattern API](https://developer.mozilla.org/en-US/docs/Web/API/URLPattern). It uses the native API when the runtime has one, and it falls back to `urlpattern-polyfill`, which [`@xmachines/play-url`](../play-url/README.md) carries as an ordinary dependency. **You install nothing and you load nothing.**
|
|
26
37
|
|
|
27
38
|
The [routing guide](../docs/guides/routing.md) states the pattern language: the forms, the modifiers, the prefix rule, and the one divergence from the standard.
|
|
28
39
|
|
|
@@ -298,7 +309,7 @@ Each `stateId` comes from the route tree, so it carries NO `#`. A host that keys
|
|
|
298
309
|
route table on the target of a `play.route` event adds the `#` itself, because the
|
|
299
310
|
event always carries the prefixed form.
|
|
300
311
|
|
|
301
|
-
> Under a mount, `@xmachines/play-vue-router` and `@xmachines/play-solid-router` read
|
|
312
|
+
> Under a mount, [`@xmachines/play-vue-router`](../play-vue-router/README.md) and [`@xmachines/play-solid-router`](../play-solid-router/README.md) read
|
|
302
313
|
> the pre-parsed route params of their framework never: under a prefix the framework
|
|
303
314
|
> matched a route of the HOST by construction, because the machine owns the suffix of
|
|
304
315
|
> the path only. Those params therefore describe the route of the machine never, even
|
|
@@ -399,9 +410,9 @@ The MAIN entry point reads no state machine. The machine half is
|
|
|
399
410
|
### The machine half — subpath `@xmachines/play-router/xstate`
|
|
400
411
|
|
|
401
412
|
A route of XMachines is a fact about a STATE. This entry point reads that fact out of an
|
|
402
|
-
XState v5 machine. The main entry point reads it never, so `xstate`
|
|
403
|
-
|
|
404
|
-
|
|
413
|
+
XState v5 machine. The main entry point reads it never, so `xstate` and `@statelyai/graph`
|
|
414
|
+
are OPTIONAL peer dependencies of this package: a consumer that imports this entry point
|
|
415
|
+
nowhere installs neither one.
|
|
405
416
|
|
|
406
417
|
```typescript
|
|
407
418
|
import { createRouteMap, extractMachineRoutes } from "@xmachines/play-router/xstate";
|
|
@@ -456,8 +467,8 @@ it safe is the same in both, so it lives here.
|
|
|
456
467
|
| Export | Description |
|
|
457
468
|
| ---------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
458
469
|
| `resolveFrameworkParams(source)` | Decides which params describe the route of the machine: `{}`, the parse of the framework, or the fallback |
|
|
459
|
-
| `
|
|
460
|
-
| `
|
|
470
|
+
| `parsePattern(pattern).names` | The names of every `:param` of a route pattern. An anonymous param carries none |
|
|
471
|
+
| `parsePattern(pattern).requiredNames` | The names the pattern REQUIRES, so an optional `:name?` is left out |
|
|
461
472
|
| `pickOwnParams(params, names, requiredNames?)` | The params that the pattern declares, or `null` when the framework covers them not. `requiredNames` says which names may NOT be absent; it defaults to every name, so a two-argument call treats an optional `:name?` as a gap |
|
|
462
473
|
| `cleanFrameworkParams(params)` | The params of a framework with no absent value, each one a string |
|
|
463
474
|
|
|
@@ -579,7 +590,7 @@ breadcrumb. It also carries three fields that the routing layer reads:
|
|
|
579
590
|
| `reenter` | `false` | Whether the transition re-enters its own domain. See the note below. |
|
|
580
591
|
| `data` | none | The extra data of the route: a literal value, or a function of the event |
|
|
581
592
|
|
|
582
|
-
`@xmachines/play-xstate` reads `handler`, `reenter`, and `data` when it generates the
|
|
593
|
+
[`@xmachines/play-xstate`](../play-xstate/README.md) reads `handler`, `reenter`, and `data` when it generates the
|
|
583
594
|
transitions. See the README of that package for what each value does.
|
|
584
595
|
|
|
585
596
|
**The four names are RESERVED, and this is a change of behaviour.** An earlier release
|
|
@@ -619,7 +630,7 @@ Always use `node.fullPath` to match a browser URL and to build a route map. Neve
|
|
|
619
630
|
- **[@xmachines/play](../play/README.md)** — Core protocol types (`PlayEvent`, `PlayError`)
|
|
620
631
|
- **[@xmachines/play-actor](../play-actor/README.md)** — the actor contract (`PlayActor`). An actor that adds `Routable` of this package satisfies `RoutableActor` structurally
|
|
621
632
|
- **[@xmachines/play-url](../play-url/README.md)** — the URL language. This package re-exports its base path and its framework params, for an adapter on `RouterBridgeBase`
|
|
622
|
-
- **[@xmachines/play-
|
|
633
|
+
- **[@xmachines/play-atom](../play-atom/README.md)** — the atom primitives that observe the actor route
|
|
623
634
|
- **[@xmachines/play-xstate](../play-xstate/README.md)** — the XState v5 logic adapter, which works with a route tree
|
|
624
635
|
- **[@xmachines/play-tanstack-router](../play-tanstack-router/README.md)** — Shared TanStack Router bridge base (framework-agnostic)
|
|
625
636
|
- **[@xmachines/play-tanstack-react-router](../play-tanstack-react-router/README.md)** — TanStack Router adapter (React)
|
package/dist/base-route-map.d.ts
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
* segment, and that number is much smaller than the number of all the routes. The
|
|
11
11
|
* class matches a parameterized route with URLPattern.
|
|
12
12
|
*/
|
|
13
|
+
import type { RouteMapOptions } from "./types.js";
|
|
13
14
|
/**
|
|
14
15
|
* One entry of the map between a state ID and a path.
|
|
15
16
|
*
|
|
@@ -42,8 +43,9 @@ export interface RouteMapping {
|
|
|
42
43
|
* - A static path, without a `:param` → a `Map` lookup in O(1)
|
|
43
44
|
* - A dynamic path → a scan of the bucket index in O(k), with `URLPattern`, where
|
|
44
45
|
* `k` is the number of the routes with the same first path segment
|
|
45
|
-
* - The class keeps each result of a first match in an LRU cache. The default
|
|
46
|
-
*
|
|
46
|
+
* - The class keeps each result of a first match in an LRU cache. The default cache
|
|
47
|
+
* holds between 500 and 1000 entries, and the `pathCache` constructor option
|
|
48
|
+
* replaces it
|
|
47
49
|
*
|
|
48
50
|
* **The syntax of a pattern:** the whole URLPattern pathname grammar. The forms used most
|
|
49
51
|
* often are:
|
|
@@ -88,6 +90,16 @@ export declare class RouteMap {
|
|
|
88
90
|
private pathToStateId;
|
|
89
91
|
private patternBuckets;
|
|
90
92
|
private pathMatchCache;
|
|
93
|
+
/** The key space of this ROUTE TABLE inside {@link pathMatchCache}, which a caller may share. */
|
|
94
|
+
private readonly pathCacheKey;
|
|
95
|
+
/**
|
|
96
|
+
* The caches that every parse and every compilation of this map reads.
|
|
97
|
+
*
|
|
98
|
+
* Each default stays SHARED on purpose. A map that built one of its own would keep its
|
|
99
|
+
* patterns out of the cache that `find-route.ts` and `router-sync.ts` read, so the same
|
|
100
|
+
* pattern would parse two times. A caller that wants the isolation passes a cache.
|
|
101
|
+
*/
|
|
102
|
+
private compileOptions;
|
|
91
103
|
/**
|
|
92
104
|
* Builds a route map from an array of the mappings between a state ID and a path.
|
|
93
105
|
*
|
|
@@ -98,17 +110,10 @@ export declare class RouteMap {
|
|
|
98
110
|
*
|
|
99
111
|
* @param mappings - The array of the `{ stateId, path }` entries. The order gives the
|
|
100
112
|
* priority when more than one pattern can match the same path.
|
|
101
|
-
* @param options -
|
|
102
|
-
* `
|
|
103
|
-
* lookups in the cache. The default is `500`. Raise it for an application with
|
|
104
|
-
* many different values in a parameterized URL, for example a page of a user
|
|
105
|
-
* profile with thousands of different IDs. After an eviction, the path goes to the
|
|
106
|
-
* bucket pattern scan in O(k) again, which is correct but slower. The smallest
|
|
107
|
-
* effective value is `1`, because QuickLRU requires it.
|
|
113
|
+
* @param options - See {@link RouteMapOptions}. A map holds TWO caches, so no option is
|
|
114
|
+
* named `cache`: each one names the cache that it carries.
|
|
108
115
|
*/
|
|
109
|
-
constructor(mappings: RouteMapping[],
|
|
110
|
-
cacheSize?: number;
|
|
111
|
-
});
|
|
116
|
+
constructor(mappings: RouteMapping[], options?: RouteMapOptions);
|
|
112
117
|
/**
|
|
113
118
|
* Resolves a URL path to its state ID.
|
|
114
119
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base-route-map.d.ts","sourceRoot":"","sources":["../src/base-route-map.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;
|
|
1
|
+
{"version":3,"file":"base-route-map.d.ts","sourceRoot":"","sources":["../src/base-route-map.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAeH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAelD;;;;;;;;;;;;;;;GAeG;AACH,MAAM,WAAW,YAAY;IAC5B,8EAA8E;IAC9E,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,uGAAuG;IACvG,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACtB;AA+DD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkDG;AACH,qBAAa,QAAQ;IACpB,8EAA8E;IAC9E,OAAO,CAAC,aAAa,CAAsB;IAC3C,OAAO,CAAC,aAAa,CAAsB;IAC3C,OAAO,CAAC,cAAc,CAGpB;IACF,OAAO,CAAC,cAAc,CAA8B;IACpD,iGAAiG;IACjG,OAAO,CAAC,QAAQ,CAAC,YAAY,CAA2B;IACxD;;;;;;OAMG;IACH,OAAO,CAAC,cAAc,CAAiB;IAEvC;;;;;;;;;;;;OAYG;gBACS,QAAQ,EAAE,YAAY,EAAE,EAAE,OAAO,GAAE,eAAoB;IAqDnE;;;;;;;;;;;;;;;OAeG;IACH,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IA4B7C;;;;;;;;;;;;;;;;OAgBG;IACH,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;CAGhD"}
|
package/dist/base-route-map.js
CHANGED
|
@@ -10,8 +10,7 @@
|
|
|
10
10
|
* segment, and that number is much smaller than the number of all the routes. The
|
|
11
11
|
* class matches a parameterized route with URLPattern.
|
|
12
12
|
*/
|
|
13
|
-
import {
|
|
14
|
-
import QuickLRU from "quick-lru";
|
|
13
|
+
import { createPatternCache, getCandidates, getCompiledPattern, getIndexKey, parsePattern, splitLocation, } from "@xmachines/play-url";
|
|
15
14
|
import { InvalidRoutePatternError } from "./errors.js";
|
|
16
15
|
/**
|
|
17
16
|
* The canonical key of a stateId: the bare form, without a `#` at its start.
|
|
@@ -25,6 +24,65 @@ import { InvalidRoutePatternError } from "./errors.js";
|
|
|
25
24
|
function canonicalStateIdKey(stateId) {
|
|
26
25
|
return stateId.startsWith("#") ? stateId.slice(1) : stateId;
|
|
27
26
|
}
|
|
27
|
+
/**
|
|
28
|
+
* The bound of the path cache that a map builds for itself.
|
|
29
|
+
*
|
|
30
|
+
* `createPatternCache` keeps two generations, so the cache holds between this number and
|
|
31
|
+
* twice it. A caller that wants another bound passes a cache: `createPatternCache(5000)`
|
|
32
|
+
* builds one. A separate size option would configure THIS cache alone and say so nowhere,
|
|
33
|
+
* and it would do nothing at all beside a cache that the caller passed.
|
|
34
|
+
*/
|
|
35
|
+
const DEFAULT_PATH_CACHE_SIZE = 500;
|
|
36
|
+
/**
|
|
37
|
+
* The id of one route table: a digest of its mappings, in order.
|
|
38
|
+
*
|
|
39
|
+
* It is the key space that each ROUTE TABLE owns inside a shared path cache. An entry of
|
|
40
|
+
* that cache says which state a path resolves to, and the answer is a pure function of
|
|
41
|
+
* the mappings and the path: two maps built from the SAME mappings resolve every path the
|
|
42
|
+
* same way, and two maps built from different mappings do not. A map with no route for
|
|
43
|
+
* `/settings/x` writes `null`, and a map that DOES hold `/settings/:s` then read that
|
|
44
|
+
* `null` and reported no state for a route of its own.
|
|
45
|
+
*
|
|
46
|
+
* The key therefore names the TABLE, and not the instance. An instance counter kept the
|
|
47
|
+
* two apart as well, and it also gave a server that rebuilds its map for each request a
|
|
48
|
+
* cache that answered nothing: every request opened a key space of its own, and the dead
|
|
49
|
+
* keys of the last one evicted the live entries of this one.
|
|
50
|
+
*
|
|
51
|
+
* Two maps built from the same mappings share the id, which is what a server that
|
|
52
|
+
* rebuilds its map for each request needs, and two maps built from different mappings do
|
|
53
|
+
* not — a map with no route for a path writes `null` for it, and a map that HOLDS one
|
|
54
|
+
* must not read that.
|
|
55
|
+
*
|
|
56
|
+
* A REGISTER of the serialized tables answered this before, and it kept every table
|
|
57
|
+
* string it had seen for the life of the process: a per-tenant table of fifty routes is a
|
|
58
|
+
* few kilobytes, and a bounded register of them still retained megabytes in exactly the
|
|
59
|
+
* per-request case that the cache exists for. A digest retains nothing.
|
|
60
|
+
*
|
|
61
|
+
* ## The collision
|
|
62
|
+
*
|
|
63
|
+
* Two DIFFERENT tables that share a digest share a key space, and the negative entries of
|
|
64
|
+
* one then answer for the other. The digest is 64 bits over the full signature, so a
|
|
65
|
+
* process that built ten thousand distinct route tables carries a chance of about 3 in
|
|
66
|
+
* 10^12 of one collision — far below the chance of the bit flip that would corrupt the
|
|
67
|
+
* cache anyway. This library already identifies by digest: an XMachines id is a Git OID.
|
|
68
|
+
*/
|
|
69
|
+
function routeTableId(mappings) {
|
|
70
|
+
// FNV-1a, in two 32-bit halves, because a bitwise operator of JavaScript truncates to
|
|
71
|
+
// 32 bits and `BigInt` costs an allocation for each character.
|
|
72
|
+
let hashLow = 0x811c9dc5;
|
|
73
|
+
let hashHigh = 0x811c9dc5;
|
|
74
|
+
for (const { stateId, path } of mappings) {
|
|
75
|
+
// The ORDER is significant: it gives the priority when more than one pattern matches,
|
|
76
|
+
// so the separators below keep `[{a, /x}, {b, /y}]` apart from `[{a, /x/b}, {/y}]`.
|
|
77
|
+
const entry = `${stateId}\u0000${path}\u0001`;
|
|
78
|
+
for (let index = 0; index < entry.length; index += 1) {
|
|
79
|
+
const code = entry.charCodeAt(index);
|
|
80
|
+
hashLow = Math.imul(hashLow ^ code, 0x01000193) >>> 0;
|
|
81
|
+
hashHigh = Math.imul(hashHigh ^ (code + index), 0x01000193) >>> 0;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return `${hashLow.toString(36)}.${hashHigh.toString(36)}`;
|
|
85
|
+
}
|
|
28
86
|
/**
|
|
29
87
|
* The shared base class of the route map for both directions.
|
|
30
88
|
*
|
|
@@ -35,8 +93,9 @@ function canonicalStateIdKey(stateId) {
|
|
|
35
93
|
* - A static path, without a `:param` → a `Map` lookup in O(1)
|
|
36
94
|
* - A dynamic path → a scan of the bucket index in O(k), with `URLPattern`, where
|
|
37
95
|
* `k` is the number of the routes with the same first path segment
|
|
38
|
-
* - The class keeps each result of a first match in an LRU cache. The default
|
|
39
|
-
*
|
|
96
|
+
* - The class keeps each result of a first match in an LRU cache. The default cache
|
|
97
|
+
* holds between 500 and 1000 entries, and the `pathCache` constructor option
|
|
98
|
+
* replaces it
|
|
40
99
|
*
|
|
41
100
|
* **The syntax of a pattern:** the whole URLPattern pathname grammar. The forms used most
|
|
42
101
|
* often are:
|
|
@@ -81,6 +140,16 @@ export class RouteMap {
|
|
|
81
140
|
pathToStateId;
|
|
82
141
|
patternBuckets;
|
|
83
142
|
pathMatchCache;
|
|
143
|
+
/** The key space of this ROUTE TABLE inside {@link pathMatchCache}, which a caller may share. */
|
|
144
|
+
pathCacheKey;
|
|
145
|
+
/**
|
|
146
|
+
* The caches that every parse and every compilation of this map reads.
|
|
147
|
+
*
|
|
148
|
+
* Each default stays SHARED on purpose. A map that built one of its own would keep its
|
|
149
|
+
* patterns out of the cache that `find-route.ts` and `router-sync.ts` read, so the same
|
|
150
|
+
* pattern would parse two times. A caller that wants the isolation passes a cache.
|
|
151
|
+
*/
|
|
152
|
+
compileOptions;
|
|
84
153
|
/**
|
|
85
154
|
* Builds a route map from an array of the mappings between a state ID and a path.
|
|
86
155
|
*
|
|
@@ -91,19 +160,26 @@ export class RouteMap {
|
|
|
91
160
|
*
|
|
92
161
|
* @param mappings - The array of the `{ stateId, path }` entries. The order gives the
|
|
93
162
|
* priority when more than one pattern can match the same path.
|
|
94
|
-
* @param options -
|
|
95
|
-
* `
|
|
96
|
-
* lookups in the cache. The default is `500`. Raise it for an application with
|
|
97
|
-
* many different values in a parameterized URL, for example a page of a user
|
|
98
|
-
* profile with thousands of different IDs. After an eviction, the path goes to the
|
|
99
|
-
* bucket pattern scan in O(k) again, which is correct but slower. The smallest
|
|
100
|
-
* effective value is `1`, because QuickLRU requires it.
|
|
163
|
+
* @param options - See {@link RouteMapOptions}. A map holds TWO caches, so no option is
|
|
164
|
+
* named `cache`: each one names the cache that it carries.
|
|
101
165
|
*/
|
|
102
|
-
constructor(mappings,
|
|
166
|
+
constructor(mappings, options = {}) {
|
|
167
|
+
const { pathCache, ...compileOptions } = options;
|
|
168
|
+
this.compileOptions = compileOptions;
|
|
103
169
|
this.stateIdToPath = new Map();
|
|
104
170
|
this.pathToStateId = new Map();
|
|
105
171
|
this.patternBuckets = new Map();
|
|
106
|
-
this.pathMatchCache =
|
|
172
|
+
this.pathMatchCache =
|
|
173
|
+
pathCache ?? createPatternCache(DEFAULT_PATH_CACHE_SIZE);
|
|
174
|
+
// A map that BUILDS its own cache owns every key in it, and a prefix would only make
|
|
175
|
+
// each key longer. A map that RECEIVES one shares it, so its keys carry the prefix.
|
|
176
|
+
if (pathCache === undefined) {
|
|
177
|
+
this.pathCacheKey = (path) => path;
|
|
178
|
+
}
|
|
179
|
+
else {
|
|
180
|
+
const prefix = `${routeTableId(mappings)}\u0002`;
|
|
181
|
+
this.pathCacheKey = (path) => prefix + path;
|
|
182
|
+
}
|
|
107
183
|
let patternOrder = 0;
|
|
108
184
|
for (const { stateId, path } of mappings) {
|
|
109
185
|
// The key is the canonical bare form. Therefore getPathByStateId accepts
|
|
@@ -115,13 +191,13 @@ export class RouteMap {
|
|
|
115
191
|
// string. A pattern such as `/books{/:id}?` keeps the literal first segment
|
|
116
192
|
// `books`, and a split on `/` read the key `books{` and put the route in a bucket
|
|
117
193
|
// that the path `/books/1` reaches never.
|
|
118
|
-
const parsed = parsePattern(path);
|
|
194
|
+
const parsed = parsePattern(path, this.compileOptions);
|
|
119
195
|
if (parsed.parameterized) {
|
|
120
196
|
const bucketKey = parsed.indexKey;
|
|
121
197
|
const bucket = this.patternBuckets.get(bucketKey) ?? [];
|
|
122
198
|
try {
|
|
123
199
|
bucket.push({
|
|
124
|
-
pattern: getCompiledPattern(path),
|
|
200
|
+
pattern: getCompiledPattern(path, this.compileOptions),
|
|
125
201
|
stateId,
|
|
126
202
|
order: patternOrder++,
|
|
127
203
|
});
|
|
@@ -158,28 +234,28 @@ export class RouteMap {
|
|
|
158
234
|
* ```
|
|
159
235
|
*/
|
|
160
236
|
getStateIdByPath(path) {
|
|
161
|
-
// Remove the query string and the hash fragment before the match. `
|
|
162
|
-
//
|
|
163
|
-
// `framework-params.ts` read it too, so the
|
|
164
|
-
// allocated two arrays of every part on the hottest lookup of
|
|
165
|
-
// function then read one element of each.
|
|
166
|
-
const
|
|
167
|
-
const cleanPath = mark === -1 ? path : path.slice(0, mark);
|
|
237
|
+
// Remove the query string and the hash fragment before the match. `splitLocation` is
|
|
238
|
+
// the ONE answer to "where does a pathname end", and `RouterBridgeBase`,
|
|
239
|
+
// `framework-params.ts` and `sanitizePathname` read it too, so the four cannot
|
|
240
|
+
// disagree. Two splits allocated two arrays of every part on the hottest lookup of
|
|
241
|
+
// the library, and this function then read one element of each.
|
|
242
|
+
const cleanPath = splitLocation(path).pathname;
|
|
168
243
|
const exactMatch = this.pathToStateId.get(cleanPath);
|
|
169
244
|
if (exactMatch !== undefined)
|
|
170
245
|
return exactMatch;
|
|
171
|
-
const
|
|
246
|
+
const cacheKey = this.pathCacheKey(cleanPath);
|
|
247
|
+
const cachedMatch = this.pathMatchCache.get(cacheKey);
|
|
172
248
|
if (cachedMatch !== undefined)
|
|
173
249
|
return cachedMatch;
|
|
174
250
|
const candidates = getCandidates(this.patternBuckets, getIndexKey(cleanPath));
|
|
175
251
|
for (const { pattern, stateId } of candidates) {
|
|
176
252
|
const match = pattern.exec({ pathname: cleanPath });
|
|
177
253
|
if (match) {
|
|
178
|
-
this.pathMatchCache.set(
|
|
254
|
+
this.pathMatchCache.set(cacheKey, stateId);
|
|
179
255
|
return stateId;
|
|
180
256
|
}
|
|
181
257
|
}
|
|
182
|
-
this.pathMatchCache.set(
|
|
258
|
+
this.pathMatchCache.set(cacheKey, null);
|
|
183
259
|
return null;
|
|
184
260
|
}
|
|
185
261
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base-route-map.js","sourceRoot":"","sources":["../src/base-route-map.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EACN,
|
|
1
|
+
{"version":3,"file":"base-route-map.js","sourceRoot":"","sources":["../src/base-route-map.ts"],"names":[],"mappings":"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"}
|
|
@@ -19,7 +19,7 @@ import { RouteMap } from "./base-route-map.js";
|
|
|
19
19
|
* for the same tree.
|
|
20
20
|
*
|
|
21
21
|
* @param routeTree - A `RouteTree`, as `extractMachineRoutes()` returns it.
|
|
22
|
-
* @param options - The optional configuration, for example `{
|
|
22
|
+
* @param options - The optional configuration, for example `{ pathCache }` to replace the LRU cache of the resolved paths.
|
|
23
23
|
* @returns A `RouteMap` for each adapter on `RouterBridgeBase`.
|
|
24
24
|
*
|
|
25
25
|
* @example
|
|
@@ -19,7 +19,7 @@ import { ROOT_NODE_ID } from "./build-tree.js";
|
|
|
19
19
|
* for the same tree.
|
|
20
20
|
*
|
|
21
21
|
* @param routeTree - A `RouteTree`, as `extractMachineRoutes()` returns it.
|
|
22
|
-
* @param options - The optional configuration, for example `{
|
|
22
|
+
* @param options - The optional configuration, for example `{ pathCache }` to replace the LRU cache of the resolved paths.
|
|
23
23
|
* @returns A `RouteMap` for each adapter on `RouterBridgeBase`.
|
|
24
24
|
*
|
|
25
25
|
* @example
|
package/dist/errors.js
CHANGED
|
@@ -5,9 +5,9 @@ import { PlayError } from "@xmachines/play/errors";
|
|
|
5
5
|
//
|
|
6
6
|
// The specifier is the `./errors` subpath, and not the root barrel. A consumer that
|
|
7
7
|
// imports `@xmachines/play-router/errors` to name a fault in a `catch` then loads the
|
|
8
|
-
// three classes alone: no pattern parser, no base path, and
|
|
9
|
-
//
|
|
10
|
-
//
|
|
8
|
+
// three classes alone: no pattern parser, no base path, and no `urlpattern-polyfill`. The
|
|
9
|
+
// root barrel of this package reaches the rest of `@xmachines/play-url` for the consumer
|
|
10
|
+
// that needs it.
|
|
11
11
|
export { InvalidRoutePatternError, InvalidBasePathError, MissingBasePathParamError, } from "@xmachines/play-url/errors";
|
|
12
12
|
/**
|
|
13
13
|
* The bridge throws this error when `RouterBridgeBase.syncActorFromRouter()`
|
package/dist/errors.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAEnD,qFAAqF;AACrF,yFAAyF;AACzF,8DAA8D;AAC9D,EAAE;AACF,oFAAoF;AACpF,sFAAsF;AACtF,
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAEnD,qFAAqF;AACrF,yFAAyF;AACzF,8DAA8D;AAC9D,EAAE;AACF,oFAAoF;AACpF,sFAAsF;AACtF,0FAA0F;AAC1F,yFAAyF;AACzF,iBAAiB;AACjB,OAAO,EACN,wBAAwB,EACxB,oBAAoB,EACpB,yBAAyB,GACzB,MAAM,4BAA4B,CAAC;AAEpC;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,OAAO,eAAgB,SAAQ,SAAS;IAC7C,YAAY,OAAe,EAAE,OAAsB;QAClD,KAAK,CAAC,kBAAkB,EAAE,yBAAyB,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QACvE,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;IAC/B,CAAC;CACD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAM,OAAO,oBAAqB,SAAQ,SAAS;IAClD;QACC,KAAK,CACJ,kBAAkB,EAClB,8BAA8B,EAC9B,iEAAiE;YAChE,uEAAuE,CACxE,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC;IACpC,CAAC;CACD;AAED;;;;;GAKG;AACH,MAAM,OAAO,mBAAoB,SAAQ,SAAS;IACjD,8CAA8C;IACrC,OAAO,CAAS;IAEzB,YAAY,OAAe;QAC1B,KAAK,CACJ,UAAU,EACV,uBAAuB,EACvB,8BAA8B,OAAO,sCAAsC,CAC3E,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;QAClC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACxB,CAAC;CACD;AAED;;;;;GAKG;AACH,MAAM,OAAO,mBAAoB,SAAQ,SAAS;IACjD,iEAAiE;IACxD,OAAO,CAAS;IAEzB,YAAY,OAAe;QAC1B,KAAK,CACJ,UAAU,EACV,6BAA6B,EAC7B,2CAA2C,OAAO,EAAE,CACpD,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;QAClC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACxB,CAAC;CACD;AAED;;;;;GAKG;AACH,MAAM,OAAO,uBAAwB,SAAQ,SAAS;IACrD,sFAAsF;IAC7E,UAAU,CAAW;IAE9B,YAAY,UAAoB;QAC/B,KAAK,CACJ,UAAU,EACV,2BAA2B,EAC3B,oCAAoC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM;YAC9D,kDAAkD;YAClD,6FAA6F,CAC9F,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,yBAAyB,CAAC;QACtC,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IAC9B,CAAC;CACD;AAED;;;;;GAKG;AACH,MAAM,OAAO,qBAAsB,SAAQ,SAAS;IACnD,mEAAmE;IAC1D,SAAS,CAAS;IAC3B,sDAAsD;IAC7C,MAAM,CAAS;IAExB,YAAY,SAAiB,EAAE,MAAc,EAAE,UAAoB;QAClE,KAAK,CACJ,gBAAgB,EAChB,+BAA+B,EAC/B,8BAA8B,SAAS,cAAc,MAAM,KAAK;YAC/D,oBAAoB,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAC7C,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAC;QACpC,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAC3B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACtB,CAAC;CACD"}
|
package/dist/find-route.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { CompileOptions } from "@xmachines/play-url";
|
|
1
2
|
import type { RouteTree, RouteNode } from "./types.js";
|
|
2
3
|
/**
|
|
3
4
|
* Finds a route node by its state ID
|
|
@@ -35,13 +36,24 @@ export declare const findRouteById: (tree: RouteTree, id: string) => RouteNode |
|
|
|
35
36
|
*
|
|
36
37
|
* @param tree - The route tree, from extractMachineRoutes
|
|
37
38
|
* @param path - The URL path, for example '/dashboard' or '/settings/profile'
|
|
39
|
+
* @param options - The caches that the pattern match reads. The default is the pair
|
|
40
|
+
* that `@xmachines/play-url` shares with every caller of the process. A server that
|
|
41
|
+
* serves many tenants passes a cache that the tenant owns, exactly as `RouteMap` and
|
|
42
|
+
* a bridge take one. A cache changes how often the work runs, and it changes no
|
|
43
|
+
* answer, so this argument is safe to leave out.
|
|
38
44
|
* @returns The route node, or undefined when the function finds none
|
|
39
45
|
*
|
|
40
46
|
* @example
|
|
41
47
|
* ```typescript
|
|
42
48
|
* const tree = extractMachineRoutes(machine);
|
|
43
49
|
* const node = findRouteByPath(tree, '/dashboard');
|
|
50
|
+
*
|
|
51
|
+
* // With a cache that one request owns and drops
|
|
52
|
+
* const node = findRouteByPath(tree, '/dashboard', {
|
|
53
|
+
* patternCache: createPatternCache(),
|
|
54
|
+
* compiledCache: createPatternCache(),
|
|
55
|
+
* });
|
|
44
56
|
* ```
|
|
45
57
|
*/
|
|
46
|
-
export declare const findRouteByPath: (tree: RouteTree, path: string) => RouteNode | undefined;
|
|
58
|
+
export declare const findRouteByPath: (tree: RouteTree, path: string, options?: CompileOptions) => RouteNode | undefined;
|
|
47
59
|
//# sourceMappingURL=find-route.d.ts.map
|
package/dist/find-route.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"find-route.d.ts","sourceRoot":"","sources":["../src/find-route.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"find-route.d.ts","sourceRoot":"","sources":["../src/find-route.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAmCvD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,aAAa,GAAI,MAAM,SAAS,EAAE,IAAI,MAAM,KAAG,SAAS,GAAG,SAEvE,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,eAAO,MAAM,eAAe,GAC3B,MAAM,SAAS,EACf,MAAM,MAAM,EACZ,UAAU,cAAc,KACtB,SAAS,GAAG,SAyBd,CAAC"}
|
package/dist/find-route.js
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
import { getCompiledPattern,
|
|
1
|
+
import { getCompiledPattern, parsePattern } from "@xmachines/play-url";
|
|
2
2
|
/**
|
|
3
3
|
* Tells you if a URL path matches a route pattern, with URLPattern.
|
|
4
4
|
*
|
|
5
5
|
* For a static pattern, which holds no param, the function makes a direct equality
|
|
6
6
|
* test, and it compiles nothing.
|
|
7
7
|
*
|
|
8
|
-
* The function
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* exactly like `RouteMap`: one match engine is below both.
|
|
8
|
+
* The function compiles through `getCompiledPattern`, so a repeated lookup compiles
|
|
9
|
+
* the same pattern never again. That call also normalizes a param name with a hyphen
|
|
10
|
+
* (`:cat-id`) exactly like `RouteMap`: one match engine is below both.
|
|
12
11
|
*
|
|
13
12
|
* It throws the `InvalidRoutePatternError` of `getCompiledPattern` when URLPattern
|
|
14
13
|
* cannot compile the pattern.
|
|
@@ -17,19 +16,21 @@ import { getCompiledPattern, isParameterizedPattern } from "@xmachines/play-url"
|
|
|
17
16
|
*
|
|
18
17
|
* @param path - The URL path, for example '/settings' or '/settings/billing'
|
|
19
18
|
* @param pattern - The route pattern, for example '/settings/:section?'
|
|
19
|
+
* @param options - The caches to read. The default is the pair that
|
|
20
|
+
* `@xmachines/play-url` shares with every caller of the process.
|
|
20
21
|
* @returns True when the path matches the pattern
|
|
21
22
|
*/
|
|
22
|
-
function matchesPattern(path, pattern) {
|
|
23
|
+
function matchesPattern(path, pattern, options) {
|
|
23
24
|
// The test reads the PARSE. `pattern.includes(":")` called `/docs/*` and `/a{/b}?/c`
|
|
24
25
|
// static, and the equality test below then answered `false` for every path that the
|
|
25
26
|
// pattern matches.
|
|
26
|
-
if (!
|
|
27
|
+
if (!parsePattern(pattern, options).parameterized)
|
|
27
28
|
return path === pattern;
|
|
28
29
|
// `getCompiledPattern` reports an invalid pattern itself, and with the REASON when it
|
|
29
30
|
// knows one — two params that land on one URLPattern group, for example. A wrap here
|
|
30
31
|
// replaced that message with the generic one and pushed the explanation down to
|
|
31
32
|
// `cause`, which is the same defect that `RouteMap` guards against in its constructor.
|
|
32
|
-
return getCompiledPattern(pattern).test({ pathname: path });
|
|
33
|
+
return getCompiledPattern(pattern, options).test({ pathname: path });
|
|
33
34
|
}
|
|
34
35
|
/**
|
|
35
36
|
* Finds a route node by its state ID
|
|
@@ -69,15 +70,26 @@ export const findRouteById = (tree, id) => {
|
|
|
69
70
|
*
|
|
70
71
|
* @param tree - The route tree, from extractMachineRoutes
|
|
71
72
|
* @param path - The URL path, for example '/dashboard' or '/settings/profile'
|
|
73
|
+
* @param options - The caches that the pattern match reads. The default is the pair
|
|
74
|
+
* that `@xmachines/play-url` shares with every caller of the process. A server that
|
|
75
|
+
* serves many tenants passes a cache that the tenant owns, exactly as `RouteMap` and
|
|
76
|
+
* a bridge take one. A cache changes how often the work runs, and it changes no
|
|
77
|
+
* answer, so this argument is safe to leave out.
|
|
72
78
|
* @returns The route node, or undefined when the function finds none
|
|
73
79
|
*
|
|
74
80
|
* @example
|
|
75
81
|
* ```typescript
|
|
76
82
|
* const tree = extractMachineRoutes(machine);
|
|
77
83
|
* const node = findRouteByPath(tree, '/dashboard');
|
|
84
|
+
*
|
|
85
|
+
* // With a cache that one request owns and drops
|
|
86
|
+
* const node = findRouteByPath(tree, '/dashboard', {
|
|
87
|
+
* patternCache: createPatternCache(),
|
|
88
|
+
* compiledCache: createPatternCache(),
|
|
89
|
+
* });
|
|
78
90
|
* ```
|
|
79
91
|
*/
|
|
80
|
-
export const findRouteByPath = (tree, path) => {
|
|
92
|
+
export const findRouteByPath = (tree, path, options) => {
|
|
81
93
|
// 1. Try the exact match first. This is the fast path of a static route
|
|
82
94
|
const node = tree.byPath.get(path);
|
|
83
95
|
if (node?.routable) {
|
|
@@ -92,7 +104,7 @@ export const findRouteByPath = (tree, path) => {
|
|
|
92
104
|
continue; // Skip each node without a route
|
|
93
105
|
}
|
|
94
106
|
// Test the path against the pattern of this node
|
|
95
|
-
if (matchesPattern(path, candidate.fullPath)) {
|
|
107
|
+
if (matchesPattern(path, candidate.fullPath, options)) {
|
|
96
108
|
return candidate;
|
|
97
109
|
}
|
|
98
110
|
}
|
package/dist/find-route.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"find-route.js","sourceRoot":"","sources":["../src/find-route.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,
|
|
1
|
+
{"version":3,"file":"find-route.js","sourceRoot":"","sources":["../src/find-route.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAIvE;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,SAAS,cAAc,CAAC,IAAY,EAAE,OAAe,EAAE,OAAwB;IAC9E,qFAAqF;IACrF,oFAAoF;IACpF,mBAAmB;IACnB,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,aAAa;QAAE,OAAO,IAAI,KAAK,OAAO,CAAC;IAC3E,sFAAsF;IACtF,qFAAqF;IACrF,gFAAgF;IAChF,uFAAuF;IACvF,OAAO,kBAAkB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;AACtE,CAAC;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,IAAe,EAAE,EAAU,EAAyB,EAAE;IACnF,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AAC/B,CAAC,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAC9B,IAAe,EACf,IAAY,EACZ,OAAwB,EACA,EAAE;IAC1B,wEAAwE;IACxE,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAEnC,IAAI,IAAI,EAAE,QAAQ,EAAE,CAAC;QACpB,OAAO,IAAI,CAAC;IACb,CAAC;IAED,oFAAoF;IACpF,4BAA4B;IAC5B,gEAAgE;IAChE,0EAA0E;IAC1E,KAAK,MAAM,SAAS,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,CAAC;QACjD,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,CAAC;YACzB,SAAS,CAAC,iCAAiC;QAC5C,CAAC;QAED,iDAAiD;QACjD,IAAI,cAAc,CAAC,IAAI,EAAE,SAAS,CAAC,QAAQ,EAAE,OAAO,CAAC,EAAE,CAAC;YACvD,OAAO,SAAS,CAAC;QAClB,CAAC;IACF,CAAC;IAED,yFAAyF;IACzF,OAAO,IAAI,CAAC;AACb,CAAC,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
export { RouterBridgeBase } from "./router-bridge-base.js";
|
|
2
|
-
export type { RouteWatcherHandle } from "./router-bridge-base.js";
|
|
3
|
-
export {
|
|
2
|
+
export type { RouteWatcherHandle, RouterBridgeOptions } from "./router-bridge-base.js";
|
|
3
|
+
export { buildPlayRouteEvent, extractQuery, extractRouteParams } from "./router-sync.js";
|
|
4
4
|
export type { RouteMatch, BuildPlayRouteEventOptions } from "./router-sync.js";
|
|
5
5
|
export { validateRouteFormat, validateStateExists, detectDuplicateRoutes, } from "./validate-routes.js";
|
|
6
6
|
export type { ResolvedRoutePath } from "./validate-routes.js";
|
|
7
7
|
export { normalizeBasePath, resolveBasePath, stripBasePath, joinBasePath, NO_BASE_PATH, } from "@xmachines/play-url";
|
|
8
8
|
export type { BasePathOptions, ResolvedBasePath } from "@xmachines/play-url";
|
|
9
|
-
export { cleanFrameworkParams,
|
|
9
|
+
export { cleanFrameworkParams, createPatternCache, parsePattern, pickOwnParams, resolveFrameworkParams, sanitizePathname, splitLocation, type CompileOptions, type ParseOptions, type FrameworkParamsSource, type ParsedPattern, type PatternCache, type SplitLocation, type URLPatternLike, } from "@xmachines/play-url";
|
|
10
10
|
export { isMountableBridge, mountKey, createRouterConnection, openProviderBridge, repointProviderBridge, } from "./provider-lifecycle.js";
|
|
11
11
|
export type { OpenProviderBridgeArgs, PlayRouterBridgeConstructor, PlayRouterProviderBaseProps, RouterConnection, } from "./provider-lifecycle.js";
|
|
12
12
|
export type { RouteInfo, RouteNode, RouteTree, RouteObject, RouteMetadata, RouteData, RouteDataResolver, PlayRouteEvent, Routable, RoutableActor, RouterBridge, MountableRouterBridge, WindowLike, LocationLike, } from "./types.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,YAAY,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,YAAY,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAGvF,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACzF,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;AAM9D,OAAO,EACN,iBAAiB,EACjB,eAAe,EACf,aAAa,EACb,YAAY,EACZ,YAAY,GACZ,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAG7E,OAAO,EACN,oBAAoB,EACpB,kBAAkB,EAClB,YAAY,EACZ,aAAa,EACb,sBAAsB,EACtB,gBAAgB,EAChB,aAAa,EACb,KAAK,cAAc,EACnB,KAAK,YAAY,EACjB,KAAK,qBAAqB,EAC1B,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,KAAK,cAAc,GACnB,MAAM,qBAAqB,CAAC;AAK7B,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;AAEjC,YAAY,EACX,SAAS,EACT,SAAS,EACT,SAAS,EACT,WAAW,EACX,aAAa,EACb,SAAS,EACT,iBAAiB,EACjB,cAAc,EACd,QAAQ,EACR,aAAa,EACb,YAAY,EACZ,qBAAqB,EACrB,UAAU,EACV,YAAY,GACZ,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,QAAQ,EAAE,KAAK,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAGlE,OAAO,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AAGzE,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAMjE,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAI1C,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/D,YAAY,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// RouterBridgeBase — the public API of an adapter of the community
|
|
2
2
|
export { RouterBridgeBase } from "./router-bridge-base.js";
|
|
3
3
|
// The router sync utilities — play-dom-router uses them, and also each adapter that passes around syncActorFromRouter()
|
|
4
|
-
export {
|
|
4
|
+
export { buildPlayRouteEvent, extractQuery, extractRouteParams } from "./router-sync.js";
|
|
5
5
|
// The route utilities
|
|
6
6
|
export { validateRouteFormat, validateStateExists, detectDuplicateRoutes, } from "./validate-routes.js";
|
|
7
7
|
// The base-path mount — it lets a host own a part of the same router as a machine.
|
|
@@ -11,7 +11,7 @@ export { validateRouteFormat, validateStateExists, detectDuplicateRoutes, } from
|
|
|
11
11
|
export { normalizeBasePath, resolveBasePath, stripBasePath, joinBasePath, NO_BASE_PATH, } from "@xmachines/play-url";
|
|
12
12
|
// The params of a framework router, reconciled with the pattern of the machine. A
|
|
13
13
|
// bridge whose framework parses the params itself calls this, and it keeps that parse.
|
|
14
|
-
export { cleanFrameworkParams,
|
|
14
|
+
export { cleanFrameworkParams, createPatternCache, parsePattern, pickOwnParams, resolveFrameworkParams, sanitizePathname, splitLocation, } from "@xmachines/play-url";
|
|
15
15
|
// The framework-free half of a PlayRouterProvider: the props, the constructor shape,
|
|
16
16
|
// and the lifecycle of the bridge. A provider of a framework adds its own effects and
|
|
17
17
|
// nothing else. This entry stays framework-agnostic — nothing here imports one.
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,mEAAmE;AACnE,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAG3D,wHAAwH;AACxH,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,mEAAmE;AACnE,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAG3D,wHAAwH;AACxH,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAGzF,sBAAsB;AACtB,OAAO,EACN,mBAAmB,EACnB,mBAAmB,EACnB,qBAAqB,GACrB,MAAM,sBAAsB,CAAC;AAG9B,mFAAmF;AACnF,gFAAgF;AAChF,sFAAsF;AACtF,mBAAmB;AACnB,OAAO,EACN,iBAAiB,EACjB,eAAe,EACf,aAAa,EACb,YAAY,EACZ,YAAY,GACZ,MAAM,qBAAqB,CAAC;AAE7B,kFAAkF;AAClF,uFAAuF;AACvF,OAAO,EACN,oBAAoB,EACpB,kBAAkB,EAClB,YAAY,EACZ,aAAa,EACb,sBAAsB,EACtB,gBAAgB,EAChB,aAAa,GAQb,MAAM,qBAAqB,CAAC;AAE7B,qFAAqF;AACrF,sFAAsF;AACtF,gFAAgF;AAChF,OAAO,EACN,iBAAiB,EACjB,QAAQ,EACR,sBAAsB,EACtB,kBAAkB,EAClB,qBAAqB,GACrB,MAAM,yBAAyB,CAAC;AAyBjC,8DAA8D;AAC9D,OAAO,EAAE,QAAQ,EAAqB,MAAM,qBAAqB,CAAC;AAElE,kFAAkF;AAClF,OAAO,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AAEzE,mFAAmF;AACnF,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAEjE,sFAAsF;AACtF,iFAAiF;AACjF,6EAA6E;AAC7E,4DAA4D;AAC5D,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAE1C,yFAAyF;AACzF,iFAAiF;AACjF,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC"}
|