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

Event log 3 events · append only
  1. 1 create-todo { title : "Buy groceries" }
  2. 2 create-todo { title : "Walk the dog" }
  3. 3 complete-todo { id : "t1" }
State · todos derived from the log
idtitledone
  • 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.

01

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.

declare
$ npm install \   @iwentsourcing/core \   @iwentsourcing/cli 
02

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.

run locally
$ npx iwentsourcing serve \   src/state/export.ts 
03

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.

deploy
$ 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.
Read the concepts
iwentsourcing
$ 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.