@joaosczip/outy-cli
v0.0.1
Published
Outbox Reader developer tooling — Prisma schema generator and CLI
Maintainers
Readme
@joaosczip/outy-cli
Developer tooling for the Transactional Outbox pattern. Provides a CLI to generate Prisma schemas and set up PostgreSQL logical replication.
Installation
bun add @joaosczip/outy-cliOr run directly without installing:
bunx @joaosczip/outy-cli --helpCommands
schema (default)
Generates the outbox model block in your Prisma schema and optionally runs prisma migrate dev.
outbox-schema [schema] [options]
Options:
-s, --schema-path Path to schema.prisma file [default: "./prisma/schema.prisma"]
-m, --model-name Prisma model name [default: "OutboxRecord"]
-t, --table-name Database table name [default: "outbox"]
--migration-name Migration name [default: "add_outbox_table"]
-c, --config Path to a JSON config file
--skip-migration Skip running prisma migrate dev [default: false]Examples:
# Generate schema with defaults (creates/updates ./prisma/schema.prisma)
outbox-schema
# Custom schema path
outbox-schema -s ./database/schema.prisma
# Use a config file
outbox-schema -c ./outbox-config.json
# Generate schema only, no migration
outbox-schema --skip-migration
# Custom model and table names
outbox-schema -m OutboxEvent -t outbox_eventsThe command appends the following model to your schema (or creates the file if it doesn't exist):
model OutboxRecord {
id String @id @default(cuid())
aggregateId String @map("aggregate_id")
aggregateType String @map("aggregate_type")
eventType String @map("event_type")
payload Json
sequenceNumber BigInt? @map("sequence_number")
createdAt DateTime @default(now()) @map("created_at")
processedAt DateTime? @map("processed_at")
status String @default("PENDING")
attempts Int @default(0)
@@map("outbox")
@@index([status])
@@index([createdAt])
@@index([sequenceNumber])
}customFields lets you append extra Prisma fields to the model, e.g.:
{
"customFields": {
"tenantId": "String?",
"version": "Int @default(1)"
}
}setup-replication
Connects to a PostgreSQL instance and creates a logical replication slot using the wal2json plugin. This automates the manual step typically done after configuring postgresql.conf.
outy setup-replication [options]
Options:
-h, --host PostgreSQL host [default: "localhost"]
-p, --port PostgreSQL port [default: 5432]
-u, --user PostgreSQL user [required]
-P, --password PostgreSQL password [required] (also reads $PGPASSWORD)
-d, --database PostgreSQL database [required]
-s, --slot-name Replication slot name [required]Prerequisites (require a server restart — must be done manually):
Add the following to postgresql.conf:
wal_level = logical
max_wal_senders = 10
max_replication_slots = 10The PostgreSQL user must have LOGIN and REPLICATION roles:
CREATE USER outbox_user WITH LOGIN REPLICATION PASSWORD 'secret';Example:
outy setup replication \
-u outbox_user \
-P secret \
-d my_database \
-s outbox_slotIf the slot already exists the command exits successfully with an informational message. If the connection or slot creation fails, it exits with code 1 and prints a hint about the REPLICATION role.
create migration
Generates a database migration for the outbox table. When no --target is given, it prints a plain SQL CREATE TABLE statement to stdout that you can run manually.
outy create migration [options]
Options:
-T, --target Migration target: prisma | sequelize | sql [default: sql (stdout)]
-t, --table-name Database table name [default: "outbox"]
--migration-name Name for the migration [default: "add_outbox_table"]
Prisma only:
-s, --schema-path Path to schema.prisma file [default: "./prisma/schema.prisma"]
-m, --model-name Prisma model name [default: "OutboxRecord"]
-c, --config Path to a JSON config file
Sequelize only:
--migrations-path Path to the migrations directory [default: auto-detected from .sequelizerc]
SQL only:
-o, --output Write SQL to this file instead of stdoutExamples:
# Print SQL to stdout (no ORM dependency)
outy create migration
# Save SQL to a file
outy create migration --output ./migrations/create_outbox.sql
# Append model to schema.prisma and run prisma migrate dev
outy create migration --target prisma
outy create migration --target prisma --schema-path ./database/schema.prisma
# Write a timestamped Sequelize migration file
outy create migration --target sequelize
outy create migration --target sequelize --migrations-path ./db/migrationsThe SQL output looks like:
CREATE TABLE IF NOT EXISTS outbox (
id UUID PRIMARY KEY,
aggregate_id TEXT NOT NULL,
aggregate_type TEXT NOT NULL,
event_type TEXT NOT NULL,
payload JSONB NOT NULL,
status TEXT NOT NULL DEFAULT 'PENDING',
attempts INTEGER NOT NULL DEFAULT 0,
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
processed_at TIMESTAMP,
sequence_number BIGINT
);
CREATE INDEX IF NOT EXISTS idx_outbox_status ON outbox(status);
CREATE INDEX IF NOT EXISTS idx_outbox_created_at ON outbox(created_at);
CREATE INDEX IF NOT EXISTS idx_outbox_sequence_number ON outbox(sequence_number);The Sequelize migration file is a standard queryInterface.createTable / dropTable module placed in the migrations directory, named <timestamp>-<migration-name>.js. The migrations directory is discovered from .sequelizerc (migrations-path key), falling back to ./migrations/.
setup client
Installs the @outbox-reader/client package using the auto-detected package manager.
outy setup clientThe command detects the package manager by looking for lockfiles in the current directory:
| Lockfile | Package manager | Install command |
|----------|----------------|-----------------|
| bun.lock / bun.lockb | bun | bun add |
| yarn.lock | yarn | yarn add |
| pnpm-lock.yaml | pnpm | pnpm add |
| package-lock.json (or none) | npm | npm install |
Example:
# Auto-detects package manager and installs @outbox-reader/client
outy setup clientGlobal flags
--help Show help
--version Show version