Quick Start
This guide walks through the core mental model: a shared event queue, a collection model, indexes, and selectors.
1. Create an Event Queue
All reactive components share one queue. The scheduler controls when subscribers run:
import { OIMEventQueue, OIMEventQueueSchedulerFactory } from '@oimdb/core';
const queue = new OIMEventQueue({
scheduler: OIMEventQueueSchedulerFactory.createMicrotask(),
});
Common schedulers:
| Scheduler | Use case |
|---|---|
createMicrotask() | Default — fast, same-tick delivery |
createTimeout(0) | Batch many writes before notifying |
createAnimationFrame() | UI-friendly, aligned with paint |
createImmediate() | Synchronous — useful in tests |
2. Create a Collection Model
The DX model keeps the core pieces together without storing indexes inside the collection:
import { createOIMCollectionKit } from '@oimdb/core';
type User = {
id: string;
name: string;
email: string;
teamId: string;
};
const users = createOIMCollectionKit<User, string>(queue, {
selectPk: (user) => user.id,
});
Writes return canonical slots — stable object references that indexes can hold:
const slot = users.collection.upsertOne({
id: 'user1',
name: 'John',
email: 'john@example.com',
teamId: 'team-a',
});
// Updating keeps the same slot object
const updatedSlot = users.collection.upsertOne({
id: 'user1',
name: 'John Doe',
email: 'john@example.com',
teamId: 'team-a',
});
console.log(slot === updatedSlot); // true
3. Subscribe to Changes
Subscriptions are key-scoped — you only pay for keys you watch:
users.collection.updateEventEmitter.subscribeOnKey('user1', () => {
console.log('user1 changed');
});
users.collection.updateEventEmitter.subscribeOnKeys(['user1', 'user2'], () => {
console.log('user1 or user2 changed');
});
After mutations, flush the queue (or wait for the scheduler):
users.collection.upsertOne({
id: 'user1',
name: 'Jane',
email: 'jane@example.com',
teamId: 'team-a',
});
await queue.flush();
4. Add an Index and Selector
Derived indexes maintain membership from entity data. Selectors give you reactive reads:
const usersByTeam = users.indexFactory.derivedSetIndex((user) => user.teamId);
const teamUsers = users.select.entitiesBySetIndexKey(usersByTeam, 'team-a');
teamUsers.watch((value) => {
console.log(value);
});
5. Process Events
Multiple writes to the same key coalesce into a single notification per flush:
users.collection.upsertOne({
id: 'user1',
name: 'A',
email: 'a@example.com',
teamId: 'team-a',
});
users.collection.upsertOne({
id: 'user1',
name: 'B',
email: 'b@example.com',
teamId: 'team-a',
});
users.collection.upsertOne({
id: 'user1',
name: 'C',
email: 'c@example.com',
teamId: 'team-a',
});
await queue.flush();
// subscribeOnKey('user1') fires once
What's Next
- Core Model — collection model, slots, and event semantics
- Indexes and Selectors — derived indexes and reactive reads
- Performance Guide — benchmarks and tuning
- Packages — integration packages (React, Redux, async)