@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,4 +1,4 @@
1
- import { InvalidRouteMetadataError } from "../errors.js";
1
+ import { InvalidRouteHandlerError, InvalidRouteMetadataError } from "../errors.js";
2
2
  /**
3
3
  * Derives the route from the metadata of an XState state
4
4
  *
@@ -18,7 +18,7 @@ import { InvalidRouteMetadataError } from "../errors.js";
18
18
  * @example
19
19
  * The basic read of a route
20
20
  * ```typescript
21
- * import { deriveRoute } from "@xmachines/play-xstate";
21
+ * import { deriveRoute } from "@xmachines/play-xstate/routing";
22
22
  * import { setup } from "xstate";
23
23
  *
24
24
  * const machine = setup({}).createMachine({
@@ -135,6 +135,100 @@ export const normalizeRoute = (route, source = "deriveRoute") => {
135
135
  }
136
136
  throw new InvalidRouteMetadataError(route, source);
137
137
  };
138
+ /**
139
+ * Reads the `reenter` flag of the route metadata.
140
+ *
141
+ * The string form of the metadata declares no flag, and the object form declares the
142
+ * flag only when it wants one. Both therefore give `false`, which is the default of
143
+ * XState for a transition. A state without a route gives `false` too, so the caller
144
+ * needs no test of its own for that case.
145
+ *
146
+ * The function does NOT check the form of the metadata. `normalizeRoute` runs first at
147
+ * every call site and throws `InvalidRouteMetadataError` on a malformed value.
148
+ *
149
+ * @param route - The route metadata: a string, an object with a `path` property, or
150
+ * `undefined` for a state that declares no route
151
+ * @returns The declared flag, or `false` where the metadata declares none
152
+ *
153
+ * @example
154
+ * ```typescript
155
+ * routeReenter("/dashboard"); // false
156
+ * routeReenter({ path: "/dashboard" }); // false
157
+ * routeReenter({ path: "/dashboard", reenter: true }); // true
158
+ * routeReenter(undefined); // false
159
+ * ```
160
+ */
161
+ export const routeReenter = (route) => typeof route === "object" && route !== null && route.reenter === true;
162
+ /**
163
+ * Reads the extra data that a route declares, resolved for one event.
164
+ *
165
+ * The field holds a literal value or a function of `{ context, event }`, which is the
166
+ * `WithDynamicParams` shape of XState. This function collapses the two into the value.
167
+ *
168
+ * The function does NOT check the form of the metadata. `normalizeRoute` runs first at
169
+ * every call site and throws `InvalidRouteMetadataError` on a malformed value.
170
+ *
171
+ * @param route - The route metadata: a string, an object with a `path` property, or
172
+ * `undefined` for a state that declares no route
173
+ * @param args - The context of the machine and the `play.route` event that asks for the
174
+ * route. The resolver reads them.
175
+ * @returns The data, or `undefined` where the route declares none
176
+ *
177
+ * @example
178
+ * ```typescript
179
+ * routeData({ path: "/a", data: { titleKey: "a" } }, args); // { titleKey: "a" }
180
+ * routeData({ path: "/a", data: ({ event }) => ({ to: event.to }) }, args);
181
+ * routeData("/a", args); // undefined
182
+ * ```
183
+ */
184
+ export const routeData = (route, args) => {
185
+ if (typeof route !== "object" || route === null)
186
+ return undefined;
187
+ const data = route.data;
188
+ if (data === undefined)
189
+ return undefined;
190
+ return typeof data === "function" ? data(args) : data;
191
+ };
192
+ /** The placements that a `meta.route` object can declare. */
193
+ const ROUTE_HANDLERS = new Set(["root", "local", "both"]);
194
+ /**
195
+ * Reads the placement of the generated `play.route` transition.
196
+ *
197
+ * `"root"` is the default, and it is the placement of XState: every route transition
198
+ * sits on the root of the machine. `"local"` moves the transition to the parent of the
199
+ * state, and `"both"` puts one transition in each place.
200
+ *
201
+ * The function does NOT check the form of the metadata. `normalizeRoute` runs first at
202
+ * every call site and throws `InvalidRouteMetadataError` on a malformed value.
203
+ *
204
+ * @param route - The route metadata: a string, an object with a `path` property, or
205
+ * `undefined` for a state that declares no route
206
+ * @param source - The `PlayError.scope` value to report for an unknown placement
207
+ * @returns The declared placement, and `"root"` where the metadata declares none
208
+ * @throws {InvalidRouteHandlerError} When the object declares a `handler` that is not
209
+ * `"root"`, `"local"`, or `"both"`. A typo would otherwise fall back to a placement
210
+ * that the author did not ask for, and it would change which states a route reaches.
211
+ *
212
+ * @example
213
+ * ```typescript
214
+ * routeHandler("/dashboard"); // "root"
215
+ * routeHandler({ path: "/dashboard" }); // "root"
216
+ * routeHandler({ path: "/dashboard", handler: "local" }); // "local"
217
+ * routeHandler({ path: "/dashboard", handler: "both" }); // "both"
218
+ * routeHandler({ path: "/dashboard", handler: "locale" }); // throws
219
+ * ```
220
+ */
221
+ export const routeHandler = (route, source = "formatPlayRouteTransitions") => {
222
+ if (typeof route !== "object" || route === null)
223
+ return "root";
224
+ const handler = route.handler;
225
+ if (handler === undefined)
226
+ return "root";
227
+ if (typeof handler !== "string" || !ROUTE_HANDLERS.has(handler)) {
228
+ throw new InvalidRouteHandlerError(handler, source);
229
+ }
230
+ return handler;
231
+ };
138
232
  /**
139
233
  * Tells you if the route path is absolute
140
234
  *
@@ -147,7 +241,7 @@ export const normalizeRoute = (route, source = "deriveRoute") => {
147
241
  *
148
242
  * @example
149
243
  * ```typescript
150
- * import { isAbsoluteRoute } from "@xmachines/play-xstate";
244
+ * import { isAbsoluteRoute } from "@xmachines/play-xstate/routing";
151
245
  *
152
246
  * console.log(isAbsoluteRoute("/dashboard")); // true
153
247
  * console.log(isAbsoluteRoute("settings")); // false
@@ -1 +1 @@
1
- {"version":3,"file":"derive-route.js","sourceRoot":"","sources":["../../src/routing/derive-route.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAC;AAEzD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuFG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,SAAkC,EAAiB,EAAE;IAChF,kFAAkF;IAClF,+EAA+E;IAC/E,8EAA8E;IAC9E,iFAAiF;IACjF,kFAAkF;IAClF,qBAAqB;IACrB,IAAI,QAAQ,GAAkB,IAAI,CAAC;IACnC,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC;QAC7C,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI;YAAE,SAAS;QACxD,IAAI,CAAC,CAAC,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK;YAAE,SAAS;QAEhD,MAAM,KAAK,GAAG,cAAc,CAAC,IAAI,CAAC,KAAsB,CAAC,CAAC;QAC1D,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,EAAE;YAAE,SAAS;QACxD,IAAI,eAAe,CAAC,KAAK,CAAC,EAAE,CAAC;YAC5B,QAAQ,GAAG,KAAK,CAAC;QAClB,CAAC;aAAM,CAAC;YACP,MAAM,IAAI,GAAW,QAAQ,KAAK,IAAI,IAAI,QAAQ,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC;YAC3E,QAAQ,GAAG,GAAG,IAAI,IAAI,KAAK,EAAE,CAAC;QAC/B,CAAC;IACF,CAAC;IAED,OAAO,QAAQ,CAAC;AACjB,CAAC,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,KAAoB,EAAE,MAAM,GAAG,aAAa,EAAU,EAAE;IACtF,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC/B,OAAO,KAAK,CAAC;IACd,CAAC;IAED,uCAAuC;IACvC,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,IAAI,KAAK,EAAE,CAAC;QAC3D,OAAQ,KAAqB,CAAC,IAAI,CAAC;IACpC,CAAC;IAED,MAAM,IAAI,yBAAyB,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;AACpD,CAAC,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,IAAY,EAAW,EAAE;IACxD,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;AAC7B,CAAC,CAAC"}
1
+ {"version":3,"file":"derive-route.js","sourceRoot":"","sources":["../../src/routing/derive-route.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,wBAAwB,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAC;AAEnF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuFG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,SAAkC,EAAiB,EAAE;IAChF,kFAAkF;IAClF,+EAA+E;IAC/E,8EAA8E;IAC9E,iFAAiF;IACjF,kFAAkF;IAClF,qBAAqB;IACrB,IAAI,QAAQ,GAAkB,IAAI,CAAC;IACnC,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC;QAC7C,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI;YAAE,SAAS;QACxD,IAAI,CAAC,CAAC,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK;YAAE,SAAS;QAEhD,MAAM,KAAK,GAAG,cAAc,CAAC,IAAI,CAAC,KAAsB,CAAC,CAAC;QAC1D,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,EAAE;YAAE,SAAS;QACxD,IAAI,eAAe,CAAC,KAAK,CAAC,EAAE,CAAC;YAC5B,QAAQ,GAAG,KAAK,CAAC;QAClB,CAAC;aAAM,CAAC;YACP,MAAM,IAAI,GAAW,QAAQ,KAAK,IAAI,IAAI,QAAQ,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC;YAC3E,QAAQ,GAAG,GAAG,IAAI,IAAI,KAAK,EAAE,CAAC;QAC/B,CAAC;IACF,CAAC;IAED,OAAO,QAAQ,CAAC;AACjB,CAAC,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,KAAoB,EAAE,MAAM,GAAG,aAAa,EAAU,EAAE;IACtF,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC/B,OAAO,KAAK,CAAC;IACd,CAAC;IAED,uCAAuC;IACvC,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,IAAI,KAAK,EAAE,CAAC;QAC3D,OAAQ,KAAqB,CAAC,IAAI,CAAC;IACpC,CAAC;IAED,MAAM,IAAI,yBAAyB,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;AACpD,CAAC,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,KAAgC,EAAW,EAAE,CACzE,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAK,KAAqB,CAAC,OAAO,KAAK,IAAI,CAAC;AAExF;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,CACxB,KAAgC,EAChC,IAAiD,EACzB,EAAE;IAC1B,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,SAAS,CAAC;IAElE,MAAM,IAAI,GAAI,KAAqB,CAAC,IAAI,CAAC;IACzC,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAEzC,OAAO,OAAO,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AACvD,CAAC,CAAC;AAEF,6DAA6D;AAC7D,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;AAE1D;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAC3B,KAAgC,EAChC,MAAM,GAAG,4BAA4B,EACT,EAAE;IAC9B,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,MAAM,CAAC;IAE/D,MAAM,OAAO,GAAI,KAAqB,CAAC,OAAO,CAAC;IAC/C,IAAI,OAAO,KAAK,SAAS;QAAE,OAAO,MAAM,CAAC;IACzC,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;QACjE,MAAM,IAAI,wBAAwB,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IACrD,CAAC;IAED,OAAO,OAAoC,CAAC;AAC7C,CAAC,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,IAAY,EAAW,EAAE;IACxD,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;AAC7B,CAAC,CAAC"}
@@ -16,13 +16,19 @@ export type RouteStateNode = {
16
16
  meta?: {
17
17
  /**
18
18
  * The template of the URL path: the string form, for example
19
- * `"/profile/:username"`, or the object form (`{ path, title }`). Both match
20
- * {@link RouteMetadata}.
19
+ * `"/profile/:username"`, or the object form (`{ path, reenter, title }`). Both
20
+ * match {@link RouteMetadata}. The object form declares the `reenter` flag of the
21
+ * generated transition, and that flag defaults to `false`.
21
22
  */
