@uistate/core
v5.6.2
Published
Lightweight event-driven state management with path-based subscriptions, wildcards, and async support
Readme
@uistate/core
Path-based state management with wildcard subscriptions and async support.
Install
npm install @uistate/coreQuick Start
import { createEventState } from '@uistate/core';
const store = createEventState({ user: { name: 'Alice' }, count: 0 });
// Exact path
store.subscribe('count', (value) => console.log('Count:', value));
// Wildcard — fires on any child of 'user'
store.subscribe('user.*', ({ path, value }) => console.log(path, value));
// Global — fires on every change
store.subscribe('*', ({ path, value }) => console.log(path, value));
store.set('user.name', 'Bob');
store.set('count', 1);API
createEventState(initialState)
Returns a store with get, set, batch, setMany, subscribe, setAsync, cancel, destroy.
store.get(path?)
store.get('user.name'); // 'Alice'
store.get('user'); // { name: 'Alice' }
store.get(); // entire statestore.set(path, value)
Sets a value and notifies subscribers. Creates intermediate objects if needed.
store.set('user.email', '[email protected]');
// state.user.email now exists even if it didn't beforestore.subscribe(path, handler)
Returns an unsubscribe function. Exact subscribers get (value, detail). Wildcard/global subscribers get (detail) where detail is { path, value, oldValue }.
const unsub = store.subscribe('count', (value, { oldValue }) => {
console.log(`${oldValue} → ${value}`);
});
unsub(); // cleanupstore.batch(fn)
Batch multiple set() calls. Subscribers fire once per unique path after the batch completes, not during. Supports nesting.
store.batch(() => {
store.set('ui.route.view', 'user');
store.set('ui.route.path', '/users/42');
store.set('ui.route.params', { id: '42' });
});
// Subscribers fire here, once per path, all state consistentstore.setMany(entries)
Set multiple paths atomically. Shorthand for batch + a loop of set calls. Accepts a plain object, an array of [path, value] pairs, or a Map.
store.setMany({
'ui.route.view': 'user',
'ui.route.path': '/users/42',
'ui.route.params': { id: '42' },
});store.setAsync(path, fetcher)
Manages async state at ${path}.status, ${path}.data, ${path}.error. Supports abort on re-call.
await store.setAsync('users', async (signal) => {
const res = await fetch('/api/users', { signal });
return res.json();
});
// store.get('users.data') → [...]
// store.get('users.status') → 'success'store.cancel(path) / store.destroy()
Cancel an in-flight async operation, or tear down the entire store.
Query Client
Convenience wrapper around setAsync for data-fetching patterns.
import { createQueryClient } from '@uistate/core/query';
const qc = createQueryClient(store);
await qc.query('users', (signal) => fetch('/api/users', { signal }).then(r => r.json()));
qc.getData('users');
qc.getStatus('users');
qc.cancel('users');
qc.invalidate('users');Ecosystem
| Package | Description | License |
|---|---|---|
| @uistate/core | Path-based state management with wildcard subscriptions and async support | MIT |
| @uistate/view | State-driven view: DOMless resolve + surgical DOM projector. View tree as first-class state | MIT |
| @uistate/react | React adapter — usePath, useIntent, useAsync hooks and EventStateProvider | MIT |
| @uistate/css | Reactive CSSOM engine — design tokens, typed validation, WCAG enforcement, all via path-based state | MIT |
| @uistate/event-test | Event-sequence testing for UIstate stores | Proprietary |
| @uistate/examples | Example applications and patterns | MIT |
| @uistate/renderer | Direct-binding reactive renderer: bind-*, set, each attributes. Zero build step | Proprietary |
| @uistate/aliases | Ergonomic single-character and short-name DOM aliases for vanilla JS | MIT |
📖 Documentation: uistate.com
License
MIT — see LICENSE.
Copyright © 2025–2026 Ajdin Imsirovic
