@xmachines/play-xstate 3.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 (80) hide show
  1. package/README.md +190 -68
  2. package/dist/capabilities.d.ts +93 -0
  3. package/dist/capabilities.d.ts.map +1 -0
  4. package/dist/capabilities.js +4 -0
  5. package/dist/capabilities.js.map +1 -0
  6. package/dist/define-player.d.ts +7 -1
  7. package/dist/define-player.d.ts.map +1 -1
  8. package/dist/define-player.js +9 -60
  9. package/dist/define-player.js.map +1 -1
  10. package/dist/errors.d.ts +64 -23
  11. package/dist/errors.d.ts.map +1 -1
  12. package/dist/errors.js +93 -31
  13. package/dist/errors.js.map +1 -1
  14. package/dist/index.d.ts +4 -6
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +11 -6
  17. package/dist/index.js.map +1 -1
  18. package/dist/player-actor.d.ts +73 -137
  19. package/dist/player-actor.d.ts.map +1 -1
  20. package/dist/player-actor.js +108 -254
  21. package/dist/player-actor.js.map +1 -1
  22. package/dist/routing/build-url.d.ts +8 -1
  23. package/dist/routing/build-url.d.ts.map +1 -1
  24. package/dist/routing/build-url.js +34 -54
  25. package/dist/routing/build-url.js.map +1 -1
  26. package/dist/routing/derive-current-route.d.ts +12 -38
  27. package/dist/routing/derive-current-route.d.ts.map +1 -1
  28. package/dist/routing/derive-current-route.js +24 -82
  29. package/dist/routing/derive-current-route.js.map +1 -1
  30. package/dist/routing/derive-initial-route.d.ts +2 -1
  31. package/dist/routing/derive-initial-route.d.ts.map +1 -1
  32. package/dist/routing/derive-initial-route.js +13 -2
  33. package/dist/routing/derive-initial-route.js.map +1 -1
  34. package/dist/routing/derive-route.d.ts +81 -2
  35. package/dist/routing/derive-route.d.ts.map +1 -1
  36. package/dist/routing/derive-route.js +97 -3
  37. package/dist/routing/derive-route.js.map +1 -1
  38. package/dist/routing/format-play-route-transitions.d.ts +8 -2
  39. package/dist/routing/format-play-route-transitions.d.ts.map +1 -1
  40. package/dist/routing/format-play-route-transitions.js +175 -43
  41. package/dist/routing/format-play-route-transitions.js.map +1 -1
  42. package/dist/routing/index.d.ts +1 -1
  43. package/dist/routing/index.d.ts.map +1 -1
  44. package/dist/routing/types.d.ts +9 -5
  45. package/dist/routing/types.d.ts.map +1 -1
  46. package/dist/state-meta.d.ts +52 -0
  47. package/dist/state-meta.d.ts.map +1 -0
  48. package/dist/state-meta.js +77 -0
  49. package/dist/state-meta.js.map +1 -0
  50. package/dist/types.d.ts +20 -5
  51. package/dist/types.d.ts.map +1 -1
  52. package/dist/view/derive-current-view.d.ts +7 -6
  53. package/dist/view/derive-current-view.d.ts.map +1 -1
  54. package/dist/view/derive-current-view.js +7 -6
  55. package/dist/view/derive-current-view.js.map +1 -1
  56. package/dist/with-routing.d.ts +45 -0
  57. package/dist/with-routing.d.ts.map +1 -0
  58. package/dist/with-routing.js +140 -0
  59. package/dist/with-routing.js.map +1 -0
  60. package/dist/with-view.d.ts +57 -0
  61. package/dist/with-view.d.ts.map +1 -0
  62. package/dist/with-view.js +158 -0
  63. package/dist/with-view.js.map +1 -0
  64. package/package.json +40 -18
  65. package/dist/guards/compose.d.ts +0 -158
  66. package/dist/guards/compose.d.ts.map +0 -1
  67. package/dist/guards/compose.js +0 -188
  68. package/dist/guards/compose.js.map +0 -1
  69. package/dist/guards/helpers.d.ts +0 -62
  70. package/dist/guards/helpers.d.ts.map +0 -1
  71. package/dist/guards/helpers.js +0 -85
  72. package/dist/guards/helpers.js.map +0 -1
  73. package/dist/guards/index.d.ts +0 -20
  74. package/dist/guards/index.d.ts.map +0 -1
  75. package/dist/guards/index.js +0 -18
  76. package/dist/guards/index.js.map +0 -1
  77. package/dist/guards/types.d.ts +0 -22
  78. package/dist/guards/types.d.ts.map +0 -1
  79. package/dist/guards/types.js +0 -2
  80. package/dist/guards/types.js.map +0 -1
