Store
Context lives inside a machine. Some state belongs outside any one machine — shared across instances. createStore is a tiny reactive cell for exactly that: a plain value plus a listener set.
import { createStore } from '@dunky-dev/state-machine'
const store = createStore({ count: 0 })
store.get() // { count: 0 }store.set({ count: 1 }) // shallow-merge a patchstore.set(s => ({ count: s.count + 1 })) // or an updater functionconst off = store.subscribe(s => console.log(s.count))off() // unsubscribeNo-op writes don’t notify — set compares the incoming patch against current values and skips unchanged fields.
Domain methods
Section titled “Domain methods”Pass a second build argument to add named methods on top. build receives the base store, so the methods read/write through it:
const tooltipStore = createStore({ openId: null as string | null }, s => ({ setOpen: (id: string | null) => s.set({ openId: id }), isOpen: (id: string) => s.get().openId === id,}))
tooltipStore.setOpen('tip-1')tooltipStore.isOpen('tip-1') // truetooltipStore.isOpen('tip-2') // falseBridging a store into a machine
Section titled “Bridging a store into a machine”A store is not wired into a machine’s select automatically. To make a machine react to a shared store, subscribe and forward a plain event:
machine({ initial: 'idle', context: { id: 'tip-1' }, states: { idle: { effects: [ ({ context, send }) => tooltipStore.subscribe(s => { send({ type: s.openId === context.id ? 'activate' : 'deactivate' }) }), ], }, },})The machine handles the event; the store drives it from outside.