@xmachines/play-xstate 6.0.0 → 7.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 (45) hide show
  1. package/README.md +87 -28
  2. package/dist/capabilities.d.ts +2 -2
  3. package/dist/capabilities.js +6 -2
  4. package/dist/capabilities.js.map +1 -1
  5. package/dist/define-player.js +8 -8
  6. package/dist/define-player.js.map +1 -1
  7. package/dist/errors.js +262 -259
  8. package/dist/errors.js.map +1 -1
  9. package/dist/index.js +4 -25
  10. package/dist/player-actor.js +318 -448
  11. package/dist/player-actor.js.map +1 -1
  12. package/dist/routing/build-url.js +74 -108
  13. package/dist/routing/build-url.js.map +1 -1
  14. package/dist/routing/derive-current-route.d.ts.map +1 -1
  15. package/dist/routing/derive-current-route.js +46 -67
  16. package/dist/routing/derive-current-route.js.map +1 -1
  17. package/dist/routing/derive-initial-route.js +53 -64
  18. package/dist/routing/derive-initial-route.js.map +1 -1
  19. package/dist/routing/derive-route.js +225 -242
  20. package/dist/routing/derive-route.js.map +1 -1
  21. package/dist/routing/format-play-route-transitions.d.ts.map +1 -1
  22. package/dist/routing/format-play-route-transitions.js +192 -257
  23. package/dist/routing/format-play-route-transitions.js.map +1 -1
  24. package/dist/state-meta.d.ts +84 -28
  25. package/dist/state-meta.d.ts.map +1 -1
  26. package/dist/state-meta.js +170 -72
  27. package/dist/state-meta.js.map +1 -1
  28. package/dist/view/derive-current-view.d.ts +18 -10
  29. package/dist/view/derive-current-view.d.ts.map +1 -1
  30. package/dist/view/derive-current-view.js +249 -128
  31. package/dist/view/derive-current-view.js.map +1 -1
  32. package/dist/with-routing.js +94 -136
  33. package/dist/with-routing.js.map +1 -1
  34. package/dist/with-view.d.ts +1 -3
  35. package/dist/with-view.d.ts.map +1 -1
  36. package/dist/with-view.js +82 -152
  37. package/dist/with-view.js.map +1 -1
  38. package/package.json +19 -19
  39. package/dist/index.js.map +0 -1
  40. package/dist/routing/index.js +0 -14
  41. package/dist/routing/index.js.map +0 -1
  42. package/dist/routing/types.js +0 -2
  43. package/dist/routing/types.js.map +0 -1
  44. package/dist/types.js +0 -2
  45. package/dist/types.js.map +0 -1
package/dist/errors.js CHANGED
@@ -1,270 +1,273 @@
1
1
  import { PlayError } from "@xmachines/play/errors";
2
2
  import { describeValue, safeString } from "@xmachines/core/utils";