@@ -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,40 +1,6 @@
1
1
  import type { AnyMachineSnapshot } from "xstate";
2
- /**
3
- * Collects the `meta` object of the active state nodes of a SINGLE branch, from the
4
- * root to a leaf. The key of each entry is the state id, and the order is the
5
- * ancestors first. {@link deriveRoute} folds this shape.
6
- *
7
- * `snapshot.getMeta()` returns a FLAT record of the meta object of every active
8
- * state. For a machine that is not parallel, that record is one chain of ancestors
9
- * already. For a PARALLEL machine, it mixes the entries of every active region. A
10
- * blind fold therefore joins a relative route of one region to an absolute route of
11
- * a sibling region, and the URL belongs to the tree of neither region. The flat
12
- * record also cannot go back into a hierarchy: when a state declares an explicit
13
- * `id`, for example a child with `id: "dashboard-overview"` under `id: "dashboard"`,
14
- * the meta keys are those ids, and they carry no information about the ancestry.
15
- *
16
- * Therefore this function walks `snapshot.value`, which holds the real hierarchy of
17
- * the active states by the state key, against the node tree of the machine. It
18
- * follows the FIRST active child at each level. This gives one deterministic branch,
19
- * which matches the historical behavior of "the first that it finds" for a parallel
20
- * machine. It also works with an explicit id, because each node carries its own `id`
21
- * and its own `meta`.
22
- *
23
- * The function returns `null` when the snapshot exposes no machine and no value to
24
- * walk. This is a defensive measure, because a real XState snapshot always exposes
25
- * them. The caller then uses `getMeta()`, as before.
26
- */
27
- export declare const firstActiveBranchMeta: (snapshot: AnyMachineSnapshot) => Record<string, unknown> | null;
28
- /**
29
- * Resolves the meta record that the route derivation and the view derivation fold:
30
- * the single active branch that {@link firstActiveBranchMeta} walks, which is
31
- * correct for a parallel machine and for an explicit id, or the flat `getMeta()`
32
- * record when the snapshot has no machine tree to walk. `deriveCurrentRoute` and
33
- * `deriveCurrentView` share this function. Therefore the two sides cannot move apart
34
- * on the selection of the branch, and they cannot move apart on their tolerance of a
35
- * degenerate snapshot.
36
- */
37
- export declare const activeStateMeta: (snapshot: AnyMachineSnapshot) => Record<string, unknown> | null;
2
+ import type { ParseOptions } from "@xmachines/play-pattern";
3
+ export { activeStateMeta, firstActiveBranchMeta } from "../state-meta.js";
38
4
  /**
39
5
  * Derives the current URL of the actor from the state metadata and the context.
40
6
  *
@@ -46,7 +12,7 @@ export declare const activeStateMeta: (snapshot: AnyMachineSnapshot) => Record<s
46
12
  * - The snapshot has no route metadata, which means a state without a route
47
13
  * - The context does not hold a necessary route parameter (`MissingRouteParamError`)
48
14
  *
49
- * 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
50
16
  * stays stable during a temporary state. Such a state appears during a transition,
51
17
  * before the context is complete, and also after a logout, when `context.username`
52
18
  * is `null` and the router bridge did not reach the new state yet. The router bridge
@@ -54,7 +20,15 @@ export declare const activeStateMeta: (snapshot: AnyMachineSnapshot) => Record<s
54
20
  * context is complete.
55
21
  *
56
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.
57
31
  * @returns The resolved URL string, or `null` when the function cannot resolve the route.
58
32
  */
