@xmachines/docs 1.0.0-beta.46 → 1.0.0-beta.50

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 (347) hide show
  1. package/README.md +135 -7
  2. package/api/@xmachines/play/README.md +134 -57
  3. package/api/@xmachines/play/classes/NonNullableError.md +4 -4
  4. package/api/@xmachines/play/classes/PlayError.md +4 -4
  5. package/api/@xmachines/play/functions/assertNonNullable.md +1 -1
  6. package/api/@xmachines/play/type-aliases/PlayEvent.md +2 -2
  7. package/api/@xmachines/play-actor/README.md +130 -155
  8. package/api/@xmachines/play-actor/classes/AbstractActor.md +3 -3
  9. package/api/@xmachines/play-actor/functions/typedSpec.md +1 -1
  10. package/api/@xmachines/play-actor/interfaces/BaseActorProviderProps.md +5 -5
  11. package/api/@xmachines/play-actor/interfaces/BaseViewContextValue.md +5 -5
  12. package/api/@xmachines/play-actor/interfaces/PlaySpec.md +2 -2
  13. package/api/@xmachines/play-actor/interfaces/Routable.md +3 -3
  14. package/api/@xmachines/play-actor/interfaces/Viewable.md +2 -2
  15. package/api/@xmachines/play-dom/README.md +140 -232
  16. package/api/@xmachines/play-dom/classes/PlayRenderer.md +4 -4
  17. package/api/@xmachines/play-dom/functions/connectRenderer.md +1 -1
  18. package/api/@xmachines/play-dom/functions/createPlayUI.md +1 -1
  19. package/api/@xmachines/play-dom/functions/createRenderer.md +1 -1
  20. package/api/@xmachines/play-dom/functions/defineRegistry.md +1 -1
  21. package/api/@xmachines/play-dom/functions/renderSpec.md +3 -3
  22. package/api/@xmachines/play-dom/interfaces/ComponentContext.md +7 -7
  23. package/api/@xmachines/play-dom/interfaces/ConnectRendererOptions.md +13 -13
  24. package/api/@xmachines/play-dom/interfaces/CreatePlayUIOptions.md +6 -6
  25. package/api/@xmachines/play-dom/interfaces/DefineRegistryResult.md +4 -4
  26. package/api/@xmachines/play-dom/interfaces/DomRenderContext.md +12 -12
  27. package/api/@xmachines/play-dom/interfaces/EventHandle.md +4 -4
  28. package/api/@xmachines/play-dom/interfaces/MountOptions.md +3 -3
  29. package/api/@xmachines/play-dom/interfaces/PlayDomOptions.md +5 -5
  30. package/api/@xmachines/play-dom/interfaces/UIProviderOptions.md +5 -5
  31. package/api/@xmachines/play-dom/type-aliases/ActionFn.md +1 -1
  32. package/api/@xmachines/play-dom/type-aliases/Actions.md +1 -1
  33. package/api/@xmachines/play-dom/type-aliases/BaseComponentProps.md +7 -7
  34. package/api/@xmachines/play-dom/type-aliases/CatalogHasActions.md +1 -1
  35. package/api/@xmachines/play-dom/type-aliases/ComponentFn.md +1 -1
  36. package/api/@xmachines/play-dom/type-aliases/ComponentRegistry.md +1 -1
  37. package/api/@xmachines/play-dom/type-aliases/DefineRegistryOptions.md +2 -2
  38. package/api/@xmachines/play-dom/type-aliases/DomComponentRenderer.md +1 -1
  39. package/api/@xmachines/play-dom/type-aliases/DomRegistry.md +1 -1
  40. package/api/@xmachines/play-dom/type-aliases/DomSchema.md +1 -1
  41. package/api/@xmachines/play-dom/type-aliases/MountFn.md +1 -1
  42. package/api/@xmachines/play-dom/type-aliases/SetState.md +1 -1
  43. package/api/@xmachines/play-dom/variables/schema.md +1 -1
  44. package/api/@xmachines/play-dom-router/README.md +160 -158
  45. package/api/@xmachines/play-dom-router/functions/connectRouter.md +1 -1
  46. package/api/@xmachines/play-dom-router/functions/createBrowserHistory.md +1 -1
  47. package/api/@xmachines/play-dom-router/functions/createRouteMap.md +1 -1
  48. package/api/@xmachines/play-dom-router/functions/createRouter.md +1 -1
  49. package/api/@xmachines/play-dom-router/interfaces/BrowserHistory.md +14 -14
  50. package/api/@xmachines/play-dom-router/interfaces/BrowserWindow.md +14 -14
  51. package/api/@xmachines/play-dom-router/interfaces/ConnectRouterOptions.md +4 -4
  52. package/api/@xmachines/play-dom-router/interfaces/PlayRouteEvent.md +6 -6
  53. package/api/@xmachines/play-dom-router/interfaces/RouteLookupContract.md +3 -3
  54. package/api/@xmachines/play-dom-router/interfaces/RouteMap.md +3 -3
  55. package/api/@xmachines/play-dom-router/interfaces/RouteMapOptions.md +2 -2
  56. package/api/@xmachines/play-dom-router/interfaces/RouteMapping.md +3 -3
  57. package/api/@xmachines/play-dom-router/interfaces/RouterBridge.md +3 -3
  58. package/api/@xmachines/play-dom-router/interfaces/VanillaRouter.md +4 -4
  59. package/api/@xmachines/play-dom-router/type-aliases/RoutableActor.md +1 -1
  60. package/api/@xmachines/play-react/README.md +109 -320
  61. package/api/@xmachines/play-react/classes/PlayErrorBoundary.md +5 -5
  62. package/api/@xmachines/play-react/functions/useActor.md +1 -1
  63. package/api/@xmachines/play-react/functions/usePlayView.md +1 -1
  64. package/api/@xmachines/play-react/functions/useSignalEffect.md +1 -1
  65. package/api/@xmachines/play-react/interfaces/ActorProviderProps.md +8 -8
  66. package/api/@xmachines/play-react/interfaces/PlayErrorBoundaryProps.md +4 -4
  67. package/api/@xmachines/play-react/interfaces/PlayErrorBoundaryState.md +3 -3
  68. package/api/@xmachines/play-react/interfaces/PlayUIProviderProps.md +8 -8
  69. package/api/@xmachines/play-react/interfaces/ViewContextValue.md +5 -5
  70. package/api/@xmachines/play-react/type-aliases/PlayActor.md +1 -1
  71. package/api/@xmachines/play-react/variables/ActorProvider.md +1 -1
  72. package/api/@xmachines/play-react/variables/PlayRenderer.md +1 -1
  73. package/api/@xmachines/play-react/variables/PlayUIProvider.md +1 -1
  74. package/api/@xmachines/play-react-router/README.md +107 -124
  75. package/api/@xmachines/play-react-router/classes/ReactRouterBridge.md +23 -23
  76. package/api/@xmachines/play-react-router/classes/RouteMap.md +4 -4
  77. package/api/@xmachines/play-react-router/functions/PlayRouterProvider.md +1 -1
  78. package/api/@xmachines/play-react-router/functions/createRouteMap.md +1 -1
  79. package/api/@xmachines/play-react-router/functions/createRouteMapFromTree.md +1 -1
  80. package/api/@xmachines/play-react-router/interfaces/PlayRouteEvent.md +6 -6
  81. package/api/@xmachines/play-react-router/interfaces/PlayRouterProviderProps.md +5 -5
  82. package/api/@xmachines/play-react-router/interfaces/RouteMapOptions.md +2 -2
  83. package/api/@xmachines/play-react-router/interfaces/RouteMapping.md +3 -3
  84. package/api/@xmachines/play-react-router/interfaces/RouterBridge.md +3 -3
  85. package/api/@xmachines/play-router/README.md +235 -475
  86. package/api/@xmachines/play-router/classes/RouteMap.md +4 -4
  87. package/api/@xmachines/play-router/classes/RouterBridgeBase.md +23 -23
  88. package/api/@xmachines/play-router/functions/buildPlayRouteEvent.md +1 -1
  89. package/api/@xmachines/play-router/functions/buildRouteTree.md +1 -1
  90. package/api/@xmachines/play-router/functions/createRouteMap.md +1 -1
  91. package/api/@xmachines/play-router/functions/createRouteMapFromTree.md +1 -1
  92. package/api/@xmachines/play-router/functions/createRouteMatcher.md +1 -1
  93. package/api/@xmachines/play-router/functions/detectDuplicateRoutes.md +1 -1
  94. package/api/@xmachines/play-router/functions/extractMachineRoutes.md +1 -1
  95. package/api/@xmachines/play-router/functions/extractQuery.md +1 -1
  96. package/api/@xmachines/play-router/functions/extractRouteParams.md +1 -1
  97. package/api/@xmachines/play-router/functions/findRouteById.md +1 -1
  98. package/api/@xmachines/play-router/functions/findRouteByPath.md +1 -1
  99. package/api/@xmachines/play-router/functions/getNavigableRoutes.md +1 -1
  100. package/api/@xmachines/play-router/functions/getRoutableRoutes.md +1 -1
  101. package/api/@xmachines/play-router/functions/getTransitionReachableRoutes.md +1 -1
  102. package/api/@xmachines/play-router/functions/isRouteReachable.md +1 -1
  103. package/api/@xmachines/play-router/functions/machineToGraph.md +1 -1
  104. package/api/@xmachines/play-router/functions/routeExists.md +1 -1
  105. package/api/@xmachines/play-router/functions/sanitizePathname.md +1 -1
  106. package/api/@xmachines/play-router/functions/validateRouteFormat.md +1 -1
  107. package/api/@xmachines/play-router/functions/validateStateExists.md +1 -1
  108. package/api/@xmachines/play-router/interfaces/BuildPlayRouteEventOptions.md +4 -4
  109. package/api/@xmachines/play-router/interfaces/LocationLike.md +3 -3
  110. package/api/@xmachines/play-router/interfaces/MachineEdgeData.md +3 -3
  111. package/api/@xmachines/play-router/interfaces/MachineNodeData.md +5 -5
  112. package/api/@xmachines/play-router/interfaces/PlayRouteEvent.md +6 -6
  113. package/api/@xmachines/play-router/interfaces/RouteInfo.md +8 -8
  114. package/api/@xmachines/play-router/interfaces/RouteMapOptions.md +2 -2
  115. package/api/@xmachines/play-router/interfaces/RouteMapping.md +3 -3
  116. package/api/@xmachines/play-router/interfaces/RouteMatch.md +3 -3
  117. package/api/@xmachines/play-router/interfaces/RouteMatcher.md +4 -4
  118. package/api/@xmachines/play-router/interfaces/RouteNode.md +10 -10
  119. package/api/@xmachines/play-router/interfaces/RouteObject.md +2 -2
  120. package/api/@xmachines/play-router/interfaces/RouteTree.md +5 -5
  121. package/api/@xmachines/play-router/interfaces/RouteWatcherHandle.md +3 -3
  122. package/api/@xmachines/play-router/interfaces/RouterBridge.md +3 -3
  123. package/api/@xmachines/play-router/interfaces/WindowLike.md +3 -3
  124. package/api/@xmachines/play-router/type-aliases/MachineGraph.md +1 -1
  125. package/api/@xmachines/play-router/type-aliases/RouteMetadata.md +1 -1
  126. package/api/@xmachines/play-signals/README.md +105 -73
  127. package/api/@xmachines/play-signals/functions/watchSignal.md +1 -1
  128. package/api/@xmachines/play-signals/interfaces/ComputedOptions.md +2 -2
  129. package/api/@xmachines/play-signals/interfaces/SignalComputed.md +2 -2
  130. package/api/@xmachines/play-signals/interfaces/SignalOptions.md +2 -2
  131. package/api/@xmachines/play-signals/interfaces/SignalState.md +3 -3
  132. package/api/@xmachines/play-signals/interfaces/SignalWatcher.md +4 -4
  133. package/api/@xmachines/play-signals/type-aliases/WatcherNotify.md +1 -1
  134. package/api/@xmachines/play-solid/README.md +117 -263
  135. package/api/@xmachines/play-solid/functions/useActor.md +1 -1
  136. package/api/@xmachines/play-solid/functions/usePlayView.md +1 -1
  137. package/api/@xmachines/play-solid/interfaces/ActorProviderProps.md +8 -8
  138. package/api/@xmachines/play-solid/interfaces/PlayUIProviderProps.md +8 -8
  139. package/api/@xmachines/play-solid/interfaces/ViewContextValue.md +5 -5
  140. package/api/@xmachines/play-solid/type-aliases/PlayActor.md +1 -1
  141. package/api/@xmachines/play-solid/variables/ActorContext.md +1 -1
  142. package/api/@xmachines/play-solid/variables/ActorProvider.md +1 -1
  143. package/api/@xmachines/play-solid/variables/PlayRenderer.md +1 -1
  144. package/api/@xmachines/play-solid/variables/PlayUIProvider.md +1 -1
  145. package/api/@xmachines/play-solid-router/README.md +93 -606
  146. package/api/@xmachines/play-solid-router/classes/RouteMap.md +4 -4
  147. package/api/@xmachines/play-solid-router/classes/SolidRouterBridge.md +24 -24
  148. package/api/@xmachines/play-solid-router/functions/PlayRouterProvider.md +1 -1
  149. package/api/@xmachines/play-solid-router/functions/createRouteMap.md +1 -1
  150. package/api/@xmachines/play-solid-router/interfaces/AbstractActor.md +3 -3
  151. package/api/@xmachines/play-solid-router/interfaces/PlayRouteEvent.md +6 -6
  152. package/api/@xmachines/play-solid-router/interfaces/PlayRouterProviderProps.md +5 -5
  153. package/api/@xmachines/play-solid-router/interfaces/RouteMapOptions.md +2 -2
  154. package/api/@xmachines/play-solid-router/interfaces/RouteMapping.md +3 -3
  155. package/api/@xmachines/play-solid-router/interfaces/RouterBridge.md +3 -3
  156. package/api/@xmachines/play-solid-router/type-aliases/RoutableActor.md +1 -1
  157. package/api/@xmachines/play-solid-router/type-aliases/SolidRouterHooks.md +4 -4
  158. package/api/@xmachines/play-svelte/README.md +111 -103
  159. package/api/@xmachines/play-svelte/functions/defineRegistry.md +1 -1
  160. package/api/@xmachines/play-svelte/functions/getActorContext.md +1 -1
  161. package/api/@xmachines/play-svelte/functions/getPlayViewContext.md +1 -1
  162. package/api/@xmachines/play-svelte/functions/setActorContext.md +1 -1
  163. package/api/@xmachines/play-svelte/interfaces/ActorProviderProps.md +8 -8
  164. package/api/@xmachines/play-svelte/interfaces/DefineRegistryOptions.md +4 -4
  165. package/api/@xmachines/play-svelte/interfaces/PlayUIProviderProps.md +11 -11
  166. package/api/@xmachines/play-svelte/interfaces/ViewContextValue.md +5 -5
  167. package/api/@xmachines/play-svelte/type-aliases/PlayActor.md +1 -1
  168. package/api/@xmachines/play-svelte-spa-router/README.md +156 -17
  169. package/api/@xmachines/play-svelte-spa-router/classes/RouteMap.md +4 -4
  170. package/api/@xmachines/play-svelte-spa-router/functions/connectRouter.md +1 -1
  171. package/api/@xmachines/play-svelte-spa-router/functions/createRouteMap.md +1 -1
  172. package/api/@xmachines/play-svelte-spa-router/interfaces/ConnectRouterOptions.md +4 -4
  173. package/api/@xmachines/play-svelte-spa-router/interfaces/PlayRouteEvent.md +6 -6
  174. package/api/@xmachines/play-svelte-spa-router/interfaces/RouteMapOptions.md +2 -2
  175. package/api/@xmachines/play-svelte-spa-router/interfaces/RouteMapping.md +3 -3
  176. package/api/@xmachines/play-svelte-spa-router/interfaces/RouterBridge.md +3 -3
  177. package/api/@xmachines/play-svelte-spa-router/interfaces/WindowLike.md +3 -3
  178. package/api/@xmachines/play-svelte-spa-router/type-aliases/RoutableActor.md +1 -1
  179. package/api/@xmachines/play-sveltekit-router/README.md +168 -17
  180. package/api/@xmachines/play-sveltekit-router/classes/RouteMap.md +4 -4
  181. package/api/@xmachines/play-sveltekit-router/functions/connectRouter.md +1 -1
  182. package/api/@xmachines/play-sveltekit-router/functions/createRouteMap.md +1 -1
  183. package/api/@xmachines/play-sveltekit-router/interfaces/ConnectRouterOptions.md +4 -4
  184. package/api/@xmachines/play-sveltekit-router/interfaces/LocationLike.md +3 -3
  185. package/api/@xmachines/play-sveltekit-router/interfaces/PlayRouteEvent.md +6 -6
  186. package/api/@xmachines/play-sveltekit-router/interfaces/RouteMapOptions.md +2 -2
  187. package/api/@xmachines/play-sveltekit-router/interfaces/RouteMapping.md +3 -3
  188. package/api/@xmachines/play-sveltekit-router/interfaces/RouterBridge.md +3 -3
  189. package/api/@xmachines/play-sveltekit-router/type-aliases/RoutableActor.md +1 -1
  190. package/api/@xmachines/play-tanstack-react-router/README.md +147 -122
  191. package/api/@xmachines/play-tanstack-react-router/classes/RouteMap.md +4 -4
  192. package/api/@xmachines/play-tanstack-react-router/classes/TanStackReactRouterBridge.md +23 -23
  193. package/api/@xmachines/play-tanstack-react-router/functions/PlayRouterProvider.md +1 -1
  194. package/api/@xmachines/play-tanstack-react-router/functions/createRouteMap.md +1 -1
  195. package/api/@xmachines/play-tanstack-react-router/functions/createRouteMapFromTree.md +1 -1
  196. package/api/@xmachines/play-tanstack-react-router/functions/extractMachineRoutes.md +1 -1
  197. package/api/@xmachines/play-tanstack-react-router/interfaces/PlayRouteEvent.md +6 -6
  198. package/api/@xmachines/play-tanstack-react-router/interfaces/PlayRouterProviderProps.md +5 -5
  199. package/api/@xmachines/play-tanstack-react-router/interfaces/RouteMapOptions.md +2 -2
  200. package/api/@xmachines/play-tanstack-react-router/interfaces/RouteMapping.md +3 -3
  201. package/api/@xmachines/play-tanstack-react-router/interfaces/RouteNavigateEvent.md +3 -3
  202. package/api/@xmachines/play-tanstack-react-router/interfaces/RouterBridge.md +3 -3
  203. package/api/@xmachines/play-tanstack-react-router/type-aliases/TanStackRouterInstance.md +1 -1
  204. package/api/@xmachines/play-tanstack-react-router/type-aliases/TanStackRouterLike.md +4 -4
  205. package/api/@xmachines/play-tanstack-solid-router/README.md +195 -173
  206. package/api/@xmachines/play-tanstack-solid-router/classes/RouteMap.md +4 -4
  207. package/api/@xmachines/play-tanstack-solid-router/classes/SolidRouterBridge.md +24 -24
  208. package/api/@xmachines/play-tanstack-solid-router/functions/PlayRouterProvider.md +1 -1
  209. package/api/@xmachines/play-tanstack-solid-router/functions/createRouteMap.md +1 -1
  210. package/api/@xmachines/play-tanstack-solid-router/interfaces/PlayRouteEvent.md +6 -6
  211. package/api/@xmachines/play-tanstack-solid-router/interfaces/PlayRouterProviderProps.md +5 -5
  212. package/api/@xmachines/play-tanstack-solid-router/interfaces/RouteMapOptions.md +2 -2
  213. package/api/@xmachines/play-tanstack-solid-router/interfaces/RouteMapping.md +3 -3
  214. package/api/@xmachines/play-tanstack-solid-router/interfaces/RouterBridge.md +3 -3
  215. package/api/@xmachines/play-tanstack-solid-router/type-aliases/RoutableActor.md +1 -1
  216. package/api/@xmachines/play-tanstack-solid-router/type-aliases/TanStackRouterInstance.md +1 -1
  217. package/api/@xmachines/play-tanstack-solid-router/type-aliases/TanStackRouterLike.md +3 -3
  218. package/api/@xmachines/play-vue/README.md +126 -271
  219. package/api/@xmachines/play-vue/functions/defineRegistry.md +1 -1
  220. package/api/@xmachines/play-vue/functions/getPlayViewContext.md +1 -1
  221. package/api/@xmachines/play-vue/functions/useActor.md +1 -1
  222. package/api/@xmachines/play-vue/interfaces/ActorProviderProps.md +5 -5
  223. package/api/@xmachines/play-vue/interfaces/PlayUIProviderProps.md +8 -8
  224. package/api/@xmachines/play-vue/interfaces/ViewContextValue.md +5 -5
  225. package/api/@xmachines/play-vue/interfaces/VisibilityProviderProps.md +1 -1
  226. package/api/@xmachines/play-vue/type-aliases/ComponentEntry.md +1 -1
  227. package/api/@xmachines/play-vue/type-aliases/ComponentsMap.md +1 -1
  228. package/api/@xmachines/play-vue/type-aliases/DefineRegistryOptions.md +2 -2
  229. package/api/@xmachines/play-vue/type-aliases/PlayActor.md +1 -1
  230. package/api/@xmachines/play-vue/variables/PlayRenderer.md +1 -1
  231. package/api/@xmachines/play-vue-router/README.md +148 -528
  232. package/api/@xmachines/play-vue-router/classes/RouteMap.md +4 -4
  233. package/api/@xmachines/play-vue-router/classes/VueRouterBridge.md +24 -24
  234. package/api/@xmachines/play-vue-router/functions/createRouteMap.md +1 -1
  235. package/api/@xmachines/play-vue-router/interfaces/PlayRouteEvent.md +6 -6
  236. package/api/@xmachines/play-vue-router/interfaces/RouteMapOptions.md +2 -2
  237. package/api/@xmachines/play-vue-router/interfaces/RouteMapping.md +3 -3
  238. package/api/@xmachines/play-vue-router/interfaces/RouterBridge.md +3 -3
  239. package/api/@xmachines/play-vue-router/type-aliases/RoutableActor.md +1 -1
  240. package/api/@xmachines/play-vue-router/variables/PlayRouterProvider.md +1 -1
  241. package/api/@xmachines/play-xstate/README.md +167 -496
  242. package/api/@xmachines/play-xstate/classes/PlayerActor.md +12 -12
  243. package/api/@xmachines/play-xstate/functions/buildRouteUrl.md +1 -1
  244. package/api/@xmachines/play-xstate/functions/composeGuards.md +1 -1
  245. package/api/@xmachines/play-xstate/functions/composeGuardsOr.md +1 -1
  246. package/api/@xmachines/play-xstate/functions/contextFieldMatches.md +1 -1
  247. package/api/@xmachines/play-xstate/functions/definePlayer.md +1 -1
  248. package/api/@xmachines/play-xstate/functions/deriveRoute.md +1 -1
  249. package/api/@xmachines/play-xstate/functions/eventMatches.md +1 -1
  250. package/api/@xmachines/play-xstate/functions/formatPlayRouteTransitions.md +1 -1
  251. package/api/@xmachines/play-xstate/functions/hasContext.md +1 -1
  252. package/api/@xmachines/play-xstate/functions/isAbsoluteRoute.md +1 -1
  253. package/api/@xmachines/play-xstate/functions/negateGuard.md +1 -1
  254. package/api/@xmachines/play-xstate/interfaces/PlayerConfig.md +3 -3
  255. package/api/@xmachines/play-xstate/interfaces/PlayerFactoryResumeOptions.md +2 -2
  256. package/api/@xmachines/play-xstate/interfaces/PlayerOptions.md +6 -6
  257. package/api/@xmachines/play-xstate/interfaces/RouteContext.md +5 -5
  258. package/api/@xmachines/play-xstate/type-aliases/ComposedGuard.md +1 -1
  259. package/api/@xmachines/play-xstate/type-aliases/Guard.md +1 -1
  260. package/api/@xmachines/play-xstate/type-aliases/GuardArray.md +1 -1
  261. package/api/@xmachines/play-xstate/type-aliases/PlayerFactory.md +1 -1
  262. package/api/@xmachines/play-xstate/type-aliases/RouteMachineConfig.md +4 -4
  263. package/api/@xmachines/play-xstate/type-aliases/RouteStateNode.md +4 -4
  264. package/api/@xmachines/shared/README.md +81 -294
  265. package/api/@xmachines/shared/vite-aliases/functions/xmAliases.md +1 -1
  266. package/api/@xmachines/shared/vite-aliases/functions/xmCacheDir.md +1 -1
  267. package/api/@xmachines/shared/vite-aliases/functions/xmOptimizeDeps.md +1 -1
  268. package/api/@xmachines/shared/vite-aliases/functions/xmResolve.md +1 -1
  269. package/api/@xmachines/shared/vitest/functions/defineXmVitestConfig.md +1 -1
  270. package/contributing/README.md +10 -0
  271. package/contributing/configuration.md +540 -0
  272. package/contributing/deployment.md +314 -0
  273. package/contributing/development.md +617 -0
  274. package/contributing/testing.md +460 -0
  275. package/examples/@xmachines/play-dom-demo/README.md +3 -3
  276. package/examples/@xmachines/play-dom-demo/functions/createNavBar.md +1 -1
  277. package/examples/@xmachines/play-dom-demo/functions/initShell.md +1 -1
  278. package/examples/@xmachines/play-dom-demo/type-aliases/AuthCatalog.md +1 -1
  279. package/examples/@xmachines/play-dom-demo/variables/About.md +1 -1
  280. package/examples/@xmachines/play-dom-demo/variables/Contact.md +1 -1
  281. package/examples/@xmachines/play-dom-demo/variables/Dashboard.md +1 -1
  282. package/examples/@xmachines/play-dom-demo/variables/Home.md +1 -1
  283. package/examples/@xmachines/play-dom-demo/variables/Login.md +1 -1
  284. package/examples/@xmachines/play-dom-demo/variables/NavBarView.md +1 -1
  285. package/examples/@xmachines/play-dom-demo/variables/Navigation.md +1 -1
  286. package/examples/@xmachines/play-dom-demo/variables/Overview.md +1 -1
  287. package/examples/@xmachines/play-dom-demo/variables/Profile.md +1 -1
  288. package/examples/@xmachines/play-dom-demo/variables/Settings.md +1 -1
  289. package/examples/@xmachines/play-dom-demo/variables/Stats.md +1 -1
  290. package/examples/@xmachines/play-dom-demo/variables/authCatalog.md +1 -1
  291. package/examples/@xmachines/play-dom-router-demo/README.md +2 -2
  292. package/examples/@xmachines/play-react-demo/README.md +1 -1
  293. package/examples/@xmachines/play-react-demo/functions/App.md +1 -1
  294. package/examples/@xmachines/play-react-demo/type-aliases/AuthCatalog.md +1 -1
  295. package/examples/@xmachines/play-react-demo/variables/About.md +1 -1
  296. package/examples/@xmachines/play-react-demo/variables/Contact.md +1 -1
  297. package/examples/@xmachines/play-react-demo/variables/Dashboard.md +1 -1
  298. package/examples/@xmachines/play-react-demo/variables/DebugPanel.md +1 -1
  299. package/examples/@xmachines/play-react-demo/variables/Home.md +1 -1
  300. package/examples/@xmachines/play-react-demo/variables/Login.md +1 -1
  301. package/examples/@xmachines/play-react-demo/variables/NavBar.md +1 -1
  302. package/examples/@xmachines/play-react-demo/variables/NavBarView.md +1 -1
  303. package/examples/@xmachines/play-react-demo/variables/Navigation.md +1 -1
  304. package/examples/@xmachines/play-react-demo/variables/Overview.md +1 -1
  305. package/examples/@xmachines/play-react-demo/variables/Profile.md +1 -1
  306. package/examples/@xmachines/play-react-demo/variables/Settings.md +1 -1
  307. package/examples/@xmachines/play-react-demo/variables/Shell.md +1 -1
  308. package/examples/@xmachines/play-react-demo/variables/Stats.md +1 -1
  309. package/examples/@xmachines/play-react-demo/variables/authCatalog.md +1 -1
  310. package/examples/@xmachines/play-react-router-demo/README.md +1 -1
  311. package/examples/@xmachines/play-solid-demo/README.md +1 -1
  312. package/examples/@xmachines/play-solid-demo/functions/App.md +1 -1
  313. package/examples/@xmachines/play-solid-demo/type-aliases/AuthCatalog.md +1 -1
  314. package/examples/@xmachines/play-solid-demo/variables/About.md +1 -1
  315. package/examples/@xmachines/play-solid-demo/variables/Contact.md +1 -1
  316. package/examples/@xmachines/play-solid-demo/variables/Dashboard.md +1 -1
  317. package/examples/@xmachines/play-solid-demo/variables/DebugPanel.md +1 -1
  318. package/examples/@xmachines/play-solid-demo/variables/Home.md +1 -1
  319. package/examples/@xmachines/play-solid-demo/variables/Login.md +1 -1
  320. package/examples/@xmachines/play-solid-demo/variables/NavBar.md +1 -1
  321. package/examples/@xmachines/play-solid-demo/variables/NavBarView.md +1 -1
  322. package/examples/@xmachines/play-solid-demo/variables/Navigation.md +1 -1
  323. package/examples/@xmachines/play-solid-demo/variables/Overview.md +1 -1
  324. package/examples/@xmachines/play-solid-demo/variables/Profile.md +1 -1
  325. package/examples/@xmachines/play-solid-demo/variables/Settings.md +1 -1
  326. package/examples/@xmachines/play-solid-demo/variables/Shell.md +1 -1
  327. package/examples/@xmachines/play-solid-demo/variables/Stats.md +1 -1
  328. package/examples/@xmachines/play-solid-demo/variables/authCatalog.md +1 -1
  329. package/examples/@xmachines/play-svelte-demo/README.md +1 -1
  330. package/examples/@xmachines/play-svelte-demo/type-aliases/AuthCatalog.md +1 -1
  331. package/examples/@xmachines/play-svelte-demo/variables/authCatalog.md +1 -1
  332. package/examples/@xmachines/play-svelte-spa-router-demo/README.md +2 -2
  333. package/examples/@xmachines/play-sveltekit-router-demo/README.md +2 -2
  334. package/examples/@xmachines/play-vue-demo/README.md +1 -1
  335. package/examples/@xmachines/play-vue-demo/type-aliases/AuthCatalog.md +1 -1
  336. package/examples/@xmachines/play-vue-demo/variables/App.md +1 -1
  337. package/examples/@xmachines/play-vue-demo/variables/authCatalog.md +1 -1
  338. package/examples/README.md +24 -25
  339. package/examples/form-validation.md +2 -2
  340. package/guides/README.md +11 -7
  341. package/guides/actor-model.md +18 -18
  342. package/guides/architecture.md +500 -0
  343. package/guides/getting-started.md +351 -142
  344. package/guides/signals.md +19 -19
  345. package/guides/state-machines.md +16 -16
  346. package/package.json +7 -5
  347. package/guides/installation.md +0 -257