3
+ //#region packages/play-xstate/src/errors.ts
3
4
  /**
4
- * `buildRouteUrl()` throws this error when the context of the actor does not hold a
5
- * necessary route parameter.
6
- *
7
- * Read the `param` field and the `template` field to identify the parameter that is
8
- * absent. Your code therefore parses no `.message` string.
9
- *
10
- * **Error code:** `PLAY_XSTATE_ROUTE_PARAM_MISSING`
11
- *
12
- * Note: `actor.currentRoute.get()` shows this error never. The route derivation
13
- * catches it, and it returns `null` for the temporary case during a transition. The
14
- * error leaves a direct `buildRouteUrl()` call only.
15
- *
16
- * @example
17
- * ```typescript
18
- * import { buildRouteUrl } from "@xmachines/play-xstate/routing";
19
- * import { MissingRouteParamError } from "@xmachines/play-xstate/errors";
20
- *
21
- * try {
22
- * buildRouteUrl("/profile/:userId", { params: {}, query: {} });
23
- * } catch (err) {
24
- * if (err instanceof MissingRouteParamError) {
25
- * console.error(
26
- * `Missing "${err.param}" for template "${err.template}"`
27
- * );
28
- * }
29
- * }
30
- * ```
31
- */
32
- export class MissingRouteParamError extends PlayError {
33
- /** The name of the route parameter that was absent, for example `"userId"`. */
34
- param;
35
- /** The route template that needs the absent parameter, for example `"/profile/:userId"`. */
36
- template;
37
- constructor(param, template) {
38
- super("buildRouteUrl", "PLAY_XSTATE_ROUTE_PARAM_MISSING", `Route parameter '${param}' is required by template '${template}' but was not found in context.`);
39
- this.name = "MissingRouteParamError";
40
- this.param = param;
41
- this.template = template;
42
- }
43
- }
5
+ * `buildRouteUrl()` throws this error when the context of the actor does not hold a
6
+ * necessary route parameter.
7
+ *
8
+ * Read the `param` field and the `template` field to identify the parameter that is
9
+ * absent. Your code therefore parses no `.message` string.
10
+ *
11
+ * **Error code:** `PLAY_XSTATE_ROUTE_PARAM_MISSING`
12
+ *
13
+ * Note: `actor.currentRoute.get()` shows this error never. The route derivation
14
+ * catches it, and it returns `null` for the temporary case during a transition. The
15
+ * error leaves a direct `buildRouteUrl()` call only.
16
+ *
17
+ * @example
18
+ * ```typescript
19
+ * import { buildRouteUrl } from "@xmachines/play-xstate/routing";
20
+ * import { MissingRouteParamError } from "@xmachines/play-xstate/errors";
21
+ *
22
+ * try {
23
+ * buildRouteUrl("/profile/:userId", { params: {}, query: {} });
24
+ * } catch (err) {
25
+ * if (err instanceof MissingRouteParamError) {
26
+ * console.error(
27
+ * `Missing "${err.param}" for template "${err.template}"`
28
+ * );
29
+ * }
30
+ * }
31
+ * ```
32
+ */
33
+ var MissingRouteParamError = class extends PlayError {
34
+ /** The name of the route parameter that was absent, for example `"userId"`. */
35
+ param;
36
+ /** The route template that needs the absent parameter, for example `"/profile/:userId"`. */
37
+ template;
38
+ constructor(param, template) {
39
+ super("buildRouteUrl", "PLAY_XSTATE_ROUTE_PARAM_MISSING", `Route parameter '${param}' is required by template '${template}' but was not found in context.`);
40
+ this.name = "MissingRouteParamError";
41
+ this.param = param;
42
+ this.template = template;
43
+ }
44
+ };
44
45
  /**
45
- * `buildRouteUrl()` throws this error when a route parameter carries a value that no path
46
- * can hold, so the template matches the built URL back never.
47
- *
48
- * A dot segment is that value. A URL parser resolves `.` and `..` BEFORE it decodes the
49
- * percent escapes, and it counts `%2e` as the dot, so every encoding of them resolves
50
- * away: `/files/..` becomes `/`. The actor would hold the route `/files/..` while the
51
- * address bar shows `/`, and the two stay out of step for the rest of the session.
52
- *
53
- * Give the param a value that names a segment. Machine state that can carry a path from a
54
- * user belongs behind a check of its own, in the same way that a base path checks the
55
- * values of its `:param` segments.
56
- *
57
- * **Error code:** `PLAY_XSTATE_ROUTE_PARAM_INVALID`
58
- *
59
- * @example
60
- * ```typescript
61
- * import { buildRouteUrl } from "@xmachines/play-xstate/routing";
62
- * import { InvalidRouteParamError } from "@xmachines/play-xstate/errors";
63
- *
64
- * try {
65
- * buildRouteUrl("/files/:name", { params: { name: ".." }, query: {} });
66
- * } catch (err) {
67
- * if (err instanceof InvalidRouteParamError) {
68
- * console.error(`"${err.value}" cannot stand in "${err.param}"`);
69
- * }
70
- * }
71
- * ```
72
- */
73
- export class InvalidRouteParamError extends PlayError {
74
- /** The name of the route parameter that carries the value, for example `"name"`. */
75
- param;
76
- /** The value that no path can hold, for example `".."`. */
77
- value;
78
- /** The route template that declares the parameter, for example `"/files/:name"`. */
79
- template;
80
- constructor(param, value, template) {
81
- super("buildRouteUrl", "PLAY_XSTATE_ROUTE_PARAM_INVALID", `Route parameter '${param}' of template '${template}' carries the value '${value}', which resolves away in a URL.`);
82
- this.name = "InvalidRouteParamError";
83
- this.param = param;
84
- this.value = value;
85
- this.template = template;
86
- }
87
- }
46
+ * `buildRouteUrl()` throws this error when a route parameter carries a value that no path
47
+ * can hold, so the template matches the built URL back never.
48
+ *
49
+ * A dot segment is that value. A URL parser resolves `.` and `..` BEFORE it decodes the
50
+ * percent escapes, and it counts `%2e` as the dot, so every encoding of them resolves
51
+ * away: `/files/..` becomes `/`. The actor would hold the route `/files/..` while the
52
+ * address bar shows `/`, and the two stay out of step for the rest of the session.
53
+ *
54
+ * Give the param a value that names a segment. Machine state that can carry a path from a
55
+ * user belongs behind a check of its own, in the same way that a base path checks the
56
+ * values of its `:param` segments.
57
+ *
58
+ * **Error code:** `PLAY_XSTATE_ROUTE_PARAM_INVALID`
59
+ *
60
+ * @example
61
+ * ```typescript
62
+ * import { buildRouteUrl } from "@xmachines/play-xstate/routing";
63
+ * import { InvalidRouteParamError } from "@xmachines/play-xstate/errors";
64
+ *
65
+ * try {
66
+ * buildRouteUrl("/files/:name", { params: { name: ".." }, query: {} });
67
+ * } catch (err) {
68
+ * if (err instanceof InvalidRouteParamError) {
69
+ * console.error(`"${err.value}" cannot stand in "${err.param}"`);
70
+ * }
71
+ * }
72
+ * ```
73
+ */
74
+ var InvalidRouteParamError = class extends PlayError {
75
+ /** The name of the route parameter that carries the value, for example `"name"`. */
76
+ param;
77
+ /** The value that no path can hold, for example `".."`. */
78
+ value;
79
+ /** The route template that declares the parameter, for example `"/files/:name"`. */
80
+ template;
81
+ constructor(param, value, template) {
82
+ super("buildRouteUrl", "PLAY_XSTATE_ROUTE_PARAM_INVALID", `Route parameter '${param}' of template '${template}' carries the value '${value}', which resolves away in a URL.`);
83
+ this.name = "InvalidRouteParamError";
84
+ this.param = param;
85
+ this.value = value;
86
+ this.template = template;
87
+ }
88
+ };
88
89
  /**
89
- * `formatPlayRouteTransitions()` throws this error when a state node declares a
90
- * `meta.route` field but no explicit `id` field.
91
- *
92
- * Without an `id`, the function can generate no `play.route` guard that targets the
93
- * state: the guard compares `event.to` with `#<id>`. An absent `id` therefore makes
94
- * the state unreachable through the routing, and nothing says so. This error shows
95
- * the fault of the configuration at the moment of the machine definition, and the
96
- * function skips no state in silence.
97
- *
98
- * **Error code:** `PLAY_XSTATE_MISSING_STATE_ID`
99
- *
100
- * @example
101
- * ```typescript
102
- * // Bad — a meta.route field without an id field:
103
- * states: {
104
- * profile: {
105
- * meta: { route: "/profile/:username" },
106
- * // ← the id: "profile" field is absent
107
- * }
108
- * }
109
- *
110
- * // Good:
111
- * states: {
112
- * profile: {
113
- * id: "profile",
114
- * meta: { route: "/profile/:username" },
115
- * }
116
- * }
117
- * ```
118
- */
119
- export class MissingStateIdError extends PlayError {
120
- /** The state key, which is the position in the tree of the states, without an explicit `id` field. */
121
- stateKey;
122
- /** The route template of the state, for example `"/profile/:username"`. */
123
- route;
124
- constructor(stateKey, route) {
125
- super("formatPlayRouteTransitions", "PLAY_XSTATE_MISSING_STATE_ID", `State "${stateKey}" declares meta.route "${route}" but has no explicit id. ` +
126
- `Add id: "${stateKey}" to the state config so play.route events can target it.`);
127
- this.name = "MissingStateIdError";
128
- this.stateKey = stateKey;
129
- this.route = route;
130
- }
131
- }
90
+ * `formatPlayRouteTransitions()` throws this error when a state node declares a
91
+ * `meta.route` field but no explicit `id` field.
92
+ *
93
+ * Without an `id`, the function can generate no `play.route` guard that targets the
94
+ * state: the guard compares `event.to` with `#<id>`. An absent `id` therefore makes
95
+ * the state unreachable through the routing, and nothing says so. This error shows
96
+ * the fault of the configuration at the moment of the machine definition, and the
97
+ * function skips no state in silence.
98
+ *
99
+ * **Error code:** `PLAY_XSTATE_MISSING_STATE_ID`
100
+ *
101
+ * @example
102
+ * ```typescript
103
+ * // Bad — a meta.route field without an id field:
104
+ * states: {
105
+ * profile: {
106
+ * meta: { route: "/profile/:username" },
107
+ * // ← the id: "profile" field is absent
108
+ * }
109
+ * }
110
+ *
111
+ * // Good:
112
+ * states: {
113
+ * profile: {
114
+ * id: "profile",
115
+ * meta: { route: "/profile/:username" },
116
+ * }
117
+ * }
118
+ * ```
119
+ */
120
+ var MissingStateIdError = class extends PlayError {
121
+ /** The state key, which is the position in the tree of the states, without an explicit `id` field. */
122
+ stateKey;
123
+ /** The route template of the state, for example `"/profile/:username"`. */
124
+ route;
125
+ constructor(stateKey, route) {
126
+ super("formatPlayRouteTransitions", "PLAY_XSTATE_MISSING_STATE_ID", `State "${stateKey}" declares meta.route "${route}" but has no explicit id. Add id: "${stateKey}" to the state config so play.route events can target it.`);
127
+ this.name = "MissingStateIdError";
128
+ this.stateKey = stateKey;
129
+ this.route = route;
130
+ }
131
+ };
132
132
  /**
133
- * The `PlayerActor` constructor throws this error when the `machine` argument is not
134
- * a valid XState machine object, which means that it is null, undefined, or not an
135
- * object.
136
- *
137
- * **Error code:** `PLAY_XSTATE_INVALID_MACHINE`
138
- */
139
- export class InvalidMachineError extends PlayError {
140
- constructor() {
141
- super("PlayerActor", "PLAY_XSTATE_INVALID_MACHINE", "PlayerActor requires a valid XState machine");
142
- this.name = "InvalidMachineError";
143
- }
144
- }
133
+ * The `PlayerActor` constructor throws this error when the `machine` argument is not
134
+ * a valid XState machine object, which means that it is null, undefined, or not an
135
+ * object.
136
+ *
137
+ * **Error code:** `PLAY_XSTATE_INVALID_MACHINE`
138
+ */
139
+ var InvalidMachineError = class extends PlayError {
140
+ constructor() {
141
+ super("PlayerActor", "PLAY_XSTATE_INVALID_MACHINE", "PlayerActor requires a valid XState machine");
142
+ this.name = "InvalidMachineError";
143
+ }
144
+ };
145
145
  /**
146
- * `normalizeRoute()` throws this error when the `meta.route` value of a state is not
147
- * a string and not an object with a `path` property.
148
- *
149
- * **Error code:** `PLAY_XSTATE_INVALID_ROUTE_METADATA`
150
- */
151
- export class InvalidRouteMetadataError extends PlayError {
152
- /** The invalid route value, as a string, for the debug work. */
153
- detail;
154
- constructor(route, source = "deriveRoute") {
155
- const detail = describeValue(route);
156
- super(source, "PLAY_XSTATE_INVALID_ROUTE_METADATA", `Invalid route metadata: ${detail}. Expected string or { path: string }`);
157
- this.name = "InvalidRouteMetadataError";
158
- this.detail = detail;
159
- }
160
- }
146
+ * `normalizeRoute()` throws this error when the `meta.route` value of a state is not
147
+ * a string and not an object with a `path` property.
148
+ *
149
+ * **Error code:** `PLAY_XSTATE_INVALID_ROUTE_METADATA`
150
+ */
151
+ var InvalidRouteMetadataError = class extends PlayError {
152
+ /** The invalid route value, as a string, for the debug work. */
153
+ detail;
154
+ constructor(route, source = "deriveRoute") {
155
+ const detail = describeValue(route);
156
+ super(source, "PLAY_XSTATE_INVALID_ROUTE_METADATA", `Invalid route metadata: ${detail}. Expected string or { path: string }`);
157
+ this.name = "InvalidRouteMetadataError";
158
+ this.detail = detail;
159
+ }
160
+ };
161
161
  /**
162
- * `formatPlayRouteTransitions()` throws this error for a `meta.route` object whose
163
- * `handler` field holds a value that the routing layer does not know.
164
- *
165
- * The field decides WHERE the generated `play.route` transition sits, and each value
166
- * produces a different reachability. `"local"` in particular makes a state reachable
167
- * only while its parent is active. A typo such as `"locale"` would therefore fall back
168
- * to a placement that the author did not ask for, and the route would behave correctly
169
- * in the test that the author wrote and wrongly everywhere else. The error refuses the
170
- * value instead.
171
- *
172
- * **Error code:** `PLAY_XSTATE_INVALID_ROUTE_HANDLER`
173
- *
174
- * @example
175
- * ```typescript
176
- * import { InvalidRouteHandlerError } from "@xmachines/play-xstate/errors";
177
- *
178
- * try {
179
- * formatPlayRouteTransitions(config);
180
- * } catch (error) {
181
- * if (error instanceof InvalidRouteHandlerError) {
182
- * console.error(error.handler); // the value that the config declared
183
- * }
184
- * }
185
- * ```
186
- */
187
- export class InvalidRouteHandlerError extends PlayError {
188
- /** The value that the config declared, as a string, for the debug work. */
189
- handler;
190
- constructor(handler, source = "formatPlayRouteTransitions") {
191
- const detail = describeValue(handler);
192
- super(source, "PLAY_XSTATE_INVALID_ROUTE_HANDLER", `Invalid route handler: ${detail}. Expected "root", "local", or "both"`);
193
- this.name = "InvalidRouteHandlerError";
194
- this.handler = detail;
195
- }
196
- }
162
+ * `formatPlayRouteTransitions()` throws this error for a `meta.route` object whose
163
+ * `handler` field holds a value that the routing layer does not know.
164
+ *
165
+ * The field decides WHERE the generated `play.route` transition sits, and each value
166
+ * produces a different reachability. `"local"` in particular makes a state reachable
167
+ * only while its parent is active. A typo such as `"locale"` would therefore fall back
168
+ * to a placement that the author did not ask for, and the route would behave correctly
169
+ * in the test that the author wrote and wrongly everywhere else. The error refuses the
170
+ * value instead.
171
+ *
172
+ * **Error code:** `PLAY_XSTATE_INVALID_ROUTE_HANDLER`
173
+ *
174
+ * @example
175
+ * ```typescript
176
+ * import { InvalidRouteHandlerError } from "@xmachines/play-xstate/errors";
177
+ *
178
+ * try {
179
+ * formatPlayRouteTransitions(config);
180
+ * } catch (error) {
181
+ * if (error instanceof InvalidRouteHandlerError) {
182
+ * console.error(error.handler); // the value that the config declared
183
+ * }
184
+ * }
185
+ * ```
186
+ */
187
+ var InvalidRouteHandlerError = class extends PlayError {
188
+ /** The value that the config declared, as a string, for the debug work. */
189
+ handler;
190
+ constructor(handler, source = "formatPlayRouteTransitions") {
191
+ const detail = describeValue(handler);
192
+ super(source, "PLAY_XSTATE_INVALID_ROUTE_HANDLER", `Invalid route handler: ${detail}. Expected "root", "local", or "both"`);
193
+ this.name = "InvalidRouteHandlerError";
194
+ this.handler = detail;
195
+ }
196
+ };
197
197
  /**
198
- * `PlayerActor.send()` throws this error when the event argument is not a plain
199
- * object.
200
- *
201
- * A `PlayEvent` needs the shape `{ type: string, ...fields }`. A `null` value, an
202
- * `undefined` value, a string, and every other value that is not an object are an
203
- * error of the programmer.
204
- *
205
- * The error holds the value in question in its readonly class field `detail`, for
206
- * the debug work. A TypeScript consumer reads `err.detail` directly, with no unsafe
207
- * cast.
208
- *
209
- * **Error code:** `PLAY_XSTATE_INVALID_EVENT`
210
- *
211
- * @example
212
- * ```typescript
213
- * import { InvalidEventError } from "@xmachines/play-xstate/errors";
214
- *
215
- * try {
216
- * actor.send(null as any);
217
- * } catch (err) {
218
- * if (err instanceof InvalidEventError) {
219
- * // err.detail has the type `unknown`, and it needs no cast
220
- * console.error("Invalid event passed to actor.send():", err.detail);
221
- * }
222
- * }
223
- * ```
224
- */
225
- export class InvalidEventError extends PlayError {
226
- /** The value in question, from the `send()` call. */
227
- detail;
228
- constructor(detail) {
229
- super("PlayerActor", "PLAY_XSTATE_INVALID_EVENT", "PlayerActor.send() received a non-object event.");
230
- this.name = "InvalidEventError";
231
- this.detail = detail;
232
- }
233
- }
198
+ * `PlayerActor.send()` throws this error when the event argument is not a plain
199
+ * object.
200
+ *
201
+ * A `PlayEvent` needs the shape `{ type: string, ...fields }`. A `null` value, an
202
+ * `undefined` value, a string, and every other value that is not an object are an
203
+ * error of the programmer.
204
+ *
205
+ * The error holds the value in question in its readonly class field `detail`, for
206
+ * the debug work. A TypeScript consumer reads `err.detail` directly, with no unsafe
207
+ * cast.
208
+ *
209
+ * **Error code:** `PLAY_XSTATE_INVALID_EVENT`
210
+ *
211
+ * @example
212
+ * ```typescript
213
+ * import { InvalidEventError } from "@xmachines/play-xstate/errors";
214
+ *
215
+ * try {
216
+ * actor.send(null as any);
217
+ * } catch (err) {
218
+ * if (err instanceof InvalidEventError) {
219
+ * // err.detail has the type `unknown`, and it needs no cast
220
+ * console.error("Invalid event passed to actor.send():", err.detail);
221
+ * }
222
+ * }
223
+ * ```
224
+ */
225
+ var InvalidEventError = class extends PlayError {
226
+ /** The value in question, from the `send()` call. */
227
+ detail;
228
+ constructor(detail) {
229
+ super("PlayerActor", "PLAY_XSTATE_INVALID_EVENT", "PlayerActor.send() received a non-object event.");
230
+ this.name = "InvalidEventError";
231
+ this.detail = detail;
232
+ }
233
+ };
234
234
  /**
235
- * The actor gives this error to `PlayerOptions.onError` when it failed with a value
236
- * that is not an `Error`, for example after a machine action ran
237
- * `throw { code: 42 }`.
238
- *
239
- * An actor error that *is* an `Error` reaches `onError` without a change, and it
240
- * keeps the identity of the machine. This case alone builds a new error. The new
241
- * error therefore carries a code that your code can match, and not a
242
- * `String(value)` message such as `"[object Object]"`. The `cause` field holds the
243
- * value from the throw.
244
- *
245
- * **Error code:** `PLAY_XSTATE_NON_ERROR_THROWN`
246
- *
247
- * @example
248
- * ```typescript
249
- * import { ActorThrewNonErrorError } from "@xmachines/play-xstate/errors";
250
- *
251
- * definePlayer({
252
- * machine,
253
- * options: {
254
- * onError: (actor, err) => {
255
- * if (err instanceof ActorThrewNonErrorError) {
256
- * // err.cause is the value that the machine threw
257
- * console.error("Machine threw a non-Error:", err.cause);
258
- * }
259
- * },
260
- * },
261
- * });
262
- * ```
263
- */
264
- export class ActorThrewNonErrorError extends PlayError {
265
- constructor(value) {
266
- super("PlayerActor", "PLAY_XSTATE_NON_ERROR_THROWN", `PlayerActor failed with a non-Error value: ${safeString(value)}.`, { cause: value });
267
- this.name = "ActorThrewNonErrorError";
268
- }
269
- }
235
+ * The actor gives this error to `PlayerOptions.onError` when it failed with a value
236
+ * that is not an `Error`, for example after a machine action ran
237
+ * `throw { code: 42 }`.
238
+ *
239
+ * An actor error that *is* an `Error` reaches `onError` without a change, and it
240
+ * keeps the identity of the machine. This case alone builds a new error. The new
241
+ * error therefore carries a code that your code can match, and not a
242
+ * `String(value)` message such as `"[object Object]"`. The `cause` field holds the
243
+ * value from the throw.
244
+ *
245
+ * **Error code:** `PLAY_XSTATE_NON_ERROR_THROWN`
246
+ *
247
+ * @example
248
+ * ```typescript
249
+ * import { ActorThrewNonErrorError } from "@xmachines/play-xstate/errors";
250
+ *
251
+ * definePlayer({
252
+ * machine,
253
+ * options: {
254
+ * onError: (actor, err) => {
255
+ * if (err instanceof ActorThrewNonErrorError) {
256
+ * // err.cause is the value that the machine threw
257
+ * console.error("Machine threw a non-Error:", err.cause);
258
+ * }
259
+ * },
260
+ * },
261
+ * });
262
+ * ```
263
+ */
264
+ var ActorThrewNonErrorError = class extends PlayError {
265
+ constructor(value) {
266
+ super("PlayerActor", "PLAY_XSTATE_NON_ERROR_THROWN", `PlayerActor failed with a non-Error value: ${safeString(value)}.`, { cause: value });
267
+ this.name = "ActorThrewNonErrorError";
268
+ }
269
+ };
270
+ //#endregion
271
+ export { ActorThrewNonErrorError, InvalidEventError, InvalidMachineError, InvalidRouteHandlerError, InvalidRouteMetadataError, InvalidRouteParamError, MissingRouteParamError, MissingStateIdError };
272
+
270
273
  //# sourceMappingURL=errors.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"errors.js","names":[],"sources":["../src/errors.ts"],"sourcesContent":["import { PlayError } from \"@xmachines/play/errors\";\nimport { describeValue, safeString } from \"@xmachines/core/utils\";\n\n/**\n * `buildRouteUrl()` throws this error when the context of the actor does not hold a\n * necessary route parameter.\n *\n * Read the `param` field and the `template` field to identify the parameter that is\n * absent. Your code therefore parses no `.message` string.\n *\n * **Error code:** `PLAY_XSTATE_ROUTE_PARAM_MISSING`\n *\n * Note: `actor.currentRoute.get()` shows this error never. The route derivation\n * catches it, and it returns `null` for the temporary case during a transition. The\n * error leaves a direct `buildRouteUrl()` call only.\n *\n * @example\n * ```typescript\n * import { buildRouteUrl } from \"@xmachines/play-xstate/routing\";\n * import { MissingRouteParamError } from \"@xmachines/play-xstate/errors\";\n *\n * try {\n * buildRouteUrl(\"/profile/:userId\", { params: {}, query: {} });\n * } catch (err) {\n * if (err instanceof MissingRouteParamError) {\n * console.error(\n * `Missing \"${err.param}\" for template \"${err.template}\"`\n * );\n * }\n * }\n * ```\n */\nexport class MissingRouteParamError extends PlayError {\n\t/** The name of the route parameter that was absent, for example `\"userId\"`. */\n\treadonly param: string;\n\n\t/** The route template that needs the absent parameter, for example `\"/profile/:userId\"`. */\n\treadonly template: string;\n\n\tconstructor(param: string, template: string) {\n\t\tsuper(\n\t\t\t\"buildRouteUrl\",\n\t\t\t\"PLAY_XSTATE_ROUTE_PARAM_MISSING\",\n\t\t\t`Route parameter '${param}' is required by template '${template}' but was not found in context.`,\n\t\t);\n\t\tthis.name = \"MissingRouteParamError\";\n\t\tthis.param = param;\n\t\tthis.template = template;\n\t}\n}\n\n/**\n * `buildRouteUrl()` throws this error when a route parameter carries a value that no path\n * can hold, so the template matches the built URL back never.\n *\n * A dot segment is that value. A URL parser resolves `.` and `..` BEFORE it decodes the\n * percent escapes, and it counts `%2e` as the dot, so every encoding of them resolves\n * away: `/files/..` becomes `/`. The actor would hold the route `/files/..` while the\n * address bar shows `/`, and the two stay out of step for the rest of the session.\n *\n * Give the param a value that names a segment. Machine state that can carry a path from a\n * user belongs behind a check of its own, in the same way that a base path checks the\n * values of its `:param` segments.\n *\n * **Error code:** `PLAY_XSTATE_ROUTE_PARAM_INVALID`\n *\n * @example\n * ```typescript\n * import { buildRouteUrl } from \"@xmachines/play-xstate/routing\";\n * import { InvalidRouteParamError } from \"@xmachines/play-xstate/errors\";\n *\n * try {\n * buildRouteUrl(\"/files/:name\", { params: { name: \"..\" }, query: {} });\n * } catch (err) {\n * if (err instanceof InvalidRouteParamError) {\n * console.error(`\"${err.value}\" cannot stand in \"${err.param}\"`);\n * }\n * }\n * ```\n */\nexport class InvalidRouteParamError extends PlayError {\n\t/** The name of the route parameter that carries the value, for example `\"name\"`. */\n\treadonly param: string;\n\n\t/** The value that no path can hold, for example `\"..\"`. */\n\treadonly value: string;\n\n\t/** The route template that declares the parameter, for example `\"/files/:name\"`. */\n\treadonly template: string;\n\n\tconstructor(param: string, value: string, template: string) {\n\t\tsuper(\n\t\t\t\"buildRouteUrl\",\n\t\t\t\"PLAY_XSTATE_ROUTE_PARAM_INVALID\",\n\t\t\t`Route parameter '${param}' of template '${template}' carries the value '${value}', which resolves away in a URL.`,\n\t\t);\n\t\tthis.name = \"InvalidRouteParamError\";\n\t\tthis.param = param;\n\t\tthis.value = value;\n\t\tthis.template = template;\n\t}\n}\n\n/**\n * `formatPlayRouteTransitions()` throws this error when a state node declares a\n * `meta.route` field but no explicit `id` field.\n *\n * Without an `id`, the function can generate no `play.route` guard that targets the\n * state: the guard compares `event.to` with `#<id>`. An absent `id` therefore makes\n * the state unreachable through the routing, and nothing says so. This error shows\n * the fault of the configuration at the moment of the machine definition, and the\n * function skips no state in silence.\n *\n * **Error code:** `PLAY_XSTATE_MISSING_STATE_ID`\n *\n * @example\n * ```typescript\n * // Bad — a meta.route field without an id field:\n * states: {\n * profile: {\n * meta: { route: \"/profile/:username\" },\n * // ← the id: \"profile\" field is absent\n * }\n * }\n *\n * // Good:\n * states: {\n * profile: {\n * id: \"profile\",\n * meta: { route: \"/profile/:username\" },\n * }\n * }\n * ```\n */\nexport class MissingStateIdError extends PlayError {\n\t/** The state key, which is the position in the tree of the states, without an explicit `id` field. */\n\treadonly stateKey: string;\n\t/** The route template of the state, for example `\"/profile/:username\"`. */\n\treadonly route: string;\n\n\tconstructor(stateKey: string, route: string) {\n\t\tsuper(\n\t\t\t\"formatPlayRouteTransitions\",\n\t\t\t\"PLAY_XSTATE_MISSING_STATE_ID\",\n\t\t\t`State \"${stateKey}\" declares meta.route \"${route}\" but has no explicit id. ` +\n\t\t\t\t`Add id: \"${stateKey}\" to the state config so play.route events can target it.`,\n\t\t);\n\t\tthis.name = \"MissingStateIdError\";\n\t\tthis.stateKey = stateKey;\n\t\tthis.route = route;\n\t}\n}\n\n/**\n * The `PlayerActor` constructor throws this error when the `machine` argument is not\n * a valid XState machine object, which means that it is null, undefined, or not an\n * object.\n *\n * **Error code:** `PLAY_XSTATE_INVALID_MACHINE`\n */\nexport class InvalidMachineError extends PlayError {\n\tconstructor() {\n\t\tsuper(\n\t\t\t\"PlayerActor\",\n\t\t\t\"PLAY_XSTATE_INVALID_MACHINE\",\n\t\t\t\"PlayerActor requires a valid XState machine\",\n\t\t);\n\t\tthis.name = \"InvalidMachineError\";\n\t}\n}\n\n/**\n * `normalizeRoute()` throws this error when the `meta.route` value of a state is not\n * a string and not an object with a `path` property.\n *\n * **Error code:** `PLAY_XSTATE_INVALID_ROUTE_METADATA`\n */\nexport class InvalidRouteMetadataError extends PlayError {\n\t/** The invalid route value, as a string, for the debug work. */\n\treadonly detail: string;\n\n\tconstructor(route: unknown, source = \"deriveRoute\") {\n\t\tconst detail = describeValue(route);\n\t\tsuper(\n\t\t\tsource,\n\t\t\t\"PLAY_XSTATE_INVALID_ROUTE_METADATA\",\n\t\t\t`Invalid route metadata: ${detail}. Expected string or { path: string }`,\n\t\t);\n\t\tthis.name = \"InvalidRouteMetadataError\";\n\t\tthis.detail = detail;\n\t}\n}\n\n/**\n * `formatPlayRouteTransitions()` throws this error for a `meta.route` object whose\n * `handler` field holds a value that the routing layer does not know.\n *\n * The field decides WHERE the generated `play.route` transition sits, and each value\n * produces a different reachability. `\"local\"` in particular makes a state reachable\n * only while its parent is active. A typo such as `\"locale\"` would therefore fall back\n * to a placement that the author did not ask for, and the route would behave correctly\n * in the test that the author wrote and wrongly everywhere else. The error refuses the\n * value instead.\n *\n * **Error code:** `PLAY_XSTATE_INVALID_ROUTE_HANDLER`\n *\n * @example\n * ```typescript\n * import { InvalidRouteHandlerError } from \"@xmachines/play-xstate/errors\";\n *\n * try {\n * formatPlayRouteTransitions(config);\n * } catch (error) {\n * if (error instanceof InvalidRouteHandlerError) {\n * console.error(error.handler); // the value that the config declared\n * }\n * }\n * ```\n */\nexport class InvalidRouteHandlerError extends PlayError {\n\t/** The value that the config declared, as a string, for the debug work. */\n\treadonly handler: string;\n\n\tconstructor(handler: unknown, source = \"formatPlayRouteTransitions\") {\n\t\tconst detail = describeValue(handler);\n\t\tsuper(\n\t\t\tsource,\n\t\t\t\"PLAY_XSTATE_INVALID_ROUTE_HANDLER\",\n\t\t\t`Invalid route handler: ${detail}. Expected \"root\", \"local\", or \"both\"`,\n\t\t);\n\t\tthis.name = \"InvalidRouteHandlerError\";\n\t\tthis.handler = detail;\n\t}\n}\n\n/**\n * `PlayerActor.send()` throws this error when the event argument is not a plain\n * object.\n *\n * A `PlayEvent` needs the shape `{ type: string, ...fields }`. A `null` value, an\n * `undefined` value, a string, and every other value that is not an object are an\n * error of the programmer.\n *\n * The error holds the value in question in its readonly class field `detail`, for\n * the debug work. A TypeScript consumer reads `err.detail` directly, with no unsafe\n * cast.\n *\n * **Error code:** `PLAY_XSTATE_INVALID_EVENT`\n *\n * @example\n * ```typescript\n * import { InvalidEventError } from \"@xmachines/play-xstate/errors\";\n *\n * try {\n * actor.send(null as any);\n * } catch (err) {\n * if (err instanceof InvalidEventError) {\n * // err.detail has the type `unknown`, and it needs no cast\n * console.error(\"Invalid event passed to actor.send():\", err.detail);\n * }\n * }\n * ```\n */\nexport class InvalidEventError extends PlayError {\n\t/** The value in question, from the `send()` call. */\n\treadonly detail: unknown;\n\n\tconstructor(detail: unknown) {\n\t\tsuper(\n\t\t\t\"PlayerActor\",\n\t\t\t\"PLAY_XSTATE_INVALID_EVENT\",\n\t\t\t\"PlayerActor.send() received a non-object event.\",\n\t\t);\n\t\tthis.name = \"InvalidEventError\";\n\t\tthis.detail = detail;\n\t}\n}\n\n/**\n * The actor gives this error to `PlayerOptions.onError` when it failed with a value\n * that is not an `Error`, for example after a machine action ran\n * `throw { code: 42 }`.\n *\n * An actor error that *is* an `Error` reaches `onError` without a change, and it\n * keeps the identity of the machine. This case alone builds a new error. The new\n * error therefore carries a code that your code can match, and not a\n * `String(value)` message such as `\"[object Object]\"`. The `cause` field holds the\n * value from the throw.\n *\n * **Error code:** `PLAY_XSTATE_NON_ERROR_THROWN`\n *\n * @example\n * ```typescript\n * import { ActorThrewNonErrorError } from \"@xmachines/play-xstate/errors\";\n *\n * definePlayer({\n * machine,\n * options: {\n * onError: (actor, err) => {\n * if (err instanceof ActorThrewNonErrorError) {\n * // err.cause is the value that the machine threw\n * console.error(\"Machine threw a non-Error:\", err.cause);\n * }\n * },\n * },\n * });\n * ```\n */\nexport class ActorThrewNonErrorError extends PlayError {\n\tconstructor(value: unknown) {\n\t\tsuper(\n\t\t\t\"PlayerActor\",\n\t\t\t\"PLAY_XSTATE_NON_ERROR_THROWN\",\n\t\t\t`PlayerActor failed with a non-Error value: ${safeString(value)}.`,\n\t\t\t{ cause: value },\n\t\t);\n\t\tthis.name = \"ActorThrewNonErrorError\";\n\t}\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgCA,IAAa,yBAAb,cAA4C,UAAU;;CAErD;;CAGA;CAEA,YAAY,OAAe,UAAkB;EAC5C,MACC,iBACA,mCACA,oBAAoB,MAAM,6BAA6B,SAAS,gCACjE;EACA,KAAK,OAAO;EACZ,KAAK,QAAQ;EACb,KAAK,WAAW;CACjB;AACD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+BA,IAAa,yBAAb,cAA4C,UAAU;;CAErD;;CAGA;;CAGA;CAEA,YAAY,OAAe,OAAe,UAAkB;EAC3D,MACC,iBACA,mCACA,oBAAoB,MAAM,iBAAiB,SAAS,uBAAuB,MAAM,iCAClF;EACA,KAAK,OAAO;EACZ,KAAK,QAAQ;EACb,KAAK,QAAQ;EACb,KAAK,WAAW;CACjB;AACD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiCA,IAAa,sBAAb,cAAyC,UAAU;;CAElD;;CAEA;CAEA,YAAY,UAAkB,OAAe;EAC5C,MACC,8BACA,gCACA,UAAU,SAAS,yBAAyB,MAAM,qCACrC,SAAS,0DACvB;EACA,KAAK,OAAO;EACZ,KAAK,WAAW;EAChB,KAAK,QAAQ;CACd;AACD;;;;;;;;AASA,IAAa,sBAAb,cAAyC,UAAU;CAClD,cAAc;EACb,MACC,eACA,+BACA,6CACD;EACA,KAAK,OAAO;CACb;AACD;;;;;;;AAQA,IAAa,4BAAb,cAA+C,UAAU;;CAExD;CAEA,YAAY,OAAgB,SAAS,eAAe;EACnD,MAAM,SAAS,cAAc,KAAK;EAClC,MACC,QACA,sCACA,2BAA2B,OAAO,sCACnC;EACA,KAAK,OAAO;EACZ,KAAK,SAAS;CACf;AACD;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BA,IAAa,2BAAb,cAA8C,UAAU;;CAEvD;CAEA,YAAY,SAAkB,SAAS,8BAA8B;EACpE,MAAM,SAAS,cAAc,OAAO;EACpC,MACC,QACA,qCACA,0BAA0B,OAAO,sCAClC;EACA,KAAK,OAAO;EACZ,KAAK,UAAU;CAChB;AACD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8BA,IAAa,oBAAb,cAAuC,UAAU;;CAEhD;CAEA,YAAY,QAAiB;EAC5B,MACC,eACA,6BACA,iDACD;EACA,KAAK,OAAO;EACZ,KAAK,SAAS;CACf;AACD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgCA,IAAa,0BAAb,cAA6C,UAAU;CACtD,YAAY,OAAgB;EAC3B,MACC,eACA,gCACA,8CAA8C,WAAW,KAAK,EAAE,IAChE,EAAE,OAAO,MAAM,CAChB;EACA,KAAK,OAAO;CACb;AACD"}
