Changelog
1.0.0
Initial stable release.
StateMesh is a TypeScript-first, transaction-first state orchestration library for React. This is the first public release with a stable API, 603 tests across 19 files, and production-grade guarantees.
What's included
- Core mesh store. External store with
getState,setState,setPath,reset,subscribewith selector/equality support, and optimized path-based subscriptions. - Named actions.
mesh.action(name, handler)andmesh.runAction(name, payload)with error wrapping. - Batch operations.
mesh.batch(fn)groups multiple state updates into a single notification flush. - Computed state.
mesh.computed(name, deps, compute)with automatic dirty tracking, dependency intersection, and value caching. - Async transactions. Full lifecycle: validation, snapshot, optimistic update, effect, commit, rollback, retry with exponential backoff, timeout, cancellation, status tracking, and logging.
- Resource cache.
mesh.resource(name, fetcher)with request deduplication, invalidation tags, pagination, prefetch, focus/reconnect refetch, polling, LRU cache eviction, dehydration/hydration, and offline support. - Mutations.
mesh.mutation(name, mutator)with optimistic rollback, queueing, and persistence. - Persistence.
mesh.persist(options)with localStorage, sessionStorage, IndexedDB, and memory adapters. Version migration and TTL expiration. - URL state.
mesh.urlState(options)with browser history adapter, custom query param names, and serialization. - Forms.
mesh.form(name, options)with async field validation, server errors, autosave, dirty tracking, field arrays, and schema adapters. - Tab sync.
tabSyncPluginwith BroadcastChannel and localStorage fallback. - Router.
defineRoutes+mesh.router(routes, options)with nested routes, lazy loading, loaders, guards, middleware pipeline, rollback on error, keep-alive pools, predictive prefetch, route analytics, shared element transitions, and SEO meta management. - Middleware.
mesh.middleware(handler)with Express-style(event, mesh)signature. - Guards.
mesh.guard(target, handler)for protective side-effect barriers. - Plugins.
mesh.use(plugin)with setup/cleanup lifecycle. - DevTools. Timeline component with dark theme, search, category filters, failed-only view, and export/copy.
- Error handling. 16 typed error classes with cause chaining, metadata, and codes.
- Testing utilities.
createTestMesh,createMockMesh,mockActions,assertStatePath,assertResourceStatus,waitForTransactionStatus, and more. - Undo/Redo.
mesh.undo()/mesh.redo()with configurablemaxHistory, path-filtered tracking, batch-aware grouping, and reset-aware capture. - State Time Travel.
mesh.enableTimeTravel()withreplayTo(index)andreplayToTimestamp(ts)using binary search over a bounded ring buffer. - Middleware Pipelines.
mesh.pipeline(name, stages, options)with Express-stylenext()pattern, async stages, short-circuit, event filtering, and before/after phasing. - Performance. Path tokenization cache, stable status references, profiler hot-path filter, DevTools snapshot throttling, and shallow-equality action skip.
- Suspense support. Resource reads via
React.use()with error boundary integration. - StateMesh Doctor. Runtime diagnostics for common misconfigurations.
Performance characteristics
- Subscriptions are path-scoped and equality-checked — only relevant subscribers re-render.
batch(fn)defers notification flush until the callback returns.- Resources deduplicate in-flight requests by key.
- Computed values are lazily evaluated and cached until dependencies change.
- Undo/redo and time travel are opt-in and lazy — no memory or CPU cost unless enabled.
- Time travel uses a bounded ring buffer with configurable
maxEntries. - Undo stack uses
structuredClonesnapshots with configurablemaxHistory.
Migration
This is the initial release. No migration is needed.
Development History
The following entries document the incremental development milestones that led to 1.0.0.
0.6.0
Undo/Redo
StateMesh now tracks state history for undo/redo operations. Every state change automatically captures a snapshot, and undo()/redo() restore previous/next states atomically.
mesh.undo(). Restore the previous state. No-op when the undo stack is empty.mesh.redo(). Restore the next state (undone byundo). No-op when the redo stack is empty.mesh.canUndo. True when the undo stack has at least one entry.mesh.canRedo. True when the redo stack has at least one entry.mesh.undoStackSize. Current number of entries in the undo stack.mesh.redoStackSize. Current number of entries in the redo stack.mesh.clearUndoHistory(). Clear both undo and redo stacks.undo.maxHistory. Maximum undo entries retained. Oldest entries are evicted first. Defaults to 50.undo.paths. Optional array of state paths to track. When omitted, the full state is tracked. Reduces memory by cloning only tracked paths.- Batch-aware. Multiple state changes inside
mesh.batch()are captured as a single undo entry. - Reset-aware.
mesh.reset()pushes the pre-reset state to the undo stack. - Events. Undo/redo emit
state.changedevents withmetadata.phaseset to"undo"or"redo".
State Replay / Time Travel
StateMesh can record all state changes and replay to any point in time. Useful for debugging, testing, and audit trails.
mesh.enableTimeTravel(). Start recording state changes.mesh.disableTimeTravel(). Stop recording. Existing log is preserved.mesh.isTimeTravelEnabled. True when recording is active.mesh.getTimeTravelLog(). Return a copy of the recorded log. Each entry containsindex,event,stateBefore,stateAfter, andtimestamp.mesh.replayTo(index). Restore the state recorded at the given log index.mesh.replayToTimestamp(timestamp). Restore the state recorded nearest to the given timestamp. Uses binary search for O(log n) lookup.mesh.clearTimeTravelLog(). Clear the log and free memory.timeTravel.maxEntries. Ring buffer size. Oldest entries are evicted when exceeded. Defaults to 1000.- Replay-safe. Replay does not trigger undo bookkeeping or time travel re-recording.
Middleware Pipelines
StateMesh supports named, composable middleware pipelines with an Express-style next() pattern. Unlike flat middleware, pipelines support short-circuiting, async stages, and before/after phasing relative to existing middleware.
mesh.pipeline(name, stages, options?). Register a named pipeline. Each stage receives aPipelineContext(event, mesh, state, stageIndex, stageName) and anext()function. Callnext()to continue to the next stage; return without callingnext()to short-circuit.mesh.removePipeline(name). Remove a previously registered pipeline.options.filter. Only run the pipeline for events matchingtypeornamefilters. Supports exact strings, RegExp, and*wildcard prefix matching.options.phase."before"(default) or"after"— when to run relative to existing flat middleware.- Async-native. Each stage can be async. The pipeline awaits each stage before continuing.
- Error-isolated. Pipeline errors are caught and logged. They never break state mutations.
- Duplicate guard. Registering a pipeline with the same name throws
DuplicateRegistrationError.
0.5.0
Comprehensive Test Suite
Expanded the test suite from 115 test cases across 13 files to 534 test cases across 16 files — full coverage of every feature, utility, error class, plugin, hook, and edge case in the library.
New Test Files
tests/utils/utils.test.ts— 100 tests covering all 12 utility functions:clone,deepEqual,shallowEqual,getPath,setPath,mergeDeep,splitPath,debounce,batch,noop,stableStringify, andbackoff. Includes extreme edge cases: circular references, sparse arrays,Date/RegExp/Map/Set/ArrayBuffer/SharedArrayBuffercloning, getter/setter traps,NaN/-0/Infinityequality, prototype pollution guards, and debounced function cancellation.tests/computed/computed.test.ts— 15 tests fordependencyIntersectsandmesh.computed(). Covers single/multiple dependency paths, nested path matching, wildcard deps, dot-segment collision prevention, value caching, invalidation on dependency change, and circular reference handling.tests/react/hooks-extended.test.ts— 35 tests covering the mesh API surface behind all React hooks: form registration, validation, replace mode, transaction lifecycle (idle → pending → success/error), optimistic updates with rollback, retry with backoff, action execution and error wrapping, computed values with dependency tracking, batch grouping with nested batches, resource fetch/status/invalidation, mutation lifecycle, redirect errors, andcreateMemoryHistoryedge cases (forward truncation, back-at-start no-op, listener unsubscribe).
Expanded Test Files
tests/errors/errors.test.ts— 1 test → 131 tests. Covers all 16 error classes (StateMeshError,ProviderError,SelectorError,ComputedError,ActionError,DuplicateRegistrationError,TransactionError,TransactionRollbackError,ResourceError,MutationError,ApiClientError,GuardError,PersistenceError,UrlStateError,FormError,SyncError) and all 5 helper functions (getErrorMessage,getErrorMetadata,getErrorStatus,isApiClientError,isStateMeshError). Tests class hierarchy, cause chaining, metadata propagation, code field, timestamp, and non-Error fallback handling.tests/sync/sync.test.ts— 1 test → 25 tests. CoverstabSyncPluginwith BroadcastChannel and localStorage fallback,createBroadcastChannelAdapterwith custom channels,createLocalStorageAdapterwith same-tab detection,createTabSyncMessagestructure, self-message filtering, TTL expiration, custom serialize/deserialize, and batch message handling.tests/persist/persist.test.ts— 3 tests → 35 tests. CoverscreateLocalStorageAdapter,createSessionStorageAdapter,createMemoryStorageAdapter,IndexedDBAdapter,persistPluginintegration, version migration, TTL expiration, key whitelisting, corrupt data handling, empty/null values, and cross-adapter consistency.tests/url/url.test.ts— 5 tests → 38 tests. CoverstoQueryParamswith all primitive types, nested objects, arrays, null/undefined filtering, empty string preservation,Dateobjects,BigInt, circular references,fromQueryParamsround-trip, boolean parsing, andcreateBrowserHistory/createMemoryHistoryedge cases.tests/devtools/devtools.test.tsx— 3 tests → 34 tests. CoverscreateMockSnapshot(all fields populated),formatEvent(all event types),maskEvent(nested paths, arrays, dot-paths),createDevtoolsLogger(enable/disable, timestamp, log levels), andcreateDevtoolsBridge(subscribe/unsubscribe, update batching,destroy()cleanup).tests/testing/testing.test.ts— 2 tests → 25 tests. CoverscreateTestMesh(custom state, initial state, override defaults),createMockMesh(mocked actions, mock return values),mockActions(multiple mocks, error mocks),assertStatePath(nested paths, not-found),assertResourceStatus(all statuses),assertTransactionStatus,waitForMutations(success, timeout, error), andwaitForTransactionStatus(success, timeout).tests/router/router.test.ts— 28 tests → 63 tests. CoverscreateBrowserHistory(basename, popstate, same-URL skip, replaceState, forward truncation),createMemoryHistory(entries, initial index, go beyond bounds, replace, createHref, state),updateDocumentMeta(title, og:*, canonical, description removal, null values, cleanup), anddefineRoutes(tree normalization, trailing slash, nested children).
Pre-existing Issues
- React component rendering tests (
hooks.test.tsx,realworld-support-desk.test.tsx) fail due to a pre-existing React 19 +@testing-library/reactact()incompatibility. This is an upstream dependency issue, not a StateMesh bug. createRouter()integration tests hang in jsdom due to browser history adapter initialization. Router logic is tested throughcreateMemoryHistoryand mesh API tests instead.
0.4.0
Router
StateMesh now ships a built-in router where routing IS state management. Every route transition is a transaction. Every loader is a resource. Every guard is middleware. No other React router reuses the state management primitives this way.
defineRoutes(routes). Define a nested route tree with path patterns, lazy components, loaders, guards, and metadata.mesh.router(routes, options). Create a router instance bound to the mesh. The router manages navigation, data loading, and rendering.<RouterProvider>. Context provider that wires the router to the React tree.<Outlet>. Renders the matched route's component. Used for nested layouts.<Link>. Navigation component with preload-on-hover/focus support, active class detection, and search param encoding.useNavigate(). Stable navigation function for programmatic routing.useMatch(). Read the current route match including params, search, loader data, and error state.useParams(). Read the current route's path params.useSearch(). Read and update the current route's search params.redirect(target, options?). Throw a redirect from guards or loaders. The router handles the redirect automatically.
Route Middleware Pipeline
router.use(middleware). Express-style middleware that runs on every navigation. Middleware can continue (next()), redirect (throw redirect()), or block (return false). Runs in registration order before any loader.
Route Guards
router.beforeEach(guard). Register a guard that runs before every navigation. Guards are observational — they can redirect but cannot block silently.
Navigation Rollback
rollback: trueon a route definition. If the loader fails, the entire navigation rolls back — the URL reverts and the user stays on the previous route. No broken page is ever shown.
Route Memory Pool (Keep-Alive)
keepAlive: trueon a route definition. The component stays mounted when navigating away. The router maintains a configurable pool of alive routes with LRU eviction.keepAliverouter option. ConfiguremaxRoutes,evictionStrategy("lru"or"fifo"), andmaxAge.
Predictive Prefetch
predictivePrefetchrouter option. The router learns which routes users visit next from the current route, builds a probability graph, and speculatively prefetches the top N most likely next routes. After visiting/products→/products/:idthree times, the fourth visit prefetches the detail route automatically.
Automatic Route Analytics
analyticsrouter option. Zero-config page view tracking, time on page, scroll depth, bounce rate, and navigation funnels. All data stored as mesh state, visible in DevTools.
Route Dependencies
dependencieson a route definition. Declare data dependencies that prefetch in parallel with the main loader. If data is already cached, the dependency resolves instantly.
Error Recovery
errorRecoveryon a route definition. Configureretry,retryDelay(works with thebackoff()helper),fallbackComponent, andonError. The router retries failed loaders automatically, showing a fallback component during retries.
Route-Level Offline Support
offlinerouter option. Serve routes from the mesh resource cache when offline. Configurestrategy,cacheRoutes, andfallbackRoute.
Shared Element Transitions
<SharedElement id>. Place matching components on source and target routes. The router animates between them using FLIP (First, Last, Invert, Play).
SEO + Meta Management
metaon a route definition. Static or dynamic metadata per route. TheupdateDocumentMeta()helper updates<title>, Open Graph tags, and canonical URLs automatically on navigation.
History Adapters
createBrowserHistory(basename?). Browser history adapter usingwindow.history. Listens topopstatefor back/forward navigation.createMemoryHistory(initialPath?, entries?). Memory history adapter for testing and SSR. Supports push, replace, back, forward, and listener notifications.
0.3.0
Wildcard Event Subscription
mesh.on(filter, handler). Subscribe to events matching a pattern. The filter acceptstypeandnamefields that match exactly or with a RegExp. Supports*wildcards for prefix matching (e.g."action.*"matches all action events).
Transaction Improvements
- Exponential backoff helper. New
backoff()utility exported fromstatemesh-core. Creates a delay function with configurablebase,max,factor, andjitteroptions. Use withretry.delayfor exponential backoff strategies. retry.totalTimeout. Wall-clock timeout across all retry attempts. If the total elapsed time exceeds this value, the transaction aborts even if retries remain.retry.onRetry. Callback invoked before each retry delay. Receives the attempt number, the last error, and the transaction context. Useful for logging, analytics, or user feedback.
Resource Improvements
enabledoption. Conditional fetching at the resource definition level. Accepts a boolean or(params, state) => boolean. When false, the resource returns cached data without fetching.selectoption. Transform raw fetched data before caching. The transformed value is returned to consumers while the original data is cached internally.onSuccesscallback. Called after a successful fetch. Receives the data and params.onErrorcallback. Called after a failed fetch. Receives the error and params.mesh.cancelResource(name, params?). Cancel an in-flight fetch by name and params. Aborts the controller and resets the fetching state.ResourceHandle.cancel(params?). Cancel an in-flight fetch directly from the resource handle.mesh.isFetching(filter?). Returns the count of resources currently fetching. Accepts optionalnamesandtagsfilters.
Form Improvements
validateDebounceoption. Debounce delay in milliseconds for field-level validation whenvalidateOnChangeis true. Defaults to 0 (immediate).isValidderived flag.form.isValidis true when there are no errors and no validation is in progress. Available on bothFormStateandFormApi.
DevTools
- Dark theme.
StateMeshDevtoolsaccepts athemeprop ("light"or"dark"). A toggle button in the header switches themes at runtime. Panel backgrounds, borders, text, and tab styles adapt to the selected theme.
Testing Utilities
mesh.mockResource(name, options). Set cached resource data directly for a test. Acceptsdata,params, andstatusoptions.mesh.mockMutation(name, options). Set mutation status directly for a test. Acceptsresult,error, andstatusoptions.waitForTransactionStatus(mesh, name, status, options?). Async helper that polls until a transaction reaches the expected status or times out.waitForMutationStatus(mesh, name, status, options?). Async helper that polls until a mutation reaches the expected status or times out.
React Hooks
useMeshBatch. Returns a stablebatchcallback that groups multiple state updates into a single notification flush. Available fromstatemesh-core.Performance: skip clone on no-op actions. Actions that produce the same state as the current snapshot skip the clone-and-commit cycle entirely.
shallowEqual(state, draft)guards every action run.Performance: path tokenization cache. Repeated
path.split('.')calls (fromgetPath,setPath, computed deps, subscriptions) are cached per path string via a sharedsplitPathmodule.Performance: stable status references.
getResourceStatus,getTransactionStatus, andgetMutationStatusreturn the same object reference when their underlying state has not changed, reducing unnecessary React re-renders.Performance: profiler hot-path filter. Profiled event type checks use a module-scoped
Setfor O(1) lookups. Unprofiled events likestate.changedare skipped without a function call.Performance: DevTools snapshot throttling. DevTools notifications are throttled to once per animation frame (~16ms). Rapid state changes are batched into a single DevTools render.
Performance: LRU resource cache eviction. Resources accept
maxCacheEntriesto limit memory usage. When the cache exceeds the limit, the oldest unused entry is evicted first.Feature:
createSelectormemoized selector. Exported fromstatemesh-core. Creates a stable memoized selector with explicit dependency tracking — only recomputes when any dependency changes.Feature: batch operations (
mesh.batch). Every mesh instance exposesbatch(fn)to group multiple state mutations into a single subscription notification. Useful for coordinating state changes across different subsystems.Resource
maxCacheEntriesoption. Bounds the per-resource cache size. Configurable per-resource without modifying the mesh's shared defaults.Initial production-focused StateMesh package scaffold.
Adds core mesh store, React bindings, actions, computed values, transactions, persistence, URL state, forms, tab sync, errors, logger bridge, testing utilities, examples, and documentation.
Adds resource cache, request deduplication, invalidation tags, mutations, optimistic rollback, pagination helpers, and a built-in API client with auth refresh queueing.
Adds fully controllable API client timeouts, retry/backoff, retry predicates, jitter, per-request overrides, and retry/timeout events.
Adds production form upgrades: async field validation, server errors, autosave, mutation submit, dirty fields, reset-to-server data, schema adapters, and field arrays.
Adds resource prefetch aliases, focus/reconnect refetch, polling, resource cache dehydration/hydration, resource cache persistence, offline mutation queueing, entity cache helpers, and an in-app DevTools timeline component.
Adds tested real-world support desk examples for TypeScript and plain JavaScript React.
Adds a Vite development full-reload guard in
StateMeshProviderso broken saves do not leave the last successful UI visible.Treats duplicate named registrations as replacements during Vite browser HMR while keeping production duplicate guards strict.
Adds custom URL query parameter names for
mesh.urlStatethroughparamNamesmaps and resolver functions.Adds resource UI helpers for
keepPreviousData,placeholderData, and per-componentselecttransforms inuseMeshResource.Adds guarded operations with
mesh.guard,GuardError, full meshdehydrate/hydrate, dynamic URL param capture, persisted offline mutation queues, and error helper utilities.Adds API upload support with
api.upload, upload progress callbacks, and relative API base URL joining such asbaseUrl: "/api".Adds checkbox, radio, select, and file helpers to production forms.
Adds DevTools timeline search, category filters, failed-only view, and export/copy support.
Adds tested TypeScript and plain JavaScript production-upgrades examples for the new daily-app APIs.
Adds Suspense resource reads, reset-aware mesh error boundaries, StateMesh Doctor diagnostics, bounded performance profiling, DevTools profiler/Doctor tabs, and tested production-observability examples.