@@ -1,37 +1,25 @@
1
1
  [API](../../README.md) / @xmachines/play-router
2
2
 
3
+ <!-- generated-by: gsd-doc-writer -->
4
+
3
5
  # @xmachines/play-router
4
6
 
5
- **Route tree extraction from XState v5 state machines with routing patterns**
7
+ Route tree extraction from XState v5 state machines. Part of [@xmachines/play](../play/README.md) Universal Player Architecture.
6
8
 
7
9
  Graph-based route extraction and bidirectional lookup enabling Actor Authority over navigation.
8
10
 
9
- ## Overview
10
-
11
- `@xmachines/play-router` extracts route trees from XState state machines using `@statelyai/graph` — a typed, JSON-serializable graph library. It converts machines to a directed `Graph` with hierarchy, transition edges, and route metadata, then builds hierarchical `RouteTree` structures with bidirectional state ID ↔ path mapping.
12
-
13
- It also exports `RouterBridgeBase`, the shared base class used by framework adapters to implement `RouterBridge` with consistent actor↔router synchronization behavior.
14
-
15
- `RouterBridgeBase` is the policy point; framework adapters are thin ports that implement only framework-specific navigate/subscribe/unsubscribe behavior.
16
-
17
- The low-level `connectRouter()` from `@xmachines/play-dom-router` uses the same router-to-actor event builder and route-map match helper as `RouterBridgeBase`, so pathname sanitization, state-id normalization, param extraction, and query extraction stay aligned across vanilla and framework adapters.
18
-
19
- Per [Play RFC](../../../rfc/play.md), this package implements:
20
-
21
- - **Actor Authority (INV-01):** Routes derive from machine definitions, not external configuration
22
-
23
- **Routing:** Supports `meta.route` detection, `play.route` event routing, and pattern matching for dynamic parameters.
11
+ Part of the [xmachines-js monorepo](../../README.md).
24
12
 
