@xmachines/play-xstate 1.0.0-beta.2 → 1.0.0-beta.21

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 +263 -107
  2. package/dist/define-player.d.ts +6 -56
  3. package/dist/define-player.d.ts.map +1 -1
  4. package/dist/define-player.js +8 -60
  5. package/dist/define-player.js.map +1 -1
  6. package/dist/define-player.typecheck.d.ts +2 -0
  7. package/dist/define-player.typecheck.d.ts.map +1 -0
  8. package/dist/define-player.typecheck.js +48 -0
  9. package/dist/define-player.typecheck.js.map +1 -0
  10. package/dist/errors.d.ts +66 -0
  11. package/dist/errors.d.ts.map +1 -0
  12. package/dist/errors.js +76 -0
  13. package/dist/errors.js.map +1 -0
  14. package/dist/guards/compose.d.ts +14 -3
  15. package/dist/guards/compose.d.ts.map +1 -1
  16. package/dist/guards/compose.js +26 -0
  17. package/dist/guards/compose.js.map +1 -1
  18. package/dist/guards/helpers.d.ts +13 -17
  19. package/dist/guards/helpers.d.ts.map +1 -1
  20. package/dist/guards/helpers.js +20 -25
  21. package/dist/guards/helpers.js.map +1 -1
  22. package/dist/guards/index.d.ts +2 -1
  23. package/dist/guards/index.d.ts.map +1 -1
  24. package/dist/guards/index.js +1 -1
  25. package/dist/guards/index.js.map +1 -1
  26. package/dist/guards/types.d.ts +3 -2
  27. package/dist/guards/types.d.ts.map +1 -1
  28. package/dist/index.d.ts +7 -8
  29. package/dist/index.d.ts.map +1 -1
  30. package/dist/index.js +3 -5
  31. package/dist/index.js.map +1 -1
  32. package/dist/player-actor.d.ts +70 -22
  33. package/dist/player-actor.d.ts.map +1 -1
  34. package/dist/player-actor.js +290 -88
  35. package/dist/player-actor.js.map +1 -1
  36. package/dist/player-actor.typecheck.d.ts +2 -0
  37. package/dist/player-actor.typecheck.d.ts.map +1 -0
  38. package/dist/player-actor.typecheck.js +27 -0
  39. package/dist/player-actor.typecheck.js.map +1 -0
  40. package/dist/routing/build-url.d.ts +22 -16
  41. package/dist/routing/build-url.d.ts.map +1 -1
  42. package/dist/routing/build-url.js +27 -20
  43. package/dist/routing/build-url.js.map +1 -1
  44. package/dist/routing/derive-route.d.ts +2 -2
  45. package/dist/routing/derive-route.d.ts.map +1 -1
  46. package/dist/routing/derive-route.js +3 -3
  47. package/dist/routing/derive-route.js.map +1 -1
  48. package/dist/routing/format-play-route-transitions.d.ts +41 -4
  49. package/dist/routing/format-play-route-transitions.d.ts.map +1 -1
  50. package/dist/routing/format-play-route-transitions.js +22 -19
  51. package/dist/routing/format-play-route-transitions.js.map +1 -1
  52. package/dist/routing/index.d.ts +2 -1
  53. package/dist/routing/index.d.ts.map +1 -1
  54. package/dist/routing/types.d.ts +8 -13
  55. package/dist/routing/types.d.ts.map +1 -1
  56. package/dist/signals/index.d.ts +0 -1
  57. package/dist/signals/index.d.ts.map +1 -1
  58. package/dist/signals/index.js +0 -1
  59. package/dist/signals/index.js.map +1 -1
  60. package/dist/signals/state-signal.d.ts +1 -1
  61. package/dist/signals/state-signal.d.ts.map +1 -1
  62. package/dist/types.d.ts +20 -14
  63. package/dist/types.d.ts.map +1 -1
  64. package/package.json +26 -19
  65. package/dist/catalog/index.d.ts +0 -12
  66. package/dist/catalog/index.d.ts.map +0 -1
  67. package/dist/catalog/index.js +0 -11
  68. package/dist/catalog/index.js.map +0 -1
  69. package/dist/catalog/types.d.ts +0 -36
  70. package/dist/catalog/types.d.ts.map +0 -1
  71. package/dist/catalog/types.js +0 -2
  72. package/dist/catalog/types.js.map +0 -1
  73. package/dist/catalog/validate-binding.d.ts +0 -21
  74. package/dist/catalog/validate-binding.d.ts.map +0 -1
  75. package/dist/catalog/validate-binding.js +0 -30
  76. package/dist/catalog/validate-binding.js.map +0 -1
  77. package/dist/catalog/validate-props.d.ts +0 -41
  78. package/dist/catalog/validate-props.d.ts.map +0 -1
  79. package/dist/catalog/validate-props.js +0 -95
  80. package/dist/catalog/validate-props.js.map +0 -1
@@ -1,28 +1,22 @@
1
1
  import { PlayerActor } from "./player-actor.js";
