@xmachines/docs 1.0.0-beta.10

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 (197) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +15 -0
  3. package/api/@xmachines/play/README.md +130 -0
  4. package/api/@xmachines/play/type-aliases/PlayEvent.md +81 -0
  5. package/api/@xmachines/play-actor/README.md +247 -0
  6. package/api/@xmachines/play-actor/classes/AbstractActor.md +520 -0
  7. package/api/@xmachines/play-actor/interfaces/Routable.md +29 -0
  8. package/api/@xmachines/play-actor/interfaces/ViewMetadata.md +17 -0
  9. package/api/@xmachines/play-actor/interfaces/Viewable.md +12 -0
  10. package/api/@xmachines/play-catalog/README.md +331 -0
  11. package/api/@xmachines/play-catalog/functions/defineCatalog.md +98 -0
  12. package/api/@xmachines/play-catalog/functions/defineComponents.md +134 -0
  13. package/api/@xmachines/play-catalog/type-aliases/Catalog.md +48 -0
  14. package/api/@xmachines/play-catalog/type-aliases/ComponentsFor.md +20 -0
  15. package/api/@xmachines/play-catalog/type-aliases/InferComponentProps.md +65 -0
  16. package/api/@xmachines/play-catalog/type-aliases/NoExtraKeys.md +17 -0
  17. package/api/@xmachines/play-react/README.md +423 -0
  18. package/api/@xmachines/play-react/classes/PlayErrorBoundary.md +613 -0
  19. package/api/@xmachines/play-react/functions/useSignalEffect.md +68 -0
  20. package/api/@xmachines/play-react/interfaces/PlayErrorBoundaryProps.md +15 -0
  21. package/api/@xmachines/play-react/interfaces/PlayErrorBoundaryState.md +14 -0
  22. package/api/@xmachines/play-react/interfaces/PlayRendererProps.md +15 -0
  23. package/api/@xmachines/play-react/variables/PlayRenderer.md +64 -0
  24. package/api/@xmachines/play-react-router/README.md +198 -0
  25. package/api/@xmachines/play-react-router/classes/ReactRouterBridge.md +321 -0
  26. package/api/@xmachines/play-react-router/classes/RouteMap.md +137 -0
  27. package/api/@xmachines/play-react-router/functions/PlayRouterProvider.md +19 -0
  28. package/api/@xmachines/play-react-router/functions/createRouteMapFromTree.md +35 -0
  29. package/api/@xmachines/play-react-router/interfaces/PlayRouteEvent.md +119 -0
  30. package/api/@xmachines/play-react-router/interfaces/PlayRouterProviderProps.md +14 -0
  31. package/api/@xmachines/play-react-router/interfaces/RouteMapping.md +17 -0
  32. package/api/@xmachines/play-react-router/interfaces/RouterBridge.md +104 -0
  33. package/api/@xmachines/play-react-router-demo/README.md +137 -0
  34. package/api/@xmachines/play-router/README.md +502 -0
  35. package/api/@xmachines/play-router/classes/BaseRouteMap.md +142 -0
  36. package/api/@xmachines/play-router/classes/RouterBridgeBase.md +300 -0
  37. package/api/@xmachines/play-router/functions/buildRouteTree.md +27 -0
  38. package/api/@xmachines/play-router/functions/connectRouter.md +67 -0
  39. package/api/@xmachines/play-router/functions/crawlMachine.md +92 -0
  40. package/api/@xmachines/play-router/functions/createBrowserHistory.md +47 -0
  41. package/api/@xmachines/play-router/functions/createRouteMap.md +53 -0
  42. package/api/@xmachines/play-router/functions/createRouter.md +76 -0
  43. package/api/@xmachines/play-router/functions/detectDuplicateRoutes.md +32 -0
  44. package/api/@xmachines/play-router/functions/extractMachineRoutes.md +64 -0
  45. package/api/@xmachines/play-router/functions/extractRoute.md +45 -0
  46. package/api/@xmachines/play-router/functions/findRouteById.md +37 -0
  47. package/api/@xmachines/play-router/functions/findRouteByPath.md +39 -0
  48. package/api/@xmachines/play-router/functions/getNavigableRoutes.md +35 -0
  49. package/api/@xmachines/play-router/functions/getRoutableRoutes.md +39 -0
  50. package/api/@xmachines/play-router/functions/routeExists.md +26 -0
  51. package/api/@xmachines/play-router/functions/validateRouteFormat.md +29 -0
  52. package/api/@xmachines/play-router/functions/validateStateExists.md +29 -0
  53. package/api/@xmachines/play-router/interfaces/BaseRouteMapping.md +27 -0
  54. package/api/@xmachines/play-router/interfaces/BrowserHistory.md +172 -0
  55. package/api/@xmachines/play-router/interfaces/BrowserWindow.md +69 -0
  56. package/api/@xmachines/play-router/interfaces/ConnectRouterOptions.md +13 -0
  57. package/api/@xmachines/play-router/interfaces/PlayRouteEvent.md +119 -0
  58. package/api/@xmachines/play-router/interfaces/RouteInfo.md +19 -0
  59. package/api/@xmachines/play-router/interfaces/RouteMap.md +56 -0
  60. package/api/@xmachines/play-router/interfaces/RouteNode.md +21 -0
  61. package/api/@xmachines/play-router/interfaces/RouteObject.md +21 -0
  62. package/api/@xmachines/play-router/interfaces/RouteTree.md +20 -0
  63. package/api/@xmachines/play-router/interfaces/RouterBridge.md +104 -0
  64. package/api/@xmachines/play-router/interfaces/StateVisit.md +15 -0
  65. package/api/@xmachines/play-router/interfaces/VanillaRouter.md +28 -0
  66. package/api/@xmachines/play-router/type-aliases/RouteMetadata.md +11 -0
  67. package/api/@xmachines/play-router-demo/README.md +137 -0
  68. package/api/@xmachines/play-signals/README.md +176 -0
  69. package/api/@xmachines/play-signals/interfaces/ComputedOptions.md +34 -0
  70. package/api/@xmachines/play-signals/interfaces/SignalComputed.md +49 -0
  71. package/api/@xmachines/play-signals/interfaces/SignalOptions.md +35 -0
  72. package/api/@xmachines/play-signals/interfaces/SignalState.md +68 -0
  73. package/api/@xmachines/play-signals/interfaces/SignalWatcher.md +97 -0
  74. package/api/@xmachines/play-signals/namespaces/Signal/README.md +22 -0
  75. package/api/@xmachines/play-signals/namespaces/Signal/classes/Computed.md +52 -0
  76. package/api/@xmachines/play-signals/namespaces/Signal/classes/State.md +72 -0
  77. package/api/@xmachines/play-signals/namespaces/Signal/interfaces/Options.md +19 -0
  78. package/api/@xmachines/play-signals/namespaces/Signal/namespaces/subtle/README.md +21 -0
  79. package/api/@xmachines/play-signals/namespaces/Signal/namespaces/subtle/classes/Watcher.md +85 -0
  80. package/api/@xmachines/play-signals/namespaces/Signal/namespaces/subtle/functions/currentComputed.md +13 -0
  81. package/api/@xmachines/play-signals/namespaces/Signal/namespaces/subtle/functions/hasSinks.md +19 -0
  82. package/api/@xmachines/play-signals/namespaces/Signal/namespaces/subtle/functions/hasSources.md +19 -0
  83. package/api/@xmachines/play-signals/namespaces/Signal/namespaces/subtle/functions/introspectSinks.md +19 -0
  84. package/api/@xmachines/play-signals/namespaces/Signal/namespaces/subtle/functions/introspectSources.md +19 -0
  85. package/api/@xmachines/play-signals/namespaces/Signal/namespaces/subtle/functions/untrack.md +25 -0
  86. package/api/@xmachines/play-signals/namespaces/Signal/namespaces/subtle/variables/unwatched.md +9 -0
  87. package/api/@xmachines/play-signals/namespaces/Signal/namespaces/subtle/variables/watched.md +9 -0
  88. package/api/@xmachines/play-signals/namespaces/Signal/variables/isComputed.md +19 -0
  89. package/api/@xmachines/play-signals/namespaces/Signal/variables/isState.md +19 -0
  90. package/api/@xmachines/play-signals/namespaces/Signal/variables/isWatcher.md +19 -0
  91. package/api/@xmachines/play-signals/type-aliases/WatcherNotify.md +32 -0
  92. package/api/@xmachines/play-solid/README.md +311 -0
  93. package/api/@xmachines/play-solid/interfaces/PlayRendererProps.md +15 -0
  94. package/api/@xmachines/play-solid/variables/PlayRenderer.md +70 -0
  95. package/api/@xmachines/play-solid-router/README.md +666 -0
  96. package/api/@xmachines/play-solid-router/classes/RouteMap.md +150 -0
  97. package/api/@xmachines/play-solid-router/classes/SolidRouterBridge.md +347 -0
  98. package/api/@xmachines/play-solid-router/functions/PlayRouterProvider.md +19 -0
  99. package/api/@xmachines/play-solid-router/functions/createRouteMap.md +32 -0
  100. package/api/@xmachines/play-solid-router/interfaces/AbstractActor.md +486 -0
  101. package/api/@xmachines/play-solid-router/interfaces/PlayRouteEvent.md +119 -0
  102. package/api/@xmachines/play-solid-router/interfaces/PlayRouterProviderProps.md +14 -0
  103. package/api/@xmachines/play-solid-router/interfaces/RouteMapping.md +14 -0
  104. package/api/@xmachines/play-solid-router/interfaces/RouterBridge.md +104 -0
  105. package/api/@xmachines/play-solid-router/type-aliases/RoutableActor.md +9 -0
  106. package/api/@xmachines/play-solid-router/type-aliases/SolidRouterHooks.md +51 -0
  107. package/api/@xmachines/play-solid-router-demo/README.md +127 -0
  108. package/api/@xmachines/play-tanstack-react-router/README.md +226 -0
  109. package/api/@xmachines/play-tanstack-react-router/classes/RouteMap.md +137 -0
  110. package/api/@xmachines/play-tanstack-react-router/classes/TanStackReactRouterBridge.md +348 -0
  111. package/api/@xmachines/play-tanstack-react-router/functions/PlayRouterProvider.md +19 -0
  112. package/api/@xmachines/play-tanstack-react-router/functions/createRouteMap.md +53 -0
  113. package/api/@xmachines/play-tanstack-react-router/functions/createRouteMapFromTree.md +35 -0
  114. package/api/@xmachines/play-tanstack-react-router/functions/extractParams.md +38 -0
  115. package/api/@xmachines/play-tanstack-react-router/functions/extractQueryParams.md +33 -0
  116. package/api/@xmachines/play-tanstack-react-router/interfaces/PlayRouteEvent.md +119 -0
  117. package/api/@xmachines/play-tanstack-react-router/interfaces/PlayRouterProviderProps.md +14 -0
  118. package/api/@xmachines/play-tanstack-react-router/interfaces/RouteMapping.md +17 -0
  119. package/api/@xmachines/play-tanstack-react-router/interfaces/RouteNavigateEvent.md +26 -0
  120. package/api/@xmachines/play-tanstack-react-router/interfaces/RouterBridge.md +104 -0
  121. package/api/@xmachines/play-tanstack-react-router/type-aliases/TanStackRouterInstance.md +9 -0
  122. package/api/@xmachines/play-tanstack-react-router/type-aliases/TanStackRouterLike.md +78 -0
  123. package/api/@xmachines/play-tanstack-react-router/variables/extractMachineRoutes.md +64 -0
  124. package/api/@xmachines/play-tanstack-react-router-demo/README.md +126 -0
  125. package/api/@xmachines/play-tanstack-solid-router/README.md +285 -0
  126. package/api/@xmachines/play-tanstack-solid-router/classes/RouteMap.md +150 -0
  127. package/api/@xmachines/play-tanstack-solid-router/classes/SolidRouterBridge.md +343 -0
  128. package/api/@xmachines/play-tanstack-solid-router/functions/PlayRouterProvider.md +19 -0
  129. package/api/@xmachines/play-tanstack-solid-router/functions/createRouteMap.md +32 -0
  130. package/api/@xmachines/play-tanstack-solid-router/interfaces/PlayRouteEvent.md +119 -0
  131. package/api/@xmachines/play-tanstack-solid-router/interfaces/PlayRouterProviderProps.md +14 -0
  132. package/api/@xmachines/play-tanstack-solid-router/interfaces/RouteMapping.md +23 -0
  133. package/api/@xmachines/play-tanstack-solid-router/interfaces/RouterBridge.md +104 -0
  134. package/api/@xmachines/play-tanstack-solid-router/type-aliases/RoutableActor.md +9 -0
  135. package/api/@xmachines/play-tanstack-solid-router/type-aliases/TanStackRouterInstance.md +9 -0
  136. package/api/@xmachines/play-tanstack-solid-router/type-aliases/TanStackRouterLike.md +78 -0
  137. package/api/@xmachines/play-tanstack-solid-router-demo/README.md +126 -0
  138. package/api/@xmachines/play-vue/README.md +292 -0
  139. package/api/@xmachines/play-vue/interfaces/PlayRendererProps.md +14 -0
  140. package/api/@xmachines/play-vue/variables/PlayRenderer.md +9 -0
  141. package/api/@xmachines/play-vue-router/README.md +604 -0
  142. package/api/@xmachines/play-vue-router/classes/RouteMap.md +209 -0
  143. package/api/@xmachines/play-vue-router/classes/VueBaseRouteMap.md +201 -0
  144. package/api/@xmachines/play-vue-router/classes/VueRouterBridge.md +360 -0
  145. package/api/@xmachines/play-vue-router/functions/createRouteMap.md +19 -0
  146. package/api/@xmachines/play-vue-router/interfaces/PlayRouteEvent.md +119 -0
  147. package/api/@xmachines/play-vue-router/interfaces/RouteMapping.md +15 -0
  148. package/api/@xmachines/play-vue-router/interfaces/RouterBridge.md +104 -0
  149. package/api/@xmachines/play-vue-router/type-aliases/RoutableActor.md +9 -0
  150. package/api/@xmachines/play-vue-router/variables/PlayRouterProvider.md +67 -0
  151. package/api/@xmachines/play-vue-router-demo/README.md +133 -0
  152. package/api/@xmachines/play-xstate/README.md +512 -0
  153. package/api/@xmachines/play-xstate/classes/PlayerActor.md +527 -0
  154. package/api/@xmachines/play-xstate/functions/buildRouteUrl.md +43 -0
  155. package/api/@xmachines/play-xstate/functions/composeGuards.md +79 -0
  156. package/api/@xmachines/play-xstate/functions/composeGuardsOr.md +67 -0
  157. package/api/@xmachines/play-xstate/functions/definePlayer.md +127 -0
  158. package/api/@xmachines/play-xstate/functions/deriveRoute.md +109 -0
  159. package/api/@xmachines/play-xstate/functions/eventMatches.md +40 -0
  160. package/api/@xmachines/play-xstate/functions/formatPlayRouteTransitions.md +54 -0
  161. package/api/@xmachines/play-xstate/functions/hasContext.md +42 -0
  162. package/api/@xmachines/play-xstate/functions/isAbsoluteRoute.md +41 -0
  163. package/api/@xmachines/play-xstate/functions/mergeViewProps.md +26 -0
  164. package/api/@xmachines/play-xstate/functions/negateGuard.md +61 -0
  165. package/api/@xmachines/play-xstate/functions/stateMatches.md +25 -0
  166. package/api/@xmachines/play-xstate/functions/validateComponentBinding.md +39 -0
  167. package/api/@xmachines/play-xstate/functions/validateViewProps.md +80 -0
  168. package/api/@xmachines/play-xstate/interfaces/CatalogEntry.md +16 -0
  169. package/api/@xmachines/play-xstate/interfaces/PlayerConfig.md +24 -0
  170. package/api/@xmachines/play-xstate/interfaces/PlayerOptions.md +26 -0
  171. package/api/@xmachines/play-xstate/interfaces/RouteContext.md +22 -0
  172. package/api/@xmachines/play-xstate/type-aliases/Catalog.md +21 -0
  173. package/api/@xmachines/play-xstate/type-aliases/ComposedGuard.md +14 -0
  174. package/api/@xmachines/play-xstate/type-aliases/Guard.md +34 -0
  175. package/api/@xmachines/play-xstate/type-aliases/GuardArray.md +20 -0
  176. package/api/@xmachines/play-xstate/type-aliases/PlayerFactory.md +29 -0
  177. package/api/@xmachines/play-xstate/type-aliases/RouteMachineConfig.md +45 -0
  178. package/api/@xmachines/play-xstate/type-aliases/RouteStateNode.md +51 -0
  179. package/api/@xmachines/play-xstate/type-aliases/ValidationResult.md +17 -0
  180. package/api/@xmachines/play-xstate/type-aliases/ViewMergeContext.md +35 -0
  181. package/api/@xmachines/shared/README.md +379 -0
  182. package/api/@xmachines/shared/functions/defineXmVitestConfig.md +29 -0
  183. package/api/@xmachines/shared/functions/xmAliases.md +24 -0
  184. package/api/README.md +25 -0
  185. package/api/llms.txt +26 -0
  186. package/examples/README.md +63 -0
  187. package/examples/basic-state-machine.md +70 -0
  188. package/examples/form-validation.md +167 -0
  189. package/examples/multi-router-integration.md +277 -0
  190. package/examples/routing-patterns.md +260 -0
  191. package/examples/traffic-light.md +99 -0
  192. package/guides/README.md +29 -0
  193. package/guides/getting-started.md +223 -0
  194. package/guides/installation.md +323 -0
  195. package/index.d.ts +3 -0
  196. package/index.js +4 -0
  197. package/package.json +54 -0