25
13
  ## Installation
26
14
 
27
15
  ```bash
28
- npm install xstate@^5.0.0
16
+ npm install xstate@^5.30.0
29
17
  npm install @xmachines/play-router
30
18
  ```
31
19
 
32
20
  **Peer dependencies:**
33
21
 
34
- - `xstate` ^5.0.0 — State machine runtime
22
+ - `xstate` ^5.30.0 — XState v5 state machine runtime
35
23
 
36
24
  **URLPattern polyfill (Node.js < 24 / older browsers):**
37
25
 
@@ -50,555 +38,327 @@ Install the polyfill:
50
38
  npm install urlpattern-polyfill
51
39
  ```
52
40
 
53
- `urlpattern-polyfill` is declared as an optional peer dependency. Package managers will not install it automatically — consumers must install and load it when their runtime lacks native URLPattern support (Node.js < 24, older browsers).
41
+ `urlpattern-polyfill` is declared as an optional peer dependency. Package managers will not install it automatically — consumers must install and load it when their runtime lacks native URLPattern support.
42
+
43
+ ## Usage
54
44
 
55
- ## Quick Start
45
+ ### Extract routes from a machine
56
46
 
57
47
  ```typescript
58
48
  import { createMachine } from "xstate";
59
- import { extractMachineRoutes, findRouteByPath } from "@xmachines/play-router";
49
+ import { extractMachineRoutes, createRouteMap } from "@xmachines/play-router";
60
50
 
