@xmachines/play-sveltekit-router 2.0.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +37 -34
- package/dist/connect-router.d.ts +5 -4
- package/dist/connect-router.d.ts.map +1 -1
- package/dist/connect-router.js +2 -2
- package/dist/connect-router.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/sveltekit-router-bridge.d.ts +30 -28
- package/dist/sveltekit-router-bridge.d.ts.map +1 -1
- package/dist/sveltekit-router-bridge.js +33 -30
- package/dist/sveltekit-router-bridge.js.map +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/types.js +1 -1
- package/package.json +7 -6
package/README.md
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
# @xmachines/play-sveltekit-router
|
|
2
2
|
|
|
3
|
-
SvelteKit router adapter for the XMachines Universal Player Architecture.
|
|
3
|
+
SvelteKit router adapter for the XMachines Universal Player Architecture. It keeps the state machine routes of a `RoutableActor` and the browser URL in step, in both directions, through the `$app/navigation` module of SvelteKit.
|
|
4
4
|
|
|
5
|
-
[](https://opensource.org/licenses/MIT) [.
|
|
5
|
+
[](https://opensource.org/licenses/MIT) [](https://www.npmjs.com/package/@xmachines/play-sveltekit-router)
|
|
8
6
|
|
|
9
7
|
## Installation
|
|
10
8
|
|
|
@@ -12,7 +10,7 @@ Part of the [xmachines-js monorepo](../../README.md).
|
|
|
12
10
|
pnpm add @xmachines/play-sveltekit-router
|
|
13
11
|
```
|
|
14
12
|
|
|
15
|
-
**Peer dependencies
|
|
13
|
+
**Peer dependencies.** Install them separately:
|
|
16
14
|
|
|
17
15
|
```bash
|
|
18
16
|
pnpm add @sveltejs/kit svelte xstate
|
|
@@ -27,6 +25,7 @@ pnpm add @sveltejs/kit svelte xstate
|
|
|
27
25
|
## Quick Start
|
|
28
26
|
|
|
29
27
|
```typescript
|
|
28
|
+
import { onDestroy } from "svelte";
|
|
30
29
|
import { connectRouter, createRouteMap } from "@xmachines/play-sveltekit-router";
|
|
31
30
|
import { definePlayer } from "@xmachines/play-xstate";
|
|
32
31
|
import { myMachine } from "./machine.js";
|
|
@@ -46,27 +45,29 @@ const disconnect = connectRouter({ actor, routeMap });
|
|
|
46
45
|
onDestroy(() => disconnect());
|
|
47
46
|
```
|
|
48
47
|
|
|
49
|
-
The bridge
|
|
48
|
+
The bridge works in both directions:
|
|
50
49
|
|
|
51
|
-
- **URL → actor:** SvelteKit `afterNavigate`
|
|
52
|
-
- **Actor → URL:**
|
|
50
|
+
- **URL → actor:** the bridge converts each SvelteKit `afterNavigate` event into a `play.route` event, then sends it to the actor.
|
|
51
|
+
- **Actor → URL:** the bridge writes each change of the actor `currentRoute` signal to the browser URL with `goto()`.
|
|
53
52
|
|
|
54
53
|
## Usage
|
|
55
54
|
|
|
56
55
|
### `connectRouter(options)` — high-level API
|
|
57
56
|
|
|
58
|
-
|
|
57
|
+
This function is the primary integration point. It creates a `SvelteKitRouterBridge`, calls `connect()`, and returns a cleanup function.
|
|
59
58
|
|
|
60
59
|
```typescript
|
|
60
|
+
import { onDestroy } from "svelte";
|
|
61
61
|
import { connectRouter, createRouteMap } from "@xmachines/play-sveltekit-router";
|
|
62
62
|
|
|
63
|
+
// machine and actor as in the Quick Start above
|
|
63
64
|
const routeMap = createRouteMap(machine);
|
|
64
65
|
|
|
65
66
|
// In a Svelte component or SvelteKit layout
|
|
66
67
|
const disconnect = connectRouter({ actor, routeMap });
|
|
67
68
|
|
|
68
|
-
//
|
|
69
|
-
const
|
|
69
|
+
// Or pass an explicit location for SSR or test environments
|
|
70
|
+
const disconnectSsr = connectRouter({
|
|
70
71
|
actor,
|
|
71
72
|
routeMap,
|
|
72
73
|
location: { pathname: "/dashboard", search: "?tab=stats" },
|
|
@@ -78,19 +79,20 @@ onDestroy(() => disconnect());
|
|
|
78
79
|
|
|
79
80
|
**`ConnectRouterOptions`:**
|
|
80
81
|
|
|
81
|
-
| Property | Type | Required | Description
|
|
82
|
-
| ---------- | ---------------------- | -------- |
|
|
83
|
-
| `actor` | `RoutableActor` | Yes | The XMachines actor
|
|
84
|
-
| `routeMap` | `RouteMap` | Yes |
|
|
85
|
-
| `location` | `LocationLike \| null` | No |
|
|
82
|
+
| Property | Type | Required | Description |
|
|
83
|
+
| ---------- | ---------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
84
|
+
| `actor` | `RoutableActor` | Yes | The XMachines actor that the bridge keeps in step with the router |
|
|
85
|
+
| `routeMap` | `RouteMap` | Yes | The bidirectional map between the state IDs and the URL paths |
|
|
86
|
+
| `location` | `LocationLike \| null` | No | The location stub for the initial URL reads. The default is `globalThis.location`. Give a mock in a test, or a stub in an SSR environment. |
|
|
86
87
|
|
|
87
88
|
### `SvelteKitRouterBridge` — low-level class
|
|
88
89
|
|
|
89
|
-
|
|
90
|
+
This class extends `RouterBridgeBase` from `@xmachines/play-router`. Use it directly when you need more control over the connection lifecycle.
|
|
90
91
|
|
|
91
92
|
```typescript
|
|
92
93
|
import { SvelteKitRouterBridge, createRouteMap } from "@xmachines/play-sveltekit-router";
|
|
93
94
|
|
|
95
|
+
// machine and actor as in the Quick Start above
|
|
94
96
|
const routeMap = createRouteMap(machine);
|
|
95
97
|
const bridge = new SvelteKitRouterBridge(actor, routeMap, location);
|
|
96
98
|
bridge.connect();
|
|
@@ -102,12 +104,12 @@ bridge.disconnect();
|
|
|
102
104
|
**SvelteKit integration details:**
|
|
103
105
|
|
|
104
106
|
- `navigateRouter` → `goto(path, { noScroll: true, keepFocus: true })`
|
|
105
|
-
- `watchRouterChanges` → registers an `afterNavigate` callback
|
|
106
|
-
- `unwatchRouterChanges` →
|
|
107
|
+
- `watchRouterChanges` → registers an `afterNavigate` callback through an indirection cell, which prevents a direct capture of `this`
|
|
108
|
+
- `unwatchRouterChanges` → sets the indirection cell to null, which releases the bridge reference before the component unmounts (SvelteKit has no API to cancel `afterNavigate`)
|
|
107
109
|
|
|
108
110
|
### `createRouteMap(machine)`
|
|
109
111
|
|
|
110
|
-
|
|
112
|
+
This factory builds a `RouteMap` from an XState machine definition. It reads each route pattern from `state.meta.route`.
|
|
111
113
|
|
|
112
114
|
```typescript
|
|
113
115
|
import { createRouteMap } from "@xmachines/play-sveltekit-router";
|
|
@@ -128,7 +130,7 @@ const routeMap = createRouteMap(machine);
|
|
|
128
130
|
|
|
129
131
|
### `RouteMap` / `RouteMapping`
|
|
130
132
|
|
|
131
|
-
|
|
133
|
+
The bidirectional map between the state IDs and the URL paths. It comes from `@xmachines/play-router`.
|
|
132
134
|
|
|
133
135
|
```typescript
|
|
134
136
|
import { RouteMap } from "@xmachines/play-sveltekit-router";
|
|
@@ -144,22 +146,23 @@ const routeMap = new RouteMap([
|
|
|
144
146
|
|
|
145
147
|
### Exported symbols
|
|
146
148
|
|
|
147
|
-
| Export
|
|
148
|
-
|
|
|
149
|
-
| `connectRouter`
|
|
150
|
-
| `
|
|
151
|
-
| `
|
|
152
|
-
| `
|
|
153
|
-
| `
|
|
154
|
-
| `
|
|
155
|
-
| `
|
|
156
|
-
| `
|
|
157
|
-
| `
|
|
158
|
-
| `
|
|
149
|
+
| Export | Kind | Description |
|
|
150
|
+
| ----------------------- | -------- | -------------------------------------------------------------------------------------------------------------- |
|
|
151
|
+
| `connectRouter` | function | High-level factory — connects the SvelteKit router to an actor, returns a cleanup function |
|
|
152
|
+
| `SvelteKitRouterBridge` | class | The low-level bridge class. It extends `RouterBridgeBase`. Use it directly for full lifecycle control |
|
|
153
|
+
| `ConnectRouterOptions` | type | The options object for `connectRouter` |
|
|
154
|
+
| `createRouteMap` | function | Builds a `RouteMap` from an XState machine definition |
|
|
155
|
+
| `RouteMap` | class | Bidirectional state ID ↔ URL path mapping (re-exported from `@xmachines/play-router`) |
|
|
156
|
+
| `RouteMapping` | type | Single `{ stateId, path }` entry for `RouteMap` construction |
|
|
157
|
+
| `RouteMapOptions` | type | Options for `RouteMap` construction |
|
|
158
|
+
| `LocationLike` | type | Minimal `{ pathname, search }` interface for location stubs |
|
|
159
|
+
| `PlayRouteEvent` | type | The event that the bridge sends to the actor on a URL change (`{ type: "play.route", to, params?, query? }`) |
|
|
160
|
+
| `RouterBridge` | type | The interface that `SvelteKitRouterBridge` implements |
|
|
161
|
+
| `RoutableActor` | type | Minimal actor interface from `@xmachines/play-router` — `currentRoute`, `initialRoute`, `send(PlayRouteEvent)` |
|
|
159
162
|
|
|
160
163
|
## Demo
|
|
161
164
|
|
|
162
|
-
|
|
165
|
+
[`examples/demo/`](examples/demo/README.md) holds a runnable Svelte 5 and SvelteKit demo of the adapter. Run it from the monorepo root:
|
|
163
166
|
|
|
164
167
|
```bash
|
|
165
168
|
pnpm install
|
package/dist/connect-router.d.ts
CHANGED
|
@@ -3,15 +3,16 @@ export interface ConnectRouterOptions {
|
|
|
3
3
|
readonly actor: RoutableActor;
|
|
4
4
|
readonly routeMap: RouteMap;
|
|
5
5
|
/**
|
|
6
|
-
*
|
|
7
|
-
*
|
|
6
|
+
* The location-like object for the initial URL reads. The default is
|
|
7
|
+
* `globalThis.location`. Give a mock in a test, or a stub in an SSR
|
|
8
|
+
* environment.
|
|
8
9
|
*/
|
|
9
10
|
readonly location?: LocationLike | null;
|
|
10
11
|
}
|
|
11
12
|
/**
|
|
12
|
-
*
|
|
13
|
+
* Connects the SvelteKit router to an actor.
|
|
13
14
|
*
|
|
14
|
-
*
|
|
15
|
+
* It returns a cleanup function. The public API surface stays as it was (D-14).
|
|
15
16
|
*
|
|
16
17
|
* @example
|
|
17
18
|
* ```typescript
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connect-router.d.ts","sourceRoot":"","sources":["../src/connect-router.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAGpF,MAAM,WAAW,oBAAoB;IACpC,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC;IAC9B,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B
|
|
1
|
+
{"version":3,"file":"connect-router.d.ts","sourceRoot":"","sources":["../src/connect-router.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAGpF,MAAM,WAAW,oBAAoB;IACpC,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC;IAC9B,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;CACxC;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,oBAAoB,GAAG,MAAM,IAAI,CAIvE"}
|
package/dist/connect-router.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { SvelteKitRouterBridge } from "./sveltekit-router-bridge.js";
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
3
|
+
* Connects the SvelteKit router to an actor.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
5
|
+
* It returns a cleanup function. The public API surface stays as it was (D-14).
|
|
6
6
|
*
|
|
7
7
|
* @example
|
|
8
8
|
* ```typescript
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connect-router.js","sourceRoot":"","sources":["../src/connect-router.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"connect-router.js","sourceRoot":"","sources":["../src/connect-router.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAarE;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,aAAa,CAAC,OAA6B;IAC1D,MAAM,MAAM,GAAG,IAAI,qBAAqB,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC5F,MAAM,CAAC,OAAO,EAAE,CAAC;IACjB,OAAO,GAAG,EAAE,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;AAClC,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* @xmachines/play-sveltekit-router - SvelteKit router adapter for XMachines Play
|
|
3
3
|
*/
|
|
4
4
|
export { RouteMap, createRouteMap, type RouteMapping, type RouteMapOptions, } from "@xmachines/play-router";
|
|
5
|
+
export { SvelteKitRouterBridge } from "./sveltekit-router-bridge.js";
|
|
5
6
|
export { connectRouter } from "./connect-router.js";
|
|
6
7
|
export type { ConnectRouterOptions } from "./connect-router.js";
|
|
7
8
|
export type { LocationLike } from "@xmachines/play-router";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACN,QAAQ,EACR,cAAc,EACd,KAAK,YAAY,EACjB,KAAK,eAAe,GACpB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,YAAY,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAChE,YAAY,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAC3D,YAAY,EAAE,cAAc,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACN,QAAQ,EACR,cAAc,EACd,KAAK,YAAY,EACjB,KAAK,eAAe,GACpB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,YAAY,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAChE,YAAY,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAC3D,YAAY,EAAE,cAAc,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -2,5 +2,6 @@
|
|
|
2
2
|
* @xmachines/play-sveltekit-router - SvelteKit router adapter for XMachines Play
|
|
3
3
|
*/
|
|
4
4
|
export { RouteMap, createRouteMap, } from "@xmachines/play-router";
|
|
5
|
+
export { SvelteKitRouterBridge } from "./sveltekit-router-bridge.js";
|
|
5
6
|
export { connectRouter } from "./connect-router.js";
|
|
6
7
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACN,QAAQ,EACR,cAAc,GAGd,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACN,QAAQ,EACR,cAAc,GAGd,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC"}
|
|
@@ -2,57 +2,59 @@ import { RouterBridgeBase } from "@xmachines/play-router";
|
|
|
2
2
|
import type { LocationLike, RouteMap } from "@xmachines/play-router";
|
|
3
3
|
import type { RoutableActor } from "@xmachines/play-router";
|
|
4
4
|
/**
|
|
5
|
-
* SvelteKit router bridge —
|
|
5
|
+
* The SvelteKit router bridge — it connects the SvelteKit navigation to RouterBridgeBase.
|
|
6
6
|
*
|
|
7
|
-
*
|
|
7
|
+
* It implements the three abstract methods:
|
|
8
8
|
* - `navigateRouter` → `goto(path, { noScroll: true, keepFocus: true })`
|
|
9
|
-
* - `watchRouterChanges` → `afterNavigate()` subscription
|
|
10
|
-
* - `unwatchRouterChanges` →
|
|
11
|
-
*
|
|
9
|
+
* - `watchRouterChanges` → an `afterNavigate()` subscription through an indirection cell
|
|
10
|
+
* - `unwatchRouterChanges` → it sets the cell to null. This releases the bridge
|
|
11
|
+
* reference of the registered closure before the component unmounts
|
|
12
12
|
*
|
|
13
|
-
*
|
|
13
|
+
* It overrides two optional hooks:
|
|
14
14
|
* - `getInitialRouterPath` → `loc.pathname`
|
|
15
15
|
* - `getInitialRouterSearch` → `loc.search`
|
|
16
16
|
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
17
|
+
* The bridge inherits the restore-or-deeplink detection and the `lastSyncedPath`
|
|
18
|
+
* echo suppression from `RouterBridgeBase`.
|
|
19
19
|
*
|
|
20
20
|
* @param actor - A `Routable` actor.
|
|
21
|
-
* @param routeMap -
|
|
22
|
-
* @param loc -
|
|
23
|
-
* `globalThis.location`.
|
|
21
|
+
* @param routeMap - The bidirectional route map.
|
|
22
|
+
* @param loc - The location-like object for the initial URL reads. The default
|
|
23
|
+
* is `globalThis.location`. Give a mock in a test, or a stub in an SSR
|
|
24
|
+
* environment.
|
|
24
25
|
*/
|
|
25
26
|
export declare class SvelteKitRouterBridge extends RouterBridgeBase {
|
|
26
27
|
private readonly loc;
|
|
27
28
|
/**
|
|
28
|
-
*
|
|
29
|
+
* The indirection cell that this class shares with the `afterNavigate` closure.
|
|
29
30
|
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
* unmounts.
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
* callback registry.
|
|
31
|
+
* The `afterNavigate` function of SvelteKit has no API to cancel a callback. A
|
|
32
|
+
* registered closure stays in the internal Set of the framework until the Svelte
|
|
33
|
+
* component unmounts. Therefore the closure does not hold `this`, because that
|
|
34
|
+
* holds the bridge in memory until the unmount. The closure holds the cell object
|
|
35
|
+
* instead, and it reads `cell.bridge` on each call. `unwatchRouterChanges` sets
|
|
36
|
+
* `cell.bridge` to `null`. This releases the bridge reference, and each later call
|
|
37
|
+
* then does nothing and costs almost nothing. The cell also keeps the internal
|
|
38
|
+
* callback registry of SvelteKit untouched.
|
|
38
39
|
*/
|
|
39
40
|
private afterNavigateCell;
|
|
40
41
|
constructor(actor: RoutableActor, routeMap: RouteMap, loc?: LocationLike | null);
|
|
41
42
|
/**
|
|
42
|
-
*
|
|
43
|
+
* Pushes a RESOLVED concrete URL path through the SvelteKit `goto` function.
|
|
43
44
|
*
|
|
44
|
-
* The base class resolves
|
|
45
|
-
*
|
|
45
|
+
* The base class resolves each stateId, and it skips a route that it cannot
|
|
46
|
+
* resolve, before it calls this method. Therefore this method pushes the value
|
|
47
|
+
* without a change.
|
|
46
48
|
*/
|
|
47
49
|
protected navigateRouter(path: string): void;
|
|
48
50
|
protected watchRouterChanges(): void;
|
|
49
51
|
/**
|
|
50
|
-
*
|
|
52
|
+
* Releases the bridge reference that the `afterNavigate` closure holds.
|
|
51
53
|
*
|
|
52
|
-
* SvelteKit
|
|
53
|
-
*
|
|
54
|
-
* makes
|
|
55
|
-
*
|
|
54
|
+
* SvelteKit has no API to cancel a callback. The registered closure stays in the
|
|
55
|
+
* internal Set of the framework until the component unmounts. A `null` value in
|
|
56
|
+
* `cell.bridge` makes each later call do nothing, and the garbage collector can
|
|
57
|
+
* then take this bridge before the component unmounts.
|
|
56
58
|
*/
|
|
57
59
|
protected unwatchRouterChanges(): void;
|
|
58
60
|
protected getInitialRouterPath(): string | null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sveltekit-router-bridge.d.ts","sourceRoot":"","sources":["../src/sveltekit-router-bridge.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AACrE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"sveltekit-router-bridge.d.ts","sourceRoot":"","sources":["../src/sveltekit-router-bridge.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AACrE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAc5D;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,qBAAa,qBAAsB,SAAQ,gBAAgB;IAC1D,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAsB;IAE1C;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,iBAAiB,CAAsC;gBAG9D,KAAK,EAAE,aAAa,EACpB,QAAQ,EAAE,QAAQ,EAClB,GAAG,GAAE,YAAY,GAAG,IAAmE;IAMxF;;;;;;OAMG;IACH,SAAS,CAAC,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAI5C,SAAS,CAAC,kBAAkB,IAAI,IAAI;IAmBpC;;;;;;;OAOG;IACH,SAAS,CAAC,oBAAoB,IAAI,IAAI;cAOnB,oBAAoB,IAAI,MAAM,GAAG,IAAI;cAIrC,sBAAsB,IAAI,MAAM,GAAG,SAAS;CAG/D"}
|
|
@@ -1,39 +1,40 @@
|
|
|
1
1
|
import { afterNavigate, goto } from "$app/navigation";
|
|
2
2
|
import { RouterBridgeBase } from "@xmachines/play-router";
|
|
3
3
|
/**
|
|
4
|
-
* SvelteKit router bridge —
|
|
4
|
+
* The SvelteKit router bridge — it connects the SvelteKit navigation to RouterBridgeBase.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
6
|
+
* It implements the three abstract methods:
|
|
7
7
|
* - `navigateRouter` → `goto(path, { noScroll: true, keepFocus: true })`
|
|
8
|
-
* - `watchRouterChanges` → `afterNavigate()` subscription
|
|
9
|
-
* - `unwatchRouterChanges` →
|
|
10
|
-
*
|
|
8
|
+
* - `watchRouterChanges` → an `afterNavigate()` subscription through an indirection cell
|
|
9
|
+
* - `unwatchRouterChanges` → it sets the cell to null. This releases the bridge
|
|
10
|
+
* reference of the registered closure before the component unmounts
|
|
11
11
|
*
|
|
12
|
-
*
|
|
12
|
+
* It overrides two optional hooks:
|
|
13
13
|
* - `getInitialRouterPath` → `loc.pathname`
|
|
14
14
|
* - `getInitialRouterSearch` → `loc.search`
|
|
15
15
|
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
16
|
+
* The bridge inherits the restore-or-deeplink detection and the `lastSyncedPath`
|
|
17
|
+
* echo suppression from `RouterBridgeBase`.
|
|
18
18
|
*
|
|
19
19
|
* @param actor - A `Routable` actor.
|
|
20
|
-
* @param routeMap -
|
|
21
|
-
* @param loc -
|
|
22
|
-
* `globalThis.location`.
|
|
20
|
+
* @param routeMap - The bidirectional route map.
|
|
21
|
+
* @param loc - The location-like object for the initial URL reads. The default
|
|
22
|
+
* is `globalThis.location`. Give a mock in a test, or a stub in an SSR
|
|
23
|
+
* environment.
|
|
23
24
|
*/
|
|
24
25
|
export class SvelteKitRouterBridge extends RouterBridgeBase {
|
|
25
26
|
loc;
|
|
26
27
|
/**
|
|
27
|
-
*
|
|
28
|
+
* The indirection cell that this class shares with the `afterNavigate` closure.
|
|
28
29
|
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
* unmounts.
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
* callback registry.
|
|
30
|
+
* The `afterNavigate` function of SvelteKit has no API to cancel a callback. A
|
|
31
|
+
* registered closure stays in the internal Set of the framework until the Svelte
|
|
32
|
+
* component unmounts. Therefore the closure does not hold `this`, because that
|
|
33
|
+
* holds the bridge in memory until the unmount. The closure holds the cell object
|
|
34
|
+
* instead, and it reads `cell.bridge` on each call. `unwatchRouterChanges` sets
|
|
35
|
+
* `cell.bridge` to `null`. This releases the bridge reference, and each later call
|
|
36
|
+
* then does nothing and costs almost nothing. The cell also keeps the internal
|
|
37
|
+
* callback registry of SvelteKit untouched.
|
|
37
38
|
*/
|
|
38
39
|
afterNavigateCell = null;
|
|
39
40
|
constructor(actor, routeMap, loc = globalThis.location ?? null) {
|
|
@@ -41,17 +42,19 @@ export class SvelteKitRouterBridge extends RouterBridgeBase {
|
|
|
41
42
|
this.loc = loc;
|
|
42
43
|
}
|
|
43
44
|
/**
|
|
44
|
-
*
|
|
45
|
+
* Pushes a RESOLVED concrete URL path through the SvelteKit `goto` function.
|
|
45
46
|
*
|
|
46
|
-
* The base class resolves
|
|
47
|
-
*
|
|
47
|
+
* The base class resolves each stateId, and it skips a route that it cannot
|
|
48
|
+
* resolve, before it calls this method. Therefore this method pushes the value
|
|
49
|
+
* without a change.
|
|
48
50
|
*/
|
|
49
51
|
navigateRouter(path) {
|
|
50
52
|
void goto(path, { noScroll: true, keepFocus: true });
|
|
51
53
|
}
|
|
52
54
|
watchRouterChanges() {
|
|
53
|
-
// Create the cell and register a closure that reads from
|
|
54
|
-
// unwatchRouterChanges()
|
|
55
|
+
// Create the cell, and register a closure that reads from the cell, and not from
|
|
56
|
+
// `this`. unwatchRouterChanges() then sets cell.bridge to null, and it therefore
|
|
57
|
+
// releases the bridge before the unmount.
|
|
55
58
|
const cell = { bridge: this };
|
|
56
59
|
this.afterNavigateCell = cell;
|
|
57
60
|
afterNavigate((navigation) => {
|
|
@@ -66,12 +69,12 @@ export class SvelteKitRouterBridge extends RouterBridgeBase {
|
|
|
66
69
|
});
|
|
67
70
|
}
|
|
68
71
|
/**
|
|
69
|
-
*
|
|
72
|
+
* Releases the bridge reference that the `afterNavigate` closure holds.
|
|
70
73
|
*
|
|
71
|
-
* SvelteKit
|
|
72
|
-
*
|
|
73
|
-
* makes
|
|
74
|
-
*
|
|
74
|
+
* SvelteKit has no API to cancel a callback. The registered closure stays in the
|
|
75
|
+
* internal Set of the framework until the component unmounts. A `null` value in
|
|
76
|
+
* `cell.bridge` makes each later call do nothing, and the garbage collector can
|
|
77
|
+
* then take this bridge before the component unmounts.
|
|
75
78
|
*/
|
|
76
79
|
unwatchRouterChanges() {
|
|
77
80
|
if (this.afterNavigateCell !== null) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sveltekit-router-bridge.js","sourceRoot":"","sources":["../src/sveltekit-router-bridge.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"sveltekit-router-bridge.js","sourceRoot":"","sources":["../src/sveltekit-router-bridge.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAgB1D;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,OAAO,qBAAsB,SAAQ,gBAAgB;IACzC,GAAG,CAAsB;IAE1C;;;;;;;;;;;OAWG;IACK,iBAAiB,GAAiC,IAAI,CAAC;IAE/D,YACC,KAAoB,EACpB,QAAkB,EAClB,MAA4B,UAA0C,CAAC,QAAQ,IAAI,IAAI;QAEvF,KAAK,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;QACvB,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;IAChB,CAAC;IAED;;;;;;OAMG;IACO,cAAc,CAAC,IAAY;QACpC,KAAK,IAAI,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACtD,CAAC;IAES,kBAAkB;QAC3B,iFAAiF;QACjF,iFAAiF;QACjF,0CAA0C;QAC1C,MAAM,IAAI,GAA0B,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;QACrD,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC;QAE9B,aAAa,CAAC,CAAC,UAAU,EAAE,EAAE;YAC5B,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;YAC3B,IAAI,CAAC,MAAM;gBAAE,OAAO;YAEpB,MAAM,GAAG,GAAG,UAAU,CAAC,EAAE,EAAE,GAAG,IAAI,MAAM,CAAC,GAAG,CAAC;YAC7C,oBAAoB;YACpB,IAAI,CAAC,GAAG;gBAAE,OAAO;YAEjB,MAAM,CAAC,mBAAmB,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;QACtD,CAAC,CAAC,CAAC;IACJ,CAAC;IAED;;;;;;;OAOG;IACO,oBAAoB;QAC7B,IAAI,IAAI,CAAC,iBAAiB,KAAK,IAAI,EAAE,CAAC;YACrC,IAAI,CAAC,iBAAiB,CAAC,MAAM,GAAG,IAAI,CAAC;YACrC,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC;QAC/B,CAAC;IACF,CAAC;IAEkB,oBAAoB;QACtC,OAAO,IAAI,CAAC,GAAG,EAAE,QAAQ,IAAI,IAAI,CAAC;IACnC,CAAC;IAEkB,sBAAsB;QACxC,OAAO,IAAI,CAAC,GAAG,EAAE,MAAM,IAAI,SAAS,CAAC;IACtC,CAAC;CACD"}
|
package/dist/types.d.ts
CHANGED
package/dist/types.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xmachines/play-sveltekit-router",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "SvelteKit router adapter for XMachines Universal Player Architecture",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"adapter",
|
|
@@ -42,13 +42,14 @@
|
|
|
42
42
|
"lint": "oxlint .",
|
|
43
43
|
"format": "oxfmt .",
|
|
44
44
|
"test": "vitest",
|
|
45
|
+
"test:coverage": "vitest run --coverage",
|
|
45
46
|
"clean": "rm -rf dist *.tsbuildinfo coverage .vitest-attachments node_modules/.svelte2tsx-* node_modules/.vite*"
|
|
46
47
|
},
|
|
47
48
|
"dependencies": {
|
|
48
|
-
"@xmachines/play": "2.
|
|
49
|
-
"@xmachines/play-actor": "2.
|
|
50
|
-
"@xmachines/play-router": "2.
|
|
51
|
-
"@xmachines/play-signals": "2.
|
|
49
|
+
"@xmachines/play": "2.1.0",
|
|
50
|
+
"@xmachines/play-actor": "2.1.0",
|
|
51
|
+
"@xmachines/play-router": "2.1.0",
|
|
52
|
+
"@xmachines/play-signals": "2.1.0"
|
|
52
53
|
},
|
|
53
54
|
"devDependencies": {
|
|
54
55
|
"@sveltejs/kit": "^2.58.0",
|
|
@@ -56,7 +57,7 @@
|
|
|
56
57
|
"@testing-library/jest-dom": "^6.9.1",
|
|
57
58
|
"@types/node": "^26.2.0",
|
|
58
59
|
"@vitest/browser-playwright": "^4.1.11",
|
|
59
|
-
"@xmachines/play-svelte": "2.
|
|
60
|
+
"@xmachines/play-svelte": "2.1.0",
|
|
60
61
|
"oxfmt": "^0.64.0",
|
|
61
62
|
"oxlint": "^1.79.0",
|
|
62
63
|
"svelte": "^5.55.5",
|