@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 CHANGED
@@ -1,10 +1,8 @@
1
1
  # @xmachines/play-sveltekit-router
2
2
 
3
- SvelteKit router adapter for the XMachines Universal Player Architecture. Provides bidirectional synchronisation between a `RoutableActor`'s state machine routes and the browser URL via SvelteKit's `$app/navigation`.
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
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![Version](https://img.shields.io/badge/version-2.0.0-blue)](https://www.npmjs.com/package/@xmachines/play-sveltekit-router)
6
-
7
- Part of the [xmachines-js monorepo](../../README.md).
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![Version](https://img.shields.io/badge/version-2.1.0-blue)](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** (must be installed separately):
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 synchronises in both directions:
48
+ The bridge works in both directions:
50
49
 
51
- - **URL → actor:** SvelteKit `afterNavigate` events are translated to `play.route` events and sent to the actor.
52
- - **Actor → URL:** Actor `currentRoute` signal changes are reflected to the browser URL via `goto()`.
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
- The primary integration point. Instantiates a `SvelteKitRouterBridge`, calls `connect()`, and returns a cleanup function.
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
- // Pass an explicit location for SSR or test environments
69
- const disconnect = connectRouter({
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 to synchronise with the router |
84
- | `routeMap` | `RouteMap` | Yes | Bidirectional state ID URL path mapping |
85
- | `location` | `LocationLike \| null` | No | Location stub for initial URL reads. Defaults to `globalThis.location`. Pass a mock in tests or a stub in SSR environments. |
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
- Extends `RouterBridgeBase` from `@xmachines/play-router`. Use directly when you need fine-grained control over the connection lifecycle.
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 via an indirection cell, avoiding direct `this` capture
106
- - `unwatchRouterChanges` → nulls the indirection cell, releasing the bridge reference before component unmount (since SvelteKit provides no programmatic cancel API for `afterNavigate`)
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
- Factory that builds a `RouteMap` from an XState machine definition. State route patterns are read from `state.meta.route`.
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
- Bidirectional state ID URL path mapping. Re-exported from `@xmachines/play-router`.
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 | Kind | Description |
148
- | ---------------------- | -------- | -------------------------------------------------------------------------------------------------------------- |
149
- | `connectRouter` | function | High-level factory — connects the SvelteKit router to an actor, returns a cleanup function |
150
- | `ConnectRouterOptions` | type | Options bag for `connectRouter` |
151
- | `createRouteMap` | function | Builds a `RouteMap` from an XState machine definition |
152
- | `RouteMap` | class | Bidirectional state ID URL path mapping (re-exported from `@xmachines/play-router`) |
153
- | `RouteMapping` | type | Single `{ stateId, path }` entry for `RouteMap` construction |
154
- | `RouteMapOptions` | type | Options for `RouteMap` construction |
155
- | `LocationLike` | type | Minimal `{ pathname, search }` interface for location stubs |
156
- | `PlayRouteEvent` | type | Event sent to the actor on URL change (`{ type: "play.route", to, params?, query? }`) |
157
- | `RouterBridge` | type | Interface implemented by `SvelteKitRouterBridge` |
158
- | `RoutableActor` | type | Minimal actor interface from `@xmachines/play-router``currentRoute`, `initialRoute`, `send(PlayRouteEvent)` |
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
- A runnable Svelte 5 + SvelteKit router adapter demo is available in [`examples/demo/`](examples/demo/README.md). To run it from the monorepo root:
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
@@ -3,15 +3,16 @@ export interface ConnectRouterOptions {
3
3
  readonly actor: RoutableActor;
4
4
  readonly routeMap: RouteMap;
5
5
  /**
6
- * Location-like object for initial URL reads. Defaults to `globalThis.location`.
7
- * Pass a mock in tests or a stub in SSR environments.
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
- * Connect SvelteKit router to actor.
13
+ * Connects the SvelteKit router to an actor.
13
14
  *
14
- * Returns a cleanup function. The public API surface is unchanged (D-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;;;OAGG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;CACxC;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,oBAAoB,GAAG,MAAM,IAAI,CAIvE"}
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"}
@@ -1,8 +1,8 @@
1
1
  import { SvelteKitRouterBridge } from "./sveltekit-router-bridge.js";
2
2
  /**
3
- * Connect SvelteKit router to actor.
3
+ * Connects the SvelteKit router to an actor.
4
4
  *
5
- * Returns a cleanup function. The public API surface is unchanged (D-14).
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;AAYrE;;;;;;;;;;;;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"}
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";
@@ -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 — integrates SvelteKit navigation with RouterBridgeBase.
5
+ * The SvelteKit router bridge — it connects the SvelteKit navigation to RouterBridgeBase.
6
6
  *
7
- * Implements the three abstract methods:
7
+ * It implements the three abstract methods:
8
8
  * - `navigateRouter` → `goto(path, { noScroll: true, keepFocus: true })`
9
- * - `watchRouterChanges` → `afterNavigate()` subscription via an indirection cell
10
- * - `unwatchRouterChanges` → nulls the cell, releasing the bridge reference
11
- * held by the registered closure before component unmount
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
- * Overrides optional hooks:
13
+ * It overrides two optional hooks:
14
14
  * - `getInitialRouterPath` → `loc.pathname`
15
15
  * - `getInitialRouterSearch` → `loc.search`
16
16
  *
17
- * Restore-vs-deeplink detection and `lastSyncedPath` echo suppression are
18
- * inherited from `RouterBridgeBase`.
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 - Bidirectional route map.
22
- * @param loc - Location-like object for initial URL reads. Defaults to
23
- * `globalThis.location`. Pass a mock in tests or a stub in SSR environments.
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
- * Indirection cell shared with the `afterNavigate` closure.
29
+ * The indirection cell that this class shares with the `afterNavigate` closure.
29
30
  *
30
- * SvelteKit's `afterNavigate` has no programmatic cancel API registered
31
- * closures remain in the framework's internal Set until the Svelte component
32
- * unmounts. Rather than capturing `this` inside the registered closure (which
33
- * would pin the bridge in memory until unmount), the closure captures the cell
34
- * object and reads `cell.bridge` on each invocation. `unwatchRouterChanges`
35
- * sets `cell.bridge` to `null`, releasing the bridge reference and making
36
- * subsequent invocations a cheap no-op without touching SvelteKit's internal
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
- * Push a RESOLVED concrete URL path via SvelteKit's `goto`.
43
+ * Pushes a RESOLVED concrete URL path through the SvelteKit `goto` function.
43
44
  *
44
- * The base class resolves stateIds and skips unresolvable routes before
45
- * calling this method the value is pushed as-is.
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
- * Release the bridge reference held inside the `afterNavigate` closure.
52
+ * Releases the bridge reference that the `afterNavigate` closure holds.
51
53
  *
52
- * SvelteKit provides no programmatic cancel API the registered closure stays
53
- * in the framework's internal Set until component unmount. Nulling `cell.bridge`
54
- * makes subsequent invocations a no-op and allows this bridge to be
55
- * garbage-collected before the component unmounts.
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;AAa5D;;;;;;;;;;;;;;;;;;;;GAoBG;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;;;;;OAKG;IACH,SAAS,CAAC,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAI5C,SAAS,CAAC,kBAAkB,IAAI,IAAI;IAkBpC;;;;;;;OAOG;IACH,SAAS,CAAC,oBAAoB,IAAI,IAAI;cAOnB,oBAAoB,IAAI,MAAM,GAAG,IAAI;cAIrC,sBAAsB,IAAI,MAAM,GAAG,SAAS;CAG/D"}
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 — integrates SvelteKit navigation with RouterBridgeBase.
4
+ * The SvelteKit router bridge — it connects the SvelteKit navigation to RouterBridgeBase.
5
5
  *
6
- * Implements the three abstract methods:
6
+ * It implements the three abstract methods:
7
7
  * - `navigateRouter` → `goto(path, { noScroll: true, keepFocus: true })`
8
- * - `watchRouterChanges` → `afterNavigate()` subscription via an indirection cell
9
- * - `unwatchRouterChanges` → nulls the cell, releasing the bridge reference
10
- * held by the registered closure before component unmount
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
- * Overrides optional hooks:
12
+ * It overrides two optional hooks:
13
13
  * - `getInitialRouterPath` → `loc.pathname`
14
14
  * - `getInitialRouterSearch` → `loc.search`
15
15
  *
16
- * Restore-vs-deeplink detection and `lastSyncedPath` echo suppression are
17
- * inherited from `RouterBridgeBase`.
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 - Bidirectional route map.
21
- * @param loc - Location-like object for initial URL reads. Defaults to
22
- * `globalThis.location`. Pass a mock in tests or a stub in SSR environments.
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
- * Indirection cell shared with the `afterNavigate` closure.
28
+ * The indirection cell that this class shares with the `afterNavigate` closure.
28
29
  *
29
- * SvelteKit's `afterNavigate` has no programmatic cancel API registered
30
- * closures remain in the framework's internal Set until the Svelte component
31
- * unmounts. Rather than capturing `this` inside the registered closure (which
32
- * would pin the bridge in memory until unmount), the closure captures the cell
33
- * object and reads `cell.bridge` on each invocation. `unwatchRouterChanges`
34
- * sets `cell.bridge` to `null`, releasing the bridge reference and making
35
- * subsequent invocations a cheap no-op without touching SvelteKit's internal
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
- * Push a RESOLVED concrete URL path via SvelteKit's `goto`.
45
+ * Pushes a RESOLVED concrete URL path through the SvelteKit `goto` function.
45
46
  *
46
- * The base class resolves stateIds and skips unresolvable routes before
47
- * calling this method the value is pushed as-is.
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 it, not from `this`.
54
- // unwatchRouterChanges() nulls cell.bridge to release the bridge before unmount.
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
- * Release the bridge reference held inside the `afterNavigate` closure.
72
+ * Releases the bridge reference that the `afterNavigate` closure holds.
70
73
  *
71
- * SvelteKit provides no programmatic cancel API the registered closure stays
72
- * in the framework's internal Set until component unmount. Nulling `cell.bridge`
73
- * makes subsequent invocations a no-op and allows this bridge to be
74
- * garbage-collected before the component unmounts.
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;AAe1D;;;;;;;;;;;;;;;;;;;;GAoBG;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;;;;;OAKG;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,8EAA8E;QAC9E,iFAAiF;QACjF,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"}
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
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Type definitions for @xmachines/play-sveltekit-router
2
+ * The type definitions of @xmachines/play-sveltekit-router
3
3
  */
4
4
  import type { AbstractActor, Routable } from "@xmachines/play-actor";
5
5
  import type { AnyActorLogic } from "xstate";
package/dist/types.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Type definitions for @xmachines/play-sveltekit-router
2
+ * The type definitions of @xmachines/play-sveltekit-router
3
3
  */
4
4
  export {};
5
5
  //# sourceMappingURL=types.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xmachines/play-sveltekit-router",
3
- "version": "2.0.0",
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.0.0",
49
- "@xmachines/play-actor": "2.0.0",
50
- "@xmachines/play-router": "2.0.0",
51
- "@xmachines/play-signals": "2.0.0"
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.0.0",
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",