61
- // Route pattern (recommended)
62
51
  const machine = createMachine({
63
52
  id: "app",
64
53
  initial: "home",
65
54
  states: {
66
55
  home: {
67
56
  id: "home",
68
- meta: { route: "/", view: { component: "Home" } },
57
+ meta: { route: "/" },
69
58
  },
70
59
  dashboard: {
71
60
  id: "dashboard",
72
- meta: { route: "/dashboard", view: { component: "Dashboard" } },
61
+ meta: { route: "/dashboard" },
73
62
  initial: "overview",
74
63
  states: {
75
64
  overview: {
76
65
  id: "overview",
77
- meta: { route: "/overview", view: { component: "Overview" } },
66
+ meta: { route: "/overview" },
78
67
  },
79
68
  settings: {
80
69
  id: "settings",
81
- meta: { route: "/settings/:section?", view: { component: "Settings" } }, // Optional parameter
70
+ meta: { route: "/settings/:section?" }, // optional parameter
82
71
  },
83
72
  },
84
73
  },
74
+ profile: {
75
+ id: "profile",
76
+ meta: { route: "/profile/:userId" }, // required parameter
77
+ },
85
78
  },
86
79
  });
87
80
 
81
+ // Build hierarchical route tree with bidirectional maps
88
82
  const tree = extractMachineRoutes(machine);
