@xmachines/play-xstate 4.0.0 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/README.md +61 -30
  2. package/dist/capabilities.d.ts +4 -3
  3. package/dist/capabilities.d.ts.map +1 -1
  4. package/dist/capabilities.js.map +1 -1
  5. package/dist/errors.d.ts +38 -0
  6. package/dist/errors.d.ts.map +1 -1
  7. package/dist/errors.js +44 -0
  8. package/dist/errors.js.map +1 -1
  9. package/dist/index.d.ts +2 -2
  10. package/dist/index.js +2 -2
  11. package/dist/player-actor.d.ts +30 -29
  12. package/dist/player-actor.d.ts.map +1 -1
  13. package/dist/player-actor.js +51 -41
  14. package/dist/player-actor.js.map +1 -1
  15. package/dist/routing/build-url.d.ts +8 -1
  16. package/dist/routing/build-url.d.ts.map +1 -1
  17. package/dist/routing/build-url.js +34 -54
  18. package/dist/routing/build-url.js.map +1 -1
  19. package/dist/routing/derive-current-route.d.ts +11 -2
  20. package/dist/routing/derive-current-route.d.ts.map +1 -1
  21. package/dist/routing/derive-current-route.js +22 -6
  22. package/dist/routing/derive-current-route.js.map +1 -1
  23. package/dist/routing/derive-initial-route.d.ts +2 -1
  24. package/dist/routing/derive-initial-route.d.ts.map +1 -1
  25. package/dist/routing/derive-initial-route.js +2 -2
  26. package/dist/routing/derive-initial-route.js.map +1 -1
  27. package/dist/routing/format-play-route-transitions.js +10 -5
  28. package/dist/routing/format-play-route-transitions.js.map +1 -1
  29. package/dist/types.d.ts +2 -2
  30. package/dist/types.d.ts.map +1 -1
  31. package/dist/view/derive-current-view.d.ts +6 -5
  32. package/dist/view/derive-current-view.d.ts.map +1 -1
  33. package/dist/view/derive-current-view.js +5 -4
  34. package/dist/view/derive-current-view.js.map +1 -1
  35. package/dist/with-routing.d.ts.map +1 -1
  36. package/dist/with-routing.js +66 -4
  37. package/dist/with-routing.js.map +1 -1
  38. package/dist/with-view.d.ts +19 -4
  39. package/dist/with-view.d.ts.map +1 -1
  40. package/dist/with-view.js +64 -56
  41. package/dist/with-view.js.map +1 -1
  42. package/package.json +14 -13
@@ -1,6 +1,6 @@
1
1
  import { Actor, } from "xstate";
2
2
  import { DISPOSE } from "@xmachines/play";
3
- import { Signal } from "@xmachines/play-signals";
3
+ import { createWritableAtom } from "@xmachines/play-atom";
4
4
  import { ActorThrewNonErrorError, InvalidEventError, InvalidMachineError } from "./errors.js";
5
5
  /**
6
6
  * Tells you if a value is an `Error`, by its identity or by its brand: `instanceof`
@@ -44,15 +44,15 @@ export const toError = (value) => {
44
44
  return new ActorThrewNonErrorError(value);
45
45
  };
46
46
  /**
47
- * Tells you if a snapshot is worth a propagation to the signals: an active
47
+ * Tells you if a snapshot is worth a propagation to the atoms: an active
48
48
  * snapshot, or a "done" snapshot, which means that the machine reached a final state
49
49
  * at the top level. The code skips an error snapshot and a stopped snapshot.
50
- * Therefore the signals keep the last observable state, and they show no artifact of
50
+ * Therefore the atoms keep the last observable state, and they show no artifact of
51
51
  * a teardown or of an error.
52
52
  */
53
53
  const isObservableSnapshot = (snapshot) => snapshot.status === "active" || snapshot.status === "done";
