55 lines
1.7 KiB
TypeScript
55 lines
1.7 KiB
TypeScript
/**
|
|
* Ensures every drizzle/*.sql migration file has a matching entry in meta/_journal.json.
|
|
* Run: bun scripts/verify-drizzle-journal.ts
|
|
*/
|
|
import { readdirSync, readFileSync } from "fs";
|
|
import path from "path";
|
|
|
|
const drizzleDir = path.resolve(import.meta.dir, "../drizzle");
|
|
const journalPath = path.join(drizzleDir, "meta/_journal.json");
|
|
|
|
const journal = JSON.parse(readFileSync(journalPath, "utf8")) as {
|
|
entries: Array<{ idx: number; tag: string }>;
|
|
};
|
|
|
|
const sqlTags = readdirSync(drizzleDir)
|
|
.filter((name) => /^\d+_.+\.sql$/.test(name))
|
|
.map((name) => name.replace(/\.sql$/, ""))
|
|
.sort();
|
|
|
|
const journalTags = journal.entries.map((entry) => entry.tag).sort();
|
|
|
|
const missingFromJournal = sqlTags.filter((tag) => !journalTags.includes(tag));
|
|
const missingSql = journalTags.filter((tag) => !sqlTags.includes(tag));
|
|
|
|
const idxSequence = journal.entries.map((entry) => entry.idx);
|
|
const expectedIdx = journal.entries.map((_, i) => i);
|
|
const badIdx = idxSequence.some((idx, i) => idx !== expectedIdx[i]);
|
|
|
|
let failed = false;
|
|
|
|
if (missingFromJournal.length > 0) {
|
|
console.error("[verify-drizzle-journal] SQL files missing from journal:");
|
|
for (const tag of missingFromJournal) console.error(` - ${tag}`);
|
|
failed = true;
|
|
}
|
|
|
|
if (missingSql.length > 0) {
|
|
console.error("[verify-drizzle-journal] Journal entries without SQL files:");
|
|
for (const tag of missingSql) console.error(` - ${tag}`);
|
|
failed = true;
|
|
}
|
|
|
|
if (badIdx) {
|
|
console.error("[verify-drizzle-journal] Journal idx values are not sequential from 0");
|
|
failed = true;
|
|
}
|
|
|
|
if (failed) {
|
|
process.exit(1);
|
|
}
|
|
|
|
console.log(
|
|
`[verify-drizzle-journal] OK — ${sqlTags.length} migrations match journal entries`,
|
|
);
|