89
83
 
90
- // Bidirectional lookup
91
- console.log(findRouteByPath(tree, "/overview")); // RouteNode
92
- console.log(tree.byStateId.get("overview")); // RouteNode
84
+ // Path → RouteNode
85
+ const node = tree.byPath.get("/dashboard"); // RouteNode for "dashboard"
93
86
 
94
- // Pattern matching for dynamic routes
95
- const settingsRoute = findRouteByPath(tree, "/settings/profile");
96
- console.log(settingsRoute?.id); // "settings"
97
- ```
87
+ // State ID RouteNode
88
+ const overview = tree.byStateId.get("overview");
89
+ console.log(overview?.fullPath); // "/overview"
98
90
 
99
- ## Vanilla Browser Example
100
-
101
- See `examples/vanilla-demo/` for a complete example using vanilla TypeScript with the browser History API.
102
-
103
- The demo demonstrates:
104
-
105
- - **RouteTree extraction** from XState machine meta.route
106
- - **History API integration** (pushState, popstate)
107
- - **Bidirectional synchronization** (actor ↔ URL)
108
- - **Protected route guards** (authentication redirects)
109
- - **Dynamic route parameters** (/profile/:userId)
110
-
111
- **Run the demo:**
112
-
113
- ```bash
114
- npm run dev -w @xmachines/play-dom-router-demo
91
+ // Build a RouteMap for framework adapters
92
+ const routeMap = createRouteMap(machine);
93
+ routeMap.getStateIdByPath("/profile/123"); // "profile"
94
+ routeMap.getPathByStateId("profile"); // "/profile/:userId"
115
95
  ```
116
96
 
117
- Open http://localhost:5174/ and explore:
118
-
119
- 1. Login with any username
120
- 2. Navigate between home and profile
121
- 3. Use browser back/forward buttons
122
- 4. Try accessing protected routes directly
123
-
124
- **Key implementation patterns:**
97
+ ### Sending `play.route` events
125
98
 
126
99
  ```typescript
