@useoneauth/events
v1.0.0
Published
> Phase 5 — Event System. The durable, immutable event stream with audit and replay.
Downloads
333
Readme
@useoneauth/events
Phase 5 — Event System. The durable, immutable event stream with audit and replay.
Pure TypeScript. An append-only EventStore holds every event in a single globally
ordered log; a durable EventBus implements the existing @useoneauth/events-core
EventPublisher interface (persist-then-fan-out), so any service can be handed it
in place of InMemoryEventBus and gain durability for free. EventReplayer rebuilds
projections from history; AuditLogProjection is a worked example.
Install
// package.json
{ "dependencies": { "@useoneauth/events": "workspace:*" } }Usage
import { EventBus, InMemoryEventStore, EventReplayer, AuditLogProjection } from "@useoneauth/events"
const store = new InMemoryEventStore()
const bus = new EventBus(store) // drop-in @useoneauth/events-core EventPublisher
const audit = new AuditLogProjection()
bus.subscribeStored("IDENTITY_CREATED", (e) => audit.handle(e))
await bus.publish({ type: "IDENTITY_CREATED", occurredAt: new Date(), payload: { identityId: "u1" } })
audit.list()
// [{ sequence: 1, type: "IDENTITY_CREATED", subjectId: "u1", summary: "IDENTITY_CREATED · subject=u1", ... }]
// Rebuild any projection from the immutable log:
const rebuilt = new AuditLogProjection()
await new EventReplayer(store).replay({}, (e) => rebuilt.handle(e))Model
- StoredEvent —
{ id, sequence, type, occurredAt, storedAt, subjectId, payload }. The store assigns the 1-based monotonicsequence; the bus assignsid,storedAt, andsubjectId. Stored events are frozen (immutable). - EventStore —
append(rejects duplicate ids),getById,query(by type / subject /sinceSequencecursor / time / limit, ordered by sequence),count. Append-only: no update/delete. - EventBus —
publishpersists first, then fans out.subscribe(type, h)gets aDomainEvent;subscribeStored(type, h)gets the fullStoredEvent(sequence + metadata) and may be async. Store-first, isolated delivery: a throwing subscriber never failspublishor blocks siblings — its error routes toonSubscriberError. - subjectResolver default:
payload.subjectId ?? identityId ?? sessionId ?? id ?? null(overridable). - EventReplayer —
replay(filter, handler)re-dispatches matching events in order. - AuditLogProjection — derives human-readable audit entries; rebuildable via replay.
Scope
No DB/HTTP/CLI; no per-aggregate streams or optimistic concurrency; no webhook
dispatch. In-memory store behind the EventStore port; a Prisma adapter is deferred.
See ARCHITECTURE.md.