@@ -0,0 +1,67 @@
1
+ [Documentation](../../../README.md) / [@xmachines/play-vue-router](../README.md) / PlayRouterProvider
2
+
3
+ # Variable: PlayRouterProvider
4
+
5
+ ```ts
6
+ const PlayRouterProvider: DefineComponent<
7
+ ExtractPropTypes<{
8
+ actor: {
9
+ required: true;
10
+ type: PropType<RoutableActor>;
11
+ };
12
+ renderer: {
13
+ required: true;
14
+ type: PropType<(actor, router) => VNodeChild>;
15
+ };
16
+ routeMap: {
17
+ required: true;
18
+ type: PropType<RouteMap>;
19
+ };
20
+ router: {
21
+ required: true;
22
+ type: PropType<Router>;
23
+ };
24
+ }>,
25
+ () => VNodeChild,
26
+ {},
27
+ {},
28
+ {},
29
+ ComponentOptionsMixin,
30
+ ComponentOptionsMixin,
31
+ {},
32
+ string,
33
+ PublicProps,
34
+ ToResolvedProps<
35
+ ExtractPropTypes<{
36
+ actor: {
37
+ required: true;
38
+ type: PropType<RoutableActor>;
39
+ };
40
+ renderer: {
41
+ required: true;
42
+ type: PropType<(actor, router) => VNodeChild>;
43
+ };
44
+ routeMap: {
45
+ required: true;
46
+ type: PropType<RouteMap>;
47
+ };
48
+ router: {
49
+ required: true;
50
+ type: PropType<Router>;
51
+ };
52
+ }>,
53
+ {}
54
+ >,
55
+ {},
56
+ {},
57
+ {},
58
+ {},
59
+ string,
60
+ ComponentProvideOptions,
61
+ true,
62
+ {},
63
+ any
64
+ >;
65
+ ```
66
+
67
+ Defined in: [play-vue-router/src/play-router-provider.ts:11](https://gitlab.com/xmachin-es/xmachines-js/-/blob/00a28432ed57807112288436d1ae4387d9f06919/packages/play-vue-router/src/play-router-provider.ts#L11)
@@ -0,0 +1,133 @@
1
+ [Documentation](../../README.md) / @xmachines/play-vue-router-demo
2
+
3
+ # Vue Router Demo
4
+
5
+ Vue Router integration demonstrating Play Architecture with Vue Composition API.
6
+
7
+ ## What This Demonstrates
8
+
9
+ - Shared auth machine reused without framework-specific business logic
10
+ - `PlayVueRouterProvider` renderer-based integration with Vue Router
11
+ - Shell-driven rendering via `PlayRenderer` with actor-authoritative navigation
12
+ - Vue Composition API mapping to TC39 Signals lifecycle
13
+ - Non-browser invariant tests plus browser E2E coverage
14
+
15
+ ## Running the Demo
16
+
17
+ From the repository root:
18
+
19
+ ```bash
20
+ npm install
21
+ npm run dev -w packages/play-vue-router/examples/demo
22
+ ```
23
+
24
+ Visit `http://localhost:5173`.
25
+
26
+ ## Step-by-Step Code Flow
27
+
28
+ Use this order to understand how the demo is wired:
29
+
30
+ 1. `src/main.ts` creates the actor via `definePlayer({ machine: authMachine, catalog })`.
31
+ 2. `src/router.ts` installs one catch-all route; `PlayRenderer` selects the actual view from actor state.
32
+ 3. `src/App.vue` uses `PlayVueRouterProvider` + `createRouteMap(authMachine)` with a renderer function to connect router navigation and actor routing events.
33
+ 4. Provider waits for `router.isReady()` so direct URL loads are handled correctly.
34
+ 5. `src/Shell.vue` renders actor-projected state (`PlayRenderer`) and sends events back to the actor.
35
+ 6. Browser tests in `test/browser/` validate startup and auth route transitions.
36
+
37
+ ```ts
38
+ // src/main.ts (shape)
39
+ const createPlayer = definePlayer({ machine: authMachine, catalog });
40
+ const actor = createPlayer();
41
+ actor.start();
42
+
43
+ const app = createApp(App);
44
+ app.provide("actor", actor);
45
+ app.use(router);
46
+ app.mount("#app");
47
+ ```
48
+
49
+ ```ts
50
+ // src/router.ts (shape)
51
+ export const routes = [{ path: "/:pathMatch(.*)*", name: "xmachines-play", component: RouteHost }];
52
+ ```
53
+
54
+ ```ts
55
+ // src/App.vue (renderer shape)
56
+ const renderShell = (currentActor, currentRouter) =>
57
+ h(Shell, {
58
+ actor: currentActor,
59
+ router: currentRouter,
60
+ });
61
+ ```
62
+
63
+ ```vue
64
+ <!-- src/components/Login.vue (shape) -->
65
+ <script setup lang="ts">
66
+ const actor = inject("actor")!;
67
+ const login = () => actor.send({ type: "auth.login", username: "demo" });
68
+ </script>
69
+ ```
70
+
71
+ ## Key Files
72
+
73
+ - `src/main.ts` - actor creation/start and app mount
74
+ - `src/router.ts` - single catch-all route record
75
+ - `src/App.vue` - provider wiring and renderer composition
76
+ - `src/Shell.vue` - actor-driven demo shell with nav, renderer, and debug panel
77
+ - `src/components/` - route and page view components
78
+ - `test/browser/startup.browser.test.ts` - startup check for home + login link rendering
79
+ - `test/browser/auth-flow.browser.test.ts` - login -> dashboard -> profile -> logout browser flow
80
+ - `test/reactivity.test.ts` - reactive integration assertions
81
+
82
+ ## State Machine & Architecture Details
83
+
84
+ The demo utilizes XMachines architectural invariants:
85
+
86
+ 1. **Actor Authority:** When a user navigates to a protected route via a link, Vue Router updates the location. The `PlayVueRouterProvider` intercepts this, translates it to a `play.route` event, and sends it to the actor. The actor evaluates guards (e.g. `isAuthenticated`) and transitions.
87
+ 2. **Passive Infrastructure:** The router does not execute Vue route guards for business logic. The actor dictates whether navigation is permitted. The Vue application only renders the state.
88
+ 3. **Signal-Only Reactivity:** The bridge leverages Vue's `watch` and `triggerRef` internally to react precisely when signals update, without polluting the Vue component tree with reactive refs that hold business state.
89
+
90
+ ## Watcher Lifecycle and Cleanup Contract
91
+
92
+ This demo uses the canonical watcher lifecycle:
93
+
94
+ 1. `notify`
95
+ 2. `queueMicrotask`
96
+ 3. `getPending()`
97
+ 4. Read actor signals and sync Vue-local render state
98
+ 5. Re-arm with `watch()`/`watch(...signals)`
99
+
100
+ Notifications are one-shot, so re-arm is required. Teardown is explicit: provider/bridge cleanup must flow through `disconnect` and watcher `unwatch`, not GC-only assumptions. The `PlayVueRouterProvider` wires this seamlessly into the component's `onUnmounted` hook.
101
+
102
+ ## Adapter Boundaries
103
+
104
+ Vue Router integration remains passive infrastructure. `RouterBridgeBase` owns shared synchronization policy and the Vue adapter is a thin framework port. Route extraction override strategies remain supported when teams need custom route-name mapping.
105
+
106
+ ## Available Scripts
107
+
108
+ ```bash
109
+ npm run dev # Start Vite dev server (default: http://localhost:5173)
110
+ npm run build # Build production assets
111
+ npm run preview # Preview production build locally
112
+ npm run test # Run unit/integration tests via Vitest
113
+ npm run test:browser # Run browser-mode tests via vitest.browser.config.ts
114
+ ```
115
+
116
+ ## Verification
117
+
118
+ Use these checks from this directory:
119
+
120
+ ```bash
121
+ npm run test
122
+ npm run test:browser
123
+ ```
124
+
125
+ Manual sanity check:
126
+
127
+ 1. Start with `npm run dev`.
128
+ 2. Open `http://localhost:5173`.
129
+ 3. Confirm login/logout transitions update both view and URL, and that accessing protected routes while logged out redirects properly.
130
+
131
+ ## Learn More
132
+
133
+ - **[Vue Router Adapter README](../play-vue-router/README.md)** - Package-level API and bridge docs
@@ -0,0 +1,512 @@
1
+ [Documentation](../../README.md) / @xmachines/play-xstate
2
+
3
+ # @xmachines/play-xstate
4
+
5
+ **XState v5 adapter for Play Architecture with signal-driven reactivity and routing**
6
+
7
+ Transform declarative state machines into live actors with TC39 Signals and parameter-aware navigation.
8
+
9
+ ## Overview
10
+
11
+ `@xmachines/play-xstate` provides `definePlayer()`, the primary API for binding XState v5 state machines to the Play Architecture actor base. It enables business logic to control routing and state through guard-enforced transitions with catalog binding, signal lifecycle management, and XState DevTools compatibility.
12
+
13
+ Per [RFC Play v1](https://gitlab.com/xmachin-es/rfc/-/blob/main/src/play-v1.md), this package implements:
14
+
15
+ - **Actor Authority (INV-01):** State machine guards decide navigation validity
16
+ - **Strict Separation (INV-02):** Zero React/framework imports in business logic
17
+ - **Signal-Only Reactivity (INV-05):** TC39 Signals expose all state changes
18
+
19
+ **Routing:** Supports `meta.route` patterns, `play.route` events with parameters, and route extraction.
20
+
21
+ ## Installation
22
+
23
+ ```bash
24
+ npm install xstate@^5.0.0
25
+ npm install @xmachines/play-xstate
26
+ ```
27
+
28
+ **Peer dependencies:**
29
+
30
+ - `xstate` ^5.0.0 — State machine runtime
31
+
32
+ > `zod` is a direct dependency of `@xmachines/play-xstate` (not a peer). You do not need to install it separately unless you use it in your own catalog schemas.
33
+
34
+ ## Quick Start
35
+
36
+ ```typescript
37
+ import { setup } from "xstate";
38
+ import { z } from "zod";
39
+ import { definePlayer } from "@xmachines/play-xstate";
40
+ import { defineCatalog } from "@xmachines/play-catalog";
41
+
42
+ // 1. Define XState machine with meta.route
43
+ const machine = setup({
44
+ types: {
45
+ context: {} as { userId: string },
46
+ events: {} as { type: "play.route"; to: string } | { type: "auth.login"; userId: string },
47
+ },
48
+ guards: {
49
+ isLoggedIn: ({ context }) => !!context.userId,
50
+ },
51
+ }).createMachine({
52
+ id: "app",
53
+ initial: "login",
54
+ context: { userId: "" },
55
+ states: {
56
+ login: {
57
+ id: "login",
58
+ meta: {
59
+ route: "/login",
60
+ view: { component: "LoginForm" },
61
+ },
62
+ on: {
63
+ "auth.login": {
64
+ guard: "isLoggedIn",
65
+ target: "dashboard",
66
+ },
67
+ },
68
+ },
69
+ dashboard: {
70
+ id: "dashboard",
71
+ meta: {
72
+ route: "/dashboard",
73
+ view: { component: "Dashboard", props: { userId: "" } },
74
+ },
75
+ },
76
+ },
77
+ });
78
+
79
+ // 2. Define catalog with Zod schemas
80
+ const catalog = defineCatalog({
81
+ LoginForm: z.object({ error: z.string().optional() }),
82
+ Dashboard: z.object({ userId: z.string() }),
83
+ });
84
+
85
+ // 3. Create player factory
86
+ const createPlayer = definePlayer({ machine, catalog });
87
+
88
+ // 4. Create and start actor
89
+ const actor = createPlayer({ userId: "" });
90
+ actor.start();
91
+
92
+ // 5. Send events (play.route with parameters)
93
+ actor.send({ type: "play.route", to: "/login" });
94
+
95
+ // 6. Observe signals
96
+ console.log(actor.currentRoute.get()); // "/login"
97
+ console.log(actor.currentView.get()); // { component: "LoginForm", props: {...} }
98
+
99
+ // 7. Cleanup
100
+ actor.dispose();
101
+ ```
102
+
103
+ ## API Reference
104
+
105
+ ### definePlayer()
106
+
107
+ Create a player factory from XState machine and catalog:
108
+
109
+ ```typescript
110
+ const createPlayer = definePlayer<TMachine, TCatalog>({
111
+ machine: AnyStateMachine,
112
+ catalog?: Catalog,
113
+ options?: PlayerOptions,
114
+ }): PlayerFactory;
115
+ ```
116
+
117
+ **Config:**
118
+
119
+ - `machine` (required) - XState v5 state machine
120
+ - `catalog` (optional) - UI component catalog with Zod schemas
121
+ - `options` (optional) - Lifecycle hooks
122
+
123
+ **Returns:** Factory function `(input?) => PlayerActor`
124
+
125
+ **Example:**
126
+
127
+ ```typescript
128
+ const createPlayer = definePlayer({
129
+ machine: authMachine,
130
+ catalog: authCatalog,
131
+ options: {
132
+ onStart: (actor) => console.log("Started:", actor.id),
133
+ onTransition: (actor, prev, next) => {
134
+ console.log("Transition:", prev.value, "→", next.value);
135
+ },
136
+ },
137
+ });
138
+
139
+ const actor1 = createPlayer({ userId: "user1" });
140
+ const actor2 = createPlayer({ userId: "user2" });
141
+ // Multiple independent actor instances
142
+ ```
143
+
144
+ ### PlayerActor
145
+
146
+ Concrete actor implementing Play signal protocol:
147
+
148
+ **Signal Properties:**
149
+
150
+ - `state: Signal.State<AnyMachineSnapshot>` — Reactive snapshot of current state
151
+ - `currentRoute: Signal.Computed<string | null>` — Derived navigation path
152
+ - `currentView: Signal.State<ViewMetadata | null>` — Current UI structure (updated at state entry)
153
+
154
+ **Actor Properties:**
155
+
156
+ - `catalog: Catalog` — Component catalog
157
+
158
+ **Constructor:**
159
+
160
+ ```typescript
161
+ new PlayerActor(machine, catalog, options, input?)
162
+ ```
163
+
164
+ - `input` — Typed as `InputFrom<TMachine>`. Consumers receive compile-time validation against the machine's input schema. Pass initial context values required by the machine.
165
+
166
+ **Methods:**
167
+
168
+ - `start()` — Start the actor (must call after creation)
169
+ - `stop()` — Stop the actor
170
+ - `send(event: PlayEvent)` — Send event to actor
171
+ - `dispose()` — Convenience cleanup (calls stop())
172
+
173
+ **Prop validation modes** (via `PlayerOptions.propValidation`):
174
+
175
+ - `"lenient"` (default) — On catalog prop validation failure, calls `onError` hook and renders with unvalidated props
176
+ - `"strict"` — On catalog prop validation failure, calls `onError` hook and sets `currentView` to `null` (blocks render)
177
+
178
+ **Example:**
179
+
180
+ ```typescript
181
+ const actor = createPlayer();
182
+ actor.start();
183
+
184
+ // Observe signals with watcher
185
+ const watcher = new Signal.subtle.Watcher(() => {
186
+ queueMicrotask(() => {
187
+ const route = actor.currentRoute.get();
188
+ console.log("Route changed:", route);
189
+ });
190
+ });
191
+ watcher.watch(actor.currentRoute);
192
+ actor.currentRoute.get(); // Initial read
193
+ ```
194
+
195
+ ### Guard Composition
196
+
197
+ ```typescript
198
+ import {
199
+ composeGuards,
200
+ composeGuardsOr,
201
+ negateGuard,
202
+ hasContext,
203
+ eventMatches,
204
+ stateMatches,
205
+ } from "@xmachines/play-xstate";
206
+
207
+ const machine = setup({
208
+ guards: {
209
+ isLoggedIn: hasContext("userId"),
210
+ isAdmin: ({ context }) => context.role === "admin",
211
+ },
212
+ }).createMachine({
213
+ on: {
214
+ accessAdmin: {
215
+ // Array means AND - all guards must pass
216
+ guard: composeGuards(["isLoggedIn", "isAdmin"]),
217
+ target: "adminPanel",
218
+ },
219
+ accessPublic: {
220
+ // OR composition - any guard passes
221
+ guard: composeGuardsOr(["isLoggedIn", ({ event }) => event.type === "guest.access"]),
222
+ target: "publicArea",
223
+ },
224
+ logout: {
225
+ // NOT composition
226
+ guard: negateGuard("isLoggedIn"),
227
+ target: "login",
228
+ },
229
+ },
230
+ });
231
+ ```
232
+
233
+ **Helpers:**
234
+
235
+ - `hasContext(path: string)` - Check if context property is truthy
236
+ - `eventMatches(type: string)` - Check event type
237
+ - `stateMatches(value: string)` - Check state value
238
+ - `composeGuards(guards: Array)` - AND composition
239
+ - `composeGuardsOr(guards: Array)` - OR composition
240
+ - `negateGuard(guard)` - NOT composition
241
+
242
+ ## Examples
243
+
244
+ ### Guard Placement Philosophy
245
+
246
+ **Guards check if you can BE in a state (state entry), not if you can TAKE an event (event handlers).**
247
+
248
+ ```typescript
249
+ import { setup } from "xstate";
250
+ import { definePlayer, formatPlayRouteTransitions } from "@xmachines/play-xstate";
251
+ import { defineCatalog } from "@xmachines/play-catalog";
252
+
253
+ // Pattern 1: RECOMMENDED - Use formatPlayRouteTransitions utility
254
+ const machineConfig = {
255
+ id: "app",
256
+ initial: "home",
257
+ context: { isAuthenticated: false },
258
+ states: {
259
+ home: {
260
+ id: "home",
261
+ meta: { route: "/", view: { component: "Home" } },
262
+ },
263
+ dashboard: {
264
+ id: "dashboard",
265
+ meta: { route: "/dashboard", view: { component: "Dashboard" } },
266
+ // Always-guard validates state entry
267
+ always: [
268
+ {
269
+ target: "login",
270
+ guard: ({ context }) => !context.isAuthenticated,
271
+ },
272
+ ],
273
+ },
274
+ login: {
275
+ id: "login",
276
+ meta: { route: "/login", view: { component: "Login" } },
277
+ },
278
+ },
279
+ };
280
+
281
+ // formatPlayRouteTransitions handles routing infrastructure
282
+ const machine = setup({
283
+ types: {
284
+ events: {} as { type: "play.route"; to: string } | { type: "auth.login" },
285
+ },
286
+ }).createMachine(formatPlayRouteTransitions(machineConfig));
287
+
288
+ const catalog = defineCatalog({
289
+ Home,
290
+ Dashboard,
291
+ Login,
292
+ });
293
+
294
+ const createPlayer = definePlayer({ machine, catalog });
295
+ const actor = createPlayer();
296
+ actor.start();
297
+
298
+ // Navigation via play.route event
299
+ actor.send({ type: "play.route", to: "/dashboard" });
300
+ // Guard validates: Can I BE in dashboard state?
301
+ // If !isAuthenticated → redirects to login
302
+ ```
303
+
304
+ **Why this works:**
305
+
306
+ - `formatPlayRouteTransitions` adds routing infrastructure (event.to → state mapping)
307
+ - Always-guards handle business logic (authentication checks)
308
+ - Clear separation: routing is infrastructure, guards are business logic
309
+
310
+ **Anti-pattern (DON'T DO THIS):**
311
+
312
+ ```typescript
313
+ // ❌ WRONG - Guard on event checking event properties
314
+ on: {
315
+ "play.route": {
316
+ guard: ({ event }) => event.to === "/dashboard",
317
+ target: "dashboard"
318
+ }
319
+ }
320
+ ```
321
+
322
+ **Reference:** See `docs/examples/routing-patterns.md` for canonical `formatPlayRouteTransitions` usage with always-guards for authentication.
323
+
324
+ ### Lifecycle Hooks
325
+
326
+ ```typescript
327
+ const createPlayer = definePlayer({
328
+ machine,
329
+ catalog,
330
+ options: {
331
+ onStart: (actor) => {
332
+ console.log("Actor started:", actor.id);
333
+ },
334
+ onStop: (actor) => {
335
+ console.log("Actor stopped:", actor.id);
336
+ },
337
+ onTransition: (actor, prev, next) => {
338
+ console.log("State change:", {
339
+ from: prev.value,
340
+ to: next.value,
341
+ timestamp: Date.now(),
342
+ });
343
+ },
344
+ onStateChange: (actor, state) => {
345
+ // Called on every state update
346
+ console.log("Snapshot updated:", state.value);
347
+ },
348
+ onError: (actor, error) => {
349
+ console.error("Actor error:", error);
350
+ // Log to monitoring service, show error UI, etc.
351
+ },
352
+ },
353
+ });
354
+ ```
355
+
356
+ ### XState DevTools Integration
357
+
358
+ ```typescript
359
+ import { createBrowserInspector } from "@statelyai/inspect";
360
+ import { definePlayer } from "@xmachines/play-xstate";
361
+
362
+ const { inspect } = createBrowserInspector();
363
+
364
+ const createPlayer = definePlayer({ machine, catalog });
365
+ const actor = createPlayer();
366
+ actor.start();
367
+
368
+ // PlayerActor maintains XState Inspector compatibility
369
+ // Inspector displays:
370
+ // - State transitions and values
371
+ // - Context data
372
+ // - Events sent to actor
373
+ // - Guard evaluation results
374
+
375
+ // Signals accessible via actor properties, not snapshots
376
+ console.log(actor.currentRoute.get()); // "/dashboard"
377
+ ```
378
+
379
+ ## Metadata Conventions
380
+
381
+ ### Route Metadata
382
+
383
+ ```typescript
384
+ // meta.route marks states as routable
385
+ states: {
386
+ dashboard: {
387
+ id: "dashboard",
388
+ meta: {
389
+ route: "/dashboard", // URL path - marks state as routable
390
+ },
391
+ },
392
+ }
393
+
394
+ // Parameters
395
+ meta: {
396
+ route: "/profile/:userId", // Required parameter
397
+ route: "/settings/:section?", // Optional parameter
398
+ }
399
+
400
+ // Inheritance
401
+ meta: {
402
+ route: "/absolute", // Starts with / → doesn't inherit parent route
403
+ route: "relative", // Doesn't start with / → inherits parent route
404
+ }
405
+ ```
406
+
407
+ ### View Metadata
408
+
409
+ ```typescript
410
+ meta: {
411
+ view: {
412
+ component: "Dashboard", // Must exist in catalog
413
+ props: { userId: "user123" }, // Validated against Zod schema
414
+ title: "Dashboard", // Additional metadata
415
+ },
416
+ }
417
+
418
+ // Dynamic props from context
419
+ meta: {
420
+ view: {
421
+ component: "Dashboard",
422
+ props: (context) => ({
423
+ userId: context.userId,
424
+ notifications: context.unreadCount,
425
+ }),
426
+ },
427
+ }
428
+ ```
429
+
430
+ ## Architecture
431
+
432
+ This package implements RFC Play v1 requirements:
433
+
434
+ **Architectural Invariants:**
435
+
436
+ - **Actor Authority (INV-01):** Guards decide navigation validity
437
+ - **Strict Separation (INV-02):** Zero framework imports
438
+ - **Signal-Only Reactivity (INV-05):** All state via TC39 Signals
439
+
440
+ **XState DevTools:** Maintains Inspector compatibility — snapshots remain pure XState format, signals accessible via actor properties.
441
+
442
+ **Routing:**
443
+
444
+ - `meta.route` property marks states as routable
445
+ - `play.route` events support parameters (enhancement)
446
+ - Route extraction for URL patterns
447
+
448
+ **Note:** Route parameter extraction uses URLPattern API. See [@xmachines/play-tanstack-react-router browser support](../play-tanstack-react-router/README.md) for polyfill requirements.
449
+
450
+ ## Related Packages
451
+
452
+ - **[@xmachines/play-actor](../play-actor/README.md)** - AbstractActor base class
453
+ - **[@xmachines/play-signals](../play-signals/README.md)** - TC39 Signals polyfill
454
+ - **[@xmachines/play-catalog](../play-catalog/README.md)** - UI schema validation
455
+ - **[@xmachines/play-router](../play-router/README.md)** - Route extraction
456
+ - **[@xmachines/play](../play/README.md)** - Protocol types (PlayEvent)
457
+
458
+ ## License
459
+
460
+ Copyright (c) 2016 [Mikael Karon](mailto:mikael@karon.se). All rights reserved.
461
+
462
+ This work is licensed under the terms of the MIT license.
463
+ For a copy, see <https://opensource.org/licenses/MIT>.
464
+
465
+ @xmachines/play-xstate - XState v5 adapter for Play Architecture
466
+
467
+ Provides definePlayer() API for binding XState state machines to the
468
+ actor base with catalog binding, signal lifecycle, and DevTools integration.
469
+
470
+ Per RFC Play v1, this package implements the Logic Layer adapter that
471
+ transforms declarative machine definitions into live actors with signal-driven
472
+ reactivity.
473
+
474
+ ## Classes
475
+
476
+ - [PlayerActor](classes/PlayerActor.md)
477
+
478
+ ## Interfaces
479
+
480
+ - [CatalogEntry](interfaces/CatalogEntry.md)
481
+ - [PlayerConfig](interfaces/PlayerConfig.md)
482
+ - [PlayerOptions](interfaces/PlayerOptions.md)
483
+ - [RouteContext](interfaces/RouteContext.md)
484
+
485
+ ## Type Aliases
486
+
487
+ - [Catalog](type-aliases/Catalog.md)
488
+ - [ComposedGuard](type-aliases/ComposedGuard.md)
489
+ - [Guard](type-aliases/Guard.md)
490
+ - [GuardArray](type-aliases/GuardArray.md)
491
+ - [PlayerFactory](type-aliases/PlayerFactory.md)
492
+ - [RouteMachineConfig](type-aliases/RouteMachineConfig.md)
493
+ - [RouteStateNode](type-aliases/RouteStateNode.md)
494
+ - [ValidationResult](type-aliases/ValidationResult.md)
495
+ - [ViewMergeContext](type-aliases/ViewMergeContext.md)
496
+
497
+ ## Functions
498
+
499
+ - [buildRouteUrl](functions/buildRouteUrl.md)
500
+ - [composeGuards](functions/composeGuards.md)
501
+ - [composeGuardsOr](functions/composeGuardsOr.md)
502
+ - [definePlayer](functions/definePlayer.md)
503
+ - [deriveRoute](functions/deriveRoute.md)
504
+ - [eventMatches](functions/eventMatches.md)
505
+ - [formatPlayRouteTransitions](functions/formatPlayRouteTransitions.md)
506
+ - [hasContext](functions/hasContext.md)
507
+ - [isAbsoluteRoute](functions/isAbsoluteRoute.md)
508
+ - [mergeViewProps](functions/mergeViewProps.md)
509
+ - [negateGuard](functions/negateGuard.md)
510
+ - [stateMatches](functions/stateMatches.md)
511
+ - [validateComponentBinding](functions/validateComponentBinding.md)
512
+ - [validateViewProps](functions/validateViewProps.md)