package/dist/index.js CHANGED
@@ -1,25 +1,4 @@
1
- /**
2
- * @xmachines/play-xstate - the XState v5 adapter of the Play Architecture
3
- *
4
- * This package gives you the definePlayer() API. That function binds an XState state
5
- * machine to the actor base, with the atom lifecycle and the DevTools
6
- * integration.
7
- *
8
- * The Play RFC gives this package as the adapter of the logic layer. It converts a
9
- * declarative machine definition into a live actor with an atom-driven
10
- * reactivity.
11
- *
12
- * @packageDocumentation
13
- */
14
- export { definePlayer } from "./define-player.js";
15
- export { PlayerActor } from "./player-actor.js";
16
- // The composition of the capabilities. Each capability itself lives behind its own entry
17
- // point — `@xmachines/play-xstate/routing` and `@xmachines/play-xstate/view` — so this
18
- // module imports neither, and an application loads only what it composes.
19
- export { compose } from "./capabilities.js";
20
- // The routing utilities live behind `@xmachines/play-xstate/routing`, with the mixin
21
- // that needs them: `deriveRoute`, `isAbsoluteRoute`, `buildRouteUrl`,
22
- // `formatPlayRouteTransitions`, and the route types. Each one names
23
- // `@xmachines/play-router` in its `.d.ts`, and that package is an OPTIONAL peer. This
24
- // entry therefore names no capability package, exactly as the view half does.
25
- //# sourceMappingURL=index.js.map
1
+ import { PlayerActor } from "./player-actor.js";
2
+ import { definePlayer } from "./define-player.js";
3
+ import { compose } from "./capabilities.js";
4
+ export { PlayerActor, compose, definePlayer };