54
54
  /**
55
- * The concrete XState actor. It implements the signal protocol of the Play Architecture
55
+ * The concrete XState actor. It implements the atom protocol of the Play Architecture
56
56
  *
57
57
  * The class extends the `Actor` class of XState directly, and it implements
58
58
  * {@link @xmachines/play-actor!PlayActor}. It gives you the XState v5 integration, and it keeps the
@@ -60,7 +60,7 @@ const isObservableSnapshot = (snapshot) => snapshot.status === "active" || snaps
60
60
  * The constructor of the base class receives the machine. Therefore a `PlayerActor`
61
61
  * **is** the XState actor, and it is no wrapper around one: every member of the
62
62
  * XState `Actor` class works on the state of this instance, and this class adds the
63
- * reactive state on the TC39 Signals for the observation by the infrastructure.
63
+ * reactive state on the atoms for the observation by the infrastructure.
64
64
  *
65
65
  * **Capabilities:** the class implements both the
66
66
  * {@link @xmachines/play-router!index.Routable} interface and the
@@ -69,7 +69,7 @@ const isObservableSnapshot = (snapshot) => snapshot.status === "active" || snaps
69
69
  *
70
70
  * **Architectural context:** the class implements **Actor Authority (INV-01)**,
71
71
  * because the guards of the XState machine control every decision of the
72
- * navigation. The infrastructure observes the signals of the actor (`state`,
72
+ * navigation. The infrastructure observes the atoms of the actor (`state`,
73
73
  * `currentRoute`, and `currentView`), but it changes no state directly: every
74
74
  * change goes through the event handlers of the state machine.
75
75
  *
@@ -101,31 +101,29 @@ const isObservableSnapshot = (snapshot) => snapshot.status === "active" || snaps
101
101
  * const actor = createPlayer();
102
102
  * actor.start();
103
103
  *
104
- * // Observe the signals
104
+ * // Observe the atoms
105
105
  * console.log(actor.currentRoute.get()); // '/'
106
106
  * console.log(actor.currentView.get()?.root); // 'home'
107
107
  * ```
108
108
  *
109
109
  * @example
110
- * The signal lifecycle with a watcher
110
+ * The atom lifecycle with a watch
111
111
  * ```typescript
112
- * import { Signal } from "@xmachines/play-signals";
112
+ * import { watchAtom } from "@xmachines/play-atom";
113
113
  *
114
- * const watcher = new Signal.subtle.Watcher(() => {
115
- * queueMicrotask(() => {
116
- * const pending = watcher.getPending();
117
- * console.log('State changed:', actor.state.get());
118
- * });
114
+ * const stop = watchAtom(actor.state, (snapshot) => {
115
+ * console.log('State changed:', snapshot.value);
119
116
  * });
120
117
  *
121
- * watcher.watch(actor.state);
122
118
  * actor.send({ type: 'play.route', to: '#about' });
123
- * // The watcher schedules its own notification in a microtask
119
+ * // watchAtom delivers the new value from a microtask
120
+ *
121
+ * stop();
124
122
  * ```
125
123
  *
126
124
  * @see [Play RFC](../../docs/rfc/play.md)
127
125
  * @see {@link definePlayer} for the creation through a factory
128
- * @see {@link @xmachines/play-actor!PlayActor} for the signal protocol
126
+ * @see {@link @xmachines/play-actor!PlayActor} for the atom protocol
129
127
  * @see {@link @xmachines/play-router!index.Routable} for the routing capability
130
128
  * @see {@link @xmachines/play-view!index.Viewable} for the view rendering capability
131
129
  *
@@ -135,10 +133,11 @@ const isObservableSnapshot = (snapshot) => snapshot.status === "active" || snaps
135
133
  * `meta.route`, which is the Stately pattern, for a URL template, and it substitutes
136
134
  * each parameter.
137
135
  *
138
- * **The pattern of the view signal:** the `currentView` signal is a direct
139
- * `Signal.State`, and not a `Signal.Computed`. The propagation to a watcher in
140
- * PlayRenderer is therefore correct. The class derives each view at the entry of a
141
- * state and keeps it, and it computes no view on a read.
136
+ * **The pattern of the view atom:** `withView` of `@xmachines/play-xstate/view` adds
137
+ * `currentView`, and that atom is a COMPUTED atom over `state`. One write for each
138
+ * transition — `state.set(snapshot)` — therefore reaches the view and the route in one
139
+ * flush, and no subscriber reads the new state beside an old derivation. The atom
140
+ * memoizes the result, so a repeated read computes no view again.
142
141
  */
