A standalone CLI for managing PostgreSQL schema migrations for projects built
with @cleverbrush/orm.
cb-orm migrate generate [name] # diff DB → schema, emit TS migration file (name defaults to "migration")
cb-orm migrate run # apply pending migrations
cb-orm migrate rollback # roll back last batch
cb-orm migrate status # list applied/pending migrations
cb-orm validate # check entity schemas against the live DB (read-only)
cb-orm db push # sync schema in-place (dev only)
npm install --save-dev @cleverbrush/orm-cliknex is a peer dependency and must be installed in your project. tsx is a regular dependency and is installed automatically.
// db.config.ts
import knex from 'knex';
import { defineConfig } from '@cleverbrush/orm-cli';
import { UserEntity, TodoEntity } from './src/db/schemas.js';
const db = knex({
client: 'pg',
connection: process.env.DATABASE_URL
});
export default defineConfig({
knex: db,
entities: { users: UserEntity, todos: TodoEntity },
migrations: {
directory: './migrations', // where .ts migration files are written
tableName: 'knex_migrations' // default; override if needed
}
});{
"scripts": {
"db:generate": "cb-orm migrate generate",
"db:run": "cb-orm migrate run",
"db:rollback": "cb-orm migrate rollback",
"db:status": "cb-orm migrate status",
"db:validate": "cb-orm validate",
"db:push": "cb-orm db push"
}
}Compares every entity in config.entities against the live database and emits
a single timestamped TypeScript migration file when differences are found.
- New tables →
CREATE TABLE. - Existing tables with column/index/FK changes →
ALTER TABLE. - Multiple tables are FK-dependency-ordered (parents created first, dropped last).
- Polymorphic (CTI) entities include one entry per variant table.
- File written as
<dir>/YYYYMMDDHHmmss_<name>.ts.
npx cb-orm migrate generate add_role_column
# → migrations/20260423120000_add_role_column.tsApplies all pending migrations via knex.migrate.latest.
npx cb-orm migrate run
# Batch 1. Applied 2 migration(s):
# ✓ 20260423000001_init.ts
# ✓ 20260423120000_add_role_column.tsUse --to <filename> to migrate up to a specific file:
npx cb-orm migrate run --to 20260423000001_init.tsRolls back the most recently applied batch.
npx cb-orm migrate rollback
# Roll back all batches:
npx cb-orm migrate rollback --allLists applied and pending migrations.
npx cb-orm migrate status
# Applied migrations:
# ✓ 20260423000001_init.ts
# Pending migrations:
# ○ 20260423120000_add_role_column.tsChecks every configured entity against the live database without applying
changes, writing migration files, or updating snapshots. It exits with status
1 when a table is missing or a schema diff is detected.
npx cb-orm validate
# Schema is in sync (4 table(s) checked).Use this in CI before deploys when you want to fail fast on schema drift.
Applies all schema changes directly to the database without writing a migration file. Runs inside a single transaction.
Warning — dev only. Requires
--yeswhenNODE_ENV=production.
npx cb-orm db push # asks for confirmation
npx cb-orm db push --yes # skip confirmation| Flag | Commands | Description |
|---|---|---|
--config <path> |
all | Path to config file (default: db.config.ts in cwd) |
--dir <path> |
all | Migrations directory (overrides config.migrations.directory) |
--to <name> |
migrate run |
Apply up to a specific migration filename |
--all |
migrate rollback |
Roll back all batches |
--yes |
db push |
Skip the interactive confirmation prompt |
The CLI delegates all schema intelligence to @cleverbrush/knex-schema:
| Step | Function |
|---|---|
| Detect new tables | tableExistsInDb(knex, tableName) |
| Generate CREATE TABLE source | generateCreateTableSource(schema) |
| Introspect live table | introspectDatabase(knex, tableName) |
| Diff schema vs DB | diffSchema(schema, dbState) |
| Generate ALTER TABLE source | generateMigration(diff, tableName) |
| Apply diff without file | applyDiff(knex, diff, tableName) |
| Validate without changes | validateEntitiesAgainstDatabase(knex, entities) |
| Polymorphic variant tables | getPolymorphicVariantSchemas(schema) |
tsx is used to load db.config.ts at runtime by registering the
tsx/esm/api hook before any dynamic import() of the config file.