22
23
  route?: RouteMetadata;
23
24
  };
24
25
  /** The nested child states. The function walks them for each further route declaration. */
25
26
  states?: Record<string, RouteStateNode>;
27
+ /**
28
+ * The event handlers of this state. The function reads them where a child asks for a
29
+ * local `play.route` handler, so that the transitions of the user survive the merge.
30
+ */
31
+ on?: Record<string, unknown> | undefined;
26
32
  [key: string]: unknown;
27
33
  };
28
34
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"format-play-route-transitions.d.ts","sourceRoot":"","sources":["../../src/routing/format-play-route-transitions.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAkBhD;;;;;;;GAOG;AACH,MAAM,MAAM,cAAc,GAAG;IAC5B;;OAEG;IACH,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,wEAAwE;IACxE,IAAI,CAAC,EAAE;QACN;;;;WAIG;QACH,KAAK,CAAC,EAAE,aAAa,CAAC;KACtB,CAAC;IACF,2FAA2F;IAC3F,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IACxC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACvB,CAAC;AAaF;;;;;;;;;;GAUG;AACH,MAAM,MAAM,kBAAkB,GAAG;IAChC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;IAC7C,EAAE,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;IACzC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACvB,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,0BAA0B,CAAC,CAAC,SAAS,kBAAkB,EAAE,aAAa,EAAE,CAAC,GAAG,CAAC,CAwH5F"}
1
+ {"version":3,"file":"format-play-route-transitions.d.ts","sourceRoot":"","sources":["../../src/routing/format-play-route-transitions.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,aAAa,EAAe,MAAM,YAAY,CAAC;AAgB7D;;;;;;;GAOG;AACH,MAAM,MAAM,cAAc,GAAG;IAC5B;;OAEG;IACH,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,wEAAwE;IACxE,IAAI,CAAC,EAAE;QACN;;;;;WAKG;QACH,KAAK,CAAC,EAAE,aAAa,CAAC;KACtB,CAAC;IACF,2FAA2F;IAC3F,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IACxC;;;OAGG;IACH,EAAE,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;IACzC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACvB,CAAC;AAiHF;;;;;;;;;;GAUG;AACH,MAAM,MAAM,kBAAkB,GAAG;IAChC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;IAC7C,EAAE,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;IACzC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACvB,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,0BAA0B,CAAC,CAAC,SAAS,kBAAkB,EAAE,aAAa,EAAE,CAAC,GAAG,CAAC,CA2L5F"}
@@ -1,7 +1,7 @@
1
1
  import { assign } from "xstate";
2
- import { shallowEqualExcept } from "@xmachines/play-actor";
2
+ import { shallowEqualExcept } from "@xmachines/play";
3
3
  import { MissingStateIdError } from "../errors.js";
4
- import { normalizeRoute } from "./derive-route.js";
4
+ import { normalizeRoute, routeData, routeHandler, routeReenter } from "./derive-route.js";
5
5
  /**
6
6
  * Reuses the previous container of the params and of the query when the new
7
7
  * container is equal to it in a shallow comparison.
@@ -13,7 +13,78 @@ import { normalizeRoute } from "./derive-route.js";
13
13
  * values, such as a popstate event to the current URL or a second send from the
14
14
  * code, emits the view again for nothing.
15
15
  */
16
- const keepEqualContainer = (prev, next) => (prev !== undefined && shallowEqualExcept(prev, next) ? prev : next);
16
+ const keepEqualContainer = (prev, next) => prev !== undefined && shallowEqualExcept(prev, next) ? prev : next;
17
+ /**
18
+ * Normalizes the `play.route` entry of an `on` record into an array.
19
+ *
20
+ * A user writes one transition or an array of them, and XState accepts both forms.
21
+ * The merge therefore needs one form.
22
+ */
23
+ const asTransitionArray = (value) => value === undefined ? [] : Array.isArray(value) ? value : [value];
24
+ /**
25
+ * True when the route declares a `data` field.
26
+ *
27
+ * The assigner below reads this ONE time, when it builds the action, and not on every
28
+ * event: the declaration of a state is static.
29
+ */
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 || {});
38
+ /**
39
+ * Builds the assign action of a generated `play.route` transition.
40
+ *
41
+ * Every generated transition gets its OWN action object, from this one factory. The
42
+ * root transition and the local transition of the same state therefore hold no shared
43
+ * object, and the body of the assign lives in one place.
44
+ *
45
+ * A route that declares no `data` gets an assign with no `data` KEY. A key that writes
46
+ * the previous value back is not the same thing: `assign` puts an own property on the
47
+ * context for each key that it carries, so a machine that declares no `data` field
48
+ * received one with no value, and the `/context` projection of every view carried it.
49
+ */
50
+ const makeRouteAssign = (routeMeta) => {
51
+ if (!declaresRouteData(routeMeta))
52
+ return assign({ params: assignParams, query: assignQuery });
53
+ return assign({
54
+ params: assignParams,
55
+ query: assignQuery,
56
+ // A resolver that answers `undefined` leaves the field of the context as it stands,
57
+ // and it therefore writes `undefined` over the data of an earlier route never.
58
+ data: ({ context, event }) => {
59
+ const previous = context.data;
60
+ const next = routeData(routeMeta, { context, event });
61
+ return next === undefined ? previous : keepEqualContainer(previous, next);
62
+ },
63
+ });
64
+ };
65
+ /**
66
+ * Rebuilds one state node with its local `play.route` transitions in place.
67
+ *
68
+ * The transitions of the user stay, and they come AFTER the generated ones: XState
69
+ * reads the candidates in their order, so a generated guard wins when it matches, and
70
+ * the transitions of the user are the fallback. This is the rule that the root of the
71
+ * machine follows too.
72
+ *
73
+ * The function writes into NO object of the caller. It returns a new node.
74
+ */
75
+ const withLocalTransitions = (node, states, transitions) => {
76
+ if (transitions.length === 0)
77
+ return { ...node, states };
78
+ const existingOn = node.on ?? {};
79
+ return {
80
+ ...node,
81
+ states,
82
+ on: {
83
+ ...existingOn,
84
+ "play.route": [...transitions, ...asTransitionArray(existingOn["play.route"])],
85
+ },
86
+ };
87
+ };
17
88
  /**
18
89
  * Makes the play.route transitions from the declarative route configs
19
90
  *
@@ -49,7 +120,14 @@ const keepEqualContainer = (prev, next) => (prev !== undefined && shallowEqualEx
49
120
  export function formatPlayRouteTransitions(machineConfig) {
50
121
  const routeTransitions = [];
51
122
  const collectRoutes = (states, parentPath = "") => {
52
- Object.entries(states).forEach(([key, stateConfig]) => {
123
+ const localTransitions = [];
124
+ let changed = false;
125
+ // The walk collects PAIRS, and `Object.fromEntries` builds the record at the end.
126
+ // A write through `nextStates[key]` would reach the `__proto__` setter of
127
+ // `Object.prototype` for a state whose key is `"__proto__"`, and it would set the
128
+ // prototype of the record instead of adding a state to it. `fromEntries` defines
129
+ // an own property for every key, so no key of a config is special.
130
+ const nextEntries = Object.entries(states).map(([key, stateConfig]) => {
53
131
  const node = stateConfig;
54
132
  // Build the complete path of the keys, from the root, for the target of the
55
133
  // transition. An XState target uses the hierarchy of the state keys, and not the
@@ -59,80 +137,134 @@ export function formatPlayRouteTransitions(machineConfig) {
59
137
  // InvalidRouteMetadataError. It then normalizes the value into the string of the
60
138
  // path. An empty path marks the state as a state without a route, in the string form
61
139
  // ("") and also in the object form ({ path: "" }).
62
- const routePath = node.meta?.route === undefined
140
+ const routeMeta = node.meta?.route;
141
+ const routePath = routeMeta === undefined
63
142
  ? ""
64
- : normalizeRoute(node.meta.route, "formatPlayRouteTransitions");
143
+ : normalizeRoute(routeMeta, "formatPlayRouteTransitions");
144
+ // Check the placement for EVERY declared route, and not only for one that
145
+ // produces a transition. A state with an empty path generates none, and a typo
146
+ // in its `handler` would otherwise wait silently until somebody gives the state
147
+ // a path.
148
+ const placement = routeHandler(routeMeta);
65
149
  if (routePath && !node.id) {
66
150
  throw new MissingStateIdError(key, routePath);
67
151
  }
68
152
  if (routePath && node.id) {
69
- const transition = {
70
- target: `.${statePath}`,
71
- guard: ({ event }) => event.to === `#${node.id}`,
72
- reenter: true,
73
- actions: assign({
74
- params: ({ context, event }) => keepEqualContainer(context.params, event.params || {}),
75
- query: ({ context, event }) => keepEqualContainer(context.query, event.query || {}),
76
- }),
77
- };
78
- routeTransitions.push(transition);
153
+ // The declaration of the state decides the flag, and the default is `false`,
154
+ // which is the default of XState. The flag spares the DOMAIN of the
155
+ // transition: under the root placement it spares the root alone, and each
156
+ // ancestor between the root and the target still runs its exit and its entry
157
+ // actions. `handler` is the field that spares those.
158
+ const reenter = routeReenter(routeMeta);
159
+ // A parent path of "" means that the parent IS the root. The root transition of
160
+ // such a state already targets `.${key}`, so it IS the local transition, and
161
+ // every placement therefore collapses to the root transition.
162
+ const parentIsRoot = parentPath === "";
163
+ const wantsRoot = parentIsRoot || placement === "root" || placement === "both";
164
+ const wantsLocal = !parentIsRoot && (placement === "local" || placement === "both");
165
+ // The ROOT transition. XState installs every route transition on the root, and
166
+ // this function keeps that placement as its default: a route from ANY state
167
+ // therefore reaches this state.
168
+ if (wantsRoot) {
169
+ routeTransitions.push({
170
+ target: `.${statePath}`,
171
+ guard: ({ event }) => event.to === `#${node.id}`,
172
+ reenter,
173
+ actions: makeRouteAssign(routeMeta),
174
+ });
175
+ }
176
+ // The LOCAL transition. It sits on the PARENT of this state, and it targets
177
+ // this state relatively. XState offers the transitions of the deepest active
178
+ // state node first, so this transition answers the event while the parent is
179
+ // active, and the parent therefore runs its exit and its entry actions NOT
180
+ // again.
181
+ //
182
+ // Under `"local"` this is the ONLY transition of the state, so a route that
183
+ // arrives while the parent is inactive matches nothing and the actor does not
184
+ // move. That is the declared intent of `"local"`: it scopes the route.
185
+ if (wantsLocal) {
186
+ localTransitions.push({
187
+ target: `.${key}`,
188
+ guard: ({ event }) => event.to === `#${node.id}`,
189
+ reenter,
190
+ actions: makeRouteAssign(routeMeta),
191
+ });
192
+ }
79
193
  }
194
+ let nextNode = stateConfig;
80
195
  if (node.states) {
81
- collectRoutes(node.states, statePath);
196
+ const child = collectRoutes(node.states, statePath);
197
+ if (child.changed || child.localTransitions.length > 0) {
198
+ // Rebuild this node, and do NOT write into the config of the caller. The
199
+ // function returns a new config, and the original must stay untouched.
200
+ nextNode = withLocalTransitions(node, child.states, child.localTransitions);
201
+ changed = true;
202
+ }
82
203
  }
204
+ return [key, nextNode];
83
205
  });
206
+ return { states: Object.fromEntries(nextEntries), localTransitions, changed };
84
207
  };
85
208
  const machineStates = machineConfig.states;
86
- if (machineStates) {
87
- collectRoutes(machineStates);
88
- }
209
+ // `states` comes back rebuilt where a descendant asked for a local handler, and it
210
+ // comes back as the original record where none did. The walk returns no local
211
+ // transition for the top level: the parent of a top-level state IS the root, and the
212
+ // root transition of such a state is already local to its parent.
213
+ const walk = machineStates ? collectRoutes(machineStates) : undefined;
89
214
  // The ROOT of the machine can declare a route of its own, which a chart does when
90
215
  // its whole document owns a path prefix, for example `/doc` with `/doc/a` under it.
91
216
  // `collectRoutes` walks `states` only, so the root got no transition, and a URL for
92
217
  // the root moved the machine nowhere: a press on BACK to `/doc` left the actor on
93
218
  // the child it already held, and the URL and the actor diverged.
94
219
  //
95
- // The transition targets the root by its id, and it re-enters. XState therefore
96
- // enters the `initial` child of the root, which is the state that a URL for the
97
- // root means.
220
+ // The transition targets the root by its ID. XState enters the `initial` child of
221
+ // an ID target, which is the state that a URL for the root means. The `reenter`
222
+ // flag does NOT decide that: a route to the root lands on the initial child of the
223
+ // root under `false` and under `true`. The flag decides only whether the root runs
224
+ // its own `exit` and `entry` actions again. The root therefore reads the flag from
225
+ // its `meta.route` like every other state, and it defaults to `false`.
98
226
  const rootNode = machineConfig;
99
- const rootRoutePath = rootNode.meta?.route === undefined
227
+ const rootRouteMeta = rootNode.meta?.route;
228
+ const rootRoutePath = rootRouteMeta === undefined
100
229
  ? ""
101
- : normalizeRoute(rootNode.meta.route, "formatPlayRouteTransitions");
230
+ : normalizeRoute(rootRouteMeta, "formatPlayRouteTransitions");
231
+ // The placement of the ROOT has no meaning, because the root has no parent to hold a
232
+ // local transition. A value that the routing layer does not know must still fail
233
+ // here, so that one typo behaves the same wherever an author writes it.
234
+ routeHandler(rootRouteMeta);
102
235
  if (rootRoutePath) {
103
236
  if (!rootNode.id)
104
237
  throw new MissingStateIdError("(the root of the machine)", rootRoutePath);
105
238
  routeTransitions.push({
106
239
  target: `#${rootNode.id}`,
107
240
  guard: ({ event }) => event.to === `#${rootNode.id}`,
108
- reenter: true,
109
- actions: assign({
110
- params: ({ context, event }) => keepEqualContainer(context.params, event.params || {}),
111
- query: ({ context, event }) => keepEqualContainer(context.query, event.query || {}),
112
- }),
241
+ reenter: routeReenter(rootRouteMeta),
242
+ actions: makeRouteAssign(rootRouteMeta),
113
243
  });
114
244
  }
245
+ const rebuiltStates = walk?.changed === true;
246
+ // A machine whose every routable state declares `handler: "local"` produces NO root
247
+ // transition, and its transitions live on the rebuilt states alone. The rebuilt
248
+ // states must therefore survive on their own, and not only beside a root
249
+ // transition.
250
+ if (routeTransitions.length === 0 && !rebuiltStates) {
251
+ return machineConfig;
252
+ }
253
+ const next = {
254
+ ...machineConfig,
255
+ ...(rebuiltStates ? { states: walk?.states } : {}),
256
+ };
115
257
  if (routeTransitions.length > 0) {
116
258
  const existingOn = machineConfig.on || {};
117
259
  // Keep each play.route transition of the user, for example a 404 fallback that a
118
260
  // person wrote, and append those transitions AFTER the generated ones: XState
119
261
  // evaluates the candidate transitions in their order. Therefore a generated guard
120
262
  // wins when it matches, and the transitions of the user are the fallback.
121
- const userRouteTransitions = existingOn["play.route"];
122
- const normalizedUserTransitions = userRouteTransitions === undefined
123
- ? []
124
- : Array.isArray(userRouteTransitions)
125
- ? userRouteTransitions
126
- : [userRouteTransitions];
127
- const updatedOn = {
263
+ next["on"] = {
128
264
  ...existingOn,
129
- "play.route": [...routeTransitions, ...normalizedUserTransitions],
130
- };
131
- return {
132
- ...machineConfig,
133
- on: updatedOn,
265
+ "play.route": [...routeTransitions, ...asTransitionArray(existingOn["play.route"])],
134
266
  };
135
267
  }
136
- return machineConfig;
268
+ return next;
137
269
  }
138
270
  //# sourceMappingURL=format-play-route-transitions.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"format-play-route-transitions.js","sourceRoot":"","sources":["../../src/routing/format-play-route-transitions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAGnD;;;;;;;;;;GAUG;AACH,MAAM,kBAAkB,GAAG,CAC1B,IAAwC,EACxC,IAA4B,EACH,EAAE,CAAC,CAAC,IAAI,KAAK,SAAS,IAAI,kBAAkB,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AA0DlG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,MAAM,UAAU,0BAA0B,CAA+B,aAAgB;IACxF,MAAM,gBAAgB,GAAsB,EAAE,CAAC;IAE/C,MAAM,aAAa,GAAG,CAAC,MAA+B,EAAE,UAAU,GAAG,EAAE,EAAE,EAAE;QAC1E,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,WAAW,CAAC,EAAE,EAAE;YACrD,MAAM,IAAI,GAAG,WAA6B,CAAC;YAC3C,4EAA4E;YAC5E,iFAAiF;YACjF,gBAAgB;YAChB,MAAM,SAAS,GAAG,UAAU,CAAC,CAAC,CAAC,GAAG,UAAU,IAAI,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC;YAC5D,qFAAqF;YACrF,iFAAiF;YACjF,qFAAqF;YACrF,mDAAmD;YACnD,MAAM,SAAS,GACd,IAAI,CAAC,IAAI,EAAE,KAAK,KAAK,SAAS;gBAC7B,CAAC,CAAC,EAAE;gBACJ,CAAC,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,4BAA4B,CAAC,CAAC;YAElE,IAAI,SAAS,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;gBAC3B,MAAM,IAAI,mBAAmB,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;YAC/C,CAAC;YAED,IAAI,SAAS,IAAI,IAAI,CAAC,EAAE,EAAE,CAAC;gBAC1B,MAAM,UAAU,GAAoB;oBACnC,MAAM,EAAE,IAAI,SAAS,EAAE;oBACvB,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,IAAI,IAAI,CAAC,EAAE,EAAE;oBAChD,OAAO,EAAE,IAAI;oBACb,OAAO,EAAE,MAAM,CAAC;wBACf,MAAM,EAAE,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,CAC9B,kBAAkB,CAChB,OAA+C,CAAC,MAAM,EACvD,KAAK,CAAC,MAAM,IAAI,EAAE,CAClB;wBACF,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,CAC7B,kBAAkB,CAChB,OAA8C,CAAC,KAAK,EACrD,KAAK,CAAC,KAAK,IAAI,EAAE,CACjB;qBACF,CAAC;iBACF,CAAC;gBAEF,gBAAgB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YACnC,CAAC;YAED,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;gBACjB,aAAa,CAAC,IAAI,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;YACvC,CAAC;QACF,CAAC,CAAC,CAAC;IACJ,CAAC,CAAC;IAEF,MAAM,aAAa,GAAG,aAAa,CAAC,MAAM,CAAC;IAC3C,IAAI,aAAa,EAAE,CAAC;QACnB,aAAa,CAAC,aAAa,CAAC,CAAC;IAC9B,CAAC;IAED,kFAAkF;IAClF,oFAAoF;IACpF,oFAAoF;IACpF,kFAAkF;IAClF,iEAAiE;IACjE,EAAE;IACF,gFAAgF;IAChF,gFAAgF;IAChF,cAAc;IACd,MAAM,QAAQ,GAAG,aAA+B,CAAC;IACjD,MAAM,aAAa,GAClB,QAAQ,CAAC,IAAI,EAAE,KAAK,KAAK,SAAS;QACjC,CAAC,CAAC,EAAE;QACJ,CAAC,CAAC,cAAc,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,EAAE,4BAA4B,CAAC,CAAC;IAEtE,IAAI,aAAa,EAAE,CAAC;QACnB,IAAI,CAAC,QAAQ,CAAC,EAAE;YAAE,MAAM,IAAI,mBAAmB,CAAC,2BAA2B,EAAE,aAAa,CAAC,CAAC;QAE5F,gBAAgB,CAAC,IAAI,CAAC;YACrB,MAAM,EAAE,IAAI,QAAQ,CAAC,EAAE,EAAE;YACzB,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,IAAI,QAAQ,CAAC,EAAE,EAAE;YACpD,OAAO,EAAE,IAAI;YACb,OAAO,EAAE,MAAM,CAAC;gBACf,MAAM,EAAE,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,CAC9B,kBAAkB,CAChB,OAA+C,CAAC,MAAM,EACvD,KAAK,CAAC,MAAM,IAAI,EAAE,CAClB;gBACF,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,CAC7B,kBAAkB,CAChB,OAA8C,CAAC,KAAK,EACrD,KAAK,CAAC,KAAK,IAAI,EAAE,CACjB;aACF,CAAC;SACF,CAAC,CAAC;IACJ,CAAC;IAED,IAAI,gBAAgB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACjC,MAAM,UAAU,GAAG,aAAa,CAAC,EAAE,IAAI,EAAE,CAAC;QAE1C,iFAAiF;QACjF,8EAA8E;QAC9E,kFAAkF;QAClF,0EAA0E;QAC1E,MAAM,oBAAoB,GAAG,UAAU,CAAC,YAAY,CAAC,CAAC;QACtD,MAAM,yBAAyB,GAC9B,oBAAoB,KAAK,SAAS;YACjC,CAAC,CAAC,EAAE;YACJ,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,oBAAoB,CAAC;gBACpC,CAAC,CAAC,oBAAoB;gBACtB,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC;QAE5B,MAAM,SAAS,GAAG;YACjB,GAAG,UAAU;YACb,YAAY,EAAE,CAAC,GAAG,gBAAgB,EAAE,GAAG,yBAAyB,CAAC;SACjE,CAAC;QAEF,OAAO;YACN,GAAG,aAAa;YAChB,EAAE,EAAE,SAAS;SACR,CAAC;IACR,CAAC;IAED,OAAO,aAAa,CAAC;AACtB,CAAC"}
1
+ {"version":3,"file":"format-play-route-transitions.js","sourceRoot":"","sources":["../../src/routing/format-play-route-transitions.ts"],"names":[],"mappings":"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"}
@@ -12,5 +12,5 @@ export { deriveInitialRoute } from "./derive-initial-route.js";
12
12
  export { buildRouteUrl } from "./build-url.js";
13
13
  export { formatPlayRouteTransitions } from "./format-play-route-transitions.js";
14
14
  export type { RouteMachineConfig, RouteStateNode } from "./format-play-route-transitions.js";
15
- export type { RouteContext, RouteObject, RouteMetadata } from "./types.js";
15
+ export type { RouteContext, RouteObject, RouteMetadata, RouteData, RouteDataResolver, } from "./types.js";
16
16
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/routing/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACjE,OAAO,EACN,eAAe,EACf,kBAAkB,EAClB,qBAAqB,GACrB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,0BAA0B,EAAE,MAAM,oCAAoC,CAAC;AAChF,YAAY,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAC7F,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/routing/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACjE,OAAO,EACN,eAAe,EACf,kBAAkB,EAClB,qBAAqB,GACrB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,0BAA0B,EAAE,MAAM,oCAAoC,CAAC;AAChF,YAAY,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAC7F,YAAY,EACX,YAAY,EACZ,WAAW,EACX,aAAa,EACb,SAAS,EACT,iBAAiB,GACjB,MAAM,YAAY,CAAC"}
@@ -1,8 +1,12 @@
1
- export interface RouteObject {
2
- path: string;
3
- [key: string]: unknown;
4
- }
5
- export type RouteMetadata = string | RouteObject;
1
+ /**
2
+ * `RouteObject` and `RouteMetadata` have ONE definition, and it lives in
3
+ * `@xmachines/play-router`. That package owns the routing protocol, and this package
4
+ * consumes it. A second definition here would be a copy that drifts: a field added to
5
+ * one of them would leave the other behind, and nothing would fail.
6
+ *
7
+ * The re-export keeps the import path of every consumer of this package unchanged.
8
+ */
9
+ export type { RouteObject, RouteMetadata, RouteData, RouteDataResolver, } from "@xmachines/play-router";
6
10
  /**
7
11
  * The context of the route construction, from the machine context.
8
12
  *
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/routing/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACvB;AAED,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,WAAW,CAAC;AAEjD;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,YAAY;IAC5B,wCAAwC;IACxC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4FAA4F;IAC5F,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,2BAA2B;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,wBAAwB;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;CACd"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/routing/types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,YAAY,EACX,WAAW,EACX,aAAa,EACb,SAAS,EACT,iBAAiB,GACjB,MAAM,wBAAwB,CAAC;AAEhC;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,YAAY;IAC5B,wCAAwC;IACxC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4FAA4F;IAC5F,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,2BAA2B;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,wBAAwB;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;CACd"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * The read of the `meta` of the active states, which BOTH capabilities share.
3
+ *
4
+ * `deriveCurrentRoute` folds this record into a URL, and `deriveCurrentView` folds the
5
+ * same record into a view spec. The two therefore cannot move apart on the selection of
6
+ * the branch, and they cannot move apart on their tolerance of a degenerate snapshot.
7
+ *
8
+ * It lives in its own module, and no longer beside the route derivation, because it
9
+ * belongs to neither capability. `@xmachines/play-xstate/view` imported it from
10
+ * `routing/derive-current-route.ts`, and that module reads `deriveRoute`, which names
11
+ * `@xmachines/play-router`. A view-only application therefore loaded the whole route
12
+ * derivation, and the OPTIONAL peer of the routing reached the runtime graph of the view
13
+ * entry point.
14
+ */
15
+ import type { AnyMachineSnapshot } from "xstate";
16
+ /**
17
+ * Collects the `meta` object of the active state nodes of a SINGLE branch, from the
18
+ * root to a leaf. The key of each entry is the state id, and the order is the
19
+ * ancestors first. {@link deriveRoute} folds this shape.
20
+ *
21
+ * `snapshot.getMeta()` returns a FLAT record of the meta object of every active
22
+ * state. For a machine that is not parallel, that record is one chain of ancestors
23
+ * already. For a PARALLEL machine, it mixes the entries of every active region. A
24
+ * blind fold therefore joins a relative route of one region to an absolute route of
25
+ * a sibling region, and the URL belongs to the tree of neither region. The flat
26
+ * record also cannot go back into a hierarchy: when a state declares an explicit
27
+ * `id`, for example a child with `id: "dashboard-overview"` under `id: "dashboard"`,
28
+ * the meta keys are those ids, and they carry no information about the ancestry.
29
+ *
30
+ * Therefore this function walks `snapshot.value`, which holds the real hierarchy of
31
+ * the active states by the state key, against the node tree of the machine. It
32
+ * follows the FIRST active child at each level. This gives one deterministic branch,
33
+ * which matches the historical behavior of "the first that it finds" for a parallel
34
+ * machine. It also works with an explicit id, because each node carries its own `id`
35
+ * and its own `meta`.
36
+ *
37
+ * The function returns `null` when the snapshot exposes no machine and no value to
38
+ * walk. This is a defensive measure, because a real XState snapshot always exposes
39
+ * them. The caller then uses `getMeta()`, as before.
40
+ */
41
+ export declare const firstActiveBranchMeta: (snapshot: AnyMachineSnapshot) => Record<string, unknown> | null;
42
+ /**
43
+ * Resolves the meta record that the route derivation and the view derivation fold:
44
+ * the single active branch that {@link firstActiveBranchMeta} walks, which is
45
+ * correct for a parallel machine and for an explicit id, or the flat `getMeta()`
46
+ * record when the snapshot has no machine tree to walk. `deriveCurrentRoute` and
47
+ * `deriveCurrentView` share this function. Therefore the two sides cannot move apart
48
+ * on the selection of the branch, and they cannot move apart on their tolerance of a
49
+ * degenerate snapshot.
50
+ */
51
+ export declare const activeStateMeta: (snapshot: AnyMachineSnapshot) => Record<string, unknown> | null;
52
+ //# sourceMappingURL=state-meta.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state-meta.d.ts","sourceRoot":"","sources":["../src/state-meta.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,QAAQ,CAAC;AAEjD;;;;;;;;;;;;;;;;;;;;;;;;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"}