Event sourcing for TypeScript
Design your events.
We handle the rest.
Declare your events and state. iwentsourcing gives you an append-only history, an audit trail, live queries and an offline-capable browser client, without designing an API for any of it.
Try it
State is just a view of the log
Add a few events, then wipe the state and replay the log. Only the log is stored, and it only ever grows.
stream personal-ada
- 1 create-todo { title : "Buy groceries" }
- 2 create-todo { title : "Walk the dog" }
- 3 complete-todo { id : "t1" }
- t1 Buy groceries true
- t2 Walk the dog false
A small simulation that runs in your browser. In iwentsourcing, handlers do this on the server and in the browser client.
What you get
Model what happened. Derive the rest.
Event sourcing as a way of working, with the plumbing taken care of.
Events and data, not endpoints
Declare typed events, state and a stream pattern in TypeScript. The server API, per-user stream instances and typed clients follow from those definitions.
An audit trail by design
Every change is an immutable, timestamped event in an append-only log. There is no separate audit log to build, and nothing to forget to write.
State you can always rebuild
State is derived from events, never the source of truth. Change your handlers and replay a stream to rebuild its state from the stored events.
Live queries
Observe state from the client and get the result set again whenever it changes, without polling or hand-written subscriptions.
Local-first browser client
The browser client stores data in IndexedDB and has an offline mode, so an app keeps working without a connection and replicates its events to the server with sync().
How it works
From definition to deployed
You do not store the current state, you store every change that led to it, like a ledger where rows are only ever added. Read the concepts.
Declare
Describe your events, the state they produce and a stream per user, group or any key you choose. Handlers are small functions that apply an event to state.
$ npm install \ @iwentsourcing/core \ @iwentsourcing/cli Run locally
The CLI serves your definitions as an HTTP API, watches your files and reloads on change. Seed events give you deterministic data to develop against.
$ npx iwentsourcing serve \ src/state/export.ts Deploy
Upload your definitions to a tenant on the hosted platform. Uploads that would break the existing schema are rejected, and running instances keep their version.
$ npx iwentsourcing upload \ src/state/export.ts \ --host \ https://api.iwentsourcing.com For people and agents
Less code to write, less to review
Whether you or an AI agent writes the code, the surface that has to be right is small: the events, the state and the handlers. The rest is the framework, and the history shows exactly what happened.
- Typed, declarative events leave little room for hidden behaviour.
- The event log is a ground truth of what happened, for people and for tools.
- The CLI covers building, uploading, seeding, listing and replaying.
$ iwentsourcing serve <entry> $ iwentsourcing build <entry> $ iwentsourcing upload <entry> $ iwentsourcing seed $ iwentsourcing list-stream $ iwentsourcing replay-stream [pattern] $ iwentsourcing login Start building
Create an account, name your first tenant, then upload your definitions from the CLI. Prefer to start locally? The framework runs without an account.