This package contains inspection tools for XState.
Check out the XState + Vue Minute Timer + Viz example on CodeSandbox
- Install with npm or yarn:
npm install @xstate/inspect
# or yarn add @xstate/inspect
Via CDN
<script src="https://unpkg.com/@xstate/inspect/dist/xstate-inspect.umd.min.js"></script>
By using the global variable XStateInspect
- Import it at the beginning of your project, before any other code is called:
import { inspect } from '@xstate/inspect';
inspect({
// options
// url: 'https://stately.ai/viz?inspect', // (default)
iframe: false // open in new window
});
- Add
{ devTools: true }
to any interpreted machines you want to visualize:
import { interpret } from 'xstate';
import { inspect } from '@xstate/inspect';
// ...
const service = interpret(someMachine, { devTools: true });
service.start();
url
(optional) - The endpoint that the Inspector sends events to. Default: https://stately.ai/viz?inspectiframe
(optional) - The iframe that loads the provided URL. If iframe is set tofalse
, then a new tab is opened instead.devTools
(optional) - Allows custom implementation for lifecycle hooks.serialize
(optional) - A custom serializer for messages sent to the URL endpoint. Useful for sanitizing sensitive information, such as credentials, from leaving your application.targetWindow
(optional) - Provide a pre-existing window location that will be used instead of opening a new window etc. When using this option, you must still provide theurl
value due to security checks in browser APIs, and theiframe
option is ignored in such a case.
When is this useful?
- Remove sensitive items, such as
credentials
- Add additional custom handling
// Remove credentials from being forwarded
inspect({
serialize: (key: string, value: any) => {
return key === "credentials" && typeof value === "object" ? {} : value;
},
});
// Add a custom local log
inspect({
serialize: (key: string, value: any) => {
if (key === "ready") {
console.log("Detected ready key");
}
return value;
},
});
When is this useful?
- Allows you to quickly see all events and transitions for your machines
- No need to add manual
console.log
statements to your machine definitions
// The URL and port of your local project (ex. Vite, Webpack, etc).
const url = "http://127.0.0.1:5174/"
const inspector = inspect({
url,
iframe: undefined,
targetWindow: window
});
// In the same window, subsribe to messages from @xstate/inspector
createWindowReceiver({}).subscribe(console.log);
// Start your machine, and all events generated are logged to the console
interpret(machine, { devTools: true }).start({});
When is this useful?
- Forward messages to a custom endpoint, that you can then listen to and add custom handling for messages
// In your client application
const url = "http://127.0.0.1:8443/"
const targetWindow = window.open(url);
const inspector = inspect({
// The URL must still be provided. This is used by postMessage, as it's
// not possible to do targetWindow.location for security reasons
url,
targetWindow
});
// In the second, hosted application
createWindowReceiver({}).subscribe((event) => {
if (event.type === "service.register") {
// Do something when a new machine is started
} else if (event.type === "service.stop") {
// Do something when a machine enters a terminal state
} else if (event.type === "service.event") {
// Do something when a machine recieves an event
} else if (event.type === "service.state") {
// Do something when a machine enters to a new state
// Note: Does not handle transitional states.
}
});