TypeORM
@postel/typeorm — run Postel's storage through your existing TypeORM DataSource (Postgres, MySQL, or SQLite).
@postel/typeorm is an ORM adapter: hand Postel the TypeORM DataSource you already use and it issues its storage queries through it (via QueryRunners + raw SQL), so outbox writes share your connection and transactions. No Postel entities are required in your schema.
pnpm add @postel/typeorm typeormnpm install @postel/typeorm typeormyarn add @postel/typeorm typeormbun add @postel/typeorm typeormPlus your database driver — pg, mysql2, or better-sqlite3.
import { DataSource } from "typeorm";
import { Postel } from "@postel/core";
import { TypeOrmStorage } from "@postel/typeorm";
import { config } from "./config.js";
const dataSource = new DataSource({ type: "postgres", url: config.databaseUrl });
await dataSource.initialize();
export const postel = Postel({
outbound: {
storage: TypeOrmStorage({ dataSource, dialect: "postgres" }),
},
});Options
| Option | Notes |
|---|---|
dataSource | The initialized TypeORM DataSource you already built. Postel talks to it through QueryRunners + raw SQL. |
dialect | "postgres", "mysql", or "sqlite" — selects the reservation strategy, capability flags, and column codecs. |
autoMigrate | Run migrations on first use (default true). |
clock | Inject a clock for deterministic time in tests. |
typeorm is a peer dependency. On Postgres and MySQL workers reserve rows under FOR UPDATE SKIP LOCKED; on SQLite in a single statement. MySQL and SQLite poll for dispatch (no LISTEN/NOTIFY); Postgres pushes. The dialect names a SQL family, so wire-compatible engines (MariaDB, PlanetScale, libSQL/Turso, …) work via the matching dialect — see compatible databases.
Shared transactions
Postel({...}).outbound.transaction(cb) hands your callback a connection-bound executor you thread into send(), so the outbox insert commits atomically with your business writes:
await postel.outbound.transaction(async (tx) => {
await postel.send({ type: "order.created", data: { /* ... */ } }, { tx });
});Migrations
autoMigrate (default true) runs the canonical migrations through your connection, version-gated and idempotent — or run your own tooling against that schema.