127
- // Extract routes from machine
128
- const routeTree = extractMachineRoutes(authMachine);
129
- const routeMatcher = createRouteMatcher(routeTree);
130
-
131
- // Actor → URL sync
132
- const watcher = new Signal.subtle.Watcher(() => {
133
- queueMicrotask(() => {
134
- watcher.getPending();
135
- const route = actor.currentRoute.get();
136
- if (route) {
137
- window.history.pushState({}, "", route);
138
- }
139
- watcher.watch(actor.currentRoute);
140
- });
100
+ import type { PlayRouteEvent } from "@xmachines/play-router";
101
+
102
+ // Navigate to a state by ID
103
+ const event: PlayRouteEvent = {
104
+ type: "play.route",
105
+ to: "#dashboard",
106
+ };
107
+ actor.send(event);
108
+
109
+ // Navigate with route parameters
110
+ actor.send({
111
+ type: "play.route",
112
+ to: "#profile",
113
+ params: { userId: "123" },
141
114
  });
142
115
 
143
- // URL → Actor sync (with pattern matching)
144
- window.addEventListener("popstate", () => {
145
- const path = window.location.pathname;
146
- const { to, params } = routeMatcher.match(path);
147
- if (to) {
148
- actor.send({ type: "play.route", to, params });
149
- }
116
+ // Navigate with query parameters
117
+ actor.send({
118
+ type: "play.route",
119
+ to: "#settings",
120
+ params: { section: "billing" },
121
+ query: { tab: "invoices" },
150
122
  });
151
-
152
- // Initial URL handling
153
- const initialPath = window.location.pathname;
154
- if (initialPath !== "/") {
155
- const { to, params } = routeMatcher.match(initialPath);
156
- if (to) {
157
- actor.send({ type: "play.route", to, params });
158
- }
159
- }
160
- ```
161
-
162
- This example shows the core routing concepts without framework dependencies, making it ideal for understanding how @xmachines/play-router integrates with browser History API.
163
-
164
- ## Canonical Watcher Lifecycle
165
-
166
- Bridge implementations should use one watcher flow:
167
-
168
- 1. `notify`
169
- 2. `queueMicrotask`
170
- 3. `getPending()`
171
- 4. read actor route and sync infrastructure state
172
- 5. re-arm with `watch(...)` or `watch()`
173
-
174
- Watcher notification is one-shot; re-arm is required.
175
-
176
- ## Bridge Cleanup Contract
177
-
178
- Bridge teardown must be explicit and deterministic:
179
-
180
- - `disconnect`/`dispose` must unwatch signal subscriptions and unhook router listeners.
181
- - Do not rely on GC-only cleanup guidance.
182
- - Infrastructure remains passive: bridges observe and forward intents, actors decide validity.
183
- - `createBrowserHistory().destroy()` (from `@xmachines/play-dom-router`) is idempotent and restores shared `window.history` patches only after the last wrapper for that window is removed.
184
- - **Note**: `createBrowserHistory()` mutates global `window.history` methods (`pushState` and `replaceState`) and coordinates wrappers with shared ref-count state. To reduce leakage, create one history wrapper per browser window at the application boundary and always pair it with `destroy()` during teardown.
185
-
186
- ## Bridge Sync Ordering
187
-
188
- `RouterBridgeBase.connect()` has an intentional ordering contract used by all framework adapters:
189
-
190
- - seed `lastSyncedPath` from `actor.currentRoute` in the constructor
191
- - install the actor route watcher
192
- - install adapter router subscriptions
193
- - resolve initial sync using `getInitialRouterPath()` and `actor.initialRoute`
194
-
195
- That final step distinguishes:
196
-
197
- - **deep-link:** browser URL differs from the machine's initial route, so router wins and the actor receives `play.route`
198
- - **restore:** browser URL is still at the machine's initial route while the actor was restored elsewhere, so actor wins and the bridge pushes the actor route back into the router
199
-
200
- Actor-originated router sync suppresses router echoes via `lastSyncedPath`. `syncRouterFromActor` resolves the concrete path and stores it before calling the adapter's navigation method; when the router callback fires with that same path, `syncActorFromRouter` short-circuits at `sanitized === lastSyncedPath` and sends no event.
201
-
202
- ## Diagnostics
203
-
204
- Router infrastructure reports runtime failures through `PlayDiagnostics` from `@xmachines/play`.
205
-
206
- - Default behavior uses `consoleDiagnostics`.
207
- - Messages follow a stable `[scope:code] message` format.
208
- - Example: `[RouterBridgeBase:PLAY_ROUTER_SYNC_FAILED] Failed to sync actor state from router location.`
209
-
210
- This keeps router errors observable while letting applications swap in their own diagnostics implementation upstream.
211
-
212
- ## API Reference
213
-
214
- ### extractMachineRoutes()
215
-
216
- Main entry point — crawls state machine, extracts routes, builds tree:
217
-
218
- ```typescript
219
- const tree = extractMachineRoutes(machine: AnyStateMachine): RouteTree;
220
123
  ```
221
124
 
222
- **Detection:**
125
+ ### Implementing a `RouterBridgeBase` adapter
223
126
 
224
- - States with `meta.route` in meta object
225
-
226
- **Returns:** `RouteTree` with:
227
-
228
- - `byPath: Map<string, RouteNode>` — URL path → route node
229
- - `byStateId: Map<string, RouteNode>` — State ID → route node
230
- - `root: RouteNode` — synthetic root node
231
- - `graph: MachineGraph` — `@statelyai/graph` Graph for hierarchy queries, reachability checks, and transition-aware navigation
232
-
233
- **Throws:** Error if routes are invalid (malformed paths, missing state IDs, duplicates)
234
-
235
- **Example:**
236
-
237
- ```typescript
238
- import { extractMachineRoutes } from "@xmachines/play-router";
239
-
240
- const tree = extractMachineRoutes(authMachine);
241
-
242
- // Query routes — use fullPath for URL matching (path is the raw meta.route segment)
243
- const loginRoute = tree.byStateId.get("login");
244
- console.log(loginRoute?.fullPath); // "/login"
245
- console.log(loginRoute?.path); // "/login" (same for absolute routes)
246
-
247
- // For nested relative routes the distinction matters:
248
- // meta.route: "overview" under "/dashboard" → path: "overview", fullPath: "/dashboard/overview"
249
- const overviewRoute = tree.byStateId.get("overview");
250
- console.log(overviewRoute?.path); // "overview" (raw segment — relative)
251
- console.log(overviewRoute?.fullPath); // "/dashboard/overview" (resolved — use this)
252
-
253
- const dashboardRoute = tree.byPath.get("/dashboard");
254
- console.log(dashboardRoute?.id); // "dashboard"
255
- ```
256
-
257
- ### machineToGraph()
258
-
259
- Converts an XState v5 machine to a typed `@statelyai/graph` `Graph`:
127
+ Extend `RouterBridgeBase` and implement the three abstract methods for your framework:
260
128
 
261
129
  ```typescript
262
- import { machineToGraph } from "@xmachines/play-router";
263
- import { getChildren, getSuccessors, hasPath } from "@statelyai/graph";
264
-
265
- const graph = machineToGraph(machine);
266
-
267
- // Hierarchy queries
268
- const children = getChildren(graph, "myMachine");
269
- const successors = getSuccessors(graph, "myMachine.home"); // transition-reachable states
270
-
271
- // Reachability
272
- const reachable = hasPath(graph, "myMachine.home", "myMachine.dashboard");
273
- ```
274
-
275
- The graph is also available on any `RouteTree` returned by `extractMachineRoutes()`:
276
-
277
- ```typescript
278
- const tree = extractMachineRoutes(machine);
279
-
280
- // Use @statelyai/graph algorithms directly on the graph
281
- const successors = getSuccessors(tree.graph!, "myMachine.home");
282
- ```
283
-
284
- **Node data** (`MachineNodeData`):
285
-
286
- - `stateId: string` — XState state ID (e.g., `"myMachine.dashboard.overview"`)
287
- - `type` — `"atomic" | "compound" | "parallel" | "final" | "history"`
288
- - `meta?: Record<string, unknown>` — original state meta object
289
- - `route?: string` — extracted route path from `meta.route`
130
+ import { RouterBridgeBase } from "@xmachines/play-router";
131
+ import type { AbstractActor, Routable } from "@xmachines/play-actor";
132
+ import type { AnyActorLogic } from "xstate";
133
+
134
+ export class MyRouterBridge extends RouterBridgeBase {
135
+ private unsubscribe: (() => void) | null = null;
136
+
137
+ constructor(
138
+ private readonly myRouter: MyRouter,
139
+ actor: AbstractActor<AnyActorLogic> & Routable,
140
+ routeMap: ReturnType<typeof createRouteMap>,
141
+ ) {
142
+ super(actor, routeMap);
143
+ }
290
144
 
291
- **Edge data** (`MachineEdgeData`):
145
+ // Tell the framework router to navigate to a path
146
+ protected navigateRouter(path: string): void {
147
+ this.myRouter.navigate(path);
148
+ }
292
149
 
293
- - `eventType: string` event type triggering this transition
294
- - `guardType?: string` — guard name/description (if transition is guarded)
150
+ // Subscribe to router location changes, call syncActorFromRouter on each
151
+ protected watchRouterChanges(): void {
152
+ this.unsubscribe = this.myRouter.subscribe((location) => {
153
+ this.syncActorFromRouter(location.pathname, location.search);
154
+ });
155
+ }
295
156
 
296
- ### createRouteMap() / createRouteMapFromTree()
157
+ // Unsubscribe from router location changes
158
+ protected unwatchRouterChanges(): void {
159
+ this.unsubscribe?.();
160
+ this.unsubscribe = null;
161
+ }
297
162
 
298
- Both build a `BaseRouteMap` using `node.fullPath` (absolute resolved paths) for browser URL matching.
163
+ // Provide the router's current path for initial deep-link sync
164
+ protected override getInitialRouterPath(): string {
165
+ return this.myRouter.state.location.pathname;
166
+ }
167
+ }
299
168
 
300
- ```typescript
301
- // Single-call form — preferred for XState machines:
302
- import { createRouteMap } from "@xmachines/play-router";
169
+ // Usage
303
170
  const routeMap = createRouteMap(machine);
304
-
305
- // Two-step form — used by framework adapter packages:
306
- import { extractMachineRoutes, createRouteMapFromTree } from "@xmachines/play-router";
307
- const routeTree = extractMachineRoutes(machine);
308
- const routeMap = createRouteMapFromTree(routeTree);
171
+ const bridge = new MyRouterBridge(myRouter, actor, routeMap);
172
+ bridge.connect();
173
+ // ...
174
+ bridge.disconnect();
309
175
  ```
310
176
 
311
- Both forms produce identical `RouteMap` results. `createRouteMapFromTree` is exposed for framework adapters (React Router, TanStack Router) that already hold the `RouteTree` separately for other purposes (e.g. graph queries). `createRouteMatcher(routeTree)` is the distinct API for URL-pattern matching that returns a `RouteMatcher`, not a `RouteMap`.
312
-
313
- **`node.path` vs `node.fullPath`:** Every `RouteNode` carries both fields. `path` is the raw `meta.route` segment as declared in the machine — it may be relative (e.g. `"overview"`). `fullPath` is the resolved absolute path (e.g. `"/dashboard/overview"`). Route maps always use `fullPath`. Only use `path` if you specifically need the declared segment.
314
-
315
- ### Query Utilities
177
+ ## API Summary
316
178
 
317
- ```typescript
318
- import {
319
- getNavigableRoutes,
320
- getRoutableRoutes,
321
- routeExists,
322
- getTransitionReachableRoutes,
323
- isRouteReachable,
324
- } from "@xmachines/play-router";
179
+ ### Route Extraction
325
180
 
326
- // Child routes (hierarchical + transition-reachable)
327
- const navigable = getNavigableRoutes(tree, "dashboard");
181
+ | Export | Description |
182
+ | ---------------------------------------- | ---------------------------------------------------------------------------------- |
183
+ | `extractMachineRoutes(machine)` | Convert an XState machine to a `RouteTree` with bidirectional state ID ↔ path maps |
184
+ | `createRouteMap(machine, options?)` | Build a `RouteMap` directly from a machine (preferred form for adapters) |
185
+ | `createRouteMapFromTree(tree, options?)` | Build a `RouteMap` from an already-extracted `RouteTree` |
186
+ | `buildRouteTree(routes)` | Build a `RouteTree` from an array of `RouteInfo` objects |
187
+ | `machineToGraph(machine)` | Convert a machine to a typed `@statelyai/graph` `Graph` for graph algorithm access |
328
188
 
329
- // All routable routes as flat array
330
- const allRoutes = getRoutableRoutes(tree);
189
+ ### Route Matching
331
190
 
332
- // Check path exists
333
- const exists = routeExists(tree, "/profile/:userId");
191
+ | Export | Description |
192
+ | ----------------------------- | ------------------------------------------------------------------------------------------ |
193
+ | `createRouteMatcher(tree)` | Create a `RouteMatcher` that matches URL paths to `#stateId` values and extracts params |
194
+ | `RouteMap` | Bidirectional `stateId ↔ path` lookup class; supports O(1) exact and O(k) pattern matching |
195
+ | `findRouteById(tree, id)` | Look up a `RouteNode` by state ID |
196
+ | `findRouteByPath(tree, path)` | Look up a `RouteNode` by URL path (supports dynamic patterns) |
334
197
 
335
- // Transition-aware: which state IDs are reachable via transitions?
336
- const reachableIds = getTransitionReachableRoutes(tree.graph!, "myMachine.home");
337
-
338
- // Is there any path from state A to state B via transitions?
339
- const canReach = isRouteReachable(tree.graph!, "myMachine.home", "myMachine.dashboard");
340
- ```
341
-
342
- ## Examples
343
-
344
- ### Route Detection
345
-
346
- ```typescript
347
- import { extractMachineRoutes, findRouteByPath } from "@xmachines/play-router";
348
- import { createMachine } from "xstate";
349
-
350
- const machine = createMachine({
351
- initial: "home",
352
- states: {
353
- home: {
354
- id: "home",
355
- meta: { route: "/", view: { component: "Home" } },
356
- },
357
- profile: {
358
- id: "profile",
359
- meta: { route: "/profile/:userId", view: { component: "Profile" } }, // Parameter pattern
360
- },
361
- settings: {
362
- id: "settings",
363
- meta: { route: "/settings/:section?", view: { component: "Settings" } }, // Optional parameter
364
- },
365
- },
366
- });
367
-
368
- const tree = extractMachineRoutes(machine);
369
-
370
- // Bidirectional mapping — use fullPath for URLs; path is the raw meta.route segment
371
- const profileById = tree.byStateId.get("profile");
372
- console.log(profileById?.fullPath); // "/profile/:userId"
373
-
374
- const profileByPath = findRouteByPath(tree, "/profile/user123");
375
- console.log(profileByPath?.id); // "profile"
376
- ```
377
-
378
- ### Hierarchical Route Tree
379
-
380
- ```typescript
381
- import { extractMachineRoutes, getNavigableRoutes } from "@xmachines/play-router";
382
-
383
- const machine = createMachine({
384
- initial: "app",
385
- states: {
386
- app: {
387
- id: "app",
388
- meta: { route: "/", view: { component: "AppShell" } },
389
- initial: "dashboard",
390
- states: {
391
- dashboard: {
392
- id: "dashboard",
393
- meta: { route: "/dashboard", view: { component: "Dashboard" } },
394
- initial: "overview",
395
- states: {
396
- overview: {
397
- id: "overview",
398
- meta: { route: "/overview", view: { component: "Overview" } },
399
- },
400
- analytics: {
401
- id: "analytics",
402
- meta: { route: "/analytics", view: { component: "Analytics" } },
403
- },
404
- },
405
- },
406
- },
407
- },
408
- },
409
- });
410
-
411
- const tree = extractMachineRoutes(machine);
412
-
413
- // Get child routes
414
- const dashboardChildren = getNavigableRoutes(tree, "dashboard");
415
- console.log(dashboardChildren.map((r) => r.id)); // ["overview", "analytics"]
416
-
417
- // Route inheritance
418
- const analyticsRoute = tree.byStateId.get("analytics");
419
- console.log(analyticsRoute?.fullPath); // "/analytics" (absolute route)
420
- ```
198
+ ### Query Utilities
421
199
 
422
- ### Pattern Matching
200
+ | Export | Description |
201
+ | ------------------------------------------------- | ------------------------------------------------------------------------- |
202
+ | `getRoutableRoutes(tree)` | All routable `RouteNode`s as a flat array |
203
+ | `getNavigableRoutes(tree, stateId)` | Child routes reachable from a state (hierarchical + transition-reachable) |
204
+ | `routeExists(tree, path)` | Check whether a path is registered in the tree |
205
+ | `getTransitionReachableRoutes(graph, stateId)` | Route paths reachable via XState transitions from a state |
206
+ | `isRouteReachable(graph, fromStateId, toStateId)` | Check whether a transition path exists between two states |
207
+
208
+ ### Router Bridge
209
+
210
+ | Export | Description |
211
+ | --------------------------------------- | ------------------------------------------------------------------------------------- |
212
+ | `RouterBridgeBase` | Abstract base class for framework router adapters; implements `RouterBridge` protocol |
213
+ | `sanitizePathname(path)` | Normalize a raw pathname; returns `null` for paths > 2048 chars or malformed input |
214
+ | `buildPlayRouteEvent(options)` | Build a `PlayRouteEvent` from a pathname + route-map match result |
215
+ | `extractRouteParams(pathname, pattern)` | Extract path parameters from a URL using URLPattern |
216
+ | `extractQuery(search)` | Extract query parameters from a URL search string |
217
+
218
+ ### Validation
219
+
220
+ | Export | Description |
221
+ | ---------------------------------------- | ------------------------------------------------- |
222
+ | `validateRouteFormat(route, stateId)` | Assert route path is non-empty |
223
+ | `validateStateExists(stateId, stateIds)` | Assert a state ID is present in the machine graph |
224
+ | `detectDuplicateRoutes(routes)` | Throw if any two states share the same URL path |
225
+
226
+ ### Key Types
227
+
228
+ | Export | Description |
229
+ | ---------------------------------- | -------------------------------------------------------------------------------------- |
230
+ | `RouterBridge` | Interface for `connect()` / `disconnect()` lifecycle |
231
+ | `RouteTree` | Hierarchical tree with `root`, `byStateId`, `byPath`, and optional `graph` |
232
+ | `RouteNode` | Single node in the tree with `id`, `path`, `fullPath`, `stateId`, `children`, `parent` |
233
+ | `RouteInfo` | Flat route descriptor extracted from a state node |
234
+ | `PlayRouteEvent` | Routing event `{ type: "play.route", to, params?, query? }` |
235
+ | `RouteMapping` | `{ stateId, path }` pair used to build a `RouteMap` |
236
+ | `RouteMapping as BaseRouteMapping` | Alias for `RouteMapping` (backwards-compat re-export) |
237
+ | `MachineGraph` | Typed `@statelyai/graph` Graph with `MachineNodeData` / `MachineEdgeData` |
238
+ | `WindowLike` | Injectable minimal `window` interface for SSR / testing |
239
+ | `LocationLike` | Injectable minimal `location` interface for SSR / testing |
240
+
241
+ ### Errors (subpath `@xmachines/play-router/errors`)
242
+
243
+ | Class | Code | When thrown |
244
+ | ---------------------------- | --------------------------------------- | ----------------------------------------------------------------- |
245
+ | `RouterSyncError` | `PLAY_ROUTER_SYNC_FAILED` | `syncActorFromRouter()` fails to send a `play.route` event |
246
+ | `DuplicateBridgeError` | `PLAY_ROUTER_DUPLICATE_BRIDGE` | A second bridge tries to connect to an actor that already has one |
247
+ | `URLPatternUnavailableError` | `PLAY_ROUTE_MAP_URLPATTERN_UNAVAILABLE` | URLPattern API is absent and no polyfill is loaded |
248
+ | `InvalidRoutePatternError` | `PLAY_ROUTE_MAP_INVALID_PATTERN` | A route pattern string is rejected by the URLPattern constructor |
249
+ | `EmptyRoutePathError` | `PLAY_ROUTE_EMPTY_PATH` | A state declares `meta.route: ""` |
250
+ | `InvalidStateIdError` | `PLAY_ROUTE_INVALID_STATE_ID` | A route references a state ID not in the machine graph |
251
+ | `DuplicateRoutePathError` | `PLAY_ROUTE_DUPLICATE_PATH` | Two or more states share the same URL path |
252
+ | `UnknownStateTypeError` | `PLAY_ROUTE_UNKNOWN_STATE_TYPE` | A state node has an unrecognised XState `.type` value |
423
253
 
424
254
  ```typescript
425
- import { extractMachineRoutes, findRouteByPath } from "@xmachines/play-router";
426
-
427
- const machine = createMachine({
428
- states: {
429
- user: {
430
- id: "user",
431
- meta: { route: "/user/:userId", view: { component: "User" } }, // Required parameter
432
- },
433
- settings: {
434
- id: "settings",
435
- meta: { route: "/settings/:section?", view: { component: "Settings" } }, // Optional parameter
436
- },
437
- },
438
- });
439
-
440
- const tree = extractMachineRoutes(machine);
441
-
442
- // Pattern matching for actual URLs
443
- const userRoute = findRouteByPath(tree, "/user/user123");
444
- console.log(userRoute?.id); // "user"
445
-
446
- const settingsDefault = findRouteByPath(tree, "/settings");
447
- console.log(settingsDefault?.id); // "settings" (optional param)
255
+ import {
256
+ RouterSyncError,
257
+ DuplicateBridgeError,
258
+ URLPatternUnavailableError,
259
+ } from "@xmachines/play-router/errors";
448
260
 
449
- const settingsProfile = findRouteByPath(tree, "/settings/profile");
450
- console.log(settingsProfile?.id); // "settings" (with param)
261
+ try {
262
+ bridge.connect();
263
+ } catch (err) {
264
+ if (err instanceof DuplicateBridgeError) {
265
+ // Actor already bridged — call disconnect() first
266
+ } else if (err instanceof RouterSyncError) {
267
+ console.error("Router sync failed:", err.message, err.cause);
268
+ }
269
+ }
451
270
  ```
452
271
 
453
272
  ## Route Configuration
454
273
 
455
- ### Route Pattern (Recommended)
274
+ ### `meta.route` patterns
456
275
 
457
- ```typescript
458
- states: {
459
- dashboard: {
460
- id: "dashboard", // Required for bidirectional lookup
461
- meta: {
462
- route: "/dashboard", // URL path - marks state as routable
463
- },
464
- },
465
- }
466
- ```
467
-
468
- ### Alternative Pattern
276
+ Routes are declared on XState state nodes via the `meta.route` field:
469
277
 
470
278
  ```typescript
471
279
  states: {
472
- dashboard: {
473
- id: "dashboard",
474
- meta: {
475
- route: "/dashboard",
476
- },
477
- },
280
+ home: {
281
+ id: "home",
282
+ meta: { route: "/" }, // static route
283
+ },
284
+ profile: {
285
+ id: "profile",
286
+ meta: { route: "/profile/:userId" }, // required parameter
287
+ },
288
+ settings: {
289
+ id: "settings",
290
+ meta: { route: "/settings/:section?" }, // optional parameter
291
+ },
292
+ docs: {
293
+ id: "docs",
294
+ meta: { route: { path: "/docs", title: "Documentation" } }, // object form
295
+ },
478
296
  }
479
297
  ```
480
298
 
481
- ### Route Inheritance
299
+ ### Relative vs absolute paths
482
300
 
483
- ```typescript
484
- states: {
485
- parent: {
486
- id: "parent",
487
- meta: { route: "/parent", view: { component: "Parent" } },
488
- states: {
489
- absolute: {
490
- id: "absolute",
491
- meta: { route: "/absolute", view: { component: "Absolute" } }, // Starts with / → doesn't inherit
492
- },
493
- relative: {
494
- id: "relative",
495
- meta: { route: "relative", view: { component: "Relative" } }, // No leading / → inherits parent path prefix
496
- // Final path: "/parent/relative"
497
- },
498
- },
499
- },
500
- }
501
- ```
502
-
503
- ### Dynamic Parameters
301
+ Child routes with a leading `/` are absolute (do not inherit the parent path). Without a leading `/`, they resolve relative to their nearest routable ancestor:
504
302
 
505
303
  ```typescript
506
- meta: {
507
- route: "/profile/:userId", // Required parameter
508
- route: "/settings/:section?", // Optional parameter
509
- route: "/docs/:category/:page", // Multiple parameters
510
- view: { component: "AnyView" },
304
+ states: {
305
+ dashboard: {
306
+ id: "dashboard",
307
+ meta: { route: "/dashboard" },
308
+ states: {
309
+ overview: {
310
+ id: "overview",
311
+ meta: { route: "/overview" }, // absolute → fullPath: "/overview"
312
+ },
313
+ stats: {
314
+ id: "stats",
315
+ meta: { route: "stats" }, // relative → fullPath: "/dashboard/stats"
316
+ },
317
+ },
318
+ },
511
319
  }
512
320
  ```
513
321
 
514
- **Parameter substitution:** Values extracted from context or event params (handled by play-xstate adapter).
515
-
516
- ## Security Utilities
517
-
518
- ### `sanitizePathname()`
322
+ Always use `node.fullPath` (never `node.path`) for browser URL matching and route map construction.
519
323
 
520
- Normalize a raw pathname before route-map lookup. Used internally by `RouterBridgeBase.syncActorFromRouter()` and available to adapters that bypass the base class:
324
+ ## Testing
521
325
 
522
- ```typescript
523
- import { sanitizePathname } from "@xmachines/play-router";
524
-
525
- // In a custom adapter's route-watch callback:
526
- const clean = sanitizePathname(rawPath);
527
- if (clean === null) return; // Reject malformed/oversized paths (> 2048 chars)
528
- // Proceed with clean normalized path
529
- ```
530
-
531
- Returns `null` for paths exceeding 2048 characters. Strips query fragments, hash fragments, and collapses duplicate slashes.
532
-
533
- ---
534
-
535
- ## Error Handling
536
-
537
- All runtime errors thrown by this package extend `PlayError` from `@xmachines/play` and
538
- are exported from the `./errors` subpath:
326
+ ```bash
327
+ # Run tests for this package
328
+ npm test -w @xmachines/play-router
539
329
 
540
- ```typescript
541
- import {
542
- RouterSyncError,
543
- URLPatternUnavailableError,
544
- InvalidRoutePatternError,
545
- } from "@xmachines/play-router/errors";
330
+ # Watch mode
331
+ npm run test:watch -w @xmachines/play-router
546
332
  ```
547
333
 
548
- | Class | Code | When thrown |
549
- | ---------------------------- | --------------------------------------- | -------------------------------------------------------------- |
550
- | `RouterSyncError` | `PLAY_ROUTER_SYNC_FAILED` | `syncActorFromRouter()` fails to send a `play.route` event |
551
- | `URLPatternUnavailableError` | `PLAY_ROUTE_MAP_URLPATTERN_UNAVAILABLE` | `createRouteMap()` called before URLPattern polyfill is loaded |
552
- | `InvalidRoutePatternError` | `PLAY_ROUTE_MAP_INVALID_PATTERN` | A route pattern string is rejected by URLPattern constructor |
553
-
554
- `InvalidRoutePatternError` carries a `pattern: string` field with the offending pattern.
334
+ The package exports a router bridge contract test suite for adapter authors:
555
335
 
556
336
  ```typescript
557
- import { PlayError } from "@xmachines/play";
558
- import { RouterSyncError } from "@xmachines/play-router/errors";
337
+ import { runBridgeContractTests } from "@xmachines/play-router/test/contract.js";
559
338
 
560
- try {
561
- bridge.connect();
562
- } catch (err) {
563
- if (err instanceof RouterSyncError) {
564
- // err.cause — the original error that triggered the sync failure
565
- monitoringService.record(err);
566
- } else if (err instanceof PlayError) {
567
- console.error(`[${err.scope}:${err.code}] ${err.message}`);
568
- }
569
- }
339
+ runBridgeContractTests({
340
+ name: "MyRouterBridge",
341
+ createHarness(initialPath) {
342
+ // return ContractHarness with bridge, actor, simulateNavigation, getLastNavigatedPath
343
+ },
344
+ });
570
345
  ```
571
346
 
572
- ## Architecture
573
-
574
- This package enables **Actor Authority (INV-01)**:
575
-
576
- 1. **Routes derive from machine:** Business logic defines routes in state machine, not external config
577
- 2. **Graph-based extraction:** `machineToGraph()` converts machines to typed `@statelyai/graph` `Graph` objects with hierarchy, transition edges, and route metadata
578
- 3. **Bidirectional mapping:** Fast lookup by path (browser URL) or by state ID (state machine)
579
- 4. **Transition-aware queries:** `getTransitionReachableRoutes()` and `isRouteReachable()` use graph algorithms for navigation reachability
580
- 5. **Build-time validation:** Invalid routes throw errors during extraction, not runtime
581
-
582
- **Enhancements:**
583
-
584
- - `meta.route` detection via state metadata — extracted into typed graph node data
585
- - Pattern matching for dynamic routes (`:param` and `:param?`)
586
- - State ID ↔ path bidirectional maps for `play.route` events
587
- - `@statelyai/graph` integration — hierarchy queries, reachability checks, transition traversal
588
-
589
347
  ## Related Packages
590
348
 
591
- - **[@xmachines/play-xstate](../play-xstate/README.md)** - XState adapter using route extraction
592
- - **[@xmachines/play-tanstack-react-router](../play-tanstack-react-router/README.md)** - TanStack Router adapter using route trees
593
- - **[@xmachines/play-react-router](../play-react-router/README.md)** - React Router v7 adapter using RouterBridgeBase
594
- - **[@xmachines/play](../play/README.md)** - Protocol types
349
+ - **[@xmachines/play](../play/README.md)** Core protocol types (`PlayEvent`, `PlayError`)
350
+ - **[@xmachines/play-actor](../play-actor/README.md)** Abstract actor base class (`AbstractActor`, `Routable`)
351
+ - **[@xmachines/play-signals](../play-signals/README.md)** TC39 Signals polyfill used for actor route observation
352
+ - **[@xmachines/play-xstate](../play-xstate/README.md)** XState v5 logic adapter that integrates with route trees
353
+ - **[@xmachines/play-tanstack-react-router](../play-tanstack-react-router/README.md)** — TanStack Router adapter (React)
354
+ - **[@xmachines/play-tanstack-solid-router](../play-tanstack-solid-router/README.md)** — TanStack Router adapter (SolidJS)
355
+ - **[@xmachines/play-react-router](../play-react-router/README.md)** — React Router v7 adapter
356
+ - **[@xmachines/play-vue-router](../play-vue-router/README.md)** — Vue Router adapter
357
+ - **[@xmachines/play-solid-router](../play-solid-router/README.md)** — SolidJS Router adapter
595
358
 
596
359
  ## License
597
360
 
598
- Copyright (c) 2016 [Mikael Karon](mailto:mikael@karon.se). All rights reserved.
599
-
600
- This work is licensed under the terms of the MIT license.
601
- For a copy, see <https://opensource.org/licenses/MIT>.
361
+ MIT see [LICENSE](LICENSE).
602
362
 
603
363
  ## Classes
604
364