Skip to content

Middleware

Middleware and event listeners observe state changes. They are observational — they cannot block or modify state mutations.

Flat Middleware

ts
mesh.middleware((event) => {
  analytics.track(event.type);
});

Event Listeners (mesh.on)

Subscribe to events matching a filter:

ts
// All action events
mesh.on({ type: "action.completed" }, (event) => {
  console.log(`Action ${event.name} completed`);
});

// All resource events (wildcard prefix)
mesh.on({ type: "resource.*" }, (event) => {
  console.log(`Resource event: ${event.type}`);
});

// Specific mutation by name pattern
mesh.on({ type: /mutation\./, name: /^orders\./ }, (event) => {
  console.log(`Order mutation: ${event.type}`);
});

// RegExp filter
mesh.on({ type: /error$/ }, (event) => {
  console.error("Error event:", event);
});

Filter Syntax

FilterMatches
{ type: "action.completed" }Exact match
{ type: "resource.*" }Wildcard prefix
{ type: /error$/ }RegExp
{ name: "cart.addItem" }By event name
{ type: "action.*", name: /^cart\./ }Combined

Error Isolation

Middleware and event listeners are error-isolated. Synchronous throws and rejected promises are caught and logged — they never break state mutations:

ts
mesh.middleware((event) => {
  throw new Error("This won't break state mutations");
});

mesh.on({ type: "state.changed" }, async (event) => {
  await fetch("/analytics", { method: "POST", body: JSON.stringify(event) });
  // If this fails, state mutations continue normally
});

Unsubscribe

ts
const unsubscribe = mesh.on({ type: "state.changed" }, handler);
// Later:
unsubscribe();

Logger Plugin

ts
import { loggerPlugin } from "statemesh-core/devtools";

mesh.use(loggerPlugin({
  enabled: process.env.NODE_ENV === "development",
  mask: ["user.email", "auth.token", "payment.card"]
}));

Important Notes

TIP

Middleware is observational. Use guards to block operations.

WARNING

Event listeners are fire-and-forget. Errors are logged to console.error but never propagated.

Next Steps

Released under the MIT License.