Commiq Docs
Examples

Event Stream

Event Stream

Every store exposes a real-time stream of all events it emits — builtin and custom. This is useful for debugging, logging, analytics, or building reactive UIs that respond to any store activity.

The API

// Subscribe
const listener = (event: StoreEvent) => {
  console.log(event.name, event.data);
};

store.openStream(listener);

// Unsubscribe
store.closeStream(listener);

Builtin Events

Every command processed by a store emits a sequence of builtin events:

Error cases:

Example: Real-Time Event Log

Subscribing to multiple stores

import type { StoreEvent } from "@naikidev/commiq";

interface LogEntry {
  storeName: string;
  eventName: string;
  data: unknown;
  time: string;
}

function createStreamLogger(
  stores: Record<string, SealedStore<any>>,
  onEntry: (entry: LogEntry) => void,
) {
  const listeners: Array<{
    store: SealedStore<any>;
    listener: (e: StoreEvent) => void;
  }> = [];

  for (const [name, store] of Object.entries(stores)) {
    const listener = (event: StoreEvent) => {
      onEntry({
        storeName: name,
        eventName: event.name,
        data: event.data,
        time: new Date().toISOString(),
      });
    };
    store.openStream(listener);
    listeners.push({ store, listener });
  }

  // Return cleanup function
  return () => {
    for (const { store, listener } of listeners) {
      store.closeStream(listener);
    }
  };
}

React component

function EventStreamViewer() {
  const [entries, setEntries] = useState<LogEntry[]>([]);

  useEffect(() => {
    const cleanup = createStreamLogger(
      { counter: counterStore, todo: todoStore },
      (entry) => setEntries((prev) => [...prev.slice(-200), entry]),
    );
    return cleanup;
  }, []);

  return (
    <table>
      <thead>
        <tr>
          <th>Time</th>
          <th>Store</th>
          <th>Event</th>
          <th>Data</th>
        </tr>
      </thead>
      <tbody>
        {entries.map((e, i) => (
          <tr key={i}>
            <td>{e.time}</td>
            <td>{e.storeName}</td>
            <td>{e.eventName}</td>
            <td>{JSON.stringify(e.data)}</td>
          </tr>
        ))}
      </tbody>
    </table>
  );
}

Filtering by event type

import { builtinEvents } from "@naikidev/commiq";

store.openStream((event) => {
  // Only state changes
  if (event.id === builtinEvents.stateChanged.id) {
    console.log("State:", event.data.prev, "→", event.data.next);
  }

  // Only errors
  if (event.id === builtinEvents.commandHandlingError.id) {
    reportError(event.data.error);
  }
});

Use Cases

Use CaseApproach
Dev toolsLog all events to console or a debug panel
AnalyticsTrack specific events and send to an analytics service
Undo/RedoRecord stateChanged events and replay prev states
Cross-store syncUse openStream directly (or event bus) to react to other stores
TestingAssert that specific events were emitted during a command

On this page