143
142
  export class PlayerActor extends Actor {
144
143
  playerOptions;
@@ -180,7 +179,7 @@ export class PlayerActor extends Actor {
180
179
  * Tells you if the current state of the actor accepts the given event.
181
180
  *
182
181
  * The type is the event union of the machine. An unknown event type is therefore a
183
- * compile error. The method evaluates the event against the snapshot signal.
182
+ * compile error. The method evaluates the event against the snapshot atom.
184
183
  *
185
184
  * @example
186
185
  * ```typescript
@@ -188,7 +187,7 @@ export class PlayerActor extends Actor {
188
187
  * ```
189
188
  */
190
189
  can(event) {
191
- // A read of the signal keeps can() reactive: a Signal.Computed over the signal
190
+ // A read of the atom keeps can() reactive: a computed atom over the atom
192
191
  // computes its value again on each transition.
193
192
  const snapshot = this.state?.get();
194
193
  // The STATUS decides first, and the presence of the method decides second.
@@ -201,7 +200,7 @@ export class PlayerActor extends Actor {
201
200
  // `done` actor answers `false` for the same reason.
202
201
  //
203
202
  // A STOPPED actor is the exception, and it is deliberate: the subscription below
204
- // updates this signal on a stable state alone, so the signal keeps the last ACTIVE
203
+ // updates this atom on a stable state alone, so the atom keeps the last ACTIVE
205
204
  // snapshot after a teardown rather than freezing on an artifact of it. `can()`
206
205
  // therefore answers for the last live state of a stopped actor.
207
206
  if (snapshot?.status !== "active")
@@ -235,11 +234,15 @@ export class PlayerActor extends Actor {
235
234
  this.playerInput = input;
236
235
  this.playerRestoredSnapshot = restoredSnapshot;
237
236
  this.playerOptions = options || {};
238
- // Initialize the state signal. Each update is synchronous, with no batching in a
237
+ // Initialize the state atom. Each update is synchronous, with no batching in a
239
238
  // microtask: XState groups the transitions of one send() call into one
240
239
  // subscription callback already, and a synchronous update shows each guard
241
240
  // redirect to a router bridge at once.
242
- this.state = new Signal.State(this.getSnapshot());
241
+ // `createWritableAtom`, and not `createAtom`. The overload pair of `createAtom` reads
242
+ // a function argument as a computed atom, and `ReturnType<TMachine["transition"]>` is
243
+ // an unresolved conditional type here, so TypeScript cannot rule a function out. It
244
+ // picks the computed signature, which returns a `ReadonlyAtom` that carries no `set`.
245
+ this.state = createWritableAtom(this.getSnapshot());
243
246
  // Observe the transitions of this actor. The code uses `super`, and not `this`, so
244
247
  // that the bookkeeping of the next-only subscriptions in the subscribe override
245
248
  // stays about the subscriptions of the user code.
@@ -247,16 +250,21 @@ export class PlayerActor extends Actor {
247
250
  next: (snapshot) => {
248
251
  // Update on a stable state only: an active snapshot, and the "done" snapshot of a
249
252
  // final state at the top level. The code skips an error snapshot and a stopped
250
- // snapshot. Therefore a signal never freezes on an artifact of a teardown.
253
+ // snapshot. Therefore an atom never freezes on an artifact of a teardown.
251
254
  if (isObservableSnapshot(snapshot)) {
252
255
  // Each state update is synchronous. Therefore a router bridge sees a guard redirect at once.
253
256
  this.state.set(snapshot);
254
- // Every capability derives here, and the ORDER is the composition order:
255
- // `compose(PlayerActor, withRouting, withView)` makes `withView` the outermost
256
- // class, so its override runs `super.onSnapshot()` first and the routing
257
- // capability therefore holds its new value before the view derives from it.
257
+ // ONE write for each transition, and the line above is it. `currentRoute` and
258
+ // `currentView` are computed atoms over `state`, so that write propagates to
259
+ // both in ONE flush, in topological order. No observer therefore reads the new
260
+ // state beside an old derivation, and the composition order of the capabilities
261
+ // decides nothing.
262
+ //
263
+ // `onSnapshot` remains for a capability that must run an EFFECT on a
264
+ // transition. A capability that publishes a value derives it instead.
265
+ //
258
266
  // The whole order of one transition:
259
- // 1. state receives its new value, and each Computed over it follows
267
+ // 1. state receives its new value, and every computed atom over it follows
260
268
  // 2. onSnapshot runs each capability, in the composition order
261
269
  // 3. the onStateChange hook runs
262
270
  // 4. send() then calls onTransition
@@ -332,7 +340,7 @@ export class PlayerActor extends Actor {
332
340
  // A call that reaches in through the construction window, for example a context
333
341
  // factory that stops its own `self`, marks the actor as stopped before the code
334
342
  // registers its internal subscription. XState drops each observer of a stopped
335
- // actor. The signals therefore move never again. There is nothing to tear down
343
+ // actor. The atoms therefore move never again. There is nothing to tear down
336
344
  // during the construction, and the code ignores such a call.
337
345
  if (!this.constructed) {
338
346
  return this;
@@ -436,17 +444,19 @@ export class PlayerActor extends Actor {
436
444
  return forward.call(this, options);
437
445
  }
438
446
  /**
439
- * The point where a capability derives its own signals from a new snapshot.
447
+ * The point where a capability derives its own atoms from a new snapshot.
440
448
  *
441
449
  * The base derives nothing: `PlayActor` asks for `state` and `send`, and this class
442
- * gives exactly those. A capability is a mixin that overrides this method, calls
443
- * `super.onSnapshot(snapshot)` FIRST, and then writes its own signal.
450
+ * gives exactly those.
451
+ *
452
+ * A capability that PUBLISHES a value overrides this method NOT. It derives the value
453
+ * with a computed atom over `state`, as `withRouting` and `withView` both do, and the
454
+ * engine then evaluates every derivation from the one write of a transition, in
455
+ * topological order. The composition order therefore decides no value.
444
456
  *
445
- * That one rule fixes the order, and the order is load-bearing. The view of a state
446
- * reads the route and the state that the same transition produced, and a router bridge
447
- * must see a guard redirect synchronously. `compose(PlayerActor, withRouting, withView)`
448
- * therefore derives the route before the view, because `withView` wraps the class that
449
- * `withRouting` returned.
457
+ * This method remains for a capability that must run an EFFECT on a transition. Such a
458
+ * mixin overrides it and calls `super.onSnapshot(snapshot)` FIRST, so that every
459
+ * capability composed before it runs its own effect first.
450
460
  *
451
461
  * The method runs after `state` holds the new snapshot and before the `onStateChange`
452
462
  * hook of the options.
@@ -1 +1 @@
1
- {"version":3,"file":"player-actor.js","sourceRoot":"","sources":["../src/player-actor.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"player-actor.js","sourceRoot":"","sources":["../src/player-actor.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ import type { ParseOptions } from "@xmachines/play-pattern";
1
2
  import type { RouteContext } from "./types.js";
2
3
  /**
3
4
  * Builds a complete URL from a route template and the context of the actor.
@@ -16,12 +17,18 @@ import type { RouteContext } from "./types.js";
16
17
  * @param context - The context object of the actor. Each route parameter must be in
17
18
  * `context.params`, because the function reads no flat context field. An absent
18
19
  * `query` field builds a URL without a query, exactly like `query: {}`.
20
+ * @param options - The caches to read, as {@link ParseOptions}. The default is the cache
21
+ * that `@xmachines/play-pattern` shares with every caller of the process. A parse is
22
+ * deterministic, so this changes how often the parser runs and it changes no answer.
19
23
  * @returns The complete URL string.
20
24
  *
21
25
  * @throws {MissingRouteParamError} When a **necessary** `:param` placeholder has no
22
26
  * value in the context. The function omits an optional parameter (`:param?`) in
23
27
  * silence when its value is absent. Import the class from
24
28
  * `@xmachines/play-xstate/errors`.
29
+ * @throws {InvalidRouteParamError} When a `:param` placeholder carries a dot segment,
30
+ * which a URL resolves away. The template matches the built URL back never, so the
31
+ * actor and the address bar would stay out of step.
25
32
  *
26
33
  * @example
27
34
  * ```typescript
@@ -32,5 +39,5 @@ import type { RouteContext } from "./types.js";
32
39
  * // → "/settings" (the optional param is absent, and there is no query string)
33
40
  * ```
34
41
  */
35
- export declare const buildRouteUrl: (routeTemplate: string, context?: RouteContext) => string;
42
+ export declare const buildRouteUrl: (routeTemplate: string, context?: RouteContext, options?: ParseOptions) => string;
36
43
  //# sourceMappingURL=build-url.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"build-url.d.ts","sourceRoot":"","sources":["../../src/routing/build-url.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAI/C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,eAAO,MAAM,aAAa,GACzB,eAAe,MAAM,EACrB,UAAS,YAA4B,KACnC,MAwCF,CAAC"}
1
+ {"version":3,"file":"build-url.d.ts","sourceRoot":"","sources":["../../src/routing/build-url.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAI/C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,eAAO,MAAM,aAAa,GACzB,eAAe,MAAM,EACrB,UAAS,YAA4B,EACrC,UAAU,YAAY,KACpB,MAgEF,CAAC"}
@@ -1,5 +1,6 @@
1
+ import { buildPath } from "@xmachines/play-pattern";
1
2
  import { isAbsoluteRoute } from "./derive-route.js";
2
- import { MissingRouteParamError } from "../errors.js";
3
+ import { InvalidRouteParamError, MissingRouteParamError } from "../errors.js";
3
4
  /**
4
5
  * Builds a complete URL from a route template and the context of the actor.
5
6
  *
@@ -17,12 +18,18 @@ import { MissingRouteParamError } from "../errors.js";
17
18
  * @param context - The context object of the actor. Each route parameter must be in
18
19
  * `context.params`, because the function reads no flat context field. An absent
19
20
  * `query` field builds a URL without a query, exactly like `query: {}`.
21
+ * @param options - The caches to read, as {@link ParseOptions}. The default is the cache
22
+ * that `@xmachines/play-pattern` shares with every caller of the process. A parse is
23
+ * deterministic, so this changes how often the parser runs and it changes no answer.
20
24
  * @returns The complete URL string.
21
25
  *
22
26
  * @throws {MissingRouteParamError} When a **necessary** `:param` placeholder has no
23
27
  * value in the context. The function omits an optional parameter (`:param?`) in
24
28
  * silence when its value is absent. Import the class from
25
29
  * `@xmachines/play-xstate/errors`.
30
+ * @throws {InvalidRouteParamError} When a `:param` placeholder carries a dot segment,
31
+ * which a URL resolves away. The template matches the built URL back never, so the
32
+ * actor and the address bar would stay out of step.
26
33
  *
27
34
  * @example
28
35
  * ```typescript
@@ -33,7 +40,7 @@ import { MissingRouteParamError } from "../errors.js";
33
40
  * // → "/settings" (the optional param is absent, and there is no query string)
34
41
  * ```
35
42
  */
36
- export const buildRouteUrl = (routeTemplate, context = { query: {} }) => {
43
+ export const buildRouteUrl = (routeTemplate, context = { query: {} }, options) => {
37
44
  // A context without a `query` field builds a URL without a query, in the same way
38
45
  // as an absent context. The generated play.route transitions assign `query` on
39
46
  // every navigation, and the shape of the initial context has no effect on that.
@@ -43,10 +50,31 @@ export const buildRouteUrl = (routeTemplate, context = { query: {} }) => {
43
50
  // Handle a relative path and an absolute path
44
51
  const basePath = context.basePath || "";
45
52
  const isAbsolute = isAbsoluteRoute(routeTemplate);
46
- // Build the base URL
47
- let url = isAbsolute ? routeTemplate : joinPaths(basePath, routeTemplate);
48
- // Replace each :param with a context value
49
- url = substituteParams(url, context);
53
+ // Build the base URL. Join every run of separators into one, exactly as
54
+ // `buildRouteTree` of `@xmachines/play-router` does for the `fullPath` that the route
55
+ // map holds: `deriveRoute` writes `${parent}/${child}`, so a parent route that ends
56
+ // with a `/` gives `/app//sub` while the map holds `/app/sub`. A bridge pushed that
57
+ // location, the router reported `/app/sub` back — `sanitizePathname` collapses it —
58
+ // and the echo test then read its OWN push as a move of the user and sent a
59
+ // `play.route` for the state the actor was in already.
60
+ //
61
+ // The collapse runs on the TEMPLATE, and not on the built path, so a `:path*` value
62
+ // keeps every separator that it carries.
63
+ let url = (isAbsolute ? routeTemplate : joinPaths(basePath, routeTemplate)).replace(/\/+/g, "/");
64
+ // Replace each param with a context value. `buildPath` of `@xmachines/play-pattern`
65
+ // reads the WHOLE pattern grammar, which is the same parse that the match reads, so a
66
+ // route that the router matches derives a URL that the router matches back. That
67
+ // package carries the language alone: no URLPattern, and no polyfill for it.
68
+ const built = buildPath(url, context.params ?? {}, options);
69
+ if (!built.ok) {
70
+ if (built.reason === "unresolvable") {
71
+ throw new InvalidRouteParamError(built.param, built.value, routeTemplate);
72
+ }
73
+ throw new MissingRouteParamError(built.missing, routeTemplate);
74
+ }
75
+ // A template of the root level with optional params only, for example `/:section?`,
76
+ // builds `""`. That value makes an invalid URL, such as `""` or `"?tab=x"`.
77
+ url = built.path === "" ? "/" : built.path;
50
78
  // Append the query params of the context. The frequent empty `query: {}` passes the
51
79
  // key check first. Therefore each recomputation allocates a URLSearchParams object
52
80
  // only when it has something to write.
@@ -66,54 +94,6 @@ export const buildRouteUrl = (routeTemplate, context = { query: {} }) => {
66
94
  }
67
95
  return url;
68
96
  };
69
- /**
70
- * Replaces each `:param` placeholder with a context value, and it escapes that
71
- * value with `encodeURIComponent`.
72
- *
73
- * The function supports an optional parameter, in the form :param?.
74
- * - It removes an optional parameter without a value completely, and it also removes the /
75
- * - It writes a warning for a necessary parameter without a value
76
- *
77
- * The lookup of a parameter:
78
- * - The function reads context.params[param] only. It reads no flat context field.
79
- *
80
- * @param template - The URL template, with the :param or :param? syntax
81
- * @param context - The context with the parameter values. It can have a params field
82
- * @returns The URL with the parameters in place, and without a double slash
83
- * @throws {MissingRouteParamError} When a necessary route parameter is absent
84
- */
85
- const substituteParams = (template, context) => {
86
- // Replace each parameter, and handle the optional syntax
87
- let hasOptionalRemoval = false;
88
- const result = template.replace(/:(\w+)(\?)?/g, (_match, param, optional) => {
89
- const value = context.params?.[param]; // nosemgrep: gitlab.eslint.detect-object-injection
90
- // The parameter has a value that is not empty: put it in place.
91
- // For an optional param, an empty string means "no value".
92
- if (value !== undefined && value !== null && value !== "") {
93
- return encodeURIComponent(String(value));
94
- }
95
- // An optional parameter without a value, or with an empty string: remove the segment
96
- if (optional === "?") {
97
- hasOptionalRemoval = true;
98
- return ""; // This leaves // in the path. The code below removes it
99
- }
100
- throw new MissingRouteParamError(param, template);
101
- });
102
- // Remove each double slash
103
- let cleaned = result.replace(/\/+/g, "/");
104
- // Remove a trailing slash only after the code removed an optional parameter.
105
- // A trailing slash of a necessary param stays, because it shows an error.
106
- if (hasOptionalRemoval && cleaned.endsWith("/")) {
107
- cleaned = cleaned.slice(0, -1);
108
- }
109
- // Return an empty path never: a template of the root level with optional params
110
- // only, for example "/:section?", becomes "" after the trim of the trailing slash.
111
- // That value makes an invalid URL, such as "" or "?tab=x". Normalize it to "/".
112
- if (cleaned === "") {
113
- cleaned = "/";
114
- }
115
- return cleaned;
116
- };
117
97
  /**
118
98
  * Joins a base path and a relative path
119
99
  *
@@ -1 +1 @@
1
- {"version":3,"file":"build-url.js","sourceRoot":"","sources":["../../src/routing/build-url.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"build-url.js","sourceRoot":"","sources":["../../src/routing/build-url.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,5 @@
1
1
  import type { AnyMachineSnapshot } from "xstate";
2
+ import type { ParseOptions } from "@xmachines/play-pattern";
2
3
  export { activeStateMeta, firstActiveBranchMeta } from "../state-meta.js";
3
4
  /**
4
5
  * Derives the current URL of the actor from the state metadata and the context.
@@ -11,7 +12,7 @@ export { activeStateMeta, firstActiveBranchMeta } from "../state-meta.js";
11
12
  * - The snapshot has no route metadata, which means a state without a route
12
13
  * - The context does not hold a necessary route parameter (`MissingRouteParamError`)
13
14
  *
14
- * The `null` value for an absent param is deliberate: the computed signal therefore
15
+ * The `null` value for an absent param is deliberate: the computed atom therefore
15
16
  * stays stable during a temporary state. Such a state appears during a transition,
16
17
  * before the context is complete, and also after a logout, when `context.username`
17
18
  * is `null` and the router bridge did not reach the new state yet. The router bridge
@@ -19,7 +20,15 @@ export { activeStateMeta, firstActiveBranchMeta } from "../state-meta.js";
19
20
  * context is complete.
20
21
  *
21
22
  * @param snapshot - The current snapshot of the XState machine.
23
+ * @param options - The caches that the parse of the route TEMPLATE reads. The default is
24
+ * the cache that `@xmachines/play-pattern` shares with every caller of the process.
25
+ *
26
+ * `withRouting` calls this function with no options, and that is deliberate: it parses
27
+ * the `meta.route` template of a state, and a machine declares a small and static set of
28
+ * those. The unbounded key space that a cache of the caller answers is the one of
29
+ * `RouterBridgeBase`, which parses a CONCRETE location — one for each value that an
30
+ * application puts in a param — and a bridge takes its caches already.
22
31
  * @returns The resolved URL string, or `null` when the function cannot resolve the route.
23
32
  */
24
- export declare const deriveCurrentRoute: (snapshot: AnyMachineSnapshot) => string | null;
33
+ export declare const deriveCurrentRoute: (snapshot: AnyMachineSnapshot, options?: ParseOptions) => string | null;
25
34
  //# sourceMappingURL=derive-current-route.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"derive-current-route.d.ts","sourceRoot":"","sources":["../../src/routing/derive-current-route.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,QAAQ,CAAC;AAQjD,OAAO,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAE1E;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,kBAAkB,GAAI,UAAU,kBAAkB,KAAG,MAAM,GAAG,IA8B1E,CAAC"}
1
+ {"version":3,"file":"derive-current-route.d.ts","sourceRoot":"","sources":["../../src/routing/derive-current-route.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,QAAQ,CAAC;AAMjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAG5D,OAAO,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAE1E;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,eAAO,MAAM,kBAAkB,GAC9B,UAAU,kBAAkB,EAC5B,UAAU,YAAY,KACpB,MAAM,GAAG,IAsCX,CAAC"}
@@ -14,7 +14,7 @@ export { activeStateMeta, firstActiveBranchMeta } from "../state-meta.js";
14
14
  * - The snapshot has no route metadata, which means a state without a route
15
15
  * - The context does not hold a necessary route parameter (`MissingRouteParamError`)
16
16
  *
17
- * The `null` value for an absent param is deliberate: the computed signal therefore
17
+ * The `null` value for an absent param is deliberate: the computed atom therefore
18
18
  * stays stable during a temporary state. Such a state appears during a transition,
19
19
  * before the context is complete, and also after a logout, when `context.username`
20
20
  * is `null` and the router bridge did not reach the new state yet. The router bridge
@@ -22,9 +22,17 @@ export { activeStateMeta, firstActiveBranchMeta } from "../state-meta.js";
22
22
  * context is complete.
23
23
  *
24
24
  * @param snapshot - The current snapshot of the XState machine.
25
+ * @param options - The caches that the parse of the route TEMPLATE reads. The default is
26
+ * the cache that `@xmachines/play-pattern` shares with every caller of the process.
27
+ *
28
+ * `withRouting` calls this function with no options, and that is deliberate: it parses
29
+ * the `meta.route` template of a state, and a machine declares a small and static set of
30
+ * those. The unbounded key space that a cache of the caller answers is the one of
31
+ * `RouterBridgeBase`, which parses a CONCRETE location — one for each value that an
32
+ * application puts in a param — and a bridge takes its caches already.
25
33
  * @returns The resolved URL string, or `null` when the function cannot resolve the route.
26
34
  */
27
- export const deriveCurrentRoute = (snapshot) => {
35
+ export const deriveCurrentRoute = (snapshot, options) => {
28
36
  const meta = activeStateMeta(snapshot);
29
37
  if (!meta) {
30
38
  return null;
@@ -34,7 +42,7 @@ export const deriveCurrentRoute = (snapshot) => {
34
42
  return null;
35
43
  }
36
44
  try {
37
- return buildRouteUrl(routeTemplate, (snapshot.context ?? {}));
45
+ return buildRouteUrl(routeTemplate, (snapshot.context ?? {}), options);
38
46
  }
39
47
  catch (error) {
40
48
  // MissingRouteParamError: the condition is temporary, and it resolves itself. A
@@ -43,14 +51,22 @@ export const deriveCurrentRoute = (snapshot) => {
43
51
  // context.params, and also after a logout, before the bridge redirects. A `null`
44
52
  // value is correct here:
45
53
  // - a router bridge reads null and skips the navigation (syncRouterFromActor, line 242)
46
- // - the signal computes its value again on the next snapshot, when the params arrive
47
- // - a throw goes to each signal watcher as an unhandled exception, for a state
48
- // that resolves itself. That is worse than a null value for one tick.
54
+ // - the atom computes its value again on the next snapshot, when the params arrive
55
+ // - a report of a condition that resolves itself is worse than a null value for
56
+ // one tick.
49
57
  // Do NOT convert this into a throw.
50
58
  if (error instanceof MissingRouteParamError) {
51
59
  return null;
52
60
  }
53
61
  // Each unexpected error goes to the caller without a change.
62
+ //
63
+ // This function is PURE, and it stays that way: it has no actor, so it holds no
64
+ // error channel and no previous value. The CALLER decides what an unexpected error
65
+ // means. `currentRoute` of `with-routing.ts` is that caller for the reactive path —
66
+ // it reports through `onError` of the actor and keeps the last route, because a
67
+ // throw from there would unwind into the transition. `initialRoute` is the other
68
+ // caller, and a throw from it fails the construction, which is where a developer
69
+ // wants to see a route template that cannot be built.
54
70
  throw error;
55
71
  }
56
72
  };
@@ -1 +1 @@
1
- {"version":3,"file":"derive-current-route.js","sourceRoot":"","sources":["../../src/routing/derive-current-route.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAE/C,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAEnD,OAAO,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAE1E;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,QAA4B,EAAiB,EAAE;IACjF,MAAM,IAAI,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;IACvC,IAAI,CAAC,IAAI,EAAE,CAAC;QACX,OAAO,IAAI,CAAC;IACb,CAAC;IAED,MAAM,aAAa,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IACxC,IAAI,CAAC,aAAa,EAAE,CAAC;QACpB,OAAO,IAAI,CAAC;IACb,CAAC;IAED,IAAI,CAAC;QACJ,OAAO,aAAa,CAAC,aAAa,EAAE,CAAC,QAAQ,CAAC,OAAO,IAAI,EAAE,CAAiB,CAAC,CAAC;IAC/E,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,gFAAgF;QAChF,oFAAoF;QACpF,gFAAgF;QAChF,iFAAiF;QACjF,yBAAyB;QACzB,0FAA0F;QAC1F,uFAAuF;QACvF,iFAAiF;QACjF,0EAA0E;QAC1E,oCAAoC;QACpC,IAAI,KAAK,YAAY,sBAAsB,EAAE,CAAC;YAC7C,OAAO,IAAI,CAAC;QACb,CAAC;QACD,6DAA6D;QAC7D,MAAM,KAAK,CAAC;IACb,CAAC;AACF,CAAC,CAAC"}
1
+ {"version":3,"file":"derive-current-route.js","sourceRoot":"","sources":["../../src/routing/derive-current-route.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAG/C,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAEnD,OAAO,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAE1E;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CACjC,QAA4B,EAC5B,OAAsB,EACN,EAAE;IAClB,MAAM,IAAI,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;IACvC,IAAI,CAAC,IAAI,EAAE,CAAC;QACX,OAAO,IAAI,CAAC;IACb,CAAC;IAED,MAAM,aAAa,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IACxC,IAAI,CAAC,aAAa,EAAE,CAAC;QACpB,OAAO,IAAI,CAAC;IACb,CAAC;IAED,IAAI,CAAC;QACJ,OAAO,aAAa,CAAC,aAAa,EAAE,CAAC,QAAQ,CAAC,OAAO,IAAI,EAAE,CAAiB,EAAE,OAAO,CAAC,CAAC;IACxF,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,gFAAgF;QAChF,oFAAoF;QACpF,gFAAgF;QAChF,iFAAiF;QACjF,yBAAyB;QACzB,0FAA0F;QAC1F,qFAAqF;QACrF,kFAAkF;QAClF,gBAAgB;QAChB,oCAAoC;QACpC,IAAI,KAAK,YAAY,sBAAsB,EAAE,CAAC;YAC7C,OAAO,IAAI,CAAC;QACb,CAAC;QACD,6DAA6D;QAC7D,EAAE;QACF,gFAAgF;QAChF,mFAAmF;QACnF,oFAAoF;QACpF,gFAAgF;QAChF,iFAAiF;QACjF,iFAAiF;QACjF,sDAAsD;QACtD,MAAM,KAAK,CAAC;IACb,CAAC;AACF,CAAC,CAAC"}
@@ -1,4 +1,5 @@
1
1
  import { type AnyStateMachine } from "xstate";
2
+ import type { ParseOptions } from "@xmachines/play-pattern";
2
3
  /**
3
4
  * Derives the initial route of the machine directly from the machine definition.
4
5
  *
@@ -39,5 +40,5 @@ import { type AnyStateMachine } from "xstate";
39
40
  * deriveInitialRoute(machine, { username: "alice" }); // "/profile/alice"
40
41
  * ```
41
42
  */
42
- export declare const deriveInitialRoute: (machine: AnyStateMachine, input?: unknown) => string | null;
43
+ export declare const deriveInitialRoute: (machine: AnyStateMachine, input?: unknown, options?: ParseOptions) => string | null;
43
44
  //# sourceMappingURL=derive-initial-route.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"derive-initial-route.d.ts","sourceRoot":"","sources":["../../src/routing/derive-initial-route.ts"],"names":[],"mappings":"AAAA,OAAO,EAA8C,KAAK,eAAe,EAAE,MAAM,QAAQ,CAAC;AAI1F;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,eAAO,MAAM,kBAAkB,GAAI,SAAS,eAAe,EAAE,QAAQ,OAAO,KAAG,MAAM,GAAG,IAwBvF,CAAC"}
1
+ {"version":3,"file":"derive-initial-route.d.ts","sourceRoot":"","sources":["../../src/routing/derive-initial-route.ts"],"names":[],"mappings":"AAAA,OAAO,EAA8C,KAAK,eAAe,EAAE,MAAM,QAAQ,CAAC;AAG1F,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAE5D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,eAAO,MAAM,kBAAkB,GAC9B,SAAS,eAAe,EACxB,QAAQ,OAAO,EACf,UAAU,YAAY,KACpB,MAAM,GAAG,IAwBX,CAAC"}
@@ -40,7 +40,7 @@ import { deriveCurrentRoute } from "./derive-current-route.js";
40
40
  * deriveInitialRoute(machine, { username: "alice" }); // "/profile/alice"
41
41
  * ```
42
42
  */
43
- export const deriveInitialRoute = (machine, input) => {
43
+ export const deriveInitialRoute = (machine, input, options) => {
44
44
  let initialSnapshot;
45
45
  try {
46
46
  [initialSnapshot] = initialTransition(machine, input);
@@ -63,6 +63,6 @@ export const deriveInitialRoute = (machine, input) => {
63
63
  // question, and it holds whichever way a later release reports the failure.
64
64
  if (initialSnapshot.status === "error")
65
65
  return null;
66
- return deriveCurrentRoute(initialSnapshot);
66
+ return deriveCurrentRoute(initialSnapshot, options);
67
67
  };
68
68
  //# sourceMappingURL=derive-initial-route.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"derive-initial-route.js","sourceRoot":"","sources":["../../src/routing/derive-initial-route.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAiD,MAAM,QAAQ,CAAC;AAE1F,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAE/D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,OAAwB,EAAE,KAAe,EAAiB,EAAE;IAC9F,IAAI,eAAmC,CAAC;IACxC,IAAI,CAAC;QACJ,CAAC,eAAe,CAAC,GAAG,iBAAiB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IACvD,CAAC;IAAC,MAAM,CAAC;QACR,gFAAgF;QAChF,oFAAoF;QACpF,qFAAqF;QACrF,iFAAiF;QACjF,OAAO,IAAI,CAAC;IACb,CAAC;IAED,qEAAqE;IACrE,6EAA6E;IAC7E,sFAAsF;IACtF,sFAAsF;IACtF,sFAAsF;IACtF,6BAA6B;IAC7B,EAAE;IACF,kFAAkF;IAClF,4EAA4E;IAC5E,IAAI,eAAe,CAAC,MAAM,KAAK,OAAO;QAAE,OAAO,IAAI,CAAC;IAEpD,OAAO,kBAAkB,CAAC,eAAe,CAAC,CAAC;AAC5C,CAAC,CAAC"}
1
+ {"version":3,"file":"derive-initial-route.js","sourceRoot":"","sources":["../../src/routing/derive-initial-route.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAiD,MAAM,QAAQ,CAAC;AAE1F,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAG/D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CACjC,OAAwB,EACxB,KAAe,EACf,OAAsB,EACN,EAAE;IAClB,IAAI,eAAmC,CAAC;IACxC,IAAI,CAAC;QACJ,CAAC,eAAe,CAAC,GAAG,iBAAiB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IACvD,CAAC;IAAC,MAAM,CAAC;QACR,gFAAgF;QAChF,oFAAoF;QACpF,qFAAqF;QACrF,iFAAiF;QACjF,OAAO,IAAI,CAAC;IACb,CAAC;IAED,qEAAqE;IACrE,6EAA6E;IAC7E,sFAAsF;IACtF,sFAAsF;IACtF,sFAAsF;IACtF,6BAA6B;IAC7B,EAAE;IACF,kFAAkF;IAClF,4EAA4E;IAC5E,IAAI,eAAe,CAAC,MAAM,KAAK,OAAO;QAAE,OAAO,IAAI,CAAC;IAEpD,OAAO,kBAAkB,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC;AACrD,CAAC,CAAC"}
@@ -28,6 +28,13 @@ const asTransitionArray = (value) => value === undefined ? [] : Array.isArray(va
28
28
  * event: the declaration of a state is static.
29
29
  */
30
30
  const declaresRouteData = (route) => typeof route === "object" && route !== null && route.data !== undefined;
31
+ /**
32
+ * The `params` and the `query` of the event, each beside the container that the context
33
+ * holds already. Neither one reads the metadata of the route, so both stand here rather
34
+ * than inside the factory, where a call rebuilt them for every generated transition.
35
+ */
36
+ const assignParams = ({ context, event }) => keepEqualContainer(context.params, event.params || {});
37
+ const assignQuery = ({ context, event }) => keepEqualContainer(context.query, event.query || {});
31
38
  /**
32
39
  * Builds the assign action of a generated `play.route` transition.
33
40
  *
@@ -41,13 +48,11 @@ const declaresRouteData = (route) => typeof route === "object" && route !== null
41
48
  * received one with no value, and the `/context` projection of every view carried it.
42
49
  */
43
50
  const makeRouteAssign = (routeMeta) => {
44
- const params = ({ context, event }) => keepEqualContainer(context.params, event.params || {});
45
- const query = ({ context, event }) => keepEqualContainer(context.query, event.query || {});
46
51
  if (!declaresRouteData(routeMeta))
47
- return assign({ params, query });
52
+ return assign({ params: assignParams, query: assignQuery });
48
53
  return assign({
49
- params,
50
- query,
54
+ params: assignParams,
55
+ query: assignQuery,
51
56
  // A resolver that answers `undefined` leaves the field of the context as it stands,
52
57
  // and it therefore writes `undefined` over the data of an earlier route never.
53
58
  data: ({ context, event }) => {