Middleware
Built-in Middleware
Section titled “Built-in Middleware”Logger Middleware
Section titled “Logger Middleware”Log all state changes before updates.
import { createStore } from '@standard-store/store';import { loggerMiddleware } from '@standard-store/store/middleware/logger';
const store = createStore(initialState, { middleware: [loggerMiddleware],});
store.setState({ count: 1 });// Console output: { count: 0 } → { count: 1 }Validation Middleware
Section titled “Validation Middleware”Enforce value constraints per key before updates.
import { createStore } from '@standard-store/store';import { validateMiddleware } from '@standard-store/store/middleware/validate';
const store = createStore(initialState, { middleware: [ validateMiddleware({ theme: (v) => ["light", "dark"].includes(v), count: (v) => typeof v === "number", }), ],});
store.setState({ theme: 'dark' }); // ✅ OKstore.setState({ theme: 'blue' }); // ❌ Throws errorCustom Middleware Interface
Section titled “Custom Middleware Interface”Middleware Structure
Section titled “Middleware Structure”interface StandardStoreMiddlewareV1 { name?: string;
onGet?<T>(key: string, value: T, next: () => T): T; onSet?<T>(key: string, value: T, next: () => void): void; onRemove?(key: string, next: () => void): void;}Methods:
| Method | Description |
|---|---|
onGet |
Intercept get operations (optional) |
onSet |
Intercept set operations (optional) |
onRemove |
Intercept remove operations (optional) |
Custom Middleware Example
Section titled “Custom Middleware Example”const customMiddleware = { name: 'analytics',
async onSet(key, value, next) { // Track state changes console.log(`Setting ${key} to`, value);
const result = await next();
// Perform side effect after state is set await analytics.track('state_change', { key, old: undefined, new: value, });
return result; },};Middleware Chaining
Section titled “Middleware Chaining”Combine multiple middleware in any order. They execute sequentially for hooks and in reverse order for after hooks.
import { loggerMiddleware } from '@standard-store/store/middleware/logger';import { validateMiddleware } from '@standard-store/store/middleware/validate';
const store = createStore(initialState, { middleware: [ loggerMiddleware, // Logs every operation validateMiddleware(rules), // Validates before updates customMiddleware, // Custom logic ],});Common Patterns
Section titled “Common Patterns”Analytics Tracking
Section titled “Analytics Tracking”const analyticsMiddleware = { name: 'analytics',
async after(state, nextState) { // Track state changes for analytics await analytics.track('state_change', { oldState: state, newState: nextState, }); },};Persistence Debouncing
Section titled “Persistence Debouncing”Debounce state updates to reduce storage writes.
const debounceMiddleware = { name: 'debounce-persist', timeoutId: null as NodeJS.Timeout | null,
after(state, nextState) { if (this.timeoutId) clearTimeout(this.timeoutId);
this.timeoutId = setTimeout(() => { localStorage.setItem('store', JSON.stringify(nextState)); }, 500); // Debounce by 500ms },};Side Effects Based on State Changes
Section titled “Side Effects Based on State Changes”Fetch data when user changes.
const sideEffectMiddleware = { name: 'fetch-user',
async after(state, nextState) { if (nextState.userId !== state.userId && nextState.userId) { // User changed, fetch their profile data const userData = await fetchUser(nextState.userId);
// Update store with fetched data store.setState({ user: userData, lastFetched: new Date() }); } },};See Also
Section titled “See Also”- Creating a Store - Using middleware in createStore