@xmachines/docs 1.0.0-beta.45 → 1.0.0-beta.48
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.
- package/README.md +135 -7
- package/api/@xmachines/play/README.md +134 -57
- package/api/@xmachines/play/classes/NonNullableError.md +4 -4
- package/api/@xmachines/play/classes/PlayError.md +4 -4
- package/api/@xmachines/play/functions/assertNonNullable.md +1 -1
- package/api/@xmachines/play/type-aliases/PlayEvent.md +2 -2
- package/api/@xmachines/play-actor/README.md +130 -155
- package/api/@xmachines/play-actor/classes/AbstractActor.md +3 -3
- package/api/@xmachines/play-actor/functions/typedSpec.md +1 -1
- package/api/@xmachines/play-actor/interfaces/BaseActorProviderProps.md +5 -5
- package/api/@xmachines/play-actor/interfaces/BaseViewContextValue.md +5 -5
- package/api/@xmachines/play-actor/interfaces/PlaySpec.md +2 -2
- package/api/@xmachines/play-actor/interfaces/Routable.md +3 -3
- package/api/@xmachines/play-actor/interfaces/Viewable.md +2 -2
- package/api/@xmachines/play-dom/README.md +140 -232
- package/api/@xmachines/play-dom/classes/PlayRenderer.md +4 -4
- package/api/@xmachines/play-dom/functions/connectRenderer.md +1 -1
- package/api/@xmachines/play-dom/functions/createPlayUI.md +1 -1
- package/api/@xmachines/play-dom/functions/createRenderer.md +1 -1
- package/api/@xmachines/play-dom/functions/defineRegistry.md +1 -1
- package/api/@xmachines/play-dom/functions/renderSpec.md +1 -1
- package/api/@xmachines/play-dom/interfaces/ComponentContext.md +7 -7
- package/api/@xmachines/play-dom/interfaces/ConnectRendererOptions.md +13 -13
- package/api/@xmachines/play-dom/interfaces/CreatePlayUIOptions.md +6 -6
- package/api/@xmachines/play-dom/interfaces/DefineRegistryResult.md +4 -4
- package/api/@xmachines/play-dom/interfaces/DomRenderContext.md +12 -12
- package/api/@xmachines/play-dom/interfaces/EventHandle.md +4 -4
- package/api/@xmachines/play-dom/interfaces/MountOptions.md +3 -3
- package/api/@xmachines/play-dom/interfaces/PlayDomOptions.md +5 -5
- package/api/@xmachines/play-dom/interfaces/UIProviderOptions.md +5 -5
- package/api/@xmachines/play-dom/type-aliases/ActionFn.md +1 -1
- package/api/@xmachines/play-dom/type-aliases/Actions.md +1 -1
- package/api/@xmachines/play-dom/type-aliases/BaseComponentProps.md +7 -7
- package/api/@xmachines/play-dom/type-aliases/CatalogHasActions.md +1 -1
- package/api/@xmachines/play-dom/type-aliases/ComponentFn.md +1 -1
- package/api/@xmachines/play-dom/type-aliases/ComponentRegistry.md +1 -1
- package/api/@xmachines/play-dom/type-aliases/DefineRegistryOptions.md +2 -2
- package/api/@xmachines/play-dom/type-aliases/DomComponentRenderer.md +1 -1
- package/api/@xmachines/play-dom/type-aliases/DomRegistry.md +1 -1
- package/api/@xmachines/play-dom/type-aliases/DomSchema.md +1 -1
- package/api/@xmachines/play-dom/type-aliases/MountFn.md +1 -1
- package/api/@xmachines/play-dom/type-aliases/SetState.md +1 -1
- package/api/@xmachines/play-dom/variables/schema.md +1 -1
- package/api/@xmachines/play-dom-router/README.md +160 -158
- package/api/@xmachines/play-dom-router/functions/connectRouter.md +1 -1
- package/api/@xmachines/play-dom-router/functions/createBrowserHistory.md +1 -1
- package/api/@xmachines/play-dom-router/functions/createRouteMap.md +1 -1
- package/api/@xmachines/play-dom-router/functions/createRouter.md +1 -1
- package/api/@xmachines/play-dom-router/interfaces/BrowserHistory.md +14 -14
- package/api/@xmachines/play-dom-router/interfaces/BrowserWindow.md +14 -14
- package/api/@xmachines/play-dom-router/interfaces/ConnectRouterOptions.md +4 -4
- package/api/@xmachines/play-dom-router/interfaces/PlayRouteEvent.md +6 -6
- package/api/@xmachines/play-dom-router/interfaces/RouteLookupContract.md +3 -3
- package/api/@xmachines/play-dom-router/interfaces/RouteMap.md +3 -3
- package/api/@xmachines/play-dom-router/interfaces/RouteMapOptions.md +2 -2
- package/api/@xmachines/play-dom-router/interfaces/RouteMapping.md +3 -3
- package/api/@xmachines/play-dom-router/interfaces/RouterBridge.md +3 -3
- package/api/@xmachines/play-dom-router/interfaces/VanillaRouter.md +4 -4
- package/api/@xmachines/play-dom-router/type-aliases/RoutableActor.md +1 -1
- package/api/@xmachines/play-react/README.md +109 -320
- package/api/@xmachines/play-react/classes/PlayErrorBoundary.md +5 -5
- package/api/@xmachines/play-react/functions/useActor.md +1 -1
- package/api/@xmachines/play-react/functions/usePlayView.md +1 -1
- package/api/@xmachines/play-react/functions/useSignalEffect.md +1 -1
- package/api/@xmachines/play-react/interfaces/ActorProviderProps.md +8 -8
- package/api/@xmachines/play-react/interfaces/PlayErrorBoundaryProps.md +4 -4
- package/api/@xmachines/play-react/interfaces/PlayErrorBoundaryState.md +3 -3
- package/api/@xmachines/play-react/interfaces/PlayUIProviderProps.md +8 -8
- package/api/@xmachines/play-react/interfaces/ViewContextValue.md +5 -5
- package/api/@xmachines/play-react/type-aliases/PlayActor.md +1 -1
- package/api/@xmachines/play-react/variables/ActorProvider.md +1 -1
- package/api/@xmachines/play-react/variables/PlayRenderer.md +1 -1
- package/api/@xmachines/play-react/variables/PlayUIProvider.md +1 -1
- package/api/@xmachines/play-react-router/README.md +107 -124
- package/api/@xmachines/play-react-router/classes/ReactRouterBridge.md +23 -23
- package/api/@xmachines/play-react-router/classes/RouteMap.md +4 -4
- package/api/@xmachines/play-react-router/functions/PlayRouterProvider.md +1 -1
- package/api/@xmachines/play-react-router/functions/createRouteMap.md +1 -1
- package/api/@xmachines/play-react-router/functions/createRouteMapFromTree.md +1 -1
- package/api/@xmachines/play-react-router/interfaces/PlayRouteEvent.md +6 -6
- package/api/@xmachines/play-react-router/interfaces/PlayRouterProviderProps.md +5 -5
- package/api/@xmachines/play-react-router/interfaces/RouteMapOptions.md +2 -2
- package/api/@xmachines/play-react-router/interfaces/RouteMapping.md +3 -3
- package/api/@xmachines/play-react-router/interfaces/RouterBridge.md +3 -3
- package/api/@xmachines/play-router/README.md +235 -475
- package/api/@xmachines/play-router/classes/RouteMap.md +4 -4
- package/api/@xmachines/play-router/classes/RouterBridgeBase.md +23 -23
- package/api/@xmachines/play-router/functions/buildPlayRouteEvent.md +1 -1
- package/api/@xmachines/play-router/functions/buildRouteTree.md +1 -1
- package/api/@xmachines/play-router/functions/createRouteMap.md +1 -1
- package/api/@xmachines/play-router/functions/createRouteMapFromTree.md +1 -1
- package/api/@xmachines/play-router/functions/createRouteMatcher.md +1 -1
- package/api/@xmachines/play-router/functions/detectDuplicateRoutes.md +1 -1
- package/api/@xmachines/play-router/functions/extractMachineRoutes.md +1 -1
- package/api/@xmachines/play-router/functions/extractQuery.md +1 -1
- package/api/@xmachines/play-router/functions/extractRouteParams.md +1 -1
- package/api/@xmachines/play-router/functions/findRouteById.md +1 -1
- package/api/@xmachines/play-router/functions/findRouteByPath.md +1 -1
- package/api/@xmachines/play-router/functions/getNavigableRoutes.md +1 -1
- package/api/@xmachines/play-router/functions/getRoutableRoutes.md +1 -1
- package/api/@xmachines/play-router/functions/getTransitionReachableRoutes.md +1 -1
- package/api/@xmachines/play-router/functions/isRouteReachable.md +1 -1
- package/api/@xmachines/play-router/functions/machineToGraph.md +1 -1
- package/api/@xmachines/play-router/functions/routeExists.md +1 -1
- package/api/@xmachines/play-router/functions/sanitizePathname.md +1 -1
- package/api/@xmachines/play-router/functions/validateRouteFormat.md +1 -1
- package/api/@xmachines/play-router/functions/validateStateExists.md +1 -1
- package/api/@xmachines/play-router/interfaces/BuildPlayRouteEventOptions.md +4 -4
- package/api/@xmachines/play-router/interfaces/LocationLike.md +3 -3
- package/api/@xmachines/play-router/interfaces/MachineEdgeData.md +3 -3
- package/api/@xmachines/play-router/interfaces/MachineNodeData.md +5 -5
- package/api/@xmachines/play-router/interfaces/PlayRouteEvent.md +6 -6
- package/api/@xmachines/play-router/interfaces/RouteInfo.md +8 -8
- package/api/@xmachines/play-router/interfaces/RouteMapOptions.md +2 -2
- package/api/@xmachines/play-router/interfaces/RouteMapping.md +3 -3
- package/api/@xmachines/play-router/interfaces/RouteMatch.md +3 -3
- package/api/@xmachines/play-router/interfaces/RouteMatcher.md +4 -4
- package/api/@xmachines/play-router/interfaces/RouteNode.md +10 -10
- package/api/@xmachines/play-router/interfaces/RouteObject.md +2 -2
- package/api/@xmachines/play-router/interfaces/RouteTree.md +5 -5
- package/api/@xmachines/play-router/interfaces/RouteWatcherHandle.md +3 -3
- package/api/@xmachines/play-router/interfaces/RouterBridge.md +3 -3
- package/api/@xmachines/play-router/interfaces/WindowLike.md +3 -3
- package/api/@xmachines/play-router/type-aliases/MachineGraph.md +1 -1
- package/api/@xmachines/play-router/type-aliases/RouteMetadata.md +1 -1
- package/api/@xmachines/play-signals/README.md +105 -73
- package/api/@xmachines/play-signals/functions/watchSignal.md +1 -1
- package/api/@xmachines/play-signals/interfaces/ComputedOptions.md +2 -2
- package/api/@xmachines/play-signals/interfaces/SignalComputed.md +2 -2
- package/api/@xmachines/play-signals/interfaces/SignalOptions.md +2 -2
- package/api/@xmachines/play-signals/interfaces/SignalState.md +3 -3
- package/api/@xmachines/play-signals/interfaces/SignalWatcher.md +4 -4
- package/api/@xmachines/play-signals/type-aliases/WatcherNotify.md +1 -1
- package/api/@xmachines/play-solid/README.md +117 -263
- package/api/@xmachines/play-solid/functions/useActor.md +1 -1
- package/api/@xmachines/play-solid/functions/usePlayView.md +1 -1
- package/api/@xmachines/play-solid/interfaces/ActorProviderProps.md +8 -8
- package/api/@xmachines/play-solid/interfaces/PlayUIProviderProps.md +8 -8
- package/api/@xmachines/play-solid/interfaces/ViewContextValue.md +5 -5
- package/api/@xmachines/play-solid/type-aliases/PlayActor.md +1 -1
- package/api/@xmachines/play-solid/variables/ActorContext.md +1 -1
- package/api/@xmachines/play-solid/variables/ActorProvider.md +1 -1
- package/api/@xmachines/play-solid/variables/PlayRenderer.md +1 -1
- package/api/@xmachines/play-solid/variables/PlayUIProvider.md +1 -1
- package/api/@xmachines/play-solid-router/README.md +93 -606
- package/api/@xmachines/play-solid-router/classes/RouteMap.md +4 -4
- package/api/@xmachines/play-solid-router/classes/SolidRouterBridge.md +24 -24
- package/api/@xmachines/play-solid-router/functions/PlayRouterProvider.md +1 -1
- package/api/@xmachines/play-solid-router/functions/createRouteMap.md +1 -1
- package/api/@xmachines/play-solid-router/interfaces/AbstractActor.md +3 -3
- package/api/@xmachines/play-solid-router/interfaces/PlayRouteEvent.md +6 -6
- package/api/@xmachines/play-solid-router/interfaces/PlayRouterProviderProps.md +5 -5
- package/api/@xmachines/play-solid-router/interfaces/RouteMapOptions.md +2 -2
- package/api/@xmachines/play-solid-router/interfaces/RouteMapping.md +3 -3
- package/api/@xmachines/play-solid-router/interfaces/RouterBridge.md +3 -3
- package/api/@xmachines/play-solid-router/type-aliases/RoutableActor.md +1 -1
- package/api/@xmachines/play-solid-router/type-aliases/SolidRouterHooks.md +4 -4
- package/api/@xmachines/play-svelte/README.md +111 -103
- package/api/@xmachines/play-svelte/functions/defineRegistry.md +1 -1
- package/api/@xmachines/play-svelte/functions/getActorContext.md +1 -1
- package/api/@xmachines/play-svelte/functions/getPlayViewContext.md +1 -1
- package/api/@xmachines/play-svelte/functions/setActorContext.md +1 -1
- package/api/@xmachines/play-svelte/interfaces/ActorProviderProps.md +8 -8
- package/api/@xmachines/play-svelte/interfaces/DefineRegistryOptions.md +4 -4
- package/api/@xmachines/play-svelte/interfaces/PlayUIProviderProps.md +11 -11
- package/api/@xmachines/play-svelte/interfaces/ViewContextValue.md +5 -5
- package/api/@xmachines/play-svelte/type-aliases/PlayActor.md +1 -1
- package/api/@xmachines/play-svelte-spa-router/README.md +156 -17
- package/api/@xmachines/play-svelte-spa-router/classes/RouteMap.md +4 -4
- package/api/@xmachines/play-svelte-spa-router/functions/connectRouter.md +1 -1
- package/api/@xmachines/play-svelte-spa-router/functions/createRouteMap.md +1 -1
- package/api/@xmachines/play-svelte-spa-router/interfaces/ConnectRouterOptions.md +4 -4
- package/api/@xmachines/play-svelte-spa-router/interfaces/PlayRouteEvent.md +6 -6
- package/api/@xmachines/play-svelte-spa-router/interfaces/RouteMapOptions.md +2 -2
- package/api/@xmachines/play-svelte-spa-router/interfaces/RouteMapping.md +3 -3
- package/api/@xmachines/play-svelte-spa-router/interfaces/RouterBridge.md +3 -3
- package/api/@xmachines/play-svelte-spa-router/interfaces/WindowLike.md +3 -3
- package/api/@xmachines/play-svelte-spa-router/type-aliases/RoutableActor.md +1 -1
- package/api/@xmachines/play-sveltekit-router/README.md +168 -17
- package/api/@xmachines/play-sveltekit-router/classes/RouteMap.md +4 -4
- package/api/@xmachines/play-sveltekit-router/functions/connectRouter.md +1 -1
- package/api/@xmachines/play-sveltekit-router/functions/createRouteMap.md +1 -1
- package/api/@xmachines/play-sveltekit-router/interfaces/ConnectRouterOptions.md +4 -4
- package/api/@xmachines/play-sveltekit-router/interfaces/LocationLike.md +3 -3
- package/api/@xmachines/play-sveltekit-router/interfaces/PlayRouteEvent.md +6 -6
- package/api/@xmachines/play-sveltekit-router/interfaces/RouteMapOptions.md +2 -2
- package/api/@xmachines/play-sveltekit-router/interfaces/RouteMapping.md +3 -3
- package/api/@xmachines/play-sveltekit-router/interfaces/RouterBridge.md +3 -3
- package/api/@xmachines/play-sveltekit-router/type-aliases/RoutableActor.md +1 -1
- package/api/@xmachines/play-tanstack-react-router/README.md +147 -122
- package/api/@xmachines/play-tanstack-react-router/classes/RouteMap.md +4 -4
- package/api/@xmachines/play-tanstack-react-router/classes/TanStackReactRouterBridge.md +23 -23
- package/api/@xmachines/play-tanstack-react-router/functions/PlayRouterProvider.md +1 -1
- package/api/@xmachines/play-tanstack-react-router/functions/createRouteMap.md +1 -1
- package/api/@xmachines/play-tanstack-react-router/functions/createRouteMapFromTree.md +1 -1
- package/api/@xmachines/play-tanstack-react-router/functions/extractMachineRoutes.md +1 -1
- package/api/@xmachines/play-tanstack-react-router/interfaces/PlayRouteEvent.md +6 -6
- package/api/@xmachines/play-tanstack-react-router/interfaces/PlayRouterProviderProps.md +5 -5
- package/api/@xmachines/play-tanstack-react-router/interfaces/RouteMapOptions.md +2 -2
- package/api/@xmachines/play-tanstack-react-router/interfaces/RouteMapping.md +3 -3
- package/api/@xmachines/play-tanstack-react-router/interfaces/RouteNavigateEvent.md +3 -3
- package/api/@xmachines/play-tanstack-react-router/interfaces/RouterBridge.md +3 -3
- package/api/@xmachines/play-tanstack-react-router/type-aliases/TanStackRouterInstance.md +1 -1
- package/api/@xmachines/play-tanstack-react-router/type-aliases/TanStackRouterLike.md +4 -4
- package/api/@xmachines/play-tanstack-solid-router/README.md +195 -173
- package/api/@xmachines/play-tanstack-solid-router/classes/RouteMap.md +4 -4
- package/api/@xmachines/play-tanstack-solid-router/classes/SolidRouterBridge.md +24 -24
- package/api/@xmachines/play-tanstack-solid-router/functions/PlayRouterProvider.md +1 -1
- package/api/@xmachines/play-tanstack-solid-router/functions/createRouteMap.md +1 -1
- package/api/@xmachines/play-tanstack-solid-router/interfaces/PlayRouteEvent.md +6 -6
- package/api/@xmachines/play-tanstack-solid-router/interfaces/PlayRouterProviderProps.md +5 -5
- package/api/@xmachines/play-tanstack-solid-router/interfaces/RouteMapOptions.md +2 -2
- package/api/@xmachines/play-tanstack-solid-router/interfaces/RouteMapping.md +3 -3
- package/api/@xmachines/play-tanstack-solid-router/interfaces/RouterBridge.md +3 -3
- package/api/@xmachines/play-tanstack-solid-router/type-aliases/RoutableActor.md +1 -1
- package/api/@xmachines/play-tanstack-solid-router/type-aliases/TanStackRouterInstance.md +1 -1
- package/api/@xmachines/play-tanstack-solid-router/type-aliases/TanStackRouterLike.md +3 -3
- package/api/@xmachines/play-vue/README.md +126 -271
- package/api/@xmachines/play-vue/functions/defineRegistry.md +1 -1
- package/api/@xmachines/play-vue/functions/getPlayViewContext.md +1 -1
- package/api/@xmachines/play-vue/functions/useActor.md +1 -1
- package/api/@xmachines/play-vue/interfaces/ActorProviderProps.md +5 -5
- package/api/@xmachines/play-vue/interfaces/PlayUIProviderProps.md +8 -8
- package/api/@xmachines/play-vue/interfaces/ViewContextValue.md +5 -5
- package/api/@xmachines/play-vue/interfaces/VisibilityProviderProps.md +1 -1
- package/api/@xmachines/play-vue/type-aliases/ComponentEntry.md +1 -1
- package/api/@xmachines/play-vue/type-aliases/ComponentsMap.md +1 -1
- package/api/@xmachines/play-vue/type-aliases/DefineRegistryOptions.md +2 -2
- package/api/@xmachines/play-vue/type-aliases/PlayActor.md +1 -1
- package/api/@xmachines/play-vue/variables/PlayRenderer.md +1 -1
- package/api/@xmachines/play-vue-router/README.md +148 -528
- package/api/@xmachines/play-vue-router/classes/RouteMap.md +4 -4
- package/api/@xmachines/play-vue-router/classes/VueRouterBridge.md +24 -24
- package/api/@xmachines/play-vue-router/functions/createRouteMap.md +1 -1
- package/api/@xmachines/play-vue-router/interfaces/PlayRouteEvent.md +6 -6
- package/api/@xmachines/play-vue-router/interfaces/RouteMapOptions.md +2 -2
- package/api/@xmachines/play-vue-router/interfaces/RouteMapping.md +3 -3
- package/api/@xmachines/play-vue-router/interfaces/RouterBridge.md +3 -3
- package/api/@xmachines/play-vue-router/type-aliases/RoutableActor.md +1 -1
- package/api/@xmachines/play-vue-router/variables/PlayRouterProvider.md +1 -1
- package/api/@xmachines/play-xstate/README.md +167 -496
- package/api/@xmachines/play-xstate/classes/PlayerActor.md +12 -12
- package/api/@xmachines/play-xstate/functions/buildRouteUrl.md +1 -1
- package/api/@xmachines/play-xstate/functions/composeGuards.md +1 -1
- package/api/@xmachines/play-xstate/functions/composeGuardsOr.md +1 -1
- package/api/@xmachines/play-xstate/functions/contextFieldMatches.md +1 -1
- package/api/@xmachines/play-xstate/functions/definePlayer.md +1 -1
- package/api/@xmachines/play-xstate/functions/deriveRoute.md +1 -1
- package/api/@xmachines/play-xstate/functions/eventMatches.md +1 -1
- package/api/@xmachines/play-xstate/functions/formatPlayRouteTransitions.md +1 -1
- package/api/@xmachines/play-xstate/functions/hasContext.md +1 -1
- package/api/@xmachines/play-xstate/functions/isAbsoluteRoute.md +1 -1
- package/api/@xmachines/play-xstate/functions/negateGuard.md +1 -1
- package/api/@xmachines/play-xstate/interfaces/PlayerConfig.md +3 -3
- package/api/@xmachines/play-xstate/interfaces/PlayerFactoryResumeOptions.md +2 -2
- package/api/@xmachines/play-xstate/interfaces/PlayerOptions.md +6 -6
- package/api/@xmachines/play-xstate/interfaces/RouteContext.md +5 -5
- package/api/@xmachines/play-xstate/type-aliases/ComposedGuard.md +1 -1
- package/api/@xmachines/play-xstate/type-aliases/Guard.md +1 -1
- package/api/@xmachines/play-xstate/type-aliases/GuardArray.md +1 -1
- package/api/@xmachines/play-xstate/type-aliases/PlayerFactory.md +1 -1
- package/api/@xmachines/play-xstate/type-aliases/RouteMachineConfig.md +4 -4
- package/api/@xmachines/play-xstate/type-aliases/RouteStateNode.md +4 -4
- package/api/@xmachines/shared/README.md +81 -294
- package/api/@xmachines/shared/vite-aliases/functions/xmAliases.md +1 -1
- package/api/@xmachines/shared/vite-aliases/functions/xmCacheDir.md +1 -1
- package/api/@xmachines/shared/vite-aliases/functions/xmOptimizeDeps.md +1 -1
- package/api/@xmachines/shared/vite-aliases/functions/xmResolve.md +1 -1
- package/api/@xmachines/shared/vitest/functions/defineXmVitestConfig.md +1 -1
- package/examples/@xmachines/play-dom-demo/README.md +4 -4
- package/examples/@xmachines/play-dom-demo/functions/createNavBar.md +1 -1
- package/examples/@xmachines/play-dom-demo/functions/initShell.md +1 -1
- package/examples/@xmachines/play-dom-demo/type-aliases/AuthCatalog.md +1 -1
- package/examples/@xmachines/play-dom-demo/variables/About.md +1 -1
- package/examples/@xmachines/play-dom-demo/variables/Contact.md +1 -1
- package/examples/@xmachines/play-dom-demo/variables/Dashboard.md +1 -1
- package/examples/@xmachines/play-dom-demo/variables/Home.md +1 -1
- package/examples/@xmachines/play-dom-demo/variables/Login.md +1 -1
- package/examples/@xmachines/play-dom-demo/variables/NavBarView.md +1 -1
- package/examples/@xmachines/play-dom-demo/variables/Navigation.md +1 -1
- package/examples/@xmachines/play-dom-demo/variables/Overview.md +1 -1
- package/examples/@xmachines/play-dom-demo/variables/Profile.md +1 -1
- package/examples/@xmachines/play-dom-demo/variables/Settings.md +1 -1
- package/examples/@xmachines/play-dom-demo/variables/Stats.md +1 -1
- package/examples/@xmachines/play-dom-demo/variables/authCatalog.md +1 -1
- package/examples/@xmachines/play-dom-router-demo/README.md +3 -3
- package/examples/@xmachines/play-react-demo/README.md +2 -2
- package/examples/@xmachines/play-react-demo/functions/App.md +1 -1
- package/examples/@xmachines/play-react-demo/type-aliases/AuthCatalog.md +1 -1
- package/examples/@xmachines/play-react-demo/variables/About.md +1 -1
- package/examples/@xmachines/play-react-demo/variables/Contact.md +1 -1
- package/examples/@xmachines/play-react-demo/variables/Dashboard.md +1 -1
- package/examples/@xmachines/play-react-demo/variables/DebugPanel.md +1 -1
- package/examples/@xmachines/play-react-demo/variables/Home.md +1 -1
- package/examples/@xmachines/play-react-demo/variables/Login.md +1 -1
- package/examples/@xmachines/play-react-demo/variables/NavBar.md +1 -1
- package/examples/@xmachines/play-react-demo/variables/NavBarView.md +1 -1
- package/examples/@xmachines/play-react-demo/variables/Navigation.md +1 -1
- package/examples/@xmachines/play-react-demo/variables/Overview.md +1 -1
- package/examples/@xmachines/play-react-demo/variables/Profile.md +1 -1
- package/examples/@xmachines/play-react-demo/variables/Settings.md +1 -1
- package/examples/@xmachines/play-react-demo/variables/Shell.md +1 -1
- package/examples/@xmachines/play-react-demo/variables/Stats.md +1 -1
- package/examples/@xmachines/play-react-demo/variables/authCatalog.md +1 -1
- package/examples/@xmachines/play-react-router-demo/README.md +2 -2
- package/examples/@xmachines/play-solid-demo/README.md +2 -2
- package/examples/@xmachines/play-solid-demo/functions/App.md +1 -1
- package/examples/@xmachines/play-solid-demo/type-aliases/AuthCatalog.md +1 -1
- package/examples/@xmachines/play-solid-demo/variables/About.md +1 -1
- package/examples/@xmachines/play-solid-demo/variables/Contact.md +1 -1
- package/examples/@xmachines/play-solid-demo/variables/Dashboard.md +1 -1
- package/examples/@xmachines/play-solid-demo/variables/DebugPanel.md +1 -1
- package/examples/@xmachines/play-solid-demo/variables/Home.md +1 -1
- package/examples/@xmachines/play-solid-demo/variables/Login.md +1 -1
- package/examples/@xmachines/play-solid-demo/variables/NavBar.md +1 -1
- package/examples/@xmachines/play-solid-demo/variables/NavBarView.md +1 -1
- package/examples/@xmachines/play-solid-demo/variables/Navigation.md +1 -1
- package/examples/@xmachines/play-solid-demo/variables/Overview.md +1 -1
- package/examples/@xmachines/play-solid-demo/variables/Profile.md +1 -1
- package/examples/@xmachines/play-solid-demo/variables/Settings.md +1 -1
- package/examples/@xmachines/play-solid-demo/variables/Shell.md +1 -1
- package/examples/@xmachines/play-solid-demo/variables/Stats.md +1 -1
- package/examples/@xmachines/play-solid-demo/variables/authCatalog.md +1 -1
- package/examples/@xmachines/play-solid-router-demo/README.md +1 -1
- package/examples/@xmachines/play-svelte-demo/README.md +2 -2
- package/examples/@xmachines/play-svelte-demo/type-aliases/AuthCatalog.md +1 -1
- package/examples/@xmachines/play-svelte-demo/variables/authCatalog.md +1 -1
- package/examples/@xmachines/play-svelte-spa-router-demo/README.md +3 -3
- package/examples/@xmachines/play-sveltekit-router-demo/README.md +3 -3
- package/examples/@xmachines/play-tanstack-react-router-demo/README.md +1 -1
- package/examples/@xmachines/play-tanstack-solid-router-demo/README.md +1 -1
- package/examples/@xmachines/play-vue-demo/README.md +2 -2
- package/examples/@xmachines/play-vue-demo/type-aliases/AuthCatalog.md +1 -1
- package/examples/@xmachines/play-vue-demo/variables/App.md +1 -1
- package/examples/@xmachines/play-vue-demo/variables/authCatalog.md +1 -1
- package/examples/@xmachines/play-vue-router-demo/README.md +1 -1
- package/examples/README.md +24 -25
- package/examples/form-validation.md +2 -2
- package/guides/README.md +7 -7
- package/guides/actor-model.md +18 -18
- package/guides/architecture.md +500 -0
- package/guides/configuration.md +556 -0
- package/guides/deployment.md +336 -0
- package/guides/development.md +617 -0
- package/guides/getting-started.md +351 -142
- package/guides/signals.md +19 -19
- package/guides/state-machines.md +16 -16
- package/guides/testing.md +460 -0
- package/package.json +5 -5
- package/guides/installation.md +0 -257
package/guides/signals.md
CHANGED
|
@@ -27,7 +27,7 @@ This model is sometimes called _glitch-free reactivity_: intermediate invalid st
|
|
|
27
27
|
|
|
28
28
|
## The three Signal primitives
|
|
29
29
|
|
|
30
|
-
XMachines uses three primitives from the [TC39 Signals proposal](https://github.com/tc39/proposal-signals), accessed via `@xmachines/play-signals
|
|
30
|
+
XMachines uses three primitives from the [TC39 Signals proposal](https://github.com/tc39/proposal-signals), accessed via [`@xmachines/play-signals`](../api/@xmachines/play-signals/README.md):
|
|
31
31
|
|
|
32
32
|
### `Signal.State` — writable values
|
|
33
33
|
|
|
@@ -78,13 +78,13 @@ actor.currentRoute.get(); // initial read required to arm the watcher
|
|
|
78
78
|
|
|
79
79
|
Watcher notifications are **one-shot**: if you do not call `watch()` again after draining pending signals, you will miss subsequent changes.
|
|
80
80
|
|
|
81
|
-
Router bridges and renderers use `Signal.subtle.Watcher` internally. For most application code, the `watchSignal()` helper covers the common case.
|
|
81
|
+
Router bridges and renderers use `Signal.subtle.Watcher` internally. For most application code, the [`watchSignal()`](../api/@xmachines/play-signals/functions/watchSignal.md) helper covers the common case.
|
|
82
82
|
|
|
83
83
|
---
|
|
84
84
|
|
|
85
|
-
## `watchSignal()` — the safe helper
|
|
85
|
+
## [`watchSignal()`](../api/@xmachines/play-signals/functions/watchSignal.md) — the safe helper
|
|
86
86
|
|
|
87
|
-
`@xmachines/play-signals` exports `watchSignal(signal, onValue)` as a lifecycle-safe wrapper around the raw watcher pattern. It returns a cleanup function:
|
|
87
|
+
[`@xmachines/play-signals`](../api/@xmachines/play-signals/README.md) exports [`watchSignal(signal, onValue)`](../api/@xmachines/play-signals/functions/watchSignal.md) as a lifecycle-safe wrapper around the raw watcher pattern. It returns a cleanup function:
|
|
88
88
|
|
|
89
89
|
```typescript
|
|
90
90
|
import { watchSignal } from "@xmachines/play-signals";
|
|
@@ -97,15 +97,15 @@ const stop = watchSignal(actor.currentRoute, (route) => {
|
|
|
97
97
|
stop();
|
|
98
98
|
```
|
|
99
99
|
|
|
100
|
-
`watchSignal()` handles three subtle correctness concerns for you:
|
|
100
|
+
[`watchSignal()`](../api/@xmachines/play-signals/functions/watchSignal.md) handles three subtle correctness concerns for you:
|
|
101
101
|
|
|
102
|
-
| Concern | What happens without it | How `watchSignal` handles it
|
|
103
|
-
| ---------------------- | -------------------------------------------------- |
|
|
104
|
-
| **Use-after-free** | Callback fires after component unmounts | `disposed` flag checked before invoking callback
|
|
105
|
-
| **Coalescing** | Rapid synchronous changes cause multiple callbacks | `needsEnqueue` guard — only one microtask queued per synchronous burst
|
|
106
|
-
| **Idempotent cleanup** | Calling the cleanup twice throws | Safe to call multiple times
|
|
102
|
+
| Concern | What happens without it | How [`watchSignal`](../api/@xmachines/play-signals/functions/watchSignal.md) handles it |
|
|
103
|
+
| ---------------------- | -------------------------------------------------- | --------------------------------------------------------------------------------------- |
|
|
104
|
+
| **Use-after-free** | Callback fires after component unmounts | `disposed` flag checked before invoking callback |
|
|
105
|
+
| **Coalescing** | Rapid synchronous changes cause multiple callbacks | `needsEnqueue` guard — only one microtask queued per synchronous burst |
|
|
106
|
+
| **Idempotent cleanup** | Calling the cleanup twice throws | Safe to call multiple times |
|
|
107
107
|
|
|
108
|
-
Use `watchSignal()` in framework adapters and application code. Use the raw `Signal.subtle.Watcher` only when building infrastructure that needs to watch multiple signals independently.
|
|
108
|
+
Use [`watchSignal()`](../api/@xmachines/play-signals/functions/watchSignal.md) in framework adapters and application code. Use the raw `Signal.subtle.Watcher` only when building infrastructure that needs to watch multiple signals independently.
|
|
109
109
|
|
|
110
110
|
---
|
|
111
111
|
|
|
@@ -113,7 +113,7 @@ Use `watchSignal()` in framework adapters and application code. Use the raw `Sig
|
|
|
113
113
|
|
|
114
114
|
The XMachines architecture chose TC39 Signals over observable libraries and event emitters for three reasons:
|
|
115
115
|
|
|
116
|
-
**1. Standardization.** Signals are a Stage 1 TC39 proposal. They are not tied to any library, bundler, or framework. Isolating the polyfill behind `@xmachines/play-signals` means the entire ecosystem can migrate to native signals when the proposal lands, with a single package update.
|
|
116
|
+
**1. Standardization.** Signals are a Stage 1 TC39 proposal. They are not tied to any library, bundler, or framework. Isolating the polyfill behind [`@xmachines/play-signals`](../api/@xmachines/play-signals/README.md) means the entire ecosystem can migrate to native signals when the proposal lands, with a single package update.
|
|
117
117
|
|
|
118
118
|
**2. Synchronous atomic propagation.** RxJS streams are asynchronous by default. Event emitters fire immediately but serially — a listener registered halfway through a sequence can see inconsistent state. Signals propagate atomically: all computeds update before any watcher fires.
|
|
119
119
|
|
|
@@ -139,7 +139,7 @@ The Play RFC defines five invariants that govern how signals are used:
|
|
|
139
139
|
|
|
140
140
|
Signals do not clean themselves up when they go out of scope. Every watcher you create must be explicitly disposed when the consuming component or adapter unmounts.
|
|
141
141
|
|
|
142
|
-
- Framework lifecycle hooks (`useEffect` cleanup in React, `onUnmounted` in Vue, `onCleanup` in Solid) must call `unwatch()` or the cleanup returned by `watchSignal()
|
|
142
|
+
- Framework lifecycle hooks (`useEffect` cleanup in React, `onUnmounted` in Vue, `onCleanup` in Solid) must call `unwatch()` or the cleanup returned by [`watchSignal()`](../api/@xmachines/play-signals/functions/watchSignal.md).
|
|
143
143
|
- Router bridge `disconnect()` methods must unwatch all signal subscriptions.
|
|
144
144
|
- If you use the raw `Signal.subtle.Watcher` API, pair every `watch()` call with `unwatch()` in teardown.
|
|
145
145
|
|
|
@@ -149,12 +149,12 @@ Failing to clean up watchers causes memory leaks and stale callbacks firing afte
|
|
|
149
149
|
|
|
150
150
|
## Summary
|
|
151
151
|
|
|
152
|
-
| Primitive
|
|
153
|
-
|
|
|
154
|
-
| `Signal.State`
|
|
155
|
-
| `Signal.Computed`
|
|
156
|
-
| `Signal.subtle.Watcher`
|
|
157
|
-
| `watchSignal()`
|
|
152
|
+
| Primitive | Role in XMachines | Who uses it |
|
|
153
|
+
| -------------------------------------------------------------------------- | ---------------------------------------------- | ---------------------------------- |
|
|
154
|
+
| `Signal.State` | Actor output: writable snapshot and view state | Actor writes; infrastructure reads |
|
|
155
|
+
| `Signal.Computed` | Lazy derivations: routes, view specs | Actor defines; adapters read |
|
|
156
|
+
| `Signal.subtle.Watcher` | Low-level reactive observation | Framework adapters, router bridges |
|
|
157
|
+
| [`watchSignal()`](../api/@xmachines/play-signals/functions/watchSignal.md) | Lifecycle-safe single-signal subscription | Application code, adapter code |
|
|
158
158
|
|
|
159
159
|
## See also
|
|
160
160
|
|
package/guides/state-machines.md
CHANGED
|
@@ -24,7 +24,7 @@ In traditional component-level state (e.g., boolean flags, `useState` combinatio
|
|
|
24
24
|
|
|
25
25
|
## How XMachines uses XState v5
|
|
26
26
|
|
|
27
|
-
XMachines wraps XState v5 via `@xmachines/play-xstate
|
|
27
|
+
XMachines wraps XState v5 via [`@xmachines/play-xstate`](../api/@xmachines/play-xstate/README.md). You define machines using XState's `setup().createMachine()` API:
|
|
28
28
|
|
|
29
29
|
```typescript
|
|
30
30
|
import { setup } from "xstate";
|
|
@@ -124,13 +124,13 @@ const appMachine = setup({
|
|
|
124
124
|
|
|
125
125
|
`meta.route` is a string path. When the machine enters a state, `actor.currentRoute` (a `Signal.Computed`) derives this path and emits it. The router bridge reads it and updates the URL.
|
|
126
126
|
|
|
127
|
-
`meta.view` is a `PlaySpec` — a `@json-render/core` spec object describing what to render. Use `typedSpec<TContext>(...)` from `@xmachines/play-actor` to validate `contextProps` entries at compile time. When the machine enters a state, `actor.currentView` is updated with this spec. The renderer reads it and projects it through framework components.
|
|
127
|
+
`meta.view` is a [`PlaySpec`](../api/@xmachines/play-actor/interfaces/PlaySpec.md) — a `@json-render/core` spec object describing what to render. Use `typedSpec<TContext>(...)` from [`@xmachines/play-actor`](../api/@xmachines/play-actor/README.md) to validate `contextProps` entries at compile time. When the machine enters a state, `actor.currentView` is updated with this spec. The renderer reads it and projects it through framework components.
|
|
128
128
|
|
|
129
129
|
**The machine is the single source of truth for both routing and views.** There is no separate route configuration file. There is no switch statement in a component deciding what to render based on the URL. The state machine encodes all of that.
|
|
130
130
|
|
|
131
131
|
---
|
|
132
132
|
|
|
133
|
-
## `formatPlayRouteTransitions` — automatic route event wiring
|
|
133
|
+
## [`formatPlayRouteTransitions`](../api/@xmachines/play-xstate/functions/formatPlayRouteTransitions.md) — automatic route event wiring
|
|
134
134
|
|
|
135
135
|
For routing to work, the machine must respond to `play.route` events (sent by router bridges when the user navigates). Writing these transitions by hand is mechanical:
|
|
136
136
|
|
|
@@ -150,7 +150,7 @@ states: {
|
|
|
150
150
|
}
|
|
151
151
|
```
|
|
152
152
|
|
|
153
|
-
`formatPlayRouteTransitions` from `@xmachines/play-xstate` generates these transitions automatically from the `id` and `meta.route` fields you already have:
|
|
153
|
+
[`formatPlayRouteTransitions`](../api/@xmachines/play-xstate/functions/formatPlayRouteTransitions.md) from [`@xmachines/play-xstate`](../api/@xmachines/play-xstate/README.md) generates these transitions automatically from the `id` and `meta.route` fields you already have:
|
|
154
154
|
|
|
155
155
|
```typescript
|
|
156
156
|
import { formatPlayRouteTransitions } from "@xmachines/play-xstate";
|
|
@@ -170,7 +170,7 @@ const appMachine = setup({
|
|
|
170
170
|
);
|
|
171
171
|
```
|
|
172
172
|
|
|
173
|
-
`formatPlayRouteTransitions` inspects all state nodes with a `meta.route` and generates the corresponding `play.route` guard transitions. The machine's context must include `params` and `query` fields (populated by the router bridge when params or query strings are present):
|
|
173
|
+
[`formatPlayRouteTransitions`](../api/@xmachines/play-xstate/functions/formatPlayRouteTransitions.md) inspects all state nodes with a `meta.route` and generates the corresponding `play.route` guard transitions. The machine's context must include `params` and `query` fields (populated by the router bridge when params or query strings are present):
|
|
174
174
|
|
|
175
175
|
```typescript
|
|
176
176
|
types: {
|
|
@@ -202,16 +202,16 @@ Guards are evaluated by XState before a transition fires. If the guard returns `
|
|
|
202
202
|
|
|
203
203
|
This is the **Actor Authority** invariant in practice: the machine decides, infrastructure adjusts.
|
|
204
204
|
|
|
205
|
-
XMachines provides guard combinators in `@xmachines/play-xstate` for composing complex conditions:
|
|
205
|
+
XMachines provides guard combinators in [`@xmachines/play-xstate`](../api/@xmachines/play-xstate/README.md) for composing complex conditions:
|
|
206
206
|
|
|
207
|
-
| Function
|
|
208
|
-
|
|
|
209
|
-
| `composeGuards(...guards)`
|
|
210
|
-
| `composeGuardsOr(...guards)`
|
|
211
|
-
| `negateGuard(guard)`
|
|
212
|
-
| `hasContext(key)`
|
|
213
|
-
| `contextFieldMatches(key, value)` | Checks a context field against a value |
|
|
214
|
-
| `eventMatches(type)`
|
|
207
|
+
| Function | What it does |
|
|
208
|
+
| --------------------------------------------------------------------------------------------------- | --------------------------------------- |
|
|
209
|
+
| [`composeGuards(...guards)`](../api/@xmachines/play-xstate/functions/composeGuards.md) | AND — all guards must pass |
|
|
210
|
+
| [`composeGuardsOr(...guards)`](../api/@xmachines/play-xstate/functions/composeGuardsOr.md) | OR — any guard must pass |
|
|
211
|
+
| [`negateGuard(guard)`](../api/@xmachines/play-xstate/functions/negateGuard.md) | NOT — inverts the guard result |
|
|
212
|
+
| [`hasContext(key)`](../api/@xmachines/play-xstate/functions/hasContext.md) | Checks that a context field is non-null |
|
|
213
|
+
| [`contextFieldMatches(key, value)`](../api/@xmachines/play-xstate/functions/contextFieldMatches.md) | Checks a context field against a value |
|
|
214
|
+
| [`eventMatches(type)`](../api/@xmachines/play-xstate/functions/eventMatches.md) | Checks the event type |
|
|
215
215
|
|
|
216
216
|
---
|
|
217
217
|
|
|
@@ -261,7 +261,7 @@ actor.start();
|
|
|
261
261
|
// Actor resumes from where it left off
|
|
262
262
|
```
|
|
263
263
|
|
|
264
|
-
`definePlayer` accepts an optional `restore` argument for this purpose. Restoration is useful for server-side rendering (hydrate with the server's snapshot), session persistence (resume after page reload), and testing (start from a known mid-flow state).
|
|
264
|
+
[`definePlayer`](../api/@xmachines/play-xstate/functions/definePlayer.md) accepts an optional `restore` argument for this purpose. Restoration is useful for server-side rendering (hydrate with the server's snapshot), session persistence (resume after page reload), and testing (start from a known mid-flow state).
|
|
265
265
|
|
|
266
266
|
---
|
|
267
267
|
|
|
@@ -283,6 +283,6 @@ actor.start();
|
|
|
283
283
|
- [Understanding TC39 Signals](signals.md) — how the actor's state is observed by infrastructure
|
|
284
284
|
- [Getting Started](getting-started.md) — step-by-step walkthrough building your first machine and actor
|
|
285
285
|
- [Routing Patterns](../examples/routing-patterns.md) — worked examples of `meta.route` and guards
|
|
286
|
-
- [@xmachines/play-xstate README](../api/@xmachines/play-xstate/README.md) — full API reference for `definePlayer
|
|
286
|
+
- [@xmachines/play-xstate README](../api/@xmachines/play-xstate/README.md) — full API reference for [`definePlayer`](../api/@xmachines/play-xstate/functions/definePlayer.md), [`PlayerActor`](../api/@xmachines/play-xstate/classes/PlayerActor.md), guard combinators
|
|
287
287
|
- [XState v5 documentation](https://stately.ai/docs/xstate) — upstream state machine library documentation
|
|
288
288
|
- [Play RFC](../rfc/play.md) — complete architectural specification
|
|
@@ -0,0 +1,460 @@
|
|
|
1
|
+
<!-- generated-by: gsd-doc-writer -->
|
|
2
|
+
|
|
3
|
+
# Testing
|
|
4
|
+
|
|
5
|
+
This document describes the test framework, test organization, how to run tests, and patterns used across the XMachines JS monorepo.
|
|
6
|
+
|
|
7
|
+
## Test Framework and Setup
|
|
8
|
+
|
|
9
|
+
**Runner:** [Vitest](https://vitest.dev/) `^4.1.4`
|
|
10
|
+
|
|
11
|
+
**Assertion library:** Vitest built-in `expect` + `@testing-library/jest-dom` matchers (auto-injected via shared setup)
|
|
12
|
+
|
|
13
|
+
**Coverage provider:** `@vitest/coverage-v8`
|
|
14
|
+
|
|
15
|
+
All packages use [`defineXmVitestConfig`](../api/@xmachines/shared/vitest/functions/defineXmVitestConfig.md) from [`@xmachines/shared/vitest`](../api/@xmachines/shared/vitest/README.md) — a factory that wraps `mergeConfig` and automatically injects shared setup files:
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
// packages/<name>/vitest.config.ts
|
|
19
|
+
import { defineXmVitestConfig } from "@xmachines/shared/vitest";
|
|
20
|
+
|
|
21
|
+
export default defineXmVitestConfig(import.meta.url, {
|
|
22
|
+
test: {
|
|
23
|
+
environment: "node", // or "jsdom" for UI renderer packages
|
|
24
|
+
include: ["test/**/*.spec.ts", "test/**/*.test.ts"],
|
|
25
|
+
exclude: ["node_modules/**"],
|
|
26
|
+
coverage: {
|
|
27
|
+
provider: "v8",
|
|
28
|
+
reporter: ["text", "html", "json-summary"],
|
|
29
|
+
include: ["src/**/*.ts"],
|
|
30
|
+
exclude: ["test/**/*", "**/*.test.ts", "**/*.d.ts", "dist/**/*"],
|
|
31
|
+
all: true,
|
|
32
|
+
thresholds: { lines: 90, functions: 90, branches: 85, statements: 90 },
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
**Auto-injected setup files:**
|
|
39
|
+
|
|
40
|
+
| File | When injected | Purpose |
|
|
41
|
+
| --------------------------------------------- | ------------------------ | ------------------------------------------------------- |
|
|
42
|
+
| `packages/shared/config/vitest.node.setup.ts` | All non-browser projects | Validates Node.js ≥ 22 runtime; throws if wrong runtime |
|
|
43
|
+
| `packages/shared/config/vitest.setup.ts` | All projects | Imports `@testing-library/jest-dom/vitest` matchers |
|
|
44
|
+
|
|
45
|
+
**Test environments by package type:**
|
|
46
|
+
|
|
47
|
+
| Environment | Packages |
|
|
48
|
+
| ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
49
|
+
| `node` | Core logic: [`@xmachines/play`](../api/@xmachines/play/README.md), `play-actor`, `play-signals`, `play-xstate`, `play-router`, router adapters |
|
|
50
|
+
| `jsdom` | UI renderers: [`@xmachines/play-react`](../api/@xmachines/play-react/README.md), `play-vue`, `play-solid`, `play-svelte`, `play-dom` |
|
|
51
|
+
| Browser (Playwright/Chromium) | Browser-specific and E2E demo tests |
|
|
52
|
+
|
|
53
|
+
## Running Tests
|
|
54
|
+
|
|
55
|
+
### All unit tests (node + jsdom)
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
npm test
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Runs `vitest run` across all 30+ package-level projects defined in `vitest.config.ts`.
|
|
62
|
+
|
|
63
|
+
### Watch mode (development)
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
npm run test:watch
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Runs `vitest` in interactive watch mode. Re-runs affected test files on save.
|
|
70
|
+
|
|
71
|
+
### Browser tests (Playwright/Chromium)
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
npm run test:browser
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Runs `vitest run --config vitest.browser.config.ts`. Executes all `*.browser.test.ts(x)` files in real Chromium via `@vitest/browser-playwright`. Covers browser-specific APIs (history, URLPattern, DOM events, real microtask timing) and full-application E2E flows in demo packages.
|
|
78
|
+
|
|
79
|
+
### Coverage
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
npm run test:coverage # Run all tests with coverage (text + html + json-summary)
|
|
83
|
+
npm run coverage:report # HTML coverage report
|
|
84
|
+
npm run coverage:summary # JSON summary for CI
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Type-checking test files
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
npm run test:build
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Runs `tsc --build tsconfig.test.json` — compiles test files (including `.typecheck.ts` files in `src/`) without executing them. This is the mechanism for catching compile-time type safety failures.
|
|
94
|
+
|
|
95
|
+
### Per-package tests (workspace)
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
npm test -w packages/play-xstate
|
|
99
|
+
npm run test:coverage -w packages/play-react
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Test File Organization
|
|
103
|
+
|
|
104
|
+
Tests live in a separate `test/` directory within each package — never co-located with source files.
|
|
105
|
+
|
|
106
|
+
```
|
|
107
|
+
packages/<name>/
|
|
108
|
+
├── src/
|
|
109
|
+
│ ├── *.ts
|
|
110
|
+
│ └── *.typecheck.ts # Compile-time-only type assertions (not Vitest tests)
|
|
111
|
+
└── test/
|
|
112
|
+
├── *.spec.ts # Protocol enforcement and type-safety tests
|
|
113
|
+
├── *.test.ts # Unit, integration, and behavioral tests
|
|
114
|
+
├── browser/
|
|
115
|
+
│ └── *.browser.test.ts(x) # Playwright browser environment tests
|
|
116
|
+
├── fixtures/ # Shared test actors, helpers, mock data
|
|
117
|
+
└── tsconfig.json # Test-specific tsconfig (extends shared/tsconfig-test)
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
**File naming conventions:**
|
|
121
|
+
|
|
122
|
+
| Extension | Purpose |
|
|
123
|
+
| ---------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
|
|
124
|
+
| `.spec.ts` | Protocol enforcement tests; compile-time type safety tests; used in core packages (`play`, `play-actor`, `play-signals`, `play-xstate`) |
|
|
125
|
+
| `.test.ts` | Unit, integration, and behavioral tests; used across all packages |
|
|
126
|
+
| `.browser.test.ts` / `.browser.test.tsx` | Playwright browser environment tests; excluded from standard `vitest.config.ts`, only run via `vitest.browser.config.ts` |
|
|
127
|
+
| `.typecheck.ts` (in `src/`) | Compile-time-only type assertion files; not Vitest test files; validated by `npm run test:build` |
|
|
128
|
+
| `router-bridge-contract.ts` | Shared contract test runner; not a test file itself; imported by adapter test files |
|
|
129
|
+
|
|
130
|
+
## Writing New Tests
|
|
131
|
+
|
|
132
|
+
### Unit and integration tests
|
|
133
|
+
|
|
134
|
+
Place new test files in the package's `test/` directory. Use `.test.ts` for standard tests and `.spec.ts` for protocol/type-safety tests in core packages.
|
|
135
|
+
|
|
136
|
+
**Basic test structure:**
|
|
137
|
+
|
|
138
|
+
```typescript
|
|
139
|
+
import { describe, it, test, expect, vi, beforeEach, afterEach } from "vitest";
|
|
140
|
+
|
|
141
|
+
describe("ClassName or functionName()", () => {
|
|
142
|
+
describe("feature group or scenario", () => {
|
|
143
|
+
test("specific behavior being verified", () => {
|
|
144
|
+
// arrange
|
|
145
|
+
const actor = createMockActor("/");
|
|
146
|
+
|
|
147
|
+
// act
|
|
148
|
+
actor.send({ type: "play.route", to: "#about" });
|
|
149
|
+
|
|
150
|
+
// assert
|
|
151
|
+
expect(actor.currentRoute.get()).toBe("/about");
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
});
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
**Import style:** Always use `.js` extensions in imports (ESM requirement):
|
|
158
|
+
|
|
159
|
+
```typescript
|
|
160
|
+
import { AbstractActor } from "../src/abstract-actor.js";
|
|
161
|
+
import { Signal } from "@xmachines/play-signals";
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
**`it` vs `test`:** Both are interchangeable. Some files alias one to the other for consistency within a file:
|
|
165
|
+
|
|
166
|
+
```typescript
|
|
167
|
+
import { it as test } from "vitest";
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### Lifecycle hooks
|
|
171
|
+
|
|
172
|
+
```typescript
|
|
173
|
+
beforeEach(() => {
|
|
174
|
+
vi.spyOn(console, "error").mockImplementation(() => {});
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
afterEach(() => {
|
|
178
|
+
vi.restoreAllMocks(); // Always restore spies
|
|
179
|
+
cleanup(); // For @testing-library/react or equivalent
|
|
180
|
+
});
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### Mocking
|
|
184
|
+
|
|
185
|
+
**Module mocking with `vi.hoisted` (required when mocks are referenced before module evaluation):**
|
|
186
|
+
|
|
187
|
+
```typescript
|
|
188
|
+
const mocks = vi.hoisted(() => ({
|
|
189
|
+
machineToGraph: vi.fn(),
|
|
190
|
+
buildRouteTree: vi.fn(),
|
|
191
|
+
}));
|
|
192
|
+
|
|
193
|
+
vi.mock("../src/machine-to-graph.js", () => ({
|
|
194
|
+
machineToGraph: mocks.machineToGraph,
|
|
195
|
+
}));
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
**Function mocks:**
|
|
199
|
+
|
|
200
|
+
```typescript
|
|
201
|
+
const sendSpy = vi.fn();
|
|
202
|
+
const navigate = vi.fn(({ to }: { to: string }) => {
|
|
203
|
+
/* side effect */
|
|
204
|
+
});
|
|
205
|
+
const mockReturnValue = vi.fn().mockReturnValue(stubValue);
|
|
206
|
+
const asyncMock = vi.fn().mockResolvedValue(undefined);
|
|
207
|
+
const failingMock = vi.fn().mockRejectedValue(new Error("fail"));
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
**Spy pattern for console suppression:**
|
|
211
|
+
|
|
212
|
+
```typescript
|
|
213
|
+
const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => {});
|
|
214
|
+
// ... test ...
|
|
215
|
+
expect(warnSpy).toHaveBeenCalled();
|
|
216
|
+
vi.restoreAllMocks(); // in afterEach
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
**What to mock:**
|
|
220
|
+
|
|
221
|
+
- Framework router objects (TanStack, Vue Router, React Router) — mock with typed `vi.fn()` interfaces
|
|
222
|
+
- `console.warn` / `console.error` when testing code that legitimately logs warnings
|
|
223
|
+
- External module collaborators when testing a unit in isolation
|
|
224
|
+
|
|
225
|
+
**What NOT to mock:**
|
|
226
|
+
|
|
227
|
+
- Signals (`Signal.State`, `Signal.Computed`, `Signal.subtle.Watcher`) — use real implementations
|
|
228
|
+
- Internal `@xmachines/*` packages — resolved to source via [`xmAliases`](../api/@xmachines/shared/vite-aliases/functions/xmAliases.md) in Vitest config
|
|
229
|
+
- XState — use real `setup()` / `createMachine()` / `createActor()`
|
|
230
|
+
|
|
231
|
+
### Test actor patterns
|
|
232
|
+
|
|
233
|
+
**Preferred: extend [`AbstractActor`](../api/@xmachines/play-actor/classes/AbstractActor.md) for full type safety:**
|
|
234
|
+
|
|
235
|
+
```typescript
|
|
236
|
+
import { AbstractActor } from "@xmachines/play-actor";
|
|
237
|
+
import type { Routable } from "@xmachines/play-actor";
|
|
238
|
+
import { Signal } from "@xmachines/play-signals";
|
|
239
|
+
import type { AnyActorLogic } from "xstate";
|
|
240
|
+
|
|
241
|
+
class MockActor extends AbstractActor<AnyActorLogic> implements Routable {
|
|
242
|
+
override state = new Signal.State({} as unknown);
|
|
243
|
+
private _routeState: Signal.State<string | null>;
|
|
244
|
+
readonly currentRoute: Signal.Computed<string | null>;
|
|
245
|
+
readonly initialRoute: string | null;
|
|
246
|
+
|
|
247
|
+
constructor(startRoute: string | null = "/") {
|
|
248
|
+
super({} as AnyActorLogic, {}); // {} as AnyActorLogic is the standard stub
|
|
249
|
+
this._routeState = new Signal.State<string | null>(startRoute);
|
|
250
|
+
this.currentRoute = new Signal.Computed(() => this._routeState.get());
|
|
251
|
+
this.initialRoute = startRoute;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
override send(_event: { readonly type: string } & Record<string, unknown>): void {
|
|
255
|
+
// no-op or capture events for assertion
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
**Factory functions for lightweight inline mocks:**
|
|
261
|
+
|
|
262
|
+
```typescript
|
|
263
|
+
function createMockActor(initialView: PlaySpec | null = null) {
|
|
264
|
+
return {
|
|
265
|
+
currentView: new Signal.State<PlaySpec | null>(initialView),
|
|
266
|
+
send: vi.fn(),
|
|
267
|
+
start: vi.fn(),
|
|
268
|
+
stop: vi.fn(),
|
|
269
|
+
getSnapshot: vi.fn(),
|
|
270
|
+
subscribe: vi.fn(),
|
|
271
|
+
state: new Signal.State({} as unknown),
|
|
272
|
+
currentRoute: new Signal.Computed(() => null),
|
|
273
|
+
} as unknown as AbstractActor<AnyActorLogic> & Viewable;
|
|
274
|
+
}
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
### Compile-time type tests
|
|
278
|
+
|
|
279
|
+
For type-only assertions, use `@ts-expect-error` in `.spec.ts` files:
|
|
280
|
+
|
|
281
|
+
```typescript
|
|
282
|
+
const bad: PlaySpec = typedSpec<MyCtx>({
|
|
283
|
+
root: "root",
|
|
284
|
+
// @ts-expect-error "typo" is not a key of MyCtx — typedSpec enforces this
|
|
285
|
+
contextProps: ["typo"],
|
|
286
|
+
elements: {},
|
|
287
|
+
});
|
|
288
|
+
// At runtime the object exists; only the compile-time error is being tested
|
|
289
|
+
expect(bad.contextProps).toEqual(["typo"]);
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
For purely structural type assertions with no runtime test needed, use `.typecheck.ts` files in `src/`:
|
|
293
|
+
|
|
294
|
+
```typescript
|
|
295
|
+
// packages/play-xstate/src/define-player.typecheck.ts
|
|
296
|
+
type IsAny<T> = 0 extends 1 & T ? true : false;
|
|
297
|
+
type AssertFalse<T extends false> = T;
|
|
298
|
+
|
|
299
|
+
const actorNotAny: AssertFalse<IsAny<typeof actor>> = false;
|
|
300
|
+
void actorNotAny;
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
These files are validated by `npm run test:build` (`tsc --build tsconfig.test.json`) — never executed by Vitest.
|
|
304
|
+
|
|
305
|
+
### Async and signal patterns
|
|
306
|
+
|
|
307
|
+
**Flushing the microtask queue (required for Signal propagation):**
|
|
308
|
+
|
|
309
|
+
```typescript
|
|
310
|
+
function waitForMicrotask(): Promise<void> {
|
|
311
|
+
return new Promise<void>((resolve) => queueMicrotask(resolve));
|
|
312
|
+
}
|
|
313
|
+
await waitForMicrotask();
|
|
314
|
+
|
|
315
|
+
// Or use Vitest's helper:
|
|
316
|
+
await vi.waitFor(() => expect(result).toBe(expected), { timeout: 100 });
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
**Signal watcher pattern:**
|
|
320
|
+
|
|
321
|
+
```typescript
|
|
322
|
+
let notified = false;
|
|
323
|
+
const watcher = new Signal.subtle.Watcher(() => {
|
|
324
|
+
notified = true;
|
|
325
|
+
});
|
|
326
|
+
watcher.watch(actor.currentRoute);
|
|
327
|
+
actor.currentRoute.get(); // Initial read required to prime computed signals
|
|
328
|
+
|
|
329
|
+
actor.state.set({ path: "/dashboard" });
|
|
330
|
+
watcher.getPending(); // Process notifications synchronously
|
|
331
|
+
|
|
332
|
+
expect(notified).toBe(true);
|
|
333
|
+
watcher.unwatch(actor.currentRoute); // Always clean up
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
**Error testing:**
|
|
337
|
+
|
|
338
|
+
```typescript
|
|
339
|
+
// Synchronous throws
|
|
340
|
+
expect(() => actor.send(null as unknown as PlayEvent)).toThrow(InvalidEventError);
|
|
341
|
+
|
|
342
|
+
// Error with message pattern
|
|
343
|
+
expect(() => extractMachineRoutes(dupMachine)).toThrow(/Duplicate route paths detected/);
|
|
344
|
+
|
|
345
|
+
// Inspect error properties
|
|
346
|
+
try {
|
|
347
|
+
extractMachineRoutes(dupMachine);
|
|
348
|
+
expect.fail("Should have thrown");
|
|
349
|
+
} catch (error: unknown) {
|
|
350
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
351
|
+
expect(message.toLowerCase()).toContain("duplicate");
|
|
352
|
+
}
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
**Testing-library pattern (React/Vue/Solid/Svelte):**
|
|
356
|
+
|
|
357
|
+
```typescript
|
|
358
|
+
// React
|
|
359
|
+
const { getByTestId } = render(withRenderer({ actor, registryResult }));
|
|
360
|
+
expect(getByTestId("fallback")).toBeTruthy();
|
|
361
|
+
await waitFor(() => expect(screen.getByRole("heading")).toBeInTheDocument());
|
|
362
|
+
|
|
363
|
+
// Vue
|
|
364
|
+
const wrapper = mount(ActorProvider, { props: { actor, registryResult }, slots: { ... } });
|
|
365
|
+
await flushPromises();
|
|
366
|
+
expect(wrapper.find("[data-testid='message']").text()).toBe("Hello");
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
**Performance/timing assertions:**
|
|
370
|
+
|
|
371
|
+
```typescript
|
|
372
|
+
const start = performance.now();
|
|
373
|
+
for (let i = 0; i < iterations; i++) {
|
|
374
|
+
actor.send({ type: "play.route", to: `#route${i}` });
|
|
375
|
+
}
|
|
376
|
+
const duration = performance.now() - start;
|
|
377
|
+
expect(duration / iterations).toBeLessThan(2.5); // ms per operation
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
## Contract Tests
|
|
381
|
+
|
|
382
|
+
The [`@xmachines/play-router`](../api/@xmachines/play-router/README.md) package exports a shared behavioral contract suite that all router bridge adapters must satisfy:
|
|
383
|
+
|
|
384
|
+
```typescript
|
|
385
|
+
// packages/play-router/test/router-bridge-contract.ts
|
|
386
|
+
export function runBridgeContractTests(opts: ContractSuiteOptions): void;
|
|
387
|
+
|
|
388
|
+
// Each adapter's test file calls it:
|
|
389
|
+
import { runBridgeContractTests } from "../../play-router/test/router-bridge-contract.js";
|
|
390
|
+
|
|
391
|
+
runBridgeContractTests({
|
|
392
|
+
name: "TanStackReactRouterBridge",
|
|
393
|
+
createHarness(initialPath) {
|
|
394
|
+
/* ... */
|
|
395
|
+
},
|
|
396
|
+
createRestoredHarness(routedPath) {
|
|
397
|
+
/* ... */
|
|
398
|
+
},
|
|
399
|
+
});
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
The contract covers: deep-link sync on connect, router→actor navigation sync, actor→router sync, guard redirect flows, duplicate event deduplication, and restore-from-snapshot behavior.
|
|
403
|
+
|
|
404
|
+
**Used by:** [`@xmachines/play-router`](../api/@xmachines/play-router/README.md), `play-tanstack-react-router`, `play-vue-router`, `play-solid-router`, `play-react-router`, and other adapter packages.
|
|
405
|
+
|
|
406
|
+
**Compile-time bridge contract verification:**
|
|
407
|
+
|
|
408
|
+
```typescript
|
|
409
|
+
import { assertImplementsRouterBridge } from "@xmachines/play-router/test/contract.js";
|
|
410
|
+
import { MyRouterBridge } from "../src/my-router-bridge.js";
|
|
411
|
+
|
|
412
|
+
assertImplementsRouterBridge<MyRouterBridge>(); // Zero runtime cost
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
## Coverage Requirements
|
|
416
|
+
|
|
417
|
+
**Provider:** `@vitest/coverage-v8`
|
|
418
|
+
|
|
419
|
+
**Reporters:** `text`, `html`, `json-summary`
|
|
420
|
+
|
|
421
|
+
**Aggregate thresholds** (root `vitest.config.ts` — regression gate for full monorepo run):
|
|
422
|
+
|
|
423
|
+
| Type | Threshold |
|
|
424
|
+
| ---------- | --------- |
|
|
425
|
+
| Lines | 80% |
|
|
426
|
+
| Functions | 80% |
|
|
427
|
+
| Branches | 75% |
|
|
428
|
+
| Statements | 80% |
|
|
429
|
+
|
|
430
|
+
**Per-package thresholds** (enforced by each package's `vitest.config.ts`):
|
|
431
|
+
|
|
432
|
+
| Package category | Lines | Functions | Branches | Statements |
|
|
433
|
+
| ------------------------------------------------------------------------------------------------------------------ | ----- | --------- | -------- | ---------- |
|
|
434
|
+
| Core packages ([`@xmachines/play`](../api/@xmachines/play/README.md), `play-actor`) | 90% | 90% | 85% | 90% |
|
|
435
|
+
| Complex logic ([`@xmachines/play-xstate`](../api/@xmachines/play-xstate/README.md), `play-router`) | 85% | 85% | 80% | 85% |
|
|
436
|
+
| Integration/adapter packages ([`@xmachines/play-react`](../api/@xmachines/play-react/README.md), `play-vue`, etc.) | 80% | 80% | 80% | 80% |
|
|
437
|
+
|
|
438
|
+
**Coverage includes:** `src/**/*.ts`, `src/**/*.tsx`, `src/**/*.vue`, `src/**/*.svelte`
|
|
439
|
+
|
|
440
|
+
**Coverage excludes:** `test/**/*`, `**/*.test.ts`, `**/*.d.ts`, `dist/**/*`
|
|
441
|
+
|
|
442
|
+
## CI Integration
|
|
443
|
+
|
|
444
|
+
Tests are expected to run in CI against Node.js ≥ 22. The `vitest.node.setup.ts` setup file enforces this at runtime — tests will fail immediately with a descriptive error if run on an older Node version.
|
|
445
|
+
|
|
446
|
+
The `npm run format:check` and `npm run lint` commands enforce code style and are run separately from tests.
|
|
447
|
+
|
|
448
|
+
Browser tests (`npm run test:browser`) require Playwright/Chromium and are run via `vitest.browser.config.ts`. The browser global setup (`vitest.browser.global-setup.ts`) raises `process.setMaxListeners` to 32 before workers spawn to prevent false-positive `MaxListenersExceededWarning` with multiple parallel browser projects.
|
|
449
|
+
|
|
450
|
+
## Test Types Reference
|
|
451
|
+
|
|
452
|
+
| Test type | Extension | Environment | Scope |
|
|
453
|
+
| ---------------------- | --------------------------- | --------------------- | ---------------------------------------------- |
|
|
454
|
+
| Unit | `.test.ts` | `node` or `jsdom` | Single module in isolation |
|
|
455
|
+
| Protocol/type safety | `.spec.ts` | `node` | Compile-time type correctness + RFC invariants |
|
|
456
|
+
| Integration | `.test.ts` | `node` | Multiple modules working together |
|
|
457
|
+
| Performance/regression | `.spec.ts` | `node` | Timing budgets for critical paths |
|
|
458
|
+
| Browser unit | `.browser.test.ts(x)` | Chromium (Playwright) | Browser-specific APIs, real microtask timing |
|
|
459
|
+
| E2E demo | `.browser.test.tsx` | Chromium (Playwright) | Full application flows in demo packages |
|
|
460
|
+
| Type-only | `.typecheck.ts` (in `src/`) | `tsc` only | Structural type assertions; no Vitest runner |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xmachines/docs",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.48",
|
|
4
4
|
"description": "Documentation for XMachines",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"documentation",
|
|
@@ -49,12 +49,12 @@
|
|
|
49
49
|
"test": "vitest run"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
|
-
"@xmachines/shared": "1.0.0-beta.
|
|
53
|
-
"oxfmt": "^0.
|
|
54
|
-
"oxlint": "^1.
|
|
52
|
+
"@xmachines/shared": "1.0.0-beta.48",
|
|
53
|
+
"oxfmt": "^0.47.0",
|
|
54
|
+
"oxlint": "^1.62.0",
|
|
55
55
|
"typedoc": "^0.28.19",
|
|
56
56
|
"typedoc-plugin-llms-txt": "^0.1.2",
|
|
57
57
|
"typedoc-plugin-markdown": "^4.11.0",
|
|
58
|
-
"vitest": "^4.1.
|
|
58
|
+
"vitest": "^4.1.5"
|
|
59
59
|
}
|
|
60
60
|
}
|