2
2
  /**
3
- * Create a player factory from XState machine and catalog
3
+ * Create a player factory from an XState machine
4
4
  *
5
- * Factory pattern that accepts an XState v5 machine and optional UI catalog,
5
+ * Factory pattern that accepts an XState v5 machine,
6
6
  * returning a function that creates {@link PlayerActor} instances. This enables
7
7
  * creating multiple actor instances from a single configuration, useful for
8
8
  * testing, multi-instance scenarios, or server-side rendering.
9
9
  *
10
- * **Architectural Context:** Implements **Strict Separation (INV-02)** by accepting
11
- * the machine definition (pure business logic) separately from the catalog (UI vocabulary).
12
- * The machine references component names in `meta.view` without importing React/framework code.
13
- *
14
10
  * @typeParam TMachine - XState v5 state machine type
15
- * @typeParam TCatalog - Optional UI component catalog type
16
11
  *
17
12
  * @param config - Player configuration object
18
13
  * @param config.machine - XState v5 state machine
19
- * @param config.catalog - Optional UI component catalog (allows machines without UI)
20
14
  * @param config.options - Optional lifecycle hooks (onStart, onTransition, etc.)
21
15
  *
22
16
  * @returns Factory function that creates actor instances with optional input context
23
17
  *
24
18
  * @example
25
- * Basic player factory without catalog
19
+ * Basic player factory
26
20
  * ```typescript
27
21
  * import { setup } from "xstate";
28
22
  * import { definePlayer } from "@xmachines/play-xstate";
@@ -41,53 +35,9 @@ import { PlayerActor } from "./player-actor.js";
41
35
  * ```
42
36
  *
43
37
  * @example
44
- * Player factory with catalog and parameter-aware routing
45
- * ```typescript
46
- * import { setup } from "xstate";
47
- * import { defineCatalog } from "@xmachines/play-catalog";
48
- * import { definePlayer } from "@xmachines/play-xstate";
49
- * import { z } from "zod";
50
- *
51
- * const catalog = defineCatalog({
52
- * HomePage: z.object({}),
53
- * ProfilePage: z.object({ userId: z.string() })
54
- * });
55
- *
56
- * const machine = setup({
57
- * types: {
58
- * context: {} as { userId: string },
59
- * events: {} as { type: 'play.route'; to: string; params?: Record<string, string> }
60
- * }
61
- * }).createMachine({
62
- * initial: 'home',
63
- * context: { userId: '' },
64
- * states: {
65
- * home: {
66
- * route: {},
67
- * meta: {
68
- * route: '/',
69
- * view: { component: 'HomePage' }
70
- * }
71
- * },
72
- * profile: {
73
- * route: {},
74
- * meta: {
75
- * route: '/profile/:userId',
76
- * view: { component: 'ProfilePage', userId: (ctx) => ctx.userId }
77
- * }
78
- * }
79
- * }
80
- * });
81
- *
82
- * const createPlayer = definePlayer({ machine, catalog });
83
- * const actor = createPlayer({ userId: 'user123' });
84
- * actor.start();
85
- * ```
86
- *
87
- * @example
88
38
  * Multiple actor instances from single factory
89
39
  * ```typescript
90
- * const createPlayer = definePlayer({ machine, catalog });
40
+ * const createPlayer = definePlayer({ machine });
91
41
  *
92
42
  * // Create actors for different users
93
43
  * const alice = createPlayer({ userId: 'alice' });
@@ -100,17 +50,15 @@ import { PlayerActor } from "./player-actor.js";
100
50
  * console.log(alice.state.get() !== bob.state.get());
101
51
  * ```
102
52
  *
103
- * @see {@link https://gitlab.com/xmachin-es/rfc/-/blob/main/src/play-v1.md | RFC Play v1}
53
+ * @see [Play RFC](../../docs/rfc/play.md)
104
54
  * @see {@link PlayerActor} for the concrete actor implementation
105
55
  * @see {@link PlayerConfig} for configuration options
106
56
  * @see {@link PlayerFactory} for factory function signature
107
57
  */
