Jadpo is experimental and not ready for production. These docs follow the compiler's main branch as of 5 Nov 2026. What's built · Install 0.3.0
jadpo
ReferenceEvents

Background workEvents

Declaring an event

On this page

An event records that something happened, so that other code can react to it later without the action that caused it waiting. You declare it as a type whose base is Event, named in the past tense, one per file in the domain's events/ folder.

domains/planning/events/todo_completed.jadpo:

example
use planning/entities { Todo }/// A todo was marked complete.type TodoCompleted = Event {    todo_id: Todo.id    completed_at: Instant}

TodoCompleted says a todo was completed, which todo and when. Event and Instant are built in. Todo is your app's own entity, a kind of stored record, and the use line brings it in from its file:

domains/planning/entities/todo.jadpo:

example
/// Something to do.entity Todo {    id: Uuid    done: Bool    policy: {        create: [Access.public]        read: [Access.public, Access.system]        update: [Access.public]    }}

Access.public lets anyone in, which keeps this example short (Policy), and jadpo migrate new initial makes the tables.

An action emits the event, and a subscriber reacts to it, so the next two topics finish this example. public type instead of type lets another domain subscribe to it (Reacting in another domain).

What an event holds

An event is written as a failure is (Declaring a failure): type X = Event { ... }, as type X = Failure { ... }. Its fields follow the ordinary type rules.

Carry ids and the facts of the moment, not whole records. A subscriber that needs more reads the current state.

One type per event

Each event is its own type. There are no event families with variants, such as TodoEvent.completed, so subscribing to an event and matching on it never depend on a list that grows.

An event nobody uses

An event nothing subscribes to is reported like any declaration nothing uses.

The event record

An event's shape is recorded, and a change to it is shown as a diff, as an API's shape is (The public API record). This matters because events waiting in the outbox when a new build ships are read with the new shape. So every event is recorded, not only public ones.

Each domain that declares an event keeps one record beside its events, domains/<domain>/events/events.jadpo_record (written by jadpo records update; never edit it by hand). It is a view in the record format (record events 1), whose header says it is generated from "the events of domain <domain>". There is no command of its own: jadpo records update writes it, and jadpo records lists it.

The record holds an event <Name> entry for each event, marked public when another domain may subscribe to it. Under each entry are its fields as its payload carries them, in the API record's wire form (words: Text { max_length: 200 }). Then comes an object, enum, input or output entry for each type a field names, written as the API record writes them. Events, fields and types are sorted by born name. Descriptions are left out, as in the API record.

The record is checked as the API record is (What is committed, and why). A missing record, one whose events changed (record.out_of_date, naming each entry added, changed or removed), and the record of a domain left with no events, are all put right by jadpo records update. A hand edit Jadpo couldn't have written is record.edited. While an event file has errors, the record isn't compared.

Events waiting in the outbox are read with the new shape, and subscribers read what an event carries, so an event is both sent and read. A change that breaks either needs a person's acceptance, as the API record's breaks do: an event removed (planning.TodoCompleted: ApiChange.event_removed), a field removed or retyped (ApiChange.output_field_removed, .output_field_retyped), a required field added (.input_field_required) or a rule tightened (.rule_tightened), each named <domain>.<Event>.<field>.

Markdown for agents: /docs/declaring-an-event.md.Built from Jadpo main at aee2e8f.