@lyku/lockstep-pg
v1.8.3
Published
Schema-driven PostgreSQL migration toolkit: drift detection, introspection, and SQL generation for @lyku/lockstep-core models
Maintainers
Readme
@lyku/lockstep-pg
Schema-driven PostgreSQL migration toolkit for @lyku/lockstep-core models. Detects drift between your code-defined schemas and a live database, then generates safe (and optionally destructive) SQL migrations.
Features
- Drift detection — compare
PostgresTableModeldefinitions against a live PostgreSQL database - Introspection — read table structure, indexes, constraints, and foreign keys from any Postgres database
- Diff engine — structural diff between introspected tables and code models, categorized into safe vs. destructive operations
- SQL generation — produces migration SQL from diffs or drift reports, including
CREATE TABLE,ALTER COLUMN,ADD INDEX, enumCHECKconstraint updates, and stock document seeding - Seed data — generate
INSERT ... ON CONFLICT DO NOTHINGstatements for fixture documents defined in table models
Installation
npm install @lyku/lockstep-pgRequires @lyku/lockstep-core as a peer dependency and pg for database connections.
Usage
Detect drift
import { detectDrift } from '@lyku/lockstep-pg';
const tables = {
users: usersModel,
posts: postsModel,
// ... your PostgresRecordModel definitions
};
const drifts = await detectDrift(process.env.PG_CONNECTION_STRING, { tables });
// Returns Drift[] — missing tables, extra columns, type mismatches, missing indexes, etc.Generate a migration
import { generateMigration } from '@lyku/lockstep-pg';
const { safe, destructive, driftCount } = await generateMigration(process.env.PG_CONNECTION_STRING, { tables });
// safe: SQL string wrapped in BEGIN/COMMIT (additive changes)
// destructive: SQL string for DROP operations (review carefully)Introspect a database
import { Client } from 'pg';
import { introspectDatabase, introspectTable } from '@lyku/lockstep-pg';
const client = new Client({ connectionString: '...' });
await client.connect();
// Single table
const table = await introspectTable(client, 'users');
// All tables
const allTables = await introspectDatabase(client);
await client.end();Diff and generate SQL
import { diffDatabase, categorizeOperations, generateMigrationSql } from '@lyku/lockstep-pg';
const ops = diffDatabase(introspectedTables, codeDefinedTables);
const { safe, destructive } = categorizeOperations(ops);
const sql = generateMigrationSql(ops);Generate seed SQL
import { generateSeedSql } from '@lyku/lockstep-pg';
const sql = generateSeedSql({ tables });
// INSERT ... ON CONFLICT DO NOTHING for each table's `docs` arrayWhere it fits
Drift types
| Type | Description |
| --------------------------- | ------------------------------------------------ |
| missing_table | Table defined in schema but absent from database |
| extra_table | Table in database but not in schema |
| missing_column | Column defined in schema but absent from table |
| extra_column | Column in table but not in schema |
| column_type_mismatch | Column type differs between schema and database |
| nullable_mismatch | NOT NULL constraint differs |
| missing_index | Index defined in schema but absent from database |
| extra_index | Index in database but not in schema |
| missing_constraint | CHECK constraint missing for enum column |
| check_constraint_mismatch | Enum CHECK constraint values differ |
| missing_stock_doc | Fixture/seed record missing from table |
License
GPL-3.0