59
- export declare const deriveCurrentRoute: (snapshot: AnyMachineSnapshot) => string | null;
33
+ export declare const deriveCurrentRoute: (snapshot: AnyMachineSnapshot, options?: ParseOptions) => string | null;
60
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;AAOjD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,eAAO,MAAM,qBAAqB,GACjC,UAAU,kBAAkB,KAC1B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAqC5B,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,eAAe,GAAI,UAAU,kBAAkB,KAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAMxF,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;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"}
@@ -1,82 +1,8 @@
1
1
  import { MissingRouteParamError } from "../errors.js";
2
2
  import { deriveRoute } from "./derive-route.js";
3
3
  import { buildRouteUrl } from "./build-url.js";
4
- /**
5
- * Collects the `meta` object of the active state nodes of a SINGLE branch, from the
6
- * root to a leaf. The key of each entry is the state id, and the order is the
7
- * ancestors first. {@link deriveRoute} folds this shape.
8
- *
9
- * `snapshot.getMeta()` returns a FLAT record of the meta object of every active
10
- * state. For a machine that is not parallel, that record is one chain of ancestors
11
- * already. For a PARALLEL machine, it mixes the entries of every active region. A
12
- * blind fold therefore joins a relative route of one region to an absolute route of
13
- * a sibling region, and the URL belongs to the tree of neither region. The flat
14
- * record also cannot go back into a hierarchy: when a state declares an explicit
15
- * `id`, for example a child with `id: "dashboard-overview"` under `id: "dashboard"`,
16
- * the meta keys are those ids, and they carry no information about the ancestry.
17
- *
18
- * Therefore this function walks `snapshot.value`, which holds the real hierarchy of
19
- * the active states by the state key, against the node tree of the machine. It
20
- * follows the FIRST active child at each level. This gives one deterministic branch,
21
- * which matches the historical behavior of "the first that it finds" for a parallel
22
- * machine. It also works with an explicit id, because each node carries its own `id`
23
- * and its own `meta`.
24
- *
25
- * The function returns `null` when the snapshot exposes no machine and no value to
26
- * walk. This is a defensive measure, because a real XState snapshot always exposes
27
- * them. The caller then uses `getMeta()`, as before.
28
- */
29
- export const firstActiveBranchMeta = (snapshot) => {
30
- const root = snapshot.machine?.root;
31
- if (!root)
32
- return null;
33
- const ordered = {};
34
- let node = root;
35
- let value = snapshot.value;
36
- while (node) {
37
- if (node.meta && typeof node.meta === "object") {
38
- ordered[node.id] = node.meta; // nosemgrep: gitlab.eslint.detect-object-injection
39
- }
40
- // Find the key of the active child at this level. A string value is the name of an
41
- // atomic active leaf. An object value is a compound node, with one key, or a
42
- // parallel node, with many keys: take the first key, for one deterministic
43
- // branch.
44
- let key;
45
- if (typeof value === "string") {
46
- key = value;
47
- }
48
- else if (value && typeof value === "object") {
49
- key = Object.keys(value)[0];
50
- }
51
- if (key === undefined)
52
- break;
53
- const child = node.states?.[key]; // nosemgrep: gitlab.eslint.detect-object-injection
54
- if (!child)
55
- break;
56
- value =
57
- typeof value === "object" && value !== null
58
- ? value[key] // nosemgrep: gitlab.eslint.detect-object-injection
59
- : {};
60
- node = child;
61
- }
62
- return ordered;
63
- };
64
- /**
65
- * Resolves the meta record that the route derivation and the view derivation fold:
66
- * the single active branch that {@link firstActiveBranchMeta} walks, which is
67
- * correct for a parallel machine and for an explicit id, or the flat `getMeta()`
68
- * record when the snapshot has no machine tree to walk. `deriveCurrentRoute` and
69
- * `deriveCurrentView` share this function. Therefore the two sides cannot move apart
70
- * on the selection of the branch, and they cannot move apart on their tolerance of a
71
- * degenerate snapshot.
72
- */
73
- export const activeStateMeta = (snapshot) => {
74
- if (!snapshot || typeof snapshot.getMeta !== "function") {
75
- return null;
76
- }
77
- const meta = firstActiveBranchMeta(snapshot) ?? snapshot.getMeta();
78
- return meta && typeof meta === "object" ? meta : null;
79
- };
4
+ import { activeStateMeta } from "../state-meta.js";
5
+ export { activeStateMeta, firstActiveBranchMeta } from "../state-meta.js";
80
6
  /**
81
7
  * Derives the current URL of the actor from the state metadata and the context.
82
8
  *
@@ -88,7 +14,7 @@ export const activeStateMeta = (snapshot) => {
88
14
  * - The snapshot has no route metadata, which means a state without a route
89
15
  * - The context does not hold a necessary route parameter (`MissingRouteParamError`)
90
16
  *
91
- * 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
92
18
  * stays stable during a temporary state. Such a state appears during a transition,
93
19
  * before the context is complete, and also after a logout, when `context.username`
94
20
  * is `null` and the router bridge did not reach the new state yet. The router bridge
@@ -96,9 +22,17 @@ export const activeStateMeta = (snapshot) => {
96
22
  * context is complete.
97
23
  *
98
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.
99
33
  * @returns The resolved URL string, or `null` when the function cannot resolve the route.
100
34
  */
