Plugins
Plugins add capabilities to the mesh. They have a lifecycle: setup runs when registered, cleanup runs when the mesh is destroyed.
Register a Plugin
ts
mesh.use({
name: "my-plugin",
setup(mesh) {
// Subscribe to events, register middleware, etc.
const unsub = mesh.on({ type: "state.changed" }, (event) => {
analytics.track("state_change", event);
});
return () => unsub(); // cleanup function
}
});Plugin Interface
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Unique plugin name |
setup | (mesh) => void | (() => void) | Yes | Setup function. Return a cleanup function. |
cleanup | () => void | No | Called when the mesh is destroyed (alternative to returning from setup) |
Duplicate Guard
Registering a plugin with the same name throws DuplicateRegistrationError:
ts
mesh.use({ name: "analytics", setup: () => {} });
mesh.use({ name: "analytics", setup: () => {} }); // ThrowsBuilt-in Plugins
| Plugin | Import | Description |
|---|---|---|
persistPlugin | statemesh-core/persist | State persistence |
tabSyncPlugin | statemesh-core/sync | Cross-tab sync |
loggerPlugin | statemesh-core/devtools | Console logger |
devtoolsBridgePlugin | statemesh-core/devtools | DevTools bridge |
Example: Analytics Plugin
ts
function analyticsPlugin(trackingId: string) {
return {
name: "analytics",
setup(mesh: Mesh) {
const unsub = mesh.on({ type: "action.completed" }, (event) => {
window.gtag("event", event.name, {
event_category: "action",
event_label: event.type
});
});
return unsub;
}
};
}
mesh.use(analyticsPlugin("G-XXXXXXXXXX"));Important Notes
TIP
Plugins are the recommended way to add cross-cutting concerns: analytics, logging, error reporting, and feature flags.
WARNING
Plugin setup runs synchronously when mesh.use() is called. If you need async initialization, handle it inside the setup function with a .then() or Promise.
Next Steps
- Cross-Tab Sync — Sync state across tabs
- DevTools — In-app DevTools
- Middleware — Event listeners
