@xmachines/docs 1.0.0 → 2.0.0-alpha.1
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 +1 -1
- package/api/@xmachines/play/classes/NonNullableError.md +11 -11
- package/api/@xmachines/play/classes/PlayError.md +11 -11
- package/api/@xmachines/play/functions/assertNonNullable.md +1 -1
- package/api/@xmachines/play/type-aliases/PlayEvent.md +4 -4
- package/api/@xmachines/play-actor/classes/AbstractActor.md +20 -19
- package/api/@xmachines/play-actor/functions/attachRenderErrorHandler.md +1 -1
- package/api/@xmachines/play-actor/functions/toAtomState.md +1 -1
- package/api/@xmachines/play-actor/functions/typedSpec.md +1 -1
- package/api/@xmachines/play-actor/interfaces/BaseActorProviderProps.md +7 -7
- package/api/@xmachines/play-actor/interfaces/BaseViewContextValue.md +7 -7
- package/api/@xmachines/play-actor/interfaces/PlaySpec.md +7 -7
- package/api/@xmachines/play-actor/interfaces/Routable.md +5 -5
- package/api/@xmachines/play-actor/interfaces/Viewable.md +4 -4
- package/api/@xmachines/play-dom/classes/PlayRenderer.md +4 -4
- 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/interfaces/CreatePlayUIOptions.md +10 -10
- package/api/@xmachines/play-dom/interfaces/MountOptions.md +5 -5
- package/api/@xmachines/play-dom/interfaces/PlayDomOptions.md +12 -12
- package/api/@xmachines/play-dom/type-aliases/MountFn.md +1 -1
- package/api/@xmachines/play-dom-router/README.md +1 -1
- 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 +2 -2
- package/api/@xmachines/play-dom-router/functions/createRouter.md +1 -1
- package/api/@xmachines/play-dom-router/interfaces/BrowserHistory.md +16 -16
- package/api/@xmachines/play-dom-router/interfaces/BrowserWindow.md +16 -16
- package/api/@xmachines/play-dom-router/interfaces/ConnectRouterOptions.md +6 -6
- package/api/@xmachines/play-dom-router/interfaces/PlayRouteEvent.md +8 -8
- package/api/@xmachines/play-dom-router/interfaces/RoutableActor.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 +4 -4
- package/api/@xmachines/play-dom-router/interfaces/RouteMapping.md +5 -5
- package/api/@xmachines/play-dom-router/interfaces/RouterBridge.md +3 -3
- package/api/@xmachines/play-dom-router/interfaces/VanillaRouter.md +6 -6
- package/api/@xmachines/play-react/README.md +1 -1
- 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 +10 -10
- package/api/@xmachines/play-react/interfaces/PlayErrorBoundaryProps.md +6 -6
- package/api/@xmachines/play-react/interfaces/PlayErrorBoundaryState.md +5 -5
- package/api/@xmachines/play-react/interfaces/PlayUIProviderProps.md +13 -13
- package/api/@xmachines/play-react/interfaces/ViewContextValue.md +7 -7
- package/api/@xmachines/play-react/type-aliases/AnyPlayActor.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 +1 -1
- package/api/@xmachines/play-react-router/classes/ReactRouterBridge.md +4 -4
- package/api/@xmachines/play-react-router/classes/RouteMap.md +4 -4
- package/api/@xmachines/play-react-router/functions/createPlayRouterProvider.md +1 -1
- package/api/@xmachines/play-react-router/functions/createRouteMap.md +2 -2
- package/api/@xmachines/play-react-router/functions/createRouteMapFromTree.md +1 -1
- package/api/@xmachines/play-react-router/interfaces/PlayActor.md +7 -7
- package/api/@xmachines/play-react-router/interfaces/PlayRouteEvent.md +8 -8
- package/api/@xmachines/play-react-router/interfaces/PlayRouterProviderBaseProps.md +7 -7
- package/api/@xmachines/play-react-router/interfaces/PlayRouterProviderProps.md +7 -7
- package/api/@xmachines/play-react-router/interfaces/RouteMapOptions.md +4 -4
- package/api/@xmachines/play-react-router/interfaces/RouteMapping.md +5 -5
- package/api/@xmachines/play-react-router/interfaces/RouterBridge.md +3 -3
- package/api/@xmachines/play-react-router/type-aliases/PlayRouterBridgeConstructor.md +1 -1
- package/api/@xmachines/play-react-router/variables/PlayRouterProvider.md +1 -1
- package/api/@xmachines/play-router/README.md +15 -7
- package/api/@xmachines/play-router/classes/RouteMap.md +4 -4
- package/api/@xmachines/play-router/classes/RouterBridgeBase.md +4 -4
- 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 +2 -2
- package/api/@xmachines/play-router/functions/createRouteMapFromTree.md +1 -1
- package/api/@xmachines/play-router/functions/detectDuplicateRoutes.md +1 -1
- package/api/@xmachines/play-router/functions/extractMachineRoutes.md +2 -2
- 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 +6 -6
- package/api/@xmachines/play-router/interfaces/LocationLike.md +5 -5
- package/api/@xmachines/play-router/interfaces/MachineEdgeData.md +7 -5
- package/api/@xmachines/play-router/interfaces/MachineNodeData.md +7 -7
- package/api/@xmachines/play-router/interfaces/PlayActor.md +7 -7
- package/api/@xmachines/play-router/interfaces/PlayRouteEvent.md +8 -8
- package/api/@xmachines/play-router/interfaces/ResolvedRoutePath.md +5 -5
- package/api/@xmachines/play-router/interfaces/RoutableActor.md +6 -6
- package/api/@xmachines/play-router/interfaces/RouteInfo.md +10 -10
- package/api/@xmachines/play-router/interfaces/RouteMapOptions.md +4 -4
- package/api/@xmachines/play-router/interfaces/RouteMapping.md +5 -5
- package/api/@xmachines/play-router/interfaces/RouteMatch.md +5 -5
- package/api/@xmachines/play-router/interfaces/RouteNode.md +12 -12
- package/api/@xmachines/play-router/interfaces/RouteObject.md +4 -4
- package/api/@xmachines/play-router/interfaces/RouteTree.md +7 -7
- 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/functions/watchSignal.md +1 -1
- package/api/@xmachines/play-signals/interfaces/ComputedOptions.md +4 -4
- package/api/@xmachines/play-signals/interfaces/SignalComputed.md +2 -2
- package/api/@xmachines/play-signals/interfaces/SignalOptions.md +4 -4
- 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/functions/useActor.md +1 -1
- package/api/@xmachines/play-solid/functions/usePlayView.md +1 -1
- package/api/@xmachines/play-solid/interfaces/ActorProviderProps.md +10 -10
- package/api/@xmachines/play-solid/interfaces/PlayUIProviderProps.md +13 -13
- package/api/@xmachines/play-solid/interfaces/ViewContextValue.md +7 -7
- package/api/@xmachines/play-solid/type-aliases/AnyPlayActor.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 +5 -5
- package/api/@xmachines/play-solid-router/classes/RouteMap.md +4 -4
- package/api/@xmachines/play-solid-router/classes/SolidRouterBridge.md +5 -5
- package/api/@xmachines/play-solid-router/functions/createPlayRouterProvider.md +1 -1
- package/api/@xmachines/play-solid-router/functions/createRouteMap.md +2 -2
- package/api/@xmachines/play-solid-router/interfaces/AbstractActor.md +20 -19
- package/api/@xmachines/play-solid-router/interfaces/PlayActor.md +7 -7
- package/api/@xmachines/play-solid-router/interfaces/PlayRouteEvent.md +8 -8
- package/api/@xmachines/play-solid-router/interfaces/PlayRouterProviderBaseProps.md +7 -7
- package/api/@xmachines/play-solid-router/interfaces/PlayRouterProviderProps.md +7 -7
- package/api/@xmachines/play-solid-router/interfaces/RouteMapOptions.md +4 -4
- package/api/@xmachines/play-solid-router/interfaces/RouteMapping.md +5 -5
- package/api/@xmachines/play-solid-router/interfaces/RouterBridge.md +3 -3
- package/api/@xmachines/play-solid-router/type-aliases/PlayRouterBridgeConstructor.md +1 -1
- 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-solid-router/variables/PlayRouterProvider.md +1 -1
- package/api/@xmachines/play-svelte/README.md +1 -1
- 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 +10 -10
- package/api/@xmachines/play-svelte/interfaces/DefineRegistryOptions.md +6 -6
- package/api/@xmachines/play-svelte/interfaces/PlayUIProviderProps.md +13 -13
- package/api/@xmachines/play-svelte/interfaces/ViewContextValue.md +7 -7
- package/api/@xmachines/play-svelte/type-aliases/AnyPlayActor.md +1 -1
- package/api/@xmachines/play-svelte-spa-router/README.md +24 -18
- 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 +2 -2
- package/api/@xmachines/play-svelte-spa-router/interfaces/ConnectRouterOptions.md +6 -6
- package/api/@xmachines/play-svelte-spa-router/interfaces/PlayRouteEvent.md +8 -8
- package/api/@xmachines/play-svelte-spa-router/interfaces/RouteMapOptions.md +4 -4
- package/api/@xmachines/play-svelte-spa-router/interfaces/RouteMapping.md +5 -5
- 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 +5 -5
- 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 +2 -2
- package/api/@xmachines/play-sveltekit-router/interfaces/ConnectRouterOptions.md +6 -6
- package/api/@xmachines/play-sveltekit-router/interfaces/LocationLike.md +5 -5
- package/api/@xmachines/play-sveltekit-router/interfaces/PlayRouteEvent.md +8 -8
- package/api/@xmachines/play-sveltekit-router/interfaces/RouteMapOptions.md +4 -4
- package/api/@xmachines/play-sveltekit-router/interfaces/RouteMapping.md +5 -5
- 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 +1 -1
- package/api/@xmachines/play-tanstack-react-router/classes/RouteMap.md +4 -4
- package/api/@xmachines/play-tanstack-react-router/classes/TanStackReactRouterBridge.md +4 -4
- package/api/@xmachines/play-tanstack-react-router/functions/createPlayRouterProvider.md +1 -1
- package/api/@xmachines/play-tanstack-react-router/functions/createRouteMap.md +2 -2
- package/api/@xmachines/play-tanstack-react-router/functions/createRouteMapFromTree.md +1 -1
- package/api/@xmachines/play-tanstack-react-router/functions/extractMachineRoutes.md +2 -2
- package/api/@xmachines/play-tanstack-react-router/interfaces/PlayActor.md +7 -7
- package/api/@xmachines/play-tanstack-react-router/interfaces/PlayRouteEvent.md +8 -8
- package/api/@xmachines/play-tanstack-react-router/interfaces/PlayRouterProviderBaseProps.md +7 -7
- package/api/@xmachines/play-tanstack-react-router/interfaces/PlayRouterProviderProps.md +7 -7
- package/api/@xmachines/play-tanstack-react-router/interfaces/RouteMapOptions.md +4 -4
- package/api/@xmachines/play-tanstack-react-router/interfaces/RouteMapping.md +5 -5
- package/api/@xmachines/play-tanstack-react-router/interfaces/RouteNavigateEvent.md +5 -5
- package/api/@xmachines/play-tanstack-react-router/interfaces/RouterBridge.md +3 -3
- package/api/@xmachines/play-tanstack-react-router/type-aliases/PlayRouterBridgeConstructor.md +1 -1
- 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-react-router/variables/PlayRouterProvider.md +1 -1
- package/api/@xmachines/play-tanstack-router/classes/TanStackRouterBridgeBase.md +2 -2
- package/api/@xmachines/play-tanstack-router/type-aliases/TanStackRouteMapLike.md +3 -3
- package/api/@xmachines/play-tanstack-router/type-aliases/TanStackRouterLike.md +4 -4
- package/api/@xmachines/play-tanstack-solid-router/README.md +5 -5
- package/api/@xmachines/play-tanstack-solid-router/classes/RouteMap.md +4 -4
- package/api/@xmachines/play-tanstack-solid-router/classes/TanStackSolidRouterBridge.md +5 -5
- package/api/@xmachines/play-tanstack-solid-router/functions/createPlayRouterProvider.md +1 -1
- package/api/@xmachines/play-tanstack-solid-router/functions/createRouteMap.md +2 -2
- package/api/@xmachines/play-tanstack-solid-router/interfaces/PlayActor.md +7 -7
- package/api/@xmachines/play-tanstack-solid-router/interfaces/PlayRouteEvent.md +8 -8
- package/api/@xmachines/play-tanstack-solid-router/interfaces/PlayRouterProviderBaseProps.md +7 -7
- package/api/@xmachines/play-tanstack-solid-router/interfaces/PlayRouterProviderProps.md +7 -7
- package/api/@xmachines/play-tanstack-solid-router/interfaces/RouteMapOptions.md +4 -4
- package/api/@xmachines/play-tanstack-solid-router/interfaces/RouteMapping.md +5 -5
- package/api/@xmachines/play-tanstack-solid-router/interfaces/RouterBridge.md +3 -3
- package/api/@xmachines/play-tanstack-solid-router/type-aliases/PlayRouterBridgeConstructor.md +1 -1
- 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 +4 -4
- package/api/@xmachines/play-tanstack-solid-router/variables/PlayRouterProvider.md +1 -1
- package/api/@xmachines/play-vue/README.md +1 -1
- 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 +7 -7
- package/api/@xmachines/play-vue/interfaces/PlayUIProviderProps.md +10 -10
- package/api/@xmachines/play-vue/interfaces/ViewContextValue.md +7 -7
- package/api/@xmachines/play-vue/interfaces/VisibilityProviderProps.md +1 -1
- package/api/@xmachines/play-vue/type-aliases/AnyPlayActor.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 +4 -4
- package/api/@xmachines/play-vue/variables/PlayRenderer.md +1 -1
- package/api/@xmachines/play-vue-router/README.md +1 -1
- package/api/@xmachines/play-vue-router/classes/RouteMap.md +4 -4
- package/api/@xmachines/play-vue-router/classes/VueRouterBridge.md +5 -5
- package/api/@xmachines/play-vue-router/functions/createRouteMap.md +2 -2
- package/api/@xmachines/play-vue-router/interfaces/PlayActor.md +7 -7
- package/api/@xmachines/play-vue-router/interfaces/PlayRouteEvent.md +8 -8
- package/api/@xmachines/play-vue-router/interfaces/RouteMapOptions.md +4 -4
- package/api/@xmachines/play-vue-router/interfaces/RouteMapping.md +5 -5
- 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 +88 -25
- package/api/@xmachines/play-xstate/classes/PlayerActor.md +34 -33
- package/api/@xmachines/play-xstate/functions/buildRouteUrl.md +1 -1
- package/api/@xmachines/play-xstate/functions/composeGuards.md +23 -17
- package/api/@xmachines/play-xstate/functions/composeGuardsOr.md +16 -16
- package/api/@xmachines/play-xstate/functions/contextFieldMatches.md +1 -1
- package/api/@xmachines/play-xstate/functions/createRoutedMachine.md +87 -0
- package/api/@xmachines/play-xstate/functions/definePlayer.md +3 -3
- 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 +45 -11
- 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 +15 -15
- package/api/@xmachines/play-xstate/interfaces/PlayerConfig.md +5 -5
- package/api/@xmachines/play-xstate/interfaces/PlayerFactoryResumeOptions.md +4 -4
- package/api/@xmachines/play-xstate/interfaces/PlayerOptions.md +8 -8
- package/api/@xmachines/play-xstate/interfaces/RouteContext.md +7 -7
- package/api/@xmachines/play-xstate/interfaces/RouteObject.md +4 -4
- package/api/@xmachines/play-xstate/type-aliases/ComposedGuard.md +26 -5
- 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/PlayRoutePayload.md +30 -0
- package/api/@xmachines/play-xstate/type-aliases/PlayerFactory.md +1 -1
- package/api/@xmachines/play-xstate/type-aliases/RouteMachineConfig.md +13 -6
- package/api/@xmachines/play-xstate/type-aliases/RouteMetadata.md +1 -1
- package/api/@xmachines/play-xstate/type-aliases/RouteStateNode.md +16 -4
- package/api/@xmachines/play-xstate/type-aliases/SetupLike.md +33 -0
- package/api/@xmachines/play-xstate/type-aliases/WithOptional.md +31 -0
- package/api/@xmachines/play-xstate/variables/emptyEventSchema.md +37 -0
- package/api/@xmachines/play-xstate/variables/playMetaSchema.md +40 -0
- package/api/@xmachines/play-xstate/variables/playRouteEventSchema.md +9 -0
- 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/vite-aliases/functions/xmSvelteRunes.md +4 -4
- package/api/@xmachines/shared/vitest/functions/defineXmBrowserConfig.md +1 -1
- package/api/@xmachines/shared/vitest/functions/defineXmVitestConfig.md +1 -1
- package/api/@xmachines/shared/vitest/interfaces/XmBrowserConfigOptions.md +6 -6
- package/contributing/architecture.md +9 -6
- package/contributing/development.md +1 -1
- 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-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-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-svelte-demo/type-aliases/AuthCatalog.md +1 -1
- package/examples/@xmachines/play-svelte-demo/variables/authCatalog.md +1 -1
- 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/README.md +1 -1
- package/examples/basic-state-machine.md +22 -24
- package/examples/form-validation.md +118 -109
- package/examples/routing-patterns.md +92 -60
- package/examples/traffic-light.md +46 -57
- package/guides/getting-started.md +79 -68
- package/guides/state-machines.md +68 -52
- package/package.json +2 -2
- package/rfc/play.md +4 -4
|
@@ -2,22 +2,28 @@
|
|
|
2
2
|
|
|
3
3
|
# Form Validation with Typed Context
|
|
4
4
|
|
|
5
|
-
Managing login form state using `setup({
|
|
5
|
+
Managing login form state using `setup({ schemas })`, typed context patches, guard logic in transition functions, and `meta.view` with `$bindState`.
|
|
6
6
|
|
|
7
7
|
## Use Case
|
|
8
8
|
|
|
9
9
|
This example mirrors the `authMachine` login pattern: a form state with a local state store (`$bindState` two-way binding), a guard on the submit action, and a `meta.view` spec describing the component tree. It covers:
|
|
10
10
|
|
|
11
|
-
- Typed context
|
|
12
|
-
-
|
|
11
|
+
- Typed context patches returned from transition functions
|
|
12
|
+
- Guard logic as early returns inside transition functions
|
|
13
13
|
- `meta.view` spec with `$bindState` for two-way form binding
|
|
14
14
|
- Sending typed domain events from the view layer
|
|
15
15
|
|
|
16
16
|
## Complete Code
|
|
17
17
|
|
|
18
18
|
```typescript
|
|
19
|
-
import { setup } from "xstate";
|
|
20
|
-
import {
|
|
19
|
+
import { setup, types } from "xstate";
|
|
20
|
+
import {
|
|
21
|
+
createRoutedMachine,
|
|
22
|
+
definePlayer,
|
|
23
|
+
emptyEventSchema,
|
|
24
|
+
playMetaSchema,
|
|
25
|
+
playRouteEventSchema,
|
|
26
|
+
} from "@xmachines/play-xstate";
|
|
21
27
|
|
|
22
28
|
// Context shape
|
|
23
29
|
interface LoginContext {
|
|
@@ -28,133 +34,136 @@ interface LoginContext {
|
|
|
28
34
|
query: Record<string, string>;
|
|
29
35
|
}
|
|
30
36
|
|
|
31
|
-
//
|
|
32
|
-
type
|
|
33
|
-
|
|
34
|
-
type: "play.route";
|
|
35
|
-
to: string;
|
|
36
|
-
params?: Record<string, string>;
|
|
37
|
-
query?: Record<string, string>;
|
|
38
|
-
}
|
|
39
|
-
| { type: "auth.login"; username: string }
|
|
40
|
-
| { type: "auth.logout" };
|
|
41
|
-
|
|
42
|
-
// 1. Typed setup — always use setup() before createMachine()
|
|
37
|
+
// 1. Typed setup — always use setup() before createMachine().
|
|
38
|
+
// The events schema maps event type -> payload shape (payload excludes `type`);
|
|
39
|
+
// event names are lowercase dot-separated.
|
|
43
40
|
const loginSetup = setup({
|
|
44
|
-
|
|
45
|
-
context:
|
|
46
|
-
|
|
47
|
-
|
|
41
|
+
schemas: {
|
|
42
|
+
context: types<LoginContext>(),
|
|
43
|
+
input: types<Partial<LoginContext> | undefined>(),
|
|
44
|
+
events: {
|
|
45
|
+
"play.route": playRouteEventSchema,
|
|
46
|
+
"auth.login": types<{ username: string }>(),
|
|
47
|
+
"auth.logout": emptyEventSchema,
|
|
48
|
+
},
|
|
49
|
+
// State meta carries route templates (meta.route) and typed PlaySpec
|
|
50
|
+
// view specs (meta.view)
|
|
51
|
+
meta: playMetaSchema,
|
|
48
52
|
},
|
|
49
53
|
});
|
|
50
54
|
|
|
51
|
-
// 2. Machine —
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
55
|
+
// 2. Machine — createRoutedMachine wires play.route support from id + meta.route
|
|
56
|
+
// pairs, with the same config typing as loginSetup.createMachine itself
|
|
57
|
+
const loginMachine = createRoutedMachine(loginSetup)({
|
|
58
|
+
id: "login",
|
|
59
|
+
initial: "idle",
|
|
60
|
+
context: ({ input }) => ({
|
|
61
|
+
isAuthenticated: input?.isAuthenticated ?? false,
|
|
62
|
+
username: input?.username ?? null,
|
|
63
|
+
errorMessage: null,
|
|
64
|
+
params: input?.params ?? {},
|
|
65
|
+
query: input?.query ?? {},
|
|
66
|
+
}),
|
|
67
|
+
|
|
68
|
+
// Root-level event handlers — accessible from any state.
|
|
69
|
+
// Transitions are plain functions: guard with an early return,
|
|
70
|
+
// update context by returning a shallow patch.
|
|
71
|
+
on: {
|
|
72
|
+
"auth.login": ({ context, event }) => {
|
|
73
|
+
// Guard: allow login only when not already authenticated
|
|
74
|
+
if (context.isAuthenticated) return;
|
|
75
|
+
return {
|
|
67
76
|
target: ".dashboard",
|
|
68
|
-
|
|
69
|
-
guard: ({ context }) => !context.isAuthenticated,
|
|
70
|
-
actions: loginSetup.assign({
|
|
77
|
+
context: {
|
|
71
78
|
isAuthenticated: true,
|
|
72
79
|
errorMessage: null,
|
|
73
|
-
// Typed by the event
|
|
74
|
-
username:
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
80
|
+
// Typed by the event schema — event.username is already narrowed
|
|
81
|
+
username: event.username,
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
},
|
|
85
|
+
"auth.logout": ({ context }) => {
|
|
86
|
+
if (!context.isAuthenticated) return;
|
|
87
|
+
return {
|
|
78
88
|
target: ".idle",
|
|
79
|
-
|
|
80
|
-
actions: loginSetup.assign({
|
|
89
|
+
context: {
|
|
81
90
|
isAuthenticated: false,
|
|
82
91
|
username: null,
|
|
83
|
-
}
|
|
84
|
-
}
|
|
92
|
+
},
|
|
93
|
+
};
|
|
85
94
|
},
|
|
95
|
+
},
|
|
86
96
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
},
|
|
97
|
+
states: {
|
|
98
|
+
idle: {
|
|
99
|
+
id: "idle",
|
|
100
|
+
meta: {
|
|
101
|
+
route: "/",
|
|
102
|
+
view: {
|
|
103
|
+
root: "root",
|
|
104
|
+
elements: {
|
|
105
|
+
root: { type: "Home", props: { title: "Welcome" }, children: [] },
|
|
97
106
|
},
|
|
98
107
|
},
|
|
99
108
|
},
|
|
109
|
+
},
|
|
100
110
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
},
|
|
111
|
+
login: {
|
|
112
|
+
id: "login",
|
|
113
|
+
meta: {
|
|
114
|
+
route: "/login",
|
|
115
|
+
view: {
|
|
116
|
+
root: "root",
|
|
117
|
+
// Local state store — initial value shown in the form field
|
|
118
|
+
state: { username: "" },
|
|
119
|
+
elements: {
|
|
120
|
+
root: {
|
|
121
|
+
type: "Login",
|
|
122
|
+
props: {
|
|
123
|
+
title: "Sign In",
|
|
124
|
+
// $bindState wires the prop to the local state store (two-way)
|
|
125
|
+
username: { $bindState: "/username" },
|
|
126
|
+
},
|
|
127
|
+
children: [],
|
|
128
|
+
on: {
|
|
129
|
+
// emit("submit") → resolves username from $state, calls login action
|
|
130
|
+
submit: {
|
|
131
|
+
action: "login",
|
|
132
|
+
params: { username: { $state: "/username" } },
|
|
124
133
|
},
|
|
125
134
|
},
|
|
126
135
|
},
|
|
127
136
|
},
|
|
128
137
|
},
|
|
129
138
|
},
|
|
139
|
+
},
|
|
130
140
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
},
|
|
141
|
+
dashboard: {
|
|
142
|
+
id: "dashboard",
|
|
143
|
+
meta: {
|
|
144
|
+
route: "/dashboard",
|
|
145
|
+
view: {
|
|
146
|
+
root: "root",
|
|
147
|
+
elements: {
|
|
148
|
+
root: {
|
|
149
|
+
type: "Dashboard",
|
|
150
|
+
props: { title: "Dashboard" },
|
|
151
|
+
children: [],
|
|
152
|
+
on: {
|
|
153
|
+
logout: { action: "logout" },
|
|
145
154
|
},
|
|
146
155
|
},
|
|
147
156
|
},
|
|
148
157
|
},
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
}
|
|
158
|
+
},
|
|
159
|
+
// always-transition: redirect to login if not authenticated
|
|
160
|
+
always: ({ context }) => {
|
|
161
|
+
if (context.isAuthenticated) return;
|
|
162
|
+
return { target: "login" };
|
|
154
163
|
},
|
|
155
164
|
},
|
|
156
|
-
}
|
|
157
|
-
);
|
|
165
|
+
},
|
|
166
|
+
});
|
|
158
167
|
|
|
159
168
|
// 3. Factory and actor
|
|
160
169
|
const createPlayer = definePlayer({ machine: loginMachine });
|
|
@@ -171,7 +180,7 @@ console.log(actor.getSnapshot().value); // "dashboard"
|
|
|
171
180
|
console.log(actor.getSnapshot().context.username); // "alice"
|
|
172
181
|
|
|
173
182
|
// 6. Guard prevents re-login while authenticated
|
|
174
|
-
actor.send({ type: "auth.login", username: "bob" }); //
|
|
183
|
+
actor.send({ type: "auth.login", username: "bob" }); // early return — transition rejected
|
|
175
184
|
console.log(actor.getSnapshot().context.username); // still "alice"
|
|
176
185
|
|
|
177
186
|
// 7. Logout
|
|
@@ -217,10 +226,10 @@ view: {
|
|
|
217
226
|
|
|
218
227
|
## Key Concepts
|
|
219
228
|
|
|
220
|
-
- **`setup({
|
|
221
|
-
-
|
|
222
|
-
- **Guards as
|
|
223
|
-
- **`always` transitions**:
|
|
229
|
+
- **`setup({ schemas })`**: Always declare context, events, input, and meta schemas before `createMachine` — via `types<T>()` for your own shapes, and the shared `playRouteEventSchema` / `playMetaSchema` / `emptyEventSchema` constants from `@xmachines/play-xstate` for the Play-standard ones. `playMetaSchema` types `meta.view` as a `PlaySpec`, so view specs are checked, not `unknown`.
|
|
230
|
+
- **Context patches**: Update context by returning a shallow `context` patch from the transition function. This provides full type inference — no `assign` action.
|
|
231
|
+
- **Guards as early returns**: `if (context.isAuthenticated) return;` — the transition function checks state invariants ("can I BE in this state?") and returns `undefined` to reject the transition.
|
|
232
|
+
- **`always` transitions**: Functions evaluated on state entry. Used for protected routes — return `{ target }` to redirect before the state is fully entered, or `undefined` to stay.
|
|
224
233
|
- **Lowercase dot-separated event types**: `"auth.login"`, `"auth.logout"`, `"play.route"` — not `SCREAMING_SNAKE_CASE`.
|
|
225
234
|
|
|
226
235
|
## Connecting the Renderer
|
|
@@ -305,6 +314,6 @@ window.addEventListener("beforeunload", () => {
|
|
|
305
314
|
## Next Steps
|
|
306
315
|
|
|
307
316
|
- **[Basic State Machine](basic-state-machine.md)** — Foundational concepts without a view layer
|
|
308
|
-
- **[Routing Patterns](routing-patterns.md)** — Parameter routes, relative routes, and `always` auth
|
|
317
|
+
- **[Routing Patterns](routing-patterns.md)** — Parameter routes, relative routes, and `always` auth redirects
|
|
309
318
|
- **[`PlaySpec`](../api/@xmachines/play-actor/interfaces/PlaySpec.md)** — Spec type governing `meta.view`, `$bindState`, `$state`, and `contextProps`
|
|
310
319
|
- **[`@xmachines/play-router`](../api/@xmachines/play-router/README.md)** — Route extraction and tree building
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
# Routing Patterns
|
|
4
4
|
|
|
5
|
-
How the `authMachine` uses `meta.route`, `play.route` events, `formatPlayRouteTransitions`, and `always`
|
|
5
|
+
How the `authMachine` uses `meta.route`, `play.route` events, `formatPlayRouteTransitions`, and `always` transitions to implement actor-authoritative URL routing.
|
|
6
6
|
|
|
7
7
|
## Overview
|
|
8
8
|
|
|
@@ -62,12 +62,17 @@ states: {
|
|
|
62
62
|
|
|
63
63
|
### `formatPlayRouteTransitions` — Auto-Generating Route Handlers
|
|
64
64
|
|
|
65
|
-
Instead of hand-writing `play.route` event handlers for every routable state,
|
|
65
|
+
Instead of hand-writing `play.route` event handlers for every routable state, create the machine through `createRoutedMachine` — it has the same signature as the setup's own `createMachine` (full config inference) and applies `formatPlayRouteTransitions` at runtime:
|
|
66
66
|
|
|
67
67
|
```typescript
|
|
68
|
-
import { setup } from "xstate";
|
|
69
|
-
import {
|
|
70
|
-
|
|
68
|
+
import { setup, types } from "xstate";
|
|
69
|
+
import {
|
|
70
|
+
createRoutedMachine,
|
|
71
|
+
definePlayer,
|
|
72
|
+
emptyEventSchema,
|
|
73
|
+
playMetaSchema,
|
|
74
|
+
playRouteEventSchema,
|
|
75
|
+
} from "@xmachines/play-xstate";
|
|
71
76
|
|
|
72
77
|
interface AuthContext {
|
|
73
78
|
isAuthenticated: boolean;
|
|
@@ -77,47 +82,72 @@ interface AuthContext {
|
|
|
77
82
|
}
|
|
78
83
|
|
|
79
84
|
const authSetup = setup({
|
|
80
|
-
|
|
81
|
-
context:
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
+
schemas: {
|
|
86
|
+
context: types<AuthContext>(),
|
|
87
|
+
input: types<Partial<AuthContext> | undefined>(),
|
|
88
|
+
events: {
|
|
89
|
+
"play.route": playRouteEventSchema,
|
|
90
|
+
"auth.login": types<{ username: string }>(),
|
|
91
|
+
"auth.logout": emptyEventSchema,
|
|
92
|
+
},
|
|
93
|
+
meta: playMetaSchema,
|
|
85
94
|
},
|
|
86
95
|
});
|
|
87
96
|
|
|
88
|
-
const authMachine = authSetup
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
query: input?.query ?? {},
|
|
97
|
-
}),
|
|
98
|
-
states: {
|
|
99
|
-
home: { id: "home", meta: { route: "/" } },
|
|
100
|
-
about: { id: "about", meta: { route: "/about" } },
|
|
101
|
-
login: { id: "login", meta: { route: "/login" } },
|
|
102
|
-
profile: { id: "profile", meta: { route: "/profile/:username" } },
|
|
103
|
-
},
|
|
97
|
+
const authMachine = createRoutedMachine(authSetup)({
|
|
98
|
+
id: "auth",
|
|
99
|
+
initial: "home",
|
|
100
|
+
context: ({ input }) => ({
|
|
101
|
+
isAuthenticated: input?.isAuthenticated ?? false,
|
|
102
|
+
username: input?.username ?? null,
|
|
103
|
+
params: input?.params ?? {},
|
|
104
|
+
query: input?.query ?? {},
|
|
104
105
|
}),
|
|
105
|
-
|
|
106
|
+
states: {
|
|
107
|
+
home: { id: "home", meta: { route: "/" } },
|
|
108
|
+
about: { id: "about", meta: { route: "/about" } },
|
|
109
|
+
login: { id: "login", meta: { route: "/login" } },
|
|
110
|
+
profile: { id: "profile", meta: { route: "/profile/:username" } },
|
|
111
|
+
},
|
|
112
|
+
});
|
|
106
113
|
```
|
|
107
114
|
|
|
108
|
-
`formatPlayRouteTransitions`
|
|
115
|
+
Under the hood, `formatPlayRouteTransitions` wires the routed states to XState v6's **native routing**: each routed state receives a static `route: {}` config (making it targetable via the built-in `xstate.route` event and visible to graph tooling), and one root-level `play.route` forwarder handles the public API by navigating those targets **directly, in one atomic transition**:
|
|
109
116
|
|
|
110
117
|
```typescript
|
|
118
|
+
// Equivalent of what formatPlayRouteTransitions produces:
|
|
119
|
+
states: {
|
|
120
|
+
home: { id: "home", meta: { route: "/" }, route: {} },
|
|
121
|
+
about: { id: "about", meta: { route: "/about" }, route: {} },
|
|
122
|
+
login: { id: "login", meta: { route: "/login" }, route: {} },
|
|
123
|
+
profile: { id: "profile", meta: { route: "/profile/:username" }, route: {} },
|
|
124
|
+
},
|
|
111
125
|
on: {
|
|
112
126
|
"play.route": [
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
127
|
+
// routeTargets maps each routed #id to its state path, collected during
|
|
128
|
+
// the crawl (or to null when the state declares its OWN route config).
|
|
129
|
+
({ event }, enq) => {
|
|
130
|
+
const target = routeTargets.get(event.to);
|
|
131
|
+
if (target === undefined) return undefined; // fall through to your fallbacks
|
|
132
|
+
if (target === null) {
|
|
133
|
+
// user-declared route config: its resolver decides (and owns any patch)
|
|
134
|
+
enq.raise({ ...event, type: "xstate.route" });
|
|
135
|
+
return {};
|
|
136
|
+
}
|
|
137
|
+
// one atomic transition: navigation + params/query patch together
|
|
138
|
+
return {
|
|
139
|
+
target,
|
|
140
|
+
reenter: true,
|
|
141
|
+
context: { params: event.params ?? {}, query: event.query ?? {} },
|
|
142
|
+
};
|
|
143
|
+
},
|
|
144
|
+
// ...your own play.route fallbacks (e.g. a 404 route) run for unknown targets
|
|
117
145
|
],
|
|
118
146
|
}
|
|
119
147
|
```
|
|
120
148
|
|
|
149
|
+
For injected routes the forwarder navigates directly — navigation and the `params`/`query` patch are one atomic transition, so exit actions see the old params and no `always` transition can observe a half-navigated state. The injected `route: {}` configs keep statically-targeted `xstate.route` edges in the graph for tooling. States that declare their **own** `route` config are re-raised as `xstate.route` instead, so the user's resolver decides (including blocking — in which case context stays untouched). Unknown targets return `undefined`, falling through to any `play.route` fallbacks you define yourself.
|
|
150
|
+
|
|
121
151
|
### `play.route` Events — Navigation
|
|
122
152
|
|
|
123
153
|
To navigate, send a `play.route` event with `to: "#stateId"`:
|
|
@@ -146,61 +176,63 @@ actor.send({
|
|
|
146
176
|
|
|
147
177
|
**`to` always uses `"#stateId"` format** — the state's `id` field prefixed with `#`. Do not pass URL paths here.
|
|
148
178
|
|
|
149
|
-
### `always`
|
|
179
|
+
### `always` Transitions — Protected Routes
|
|
150
180
|
|
|
151
|
-
Use XState `always` transitions to protect states.
|
|
181
|
+
Use XState `always` transitions to protect states. An `always` transition is a function evaluated on state entry: return `{ target }` to redirect _before_ the state is fully entered, or `undefined` to stay:
|
|
152
182
|
|
|
153
183
|
```typescript
|
|
154
184
|
dashboard: {
|
|
155
185
|
id: "dashboard",
|
|
156
186
|
meta: { route: "/dashboard" },
|
|
157
|
-
always: {
|
|
187
|
+
always: ({ context }) => {
|
|
158
188
|
// If not authenticated, redirect to login immediately
|
|
159
|
-
|
|
160
|
-
target: "login"
|
|
189
|
+
if (context.isAuthenticated) return;
|
|
190
|
+
return { target: "login" };
|
|
161
191
|
},
|
|
162
192
|
},
|
|
163
193
|
profile: {
|
|
164
194
|
id: "profile",
|
|
165
195
|
meta: { route: "/profile/:username" },
|
|
166
|
-
always: {
|
|
167
|
-
|
|
168
|
-
target: "login"
|
|
196
|
+
always: ({ context }) => {
|
|
197
|
+
if (context.isAuthenticated) return;
|
|
198
|
+
return { target: "login" };
|
|
169
199
|
},
|
|
170
200
|
},
|
|
171
201
|
```
|
|
172
202
|
|
|
173
|
-
**Why `always` and not
|
|
203
|
+
**Why `always` and not guards on events?** Guard checks inside event transitions answer "can I TAKE this transition?". `always` transitions check "can I BE in this state?" — the correct invariant for authentication. The actor enforces the check even on direct URL access (browser back/forward or deep link), because the router sends a `play.route` event which triggers the `always` transition.
|
|
174
204
|
|
|
175
205
|
### Root-Level Event Handlers
|
|
176
206
|
|
|
177
207
|
Domain events placed at the root `on:` level are handled from any state:
|
|
178
208
|
|
|
179
209
|
```typescript
|
|
180
|
-
const authMachine = authSetup
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
210
|
+
const authMachine = createRoutedMachine(authSetup)({
|
|
211
|
+
// ...
|
|
212
|
+
on: {
|
|
213
|
+
"auth.login": ({ context, event }) => {
|
|
214
|
+
if (context.isAuthenticated) return;
|
|
215
|
+
return {
|
|
185
216
|
target: ".dashboard",
|
|
186
|
-
|
|
187
|
-
actions: authSetup.assign({
|
|
217
|
+
context: {
|
|
188
218
|
isAuthenticated: true,
|
|
189
|
-
username:
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
|
|
219
|
+
username: event.username,
|
|
220
|
+
},
|
|
221
|
+
};
|
|
222
|
+
},
|
|
223
|
+
"auth.logout": ({ context }) => {
|
|
224
|
+
if (!context.isAuthenticated) return;
|
|
225
|
+
return {
|
|
193
226
|
target: ".home",
|
|
194
|
-
|
|
195
|
-
actions: authSetup.assign({
|
|
227
|
+
context: {
|
|
196
228
|
isAuthenticated: false,
|
|
197
229
|
username: null,
|
|
198
|
-
}
|
|
199
|
-
}
|
|
230
|
+
},
|
|
231
|
+
};
|
|
200
232
|
},
|
|
201
|
-
|
|
202
|
-
}
|
|
203
|
-
);
|
|
233
|
+
},
|
|
234
|
+
states: {/* ... */},
|
|
235
|
+
});
|
|
204
236
|
```
|
|
205
237
|
|
|
206
238
|
## Complete Actor Usage
|
|
@@ -287,7 +319,7 @@ function App() {
|
|
|
287
319
|
| **Actor Authority (INV-01)** | Guards on the machine validate every navigation. The router cannot change state directly. |
|
|
288
320
|
| **Passive Infrastructure (INV-04)** | The router observes `actor.currentRoute` — it never decides where to go. |
|
|
289
321
|
| **State-Driven Reset (INV-03)** | Browser back/forward sends `play.route` events to the actor. History is driven by actor state. |
|
|
290
|
-
| **Strict Separation (INV-02)** | The machine has zero framework imports. Guards,
|
|
322
|
+
| **Strict Separation (INV-02)** | The machine has zero framework imports. Guards, transitions, and context are pure TypeScript. |
|
|
291
323
|
|
|
292
324
|
## Next Steps
|
|
293
325
|
|