101
- export const deriveCurrentRoute = (snapshot) => {
35
+ export const deriveCurrentRoute = (snapshot, options) => {
102
36
  const meta = activeStateMeta(snapshot);
103
37
  if (!meta) {
104
38
  return null;
@@ -108,7 +42,7 @@ export const deriveCurrentRoute = (snapshot) => {
108
42
  return null;
109
43
  }
110
44
  try {
111
- return buildRouteUrl(routeTemplate, (snapshot.context ?? {}));
45
+ return buildRouteUrl(routeTemplate, (snapshot.context ?? {}), options);
112
46
  }
113
47
  catch (error) {
114
48
  // MissingRouteParamError: the condition is temporary, and it resolves itself. A
@@ -117,14 +51,22 @@ export const deriveCurrentRoute = (snapshot) => {
117
51
  // context.params, and also after a logout, before the bridge redirects. A `null`
118
52
  // value is correct here:
119
53
  // - a router bridge reads null and skips the navigation (syncRouterFromActor, line 242)
120
- // - the signal computes its value again on the next snapshot, when the params arrive
121
- // - a throw goes to each signal watcher as an unhandled exception, for a state
122
- // 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.
123
57
  // Do NOT convert this into a throw.
124
58
  if (error instanceof MissingRouteParamError) {
125
59
  return null;
126
60
  }
127
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.
128
70
  throw error;
129
71
  }
130
72
  };
@@ -1 +1 @@
1
- {"version":3,"file":"derive-current-route.js","sourceRoot":"","sources":["../../src/routing/derive-current-route.ts"],"names":[],"mappings":"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"}
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,IAavF,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);
@@ -52,6 +52,17 @@ export const deriveInitialRoute = (machine, input) => {
52
52
  // that snapshot also has no route metadata. Report "no initial route to derive".
53
53
  return null;
54
54
  }
55
- return deriveCurrentRoute(initialSnapshot);
55
+ // The SAME failure, reported the other way. XState 5.32 threw out of
56
+ // `initialTransition` for a context factory that throws, and 5.33 returns an
57
+ // error-status snapshot instead, with the reason on `snapshot.error`. The catch above
58
+ // therefore stopped firing, and a machine whose context never built derived the route
59
+ // of its initial state — `/login` for a factory that threw — which a bridge then took
60
+ // as the place of the actor.
61
+ //
62
+ // Both shapes mean the same thing, so both answer the same way. The status is the
63
+ // question, and it holds whichever way a later release reports the failure.
64
+ if (initialSnapshot.status === "error")
65
+ return null;
66
+ return deriveCurrentRoute(initialSnapshot, options);
56
67
  };
57
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,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"}
@@ -1,3 +1,4 @@
1
+ import type { PlayRouteEvent, RouteData } from "@xmachines/play-router";
1
2
  import type { RouteMetadata } from "./types.js";
2
3
  /**
3
4
  * Derives the route from the metadata of an XState state
@@ -18,7 +19,7 @@ import type { RouteMetadata } from "./types.js";
18
19
  * @example
19
20
  * The basic read of a route
20
21
  * ```typescript
21
- * import { deriveRoute } from "@xmachines/play-xstate";
22
+ * import { deriveRoute } from "@xmachines/play-xstate/routing";
22
23
  * import { setup } from "xstate";
23
24
  *
24
25
  * const machine = setup({}).createMachine({
@@ -101,6 +102,84 @@ export declare const deriveRoute: (stateMeta: Record<string, unknown>) => string
101
102
  * @throws {InvalidRouteMetadataError} When the form of the route is invalid
102
103
  */
103
104
  export declare const normalizeRoute: (route: RouteMetadata, source?: string) => string;
105
+ /**
106
+ * Reads the `reenter` flag of the route metadata.
107
+ *
108
+ * The string form of the metadata declares no flag, and the object form declares the
109
+ * flag only when it wants one. Both therefore give `false`, which is the default of
110
+ * XState for a transition. A state without a route gives `false` too, so the caller
111
+ * needs no test of its own for that case.
112
+ *
113
+ * The function does NOT check the form of the metadata. `normalizeRoute` runs first at
114
+ * every call site and throws `InvalidRouteMetadataError` on a malformed value.
115
+ *
116
+ * @param route - The route metadata: a string, an object with a `path` property, or
117
+ * `undefined` for a state that declares no route
118
+ * @returns The declared flag, or `false` where the metadata declares none
119
+ *
120
+ * @example
121
+ * ```typescript
122
+ * routeReenter("/dashboard"); // false
123
+ * routeReenter({ path: "/dashboard" }); // false
124
+ * routeReenter({ path: "/dashboard", reenter: true }); // true
125
+ * routeReenter(undefined); // false
126
+ * ```
127
+ */
128
+ export declare const routeReenter: (route: RouteMetadata | undefined) => boolean;
129
+ /**
130
+ * Reads the extra data that a route declares, resolved for one event.
131
+ *
132
+ * The field holds a literal value or a function of `{ context, event }`, which is the
133
+ * `WithDynamicParams` shape of XState. This function collapses the two into the value.
134
+ *
135
+ * The function does NOT check the form of the metadata. `normalizeRoute` runs first at
136
+ * every call site and throws `InvalidRouteMetadataError` on a malformed value.
137
+ *
138
+ * @param route - The route metadata: a string, an object with a `path` property, or
139
+ * `undefined` for a state that declares no route
140
+ * @param args - The context of the machine and the `play.route` event that asks for the
141
+ * route. The resolver reads them.
142
+ * @returns The data, or `undefined` where the route declares none
143
+ *
144
+ * @example
145
+ * ```typescript
146
+ * routeData({ path: "/a", data: { titleKey: "a" } }, args); // { titleKey: "a" }
147
+ * routeData({ path: "/a", data: ({ event }) => ({ to: event.to }) }, args);
148
+ * routeData("/a", args); // undefined
149
+ * ```
150
+ */
151
+ export declare const routeData: (route: RouteMetadata | undefined, args: {
152
+ context: unknown;
153
+ event: PlayRouteEvent;
154
+ }) => RouteData | undefined;
155
+ /**
156
+ * Reads the placement of the generated `play.route` transition.
157
+ *
158
+ * `"root"` is the default, and it is the placement of XState: every route transition
159
+ * sits on the root of the machine. `"local"` moves the transition to the parent of the
160
+ * state, and `"both"` puts one transition in each place.
161
+ *
162
+ * The function does NOT check the form of the metadata. `normalizeRoute` runs first at
163
+ * every call site and throws `InvalidRouteMetadataError` on a malformed value.
164
+ *
165
+ * @param route - The route metadata: a string, an object with a `path` property, or
166
+ * `undefined` for a state that declares no route
167
+ * @param source - The `PlayError.scope` value to report for an unknown placement
168
+ * @returns The declared placement, and `"root"` where the metadata declares none
169
+ * @throws {InvalidRouteHandlerError} When the object declares a `handler` that is not
170
+ * `"root"`, `"local"`, or `"both"`. A typo would otherwise fall back to a placement
171
+ * that the author did not ask for, and it would change which states a route reaches.
172
+ *
173
+ * @example
174
+ * ```typescript
175
+ * routeHandler("/dashboard"); // "root"
176
+ * routeHandler({ path: "/dashboard" }); // "root"
177
+ * routeHandler({ path: "/dashboard", handler: "local" }); // "local"
178
+ * routeHandler({ path: "/dashboard", handler: "both" }); // "both"
179
+ * routeHandler({ path: "/dashboard", handler: "locale" }); // throws
180
+ * ```
181
+ */
182
+ export declare const routeHandler: (route: RouteMetadata | undefined, source?: string) => "root" | "local" | "both";
104
183
  /**
105
184
  * Tells you if the route path is absolute
106
185
  *
@@ -113,7 +192,7 @@ export declare const normalizeRoute: (route: RouteMetadata, source?: string) =>
113
192
  *
114
193
  * @example
115
194
  * ```typescript
116
- * import { isAbsoluteRoute } from "@xmachines/play-xstate";
195
+ * import { isAbsoluteRoute } from "@xmachines/play-xstate/routing";
117
196
  *
118
197
  * console.log(isAbsoluteRoute("/dashboard")); // true
119
198
  * console.log(isAbsoluteRoute("settings")); // false
@@ -1 +1 @@
1
- {"version":3,"file":"derive-route.d.ts","sourceRoot":"","sources":["../../src/routing/derive-route.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAe,MAAM,YAAY,CAAC;AAG7D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuFG;AACH,eAAO,MAAM,WAAW,GAAI,WAAW,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAG,MAAM,GAAG,IAuBzE,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,cAAc,GAAI,OAAO,aAAa,EAAE,eAAsB,KAAG,MAW7E,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,eAAe,GAAI,MAAM,MAAM,KAAG,OAE9C,CAAC"}
1
+ {"version":3,"file":"derive-route.d.ts","sourceRoot":"","sources":["../../src/routing/derive-route.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACxE,OAAO,KAAK,EAAE,aAAa,EAAe,MAAM,YAAY,CAAC;AAG7D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuFG;AACH,eAAO,MAAM,WAAW,GAAI,WAAW,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAG,MAAM,GAAG,IAuBzE,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,cAAc,GAAI,OAAO,aAAa,EAAE,eAAsB,KAAG,MAW7E,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,YAAY,GAAI,OAAO,aAAa,GAAG,SAAS,KAAG,OACuB,CAAC;AAExF;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,SAAS,GACrB,OAAO,aAAa,GAAG,SAAS,EAChC,MAAM;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,cAAc,CAAA;CAAE,KAC/C,SAAS,GAAG,SAOd,CAAC;AAKF;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,eAAO,MAAM,YAAY,GACxB,OAAO,aAAa,GAAG,SAAS,EAChC,eAAqC,KACnC,MAAM,GAAG,OAAO,GAAG,MAUrB,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,eAAe,GAAI,MAAM,MAAM,KAAG,OAE9C,CAAC"}