Commands & Events
These are the v1 docs. They are not maintained.
This page is a verbatim snapshot of the commiq 1.x documentation, kept for people still running 1.x. It is not corrected and not tested against any release. Several pages contain claims that were wrong when written: examples that do not run as printed, sealStore described as read-only when it was not, handledEvent presented as a working subscription pattern when it never matched, and effects described as swallowing only AbortError when they swallowed everything.
Do not treat anything here as a statement about how commiq 2.x behaves.
What changed in 2.0 and how to upgrade · Current documentation
Site search only indexes the current docs. Use the sidebar to browse these pages.
Commands & Events
createCommand(name, data)
Creates a command object to be queued on a store.
import { createCommand } from "@naikidev/commiq";
const cmd = createCommand("addTodo", { text: "Buy milk" });
// { name: "addTodo", data: { text: "Buy milk" }, correlationId: "", causedBy: null }Note: correlationId is assigned automatically when the command is queued via store.queue(). The empty string from createCommand is overwritten with a unique nanoid.
Tip: wrap in factory functions for a clean API:
export const addTodo = (text: string) => createCommand("addTodo", text);
export const toggleTodo = (id: number) => createCommand("toggleTodo", id);createEvent<D>(name)
Creates an event definition. The returned object contains a unique symbol id — this ensures events are matched by identity, not string comparison.
import { createEvent } from "@naikidev/commiq";
const userCreated = createEvent<{ name: string }>("userCreated");Use it to emit from a handler:
store.addCommandHandler("createUser", (ctx, cmd) => {
ctx.setState({ user: cmd.data });
ctx.emit(userCreated, { name: cmd.data.name });
});And to listen:
store.addEventHandler(userCreated, (ctx, event) => {
ctx.queue(createCommand("sendEmail", { to: event.data.name }));
});handledEvent(commandName)
Creates an event definition matching the auto-notify naming convention (<commandName>:handled). Useful when subscribing to auto-notified command events.
import { handledEvent } from "@naikidev/commiq";
const incHandled = handledEvent("increment");
// { id: Symbol("increment:handled"), name: "increment:handled" }To auto-notify, set notify: true on the handler:
store.addCommandHandler("increment", handler, { notify: true });matchEvent(event, eventDef)
Type guard that narrows a StoreEvent to its specific data type based on the event definition's symbol identity.
import { matchEvent, BuiltinEvent } from "@naikidev/commiq";
store.openStream((event) => {
if (matchEvent(event, BuiltinEvent.StateChanged)) {
// event.data is typed as { prev: S; next: S }
console.log(event.data.prev, "→", event.data.next);
}
});openStream listeners receive StoreEvent with data: unknown. Since TypeScript cannot narrow generic types through symbol identity checks, matchEvent provides the type-safe bridge:
// Without matchEvent — requires unsafe cast
if (event.id === BuiltinEvent.CommandHandlingError.id) {
const { command, error } = event.data as { command: Command; error: unknown };
}
// With matchEvent — fully typed
if (matchEvent(event, BuiltinEvent.CommandHandlingError)) {
const { command, error } = event.data; // inferred
}Works with custom events too:
const OrderPlaced = createEvent<{ orderId: string }>("order:placed");
store.openStream((event) => {
if (matchEvent(event, OrderPlaced)) {
console.log(event.data.orderId); // string
}
});Typed APIs like addEventHandler, bus.on, and effects.on already infer data types from the EventDef — use matchEvent only in raw openStream listeners.
sealStore(store)
Wraps a store in a read-only proxy that only exposes:
state— current state (getter)queue(command)— dispatch a commandflush()— wait for all queued commands to completeopenStream(listener)/closeStream(listener)— subscribe to events
import { sealStore } from "@naikidev/commiq";
const sealed = sealStore(store);
sealed.state; // allowed
sealed.queue(cmd); // allowed
await sealed.flush(); // allowed
sealed.addCommandHandler; // undefined (not exposed)createEventBus()
Creates a bus that routes events between multiple stores.
import { createEventBus } from "@naikidev/commiq";
const bus = createEventBus();
bus.connect(storeA);
bus.connect(storeB);
bus.on(userCreated, (event) => {
storeB.queue(createCommand("greet", { name: event.data.name }));
});
// Later, disconnect:
bus.disconnect(storeA);| Method | Description |
|---|---|
connect | Subscribe the bus to a store's stream |
disconnect | Unsubscribe from a store's stream |
on | Register a handler for a specific event |