refactor(freight-api): split migration histories between IAM and freight

This commit is contained in:
ghost2023
2026-08-05 10:26:25 +03:00
parent 9485e7e9cf
commit 321f3612ec
5 changed files with 278 additions and 53 deletions

View File

@@ -11,7 +11,7 @@ One script, runs from anywhere in the repo (resolves `pg` from `apps/edr-freight
node .claude/skills/edr-db/query.cjs "SELECT ... " # run SQL, console.table output
node .claude/skills/edr-db/query.cjs explain "SELECT ..." # EXPLAIN-validate only (no rows touched)
node .claude/skills/edr-db/query.cjs columns <table> # freight.<table> column list
node .claude/skills/edr-db/query.cjs migrations [like] # public.migrations rows (newest first)
node .claude/skills/edr-db/query.cjs migrations [like] # migration rows, newest first (freight.migrations + iam.typeorm_migrations)
node .claude/skills/edr-db/query.cjs drift <table> # bare column names, for diffing vs the entity
```
@@ -31,7 +31,11 @@ defaulting to the shared dev database (`edr_dev`).
(`WHERE NOT EXISTS` guards) — watch-mode API instances race `migrationsRun`,
and non-idempotent statements have double-run here before.
- Timestamps for new migrations: must be unique across `src/migrations/` AND
higher than `SELECT max(timestamp) FROM public.migrations`.
higher than `SELECT max(timestamp) FROM freight.migrations`.
- Freight and IAM keep separate histories: `freight.migrations` for
`apps/edr-freight-api/src/migrations/*`, `iam.typeorm_migrations` for the
`@tria-plc/iamapi-common` migrations. `public.migrations` is the pre-split
table, left in place for rollback — never write to it.
## Diagnosing a pasted 400/500 (the recurring loop)

View File

@@ -8,7 +8,7 @@
* node .claude/skills/edr-db/query.cjs "SELECT ... " run SQL (console.table)
* node .claude/skills/edr-db/query.cjs explain "SELECT..." EXPLAIN-validate only
* node .claude/skills/edr-db/query.cjs columns <table> list freight.<table> columns
* node .claude/skills/edr-db/query.cjs migrations [like] public.migrations rows
* node .claude/skills/edr-db/query.cjs migrations [like] freight/iam migration rows
* node .claude/skills/edr-db/query.cjs drift <table> columns vs entity check helper
*
* Connection: DB_HOST/DB_PORT/DB_USER/DB_PASSWORD/DB_NAME env vars, falling
@@ -52,12 +52,27 @@ async function main() {
console.table(r.rows);
} else if (first === 'migrations') {
const like = rest[0] ? `%${rest[0]}%` : '%';
const r = await c.query(
`SELECT id, timestamp, name FROM public.migrations
WHERE name ILIKE $1 ORDER BY id DESC LIMIT 40`,
[like],
);
console.table(r.rows);
// Histories are split per owner: freight.migrations (this app) and
// iam.typeorm_migrations (@tria-plc/iamapi-common). public.migrations is the
// pre-split table, kept for rollback — read it only if the split has not
// been applied to this DB yet.
const sources = [
['freight', 'freight.migrations'],
['iam', 'iam.typeorm_migrations'],
['legacy', 'public.migrations'],
];
const rows = [];
for (const [owner, table] of sources) {
const present = await c.query(`SELECT to_regclass($1) IS NOT NULL AS ok`, [table]);
if (!present.rows[0].ok) continue;
const r = await c.query(
`SELECT id, timestamp, name FROM ${table}
WHERE name ILIKE $1 ORDER BY id DESC LIMIT 40`,
[like],
);
rows.push(...r.rows.map((row) => ({ owner, ...row })));
}
console.table(rows);
} else if (first === 'drift') {
// Quick drift signal: DB columns for the table. Compare by eye against
// the entity's @Column names; a recorded-but-absent column = drift.