108
58
  export const definePlayer = (config) => {
109
- const { machine, catalog, options } = config;
110
- // Return factory function
111
- // Per CONTEXT.md: "Factory function for creating multiple actor instances"
112
- return (input) => {
113
- return new PlayerActor(machine, catalog || {}, options || {}, input);
59
+ const { machine, options } = config;
60
+ return (input, restore) => {
61
+ return new PlayerActor(machine, options ?? {}, input, restore?.snapshot);
114
62
  };
115
63
  };
116
64
  //# sourceMappingURL=define-player.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"define-player.js","sourceRoot":"","sources":["../src/define-player.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyGG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAC3B,MAAwC,EACxB,EAAE;IAClB,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC;IAE7C,0BAA0B;IAC1B,2EAA2E;IAC3E,OAAO,CAAC,KAAW,EAAO,EAAE;QAC3B,OAAO,IAAI,WAAW,CAAC,OAAO,EAAE,OAAO,IAAI,EAAE,EAAE,OAAO,IAAI,EAAE,EAAE,KAAK,CAAC,CAAC;IACtE,CAAC,CAAC;AACH,CAAC,CAAC"}
1
+ {"version":3,"file":"define-player.js","sourceRoot":"","sources":["../src/define-player.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuDG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAC3B,MAA8B,EACJ,EAAE;IAC5B,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC;IAEpC,OAAO,CAAC,KAA2B,EAAE,OAA8C,EAAE,EAAE;QACtF,OAAO,IAAI,WAAW,CAAC,OAAO,EAAE,OAAO,IAAI,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;IAC1E,CAAC,CAAC;AACH,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=define-player.typecheck.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"define-player.typecheck.d.ts","sourceRoot":"","sources":["../src/define-player.typecheck.ts"],"names":[],"mappings":""}
@@ -0,0 +1,48 @@
1
+ import { setup } from "xstate";
2
+ import { definePlayer } from "./define-player.js";
3
+ const machine = setup({
4
+ types: {
5
+ context: {},
6
+ input: {},
7
+ events: {},
8
+ },
9
+ }).createMachine({
10
+ context: ({ input }) => ({ count: input.count }),
11
+ initial: "active",
12
+ states: {
13
+ active: {
14
+ on: {
15
+ inc: {
16
+ actions: ({ context }) => {
17
+ context.count += 1;
18
+ },
19
+ },
20
+ },
21
+ },
22
+ },
23
+ });
24
+ const createPlayer = definePlayer({
25
+ machine,
26
+ options: {
27
+ onTransition: (actor, prevState, nextState) => {
28
+ const actorNotAny = false;
29
+ const prevNotAny = false;
30
+ const nextNotAny = false;
31
+ void actorNotAny;
32
+ void prevNotAny;
33
+ void nextNotAny;
34
+ },
35
+ },
36
+ });
37
+ const actor = createPlayer({ count: 1 });
38
+ const snapshot = actor.getSnapshot();
39
+ const restoredActor = createPlayer({ count: 1 }, { snapshot });
40
+ const returnNotAny = false;
41
+ const restoredReturnNotAny = false;
42
+ void returnNotAny;
43
+ void restoredReturnNotAny;
44
+ // @ts-expect-error factory input must match machine input shape
45
+ createPlayer("invalid");
46
+ // @ts-expect-error snapshot must be nested under the `snapshot` key
47
+ createPlayer({ count: 1 }, { persisted: snapshot });
48
+ //# sourceMappingURL=define-player.typecheck.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"define-player.typecheck.js","sourceRoot":"","sources":["../src/define-player.typecheck.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AAC/B,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAKlD,MAAM,OAAO,GAAG,KAAK,CAAC;IACrB,KAAK,EAAE;QACN,OAAO,EAAE,EAAuB;QAChC,KAAK,EAAE,EAAuB;QAC9B,MAAM,EAAE,EAAqB;KAC7B;CACD,CAAC,CAAC,aAAa,CAAC;IAChB,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC;IAChD,OAAO,EAAE,QAAQ;IACjB,MAAM,EAAE;QACP,MAAM,EAAE;YACP,EAAE,EAAE;gBACH,GAAG,EAAE;oBACJ,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE;wBACxB,OAAO,CAAC,KAAK,IAAI,CAAC,CAAC;oBACpB,CAAC;iBACD;aACD;SACD;KACD;CACD,CAAC,CAAC;AAEH,MAAM,YAAY,GAAG,YAAY,CAAC;IACjC,OAAO;IACP,OAAO,EAAE;QACR,YAAY,EAAE,CAAC,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,EAAE;YAK7C,MAAM,WAAW,GAA4B,KAAK,CAAC;YACnD,MAAM,UAAU,GAA2B,KAAK,CAAC;YACjD,MAAM,UAAU,GAA2B,KAAK,CAAC;YAEjD,KAAK,WAAW,CAAC;YACjB,KAAK,UAAU,CAAC;YAChB,KAAK,UAAU,CAAC;QACjB,CAAC;KACD;CACD,CAAC,CAAC;AAEH,MAAM,KAAK,GAAG,YAAY,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;AACzC,MAAM,QAAQ,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;AACrC,MAAM,aAAa,GAAG,YAAY,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC;AAI/D,MAAM,YAAY,GAA6B,KAAK,CAAC;AACrD,MAAM,oBAAoB,GAAqC,KAAK,CAAC;AACrE,KAAK,YAAY,CAAC;AAClB,KAAK,oBAAoB,CAAC;AAE1B,gEAAgE;AAChE,YAAY,CAAC,SAAS,CAAC,CAAC;AAExB,oEAAoE;AACpE,YAAY,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,CAAC"}
@@ -0,0 +1,66 @@
1
+ import { PlayError } from "@xmachines/play";
2
+ /**
3
+ * Thrown by `buildRouteUrl()` when a required route parameter is absent from the
4
+ * actor's context.
5
+ *
6
+ * Use the `param` and `template` fields to identify the missing parameter without
7
+ * parsing the `.message` string.
8
+ *
9
+ * **Error code:** `PLAY_ROUTE_PARAM_MISSING`
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * import { MissingRouteParamError } from "@xmachines/play-xstate/errors";
14
+ *
15
+ * // The route template "/profile/:userId" requires "userId" in context.
16
+ * // If userId is absent, MissingRouteParamError is thrown when the
17
+ * // actor.currentRoute signal is read.
18
+ *
19
+ * try {
20
+ * actor.currentRoute.get();
21
+ * } catch (err) {
22
+ * if (err instanceof MissingRouteParamError) {
23
+ * console.error(
24
+ * `Missing "${err.param}" for template "${err.template}"`
25
+ * );
26
+ * }
27
+ * }
28
+ * ```
29
+ */
30
+ export declare class MissingRouteParamError extends PlayError {
31
+ /** The name of the route parameter that was missing (e.g. `"userId"`). */
32
+ readonly param: string;
33
+ /** The route template that required the missing parameter (e.g. `"/profile/:userId"`). */
34
+ readonly template: string;
35
+ constructor(param: string, template: string);
36
+ }
37
+ /**
38
+ * Thrown by `PlayerActor.send()` when the event argument is not a plain object.
39
+ *
40
+ * `PlayEvent` requires `{ type: string, ...fields }`. Passing `null`, `undefined`,
41
+ * a string, or any other non-object value is a programmer error.
42
+ *
43
+ * The offending value is attached as the `detail` readonly class field for debugging.
44
+ * TypeScript consumers can access `err.detail` directly without any unsafe cast.
45
+ *
46
+ * **Error code:** `PLAY_INVALID_EVENT`
47
+ *
48
+ * @example
49
+ * ```typescript
50
+ * import { InvalidEventError } from "@xmachines/play-xstate/errors";
51
+ *
52
+ * try {
53
+ * actor.send(null as any);
54
+ * } catch (err) {
55
+ * if (err instanceof InvalidEventError) {
56
+ * // err.detail is typed as `unknown` — no cast needed
57
+ * console.error("Invalid event passed to actor.send():", err.detail);
58
+ * }
59
+ * }
60
+ * ```
61
+ */
62
+ export declare class InvalidEventError extends PlayError {
63
+ readonly detail: unknown;
64
+ constructor(detail: unknown);
65
+ }
66
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,qBAAa,sBAAuB,SAAQ,SAAS;IACpD,0EAA0E;IAC1E,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAEvB,0FAA0F;IAC1F,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;gBAEd,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;CAU3C;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,qBAAa,iBAAkB,SAAQ,SAAS;IAC/C,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;gBAEb,MAAM,EAAE,OAAO;CAU3B"}
package/dist/errors.js ADDED
@@ -0,0 +1,76 @@
1
+ import { PlayError } from "@xmachines/play";
2
+ /**
3
+ * Thrown by `buildRouteUrl()` when a required route parameter is absent from the
4
+ * actor's context.
5
+ *
6
+ * Use the `param` and `template` fields to identify the missing parameter without
7
+ * parsing the `.message` string.
8
+ *
9
+ * **Error code:** `PLAY_ROUTE_PARAM_MISSING`
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * import { MissingRouteParamError } from "@xmachines/play-xstate/errors";
14
+ *
15
+ * // The route template "/profile/:userId" requires "userId" in context.
16
+ * // If userId is absent, MissingRouteParamError is thrown when the
17
+ * // actor.currentRoute signal is read.
18
+ *
19
+ * try {
20
+ * actor.currentRoute.get();
21
+ * } catch (err) {
22
+ * if (err instanceof MissingRouteParamError) {
23
+ * console.error(
24
+ * `Missing "${err.param}" for template "${err.template}"`
25
+ * );
26
+ * }
27
+ * }
28
+ * ```
29
+ */
30
+ export class MissingRouteParamError extends PlayError {
31
+ /** The name of the route parameter that was missing (e.g. `"userId"`). */
32
+ param;
33
+ /** The route template that required the missing parameter (e.g. `"/profile/:userId"`). */
34
+ template;
35
+ constructor(param, template) {
36
+ super("buildRouteUrl", "PLAY_ROUTE_PARAM_MISSING", `Route parameter '${param}' is required by template '${template}' but was not found in context.`);
37
+ this.name = "MissingRouteParamError";
38
+ this.param = param;
39
+ this.template = template;
40
+ }
41
+ }
42
+ /**
43
+ * Thrown by `PlayerActor.send()` when the event argument is not a plain object.
44
+ *
45
+ * `PlayEvent` requires `{ type: string, ...fields }`. Passing `null`, `undefined`,
46
+ * a string, or any other non-object value is a programmer error.
47
+ *
48
+ * The offending value is attached as the `detail` readonly class field for debugging.
49
+ * TypeScript consumers can access `err.detail` directly without any unsafe cast.
50
+ *
51
+ * **Error code:** `PLAY_INVALID_EVENT`
52
+ *
53
+ * @example
54
+ * ```typescript
55
+ * import { InvalidEventError } from "@xmachines/play-xstate/errors";
56
+ *
57
+ * try {
58
+ * actor.send(null as any);
59
+ * } catch (err) {
60
+ * if (err instanceof InvalidEventError) {
61
+ * // err.detail is typed as `unknown` — no cast needed
62
+ * console.error("Invalid event passed to actor.send():", err.detail);
63
+ * }
64
+ * }
65
+ * ```
66
+ */
67
+ export class InvalidEventError extends PlayError {
68
+ detail;
69
+ constructor(detail) {
70
+ super("PlayerActor", "PLAY_INVALID_EVENT", "PlayerActor.send() received a non-object event.");
71
+ this.name = "InvalidEventError";
72
+ // Attach the invalid value for debugging without it appearing in the message
73
+ Object.defineProperty(this, "detail", { value: detail, enumerable: true });
74
+ }
75
+ }
76
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAM,OAAO,sBAAuB,SAAQ,SAAS;IACpD,0EAA0E;IACjE,KAAK,CAAS;IAEvB,0FAA0F;IACjF,QAAQ,CAAS;IAE1B,YAAY,KAAa,EAAE,QAAgB;QAC1C,KAAK,CACJ,eAAe,EACf,0BAA0B,EAC1B,oBAAoB,KAAK,8BAA8B,QAAQ,iCAAiC,CAChG,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,wBAAwB,CAAC;QACrC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC1B,CAAC;CACD;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,OAAO,iBAAkB,SAAQ,SAAS;IACtC,MAAM,CAAU;IAEzB,YAAY,MAAe;QAC1B,KAAK,CACJ,aAAa,EACb,oBAAoB,EACpB,iDAAiD,CACjD,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,mBAAmB,CAAC;QAChC,6EAA6E;QAC7E,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5E,CAAC;CACD"}
@@ -1,4 +1,15 @@
1
+ import type { GuardPredicate } from "xstate";
1
2
  import type { Guard, GuardArray } from "./types.js";
3
+ import type { MachineContext, EventObject, ParameterizedObject } from "xstate";
4
+ /**
5
+ * Narrowest public return type for guard composition helpers.
6
+ *
7
+ * `GuardPredicate<MachineContext, EventObject, unknown, ParameterizedObject>` is the
8
+ * widest-compatible concrete XState guard type that does not use `any`.
9
+ *
10
+ * @public
11
+ */
12
+ export type ComposedGuard = GuardPredicate<MachineContext, EventObject, unknown, ParameterizedObject>;
2
13
  /**
3
14
  * Compose guards with AND logic using XState's and() helper
4
15
  *
@@ -54,7 +65,7 @@ import type { Guard, GuardArray } from "./types.js";
54
65
  * @see {@link composeGuardsOr} for OR composition
55
66
  * @see {@link negateGuard} for NOT logic
56
67
  */
57
- export declare const composeGuards: <TContext = any, TEvent = any>(guards: GuardArray<TContext, TEvent>) => any;
68
+ export declare const composeGuards: <TContext = any, TEvent = any>(guards: GuardArray<TContext, TEvent>) => ComposedGuard;
58
69
  /**
59
70
  * Compose guards with OR logic using XState's or() helper
60
71
  *
@@ -95,7 +106,7 @@ export declare const composeGuards: <TContext = any, TEvent = any>(guards: Guard
95
106
  * @see {@link composeGuards} for AND composition
96
107
  * @see {@link negateGuard} for NOT logic
97
108
  */
98
- export declare const composeGuardsOr: <TContext = any, TEvent = any>(guards: GuardArray<TContext, TEvent>) => any;
109
+ export declare const composeGuardsOr: <TContext = any, TEvent = any>(guards: GuardArray<TContext, TEvent>) => ComposedGuard;
99
110
  /**
100
111
  * Negate a guard using XState's not() helper
101
112
  *
@@ -132,5 +143,5 @@ export declare const composeGuardsOr: <TContext = any, TEvent = any>(guards: Gua
132
143
  * @see {@link composeGuards} for AND composition
133
144
  * @see {@link composeGuardsOr} for OR composition
134
145
  */
135
- export declare const negateGuard: <TContext = any, TEvent = any>(guard: Guard<TContext, TEvent> | string) => any;
146
+ export declare const negateGuard: <TContext = any, TEvent = any>(guard: Guard<TContext, TEvent> | string) => ComposedGuard;
136
147
  //# sourceMappingURL=compose.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"compose.d.ts","sourceRoot":"","sources":["../../src/guards/compose.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAEpD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsDG;AACH,eAAO,MAAM,aAAa,GAAI,QAAQ,GAAG,GAAG,EAAE,MAAM,GAAG,GAAG,EACzD,QAAQ,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC,KAClC,GAYF,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,eAAO,MAAM,eAAe,GAAI,QAAQ,GAAG,GAAG,EAAE,MAAM,GAAG,GAAG,EAC3D,QAAQ,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC,KAClC,GAUF,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,eAAO,MAAM,WAAW,GAAI,QAAQ,GAAG,GAAG,EAAE,MAAM,GAAG,GAAG,EACvD,OAAO,KAAK,CAAC,QAAQ,EAAE,MAAM,CAAC,GAAG,MAAM,KACrC,GAEF,CAAC"}
1
+ {"version":3,"file":"compose.d.ts","sourceRoot":"","sources":["../../src/guards/compose.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AAC7C,OAAO,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACpD,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,mBAAmB,EAAE,MAAM,QAAQ,CAAC;AAE/E;;;;;;;GAOG;AACH,MAAM,MAAM,aAAa,GAAG,cAAc,CACzC,cAAc,EACd,WAAW,EACX,OAAO,EACP,mBAAmB,CACnB,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsDG;AAEH,eAAO,MAAM,aAAa,GAAI,QAAQ,GAAG,GAAG,EAAE,MAAM,GAAG,GAAG,EACzD,QAAQ,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC,KAClC,aAqBF,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAEH,eAAO,MAAM,eAAe,GAAI,QAAQ,GAAG,GAAG,EAAE,MAAM,GAAG,GAAG,EAC3D,QAAQ,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC,KAClC,aAmBF,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAEH,eAAO,MAAM,WAAW,GAAI,QAAQ,GAAG,GAAG,EAAE,MAAM,GAAG,GAAG,EACvD,OAAO,KAAK,CAAC,QAAQ,EAAE,MAAM,CAAC,GAAG,MAAM,KACrC,aAOF,CAAC"}
@@ -54,15 +54,25 @@ import { and, or, not } from "xstate";
54
54
  * @see {@link composeGuardsOr} for OR composition
55
55
  * @see {@link negateGuard} for NOT logic
56
56
  */
57
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
57
58
  export const composeGuards = (guards) => {
58
59
  if (guards.length === 0) {
59
60
  throw new Error("composeGuards requires at least one guard");
60
61
  }
61
62
  if (guards.length === 1) {
63
+ // Single guard passthrough — cast through unknown because our Guard<TContext, TEvent>
64
+ // does not structurally match ComposedGuard at compile time (generic event mismatch).
65
+ // At runtime both are plain function objects with identical shape.
66
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
62
67
  return guards[0];
63
68
  }
64
69
  // Use XState's built-in and() for type inference and serialization
65
70
  // Per RESEARCH.md: Don't hand-roll guard composition
71
+ // XState 5.28.0: and() requires `readonly [...tuple]` but our GuardArray is a mutable array.
72
+ // We cast through unknown to express the narrowest possible type boundary rather than
73
+ // escaping to `any`. The runtime value is identical.
74
+ // Track XState typing improvements: https://github.com/statelyai/xstate/issues
75
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
66
76
  return and(guards);
67
77
  };
68
78
  /**
@@ -105,13 +115,23 @@ export const composeGuards = (guards) => {
105
115
  * @see {@link composeGuards} for AND composition
106
116
  * @see {@link negateGuard} for NOT logic
107
117
  */
118
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
108
119
  export const composeGuardsOr = (guards) => {
109
120
  if (guards.length === 0) {
110
121
  throw new Error("composeGuardsOr requires at least one guard");
111
122
  }
112
123
  if (guards.length === 1) {
124
+ // Single guard passthrough — cast through unknown because our Guard<TContext, TEvent>
125
+ // does not structurally match ComposedGuard at compile time (generic event mismatch).
126
+ // At runtime both are plain function objects with identical shape.
127
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
113
128
  return guards[0];
114
129
  }
130
+ // XState 5.28.0: or() requires `readonly [...tuple]` but our GuardArray is a mutable array.
131
+ // We cast through unknown to express the narrowest possible type boundary rather than
132
+ // escaping to `any`. The runtime value is identical.
133
+ // Track XState typing improvements: https://github.com/statelyai/xstate/issues
134
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
115
135
  return or(guards);
116
136
  };
117
137
  /**
@@ -150,7 +170,13 @@ export const composeGuardsOr = (guards) => {
150
170
  * @see {@link composeGuards} for AND composition
151
171
  * @see {@link composeGuardsOr} for OR composition
152
172
  */
173
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
153
174
  export const negateGuard = (guard) => {
175
+ // XState 5.28.0: not() requires a specific SingleGuardArg shape, not our Guard type.
176
+ // We cast through unknown to express the narrowest possible type boundary rather than
177
+ // escaping to `any`. The runtime value is identical.
178
+ // Track XState typing improvements: https://github.com/statelyai/xstate/issues
179
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
154
180
  return not(guard);
155
181
  };
156
182
  //# sourceMappingURL=compose.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"compose.js","sourceRoot":"","sources":["../../src/guards/compose.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,MAAM,QAAQ,CAAC;AAGtC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsDG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAC5B,MAAoC,EAC9B,EAAE;IACR,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;IAC9D,CAAC;IAED,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,mEAAmE;IACnE,qDAAqD;IACrD,OAAO,GAAG,CAAC,MAAa,CAAC,CAAC;AAC3B,CAAC,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAC9B,MAAoC,EAC9B,EAAE;IACR,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;IAChE,CAAC;IAED,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,OAAO,EAAE,CAAC,MAAa,CAAC,CAAC;AAC1B,CAAC,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,CAC1B,KAAuC,EACjC,EAAE;IACR,OAAO,GAAG,CAAC,KAAY,CAAC,CAAC;AAC1B,CAAC,CAAC"}
1
+ {"version":3,"file":"compose.js","sourceRoot":"","sources":["../../src/guards/compose.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,MAAM,QAAQ,CAAC;AAoBtC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsDG;AACH,8DAA8D;AAC9D,MAAM,CAAC,MAAM,aAAa,GAAG,CAC5B,MAAoC,EACpB,EAAE;IAClB,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;IAC9D,CAAC;IAED,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,sFAAsF;QACtF,sFAAsF;QACtF,mEAAmE;QACnE,8DAA8D;QAC9D,OAAO,MAAM,CAAC,CAAC,CAA6B,CAAC;IAC9C,CAAC;IAED,mEAAmE;IACnE,qDAAqD;IACrD,6FAA6F;IAC7F,sFAAsF;IACtF,qDAAqD;IACrD,+EAA+E;IAC/E,8DAA8D;IAC9D,OAAO,GAAG,CAAC,MAA8C,CAAC,CAAC;AAC5D,CAAC,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,8DAA8D;AAC9D,MAAM,CAAC,MAAM,eAAe,GAAG,CAC9B,MAAoC,EACpB,EAAE;IAClB,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;IAChE,CAAC;IAED,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,sFAAsF;QACtF,sFAAsF;QACtF,mEAAmE;QACnE,8DAA8D;QAC9D,OAAO,MAAM,CAAC,CAAC,CAA6B,CAAC;IAC9C,CAAC;IAED,4FAA4F;IAC5F,sFAAsF;IACtF,qDAAqD;IACrD,+EAA+E;IAC/E,8DAA8D;IAC9D,OAAO,EAAE,CAAC,MAA6C,CAAC,CAAC;AAC1D,CAAC,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,8DAA8D;AAC9D,MAAM,CAAC,MAAM,WAAW,GAAG,CAC1B,KAAuC,EACvB,EAAE;IAClB,qFAAqF;IACrF,sFAAsF;IACtF,qDAAqD;IACrD,+EAA+E;IAC/E,8DAA8D;IAC9D,OAAO,GAAG,CAAC,KAA6C,CAAC,CAAC;AAC3D,CAAC,CAAC"}
@@ -1,4 +1,5 @@
1
1
  import type { Guard } from "./types.js";
2
+ import type { PlayEvent } from "@xmachines/play";
2
3
  /**
3
4
  * Check if context has a truthy value at path
4
5
  *
@@ -17,7 +18,7 @@ import type { Guard } from "./types.js";
17
18
  * @param path - Dot-separated path to context property
18
19
  * @returns Guard predicate checking if property is truthy
19
20
  */
20
- export declare const hasContext: <TContext = any>(path: string) => Guard<TContext, any>;
21
+ export declare const hasContext: <TContext = Record<string, unknown>>(path: string) => Guard<TContext, PlayEvent>;
21
22
  /**
22
23
  * Check if event type matches expected type
23
24
  *
@@ -37,24 +38,19 @@ export declare const hasContext: <TContext = any>(path: string) => Guard<TContex
37
38
  * @param eventType - Expected event type
38
39
  * @returns Guard predicate checking event type
39
40
  */
40
- export declare const eventMatches: <TEvent extends {
41
- type: string;
42
- } = any>(eventType: string) => Guard<any, TEvent>;
41
+ export declare const eventMatches: <TEvent extends PlayEvent = PlayEvent>(eventType: string) => Guard<unknown, TEvent>;
43
42
  /**
44
- * Check if current state matches expected value
43
+ * Check if a context field matches an expected value.
45
44
  *
46
- * @example
47
- * ```typescript
48
- * const machine = setup({
49
- * guards: {
50
- * isLoggedIn: stateMatches('authenticated'),
51
- * isDashboard: stateMatches('authenticated.dashboard')
52
- * }
53
- * });
54
- * ```
45
+ * - Accepts an explicit dot-separated field path (e.g. `"user.role"`)
46
+ * - Uses strict equality for primitives, deep structural equality for objects
47
+ * - Does NOT use substring matching — `"a"` will not match `"active"`
48
+ *
49
+ * For XState state-node matching, use the built-in `in:` guard syntax instead.
55
50
  *
56
- * @param stateValue - Expected state value (string or object)
57
- * @returns Guard predicate checking state value
51
+ * @param fieldPath - Dot-separated path to context property (e.g., "status", "user.role")
52
+ * @param expectedValue - Value to compare against (string or object)
53
+ * @returns Guard predicate checking if context field matches
58
54
  */
59
- export declare const stateMatches: <TContext = any>(stateValue: string) => Guard<TContext, any>;
55
+ export declare const contextFieldMatches: <TContext = Record<string, unknown>>(fieldPath: string, expectedValue: unknown) => Guard<TContext, PlayEvent>;
60
56
  //# sourceMappingURL=helpers.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/guards/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAExC;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,UAAU,GACrB,QAAQ,GAAG,GAAG,EAAE,MAAM,MAAM,KAAG,KAAK,CAAC,QAAQ,EAAE,GAAG,CAIlD,CAAC;AAEH;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,YAAY,GACvB,MAAM,SAAS;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,GAAG,EAAE,WAAW,MAAM,KAAG,KAAK,CAAC,GAAG,EAAE,MAAM,CAG5E,CAAC;AAEH;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,YAAY,GACvB,QAAQ,GAAG,GAAG,EAAE,YAAY,MAAM,KAAG,KAAK,CAAC,QAAQ,EAAE,GAAG,CAexD,CAAC"}
1
+ {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/guards/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEjD;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,UAAU,GACrB,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,MAAM,KAAG,KAAK,CAAC,QAAQ,EAAE,SAAS,CAI5E,CAAC;AAEH;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,YAAY,GACvB,MAAM,SAAS,SAAS,GAAG,SAAS,EAAE,WAAW,MAAM,KAAG,KAAK,CAAC,OAAO,EAAE,MAAM,CAG/E,CAAC;AAEH;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,mBAAmB,GAC9B,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAClC,WAAW,MAAM,EACjB,eAAe,OAAO,KACpB,KAAK,CAAC,QAAQ,EAAE,SAAS,CAa3B,CAAC"}
@@ -43,34 +43,29 @@ export const eventMatches = (eventType) => ({ event }) => {
43
43
  return event.type === eventType;
44
44
  };
45
45
  /**
46
- * Check if current state matches expected value
46
+ * Check if a context field matches an expected value.
47
47
  *
48
- * @example
49
- * ```typescript
50
- * const machine = setup({
51
- * guards: {
52
- * isLoggedIn: stateMatches('authenticated'),
53
- * isDashboard: stateMatches('authenticated.dashboard')
54
- * }
55
- * });
56
- * ```
48
+ * - Accepts an explicit dot-separated field path (e.g. `"user.role"`)
49
+ * - Uses strict equality for primitives, deep structural equality for objects
50
+ * - Does NOT use substring matching — `"a"` will not match `"active"`
51
+ *
52
+ * For XState state-node matching, use the built-in `in:` guard syntax instead.
57
53
  *
58
- * @param stateValue - Expected state value (string or object)
59
- * @returns Guard predicate checking state value
54
+ * @param fieldPath - Dot-separated path to context property (e.g., "status", "user.role")
55
+ * @param expectedValue - Value to compare against (string or object)
56
+ * @returns Guard predicate checking if context field matches
60
57
  */
61
- export const stateMatches = (stateValue) => ({ context }) => {
62
- // Note: This helper checks context for state info
63
- // For actual XState state matching, use machine.matches() in actions
64
- // This is a simplified version for context-based state checks
65
- const currentState = context._state || context.state;
66
- if (!currentState)
67
- return false;
68
- // Simple string matching (can be enhanced for nested states)
69
- if (typeof currentState === "string") {
70
- return currentState === stateValue;
58
+ export const contextFieldMatches = (fieldPath, expectedValue) => ({ context }) => {
59
+ const actual = getNestedValue(context, fieldPath);
60
+ if (actual === expectedValue)
61
+ return true;
62
+ if (typeof actual === "object" &&
63
+ typeof expectedValue === "object" &&
64
+ actual !== null &&
65
+ expectedValue !== null) {
66
+ return JSON.stringify(actual) === JSON.stringify(expectedValue);
71
67
  }
72
- // Object state matching
73
- return JSON.stringify(currentState).includes(stateValue);
68
+ return false;
74
69
  };
75
70
  /**
76
71
  * Get nested value from object using dot-separated path
@@ -81,7 +76,7 @@ const getNestedValue = (obj, path) => {
81
76
  const keys = path.split(".");
82
77
  let value = obj;
83
78
  for (const key of keys) {
84
- if (value === null || value === undefined) {
79
+ if (value === null || value === undefined || typeof value !== "object") {
85
80
  return undefined;
86
81
  }
87
82
  value = value[key];
@@ -1 +1 @@
1
- {"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../src/guards/helpers.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,MAAM,UAAU,GACtB,CAAiB,IAAY,EAAwB,EAAE,CACvD,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE;IACf,MAAM,KAAK,GAAG,cAAc,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAC5C,OAAO,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,EAAE,CAAC;AAC9D,CAAC,CAAC;AAEH;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,CAAC,MAAM,YAAY,GACxB,CAAwC,SAAiB,EAAsB,EAAE,CACjF,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE;IACb,OAAO,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC;AACjC,CAAC,CAAC;AAEH;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,MAAM,YAAY,GACxB,CAAiB,UAAkB,EAAwB,EAAE,CAC7D,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE;IACf,kDAAkD;IAClD,qEAAqE;IACrE,8DAA8D;IAC9D,MAAM,YAAY,GAAI,OAAe,CAAC,MAAM,IAAK,OAAe,CAAC,KAAK,CAAC;IACvE,IAAI,CAAC,YAAY;QAAE,OAAO,KAAK,CAAC;IAEhC,6DAA6D;IAC7D,IAAI,OAAO,YAAY,KAAK,QAAQ,EAAE,CAAC;QACtC,OAAO,YAAY,KAAK,UAAU,CAAC;IACpC,CAAC;IAED,wBAAwB;IACxB,OAAO,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;AAC1D,CAAC,CAAC;AAEH;;;;GAIG;AACH,MAAM,cAAc,GAAG,CAAC,GAAQ,EAAE,IAAY,EAAO,EAAE;IACtD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC7B,IAAI,KAAK,GAAG,GAAG,CAAC;IAEhB,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACxB,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YAC3C,OAAO,SAAS,CAAC;QAClB,CAAC;QACD,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC;IACpB,CAAC;IAED,OAAO,KAAK,CAAC;AACd,CAAC,CAAC"}
1
+ {"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../src/guards/helpers.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,MAAM,UAAU,GACtB,CAAqC,IAAY,EAA8B,EAAE,CACjF,CAAC,EAAE,OAAO,EAAyB,EAAE,EAAE;IACtC,MAAM,KAAK,GAAG,cAAc,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAC5C,OAAO,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,EAAE,CAAC;AAC9D,CAAC,CAAC;AAEH;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,CAAC,MAAM,YAAY,GACxB,CAAuC,SAAiB,EAA0B,EAAE,CACpF,CAAC,EAAE,KAAK,EAAqB,EAAE,EAAE;IAChC,OAAO,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC;AACjC,CAAC,CAAC;AAEH;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAC/B,CACC,SAAiB,EACjB,aAAsB,EACO,EAAE,CAChC,CAAC,EAAE,OAAO,EAAyB,EAAE,EAAE;IACtC,MAAM,MAAM,GAAG,cAAc,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;IAClD,IAAI,MAAM,KAAK,aAAa;QAAE,OAAO,IAAI,CAAC;IAC1C,IACC,OAAO,MAAM,KAAK,QAAQ;QAC1B,OAAO,aAAa,KAAK,QAAQ;QACjC,MAAM,KAAK,IAAI;QACf,aAAa,KAAK,IAAI,EACrB,CAAC;QACF,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC;IACjE,CAAC;IACD,OAAO,KAAK,CAAC;AACd,CAAC,CAAC;AAEH;;;;GAIG;AACH,MAAM,cAAc,GAAG,CAAC,GAAY,EAAE,IAAY,EAAW,EAAE;IAC9D,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC7B,IAAI,KAAK,GAAG,GAAG,CAAC;IAEhB,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACxB,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YACxE,OAAO,SAAS,CAAC;QAClB,CAAC;QACD,KAAK,GAAI,KAAiC,CAAC,GAAG,CAAC,CAAC;IACjD,CAAC;IAED,OAAO,KAAK,CAAC;AACd,CAAC,CAAC"}
@@ -7,6 +7,7 @@
7
7
  * @packageDocumentation
8
8
  */
9
9
  export { composeGuards, composeGuardsOr, negateGuard } from "./compose.js";
10
- export { hasContext, eventMatches, stateMatches } from "./helpers.js";
10
+ export type { ComposedGuard } from "./compose.js";
11
+ export { hasContext, eventMatches, contextFieldMatches } from "./helpers.js";
11
12
  export type { Guard, GuardArray } from "./types.js";
12
13
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/guards/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3E,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACtE,YAAY,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/guards/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3E,YAAY,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAC7E,YAAY,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC"}
@@ -7,5 +7,5 @@
7
7
  * @packageDocumentation
8
8
  */
9
9
  export { composeGuards, composeGuardsOr, negateGuard } from "./compose.js";
10
- export { hasContext, eventMatches, stateMatches } from "./helpers.js";
10
+ export { hasContext, eventMatches, contextFieldMatches } from "./helpers.js";
11
11
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/guards/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3E,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/guards/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3E,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC"}
@@ -1,3 +1,4 @@
1
+ import type { PlayEvent } from "@xmachines/play";
1
2
  /**
2
3
  * Standard XState guard function signature
3
4
  *
@@ -8,7 +9,7 @@
8
9
  * @param args.event - Event that triggered the guard evaluation
9
10
  * @returns boolean indicating if guard passes
10
11
  */
11
- export type Guard<TContext = any, TEvent = any> = (args: {
12
+ export type Guard<TContext = Record<string, unknown>, TEvent = PlayEvent> = (args: {
12
13
  context: TContext;
13
14
  event: TEvent;
14
15
  }) => boolean;
@@ -17,5 +18,5 @@ export type Guard<TContext = any, TEvent = any> = (args: {
17
18
  *
18
19
  * Per CONTEXT.md: Array means AND - all guards must pass
19
20
  */
20
- export type GuardArray<TContext = any, TEvent = any> = Array<Guard<TContext, TEvent>> | Array<string>;
21
+ export type GuardArray<TContext = Record<string, unknown>, TEvent = PlayEvent> = Array<Guard<TContext, TEvent>> | Array<string>;
21
22
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/guards/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,MAAM,MAAM,KAAK,CAAC,QAAQ,GAAG,GAAG,EAAE,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,EAAE;IACxD,OAAO,EAAE,QAAQ,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;CACd,KAAK,OAAO,CAAC;AAEd;;;;GAIG;AACH,MAAM,MAAM,UAAU,CAAC,QAAQ,GAAG,GAAG,EAAE,MAAM,GAAG,GAAG,IAChD,KAAK,CAAC,KAAK,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,GAC9B,KAAK,CAAC,MAAM,CAAC,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/guards/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEjD;;;;;;;;;GASG;AACH,MAAM,MAAM,KAAK,CAAC,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,IAAI,CAAC,IAAI,EAAE;IAClF,OAAO,EAAE,QAAQ,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;CACd,KAAK,OAAO,CAAC;AAEd;;;;GAIG;AACH,MAAM,MAAM,UAAU,CAAC,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,IAC1E,KAAK,CAAC,KAAK,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,GAC9B,KAAK,CAAC,MAAM,CAAC,CAAC"}