fix(api): run baseline migration first so an empty database boots
Migrations were applied in plain name order, so 0002_admin_schema.sql ran before 20260910113720_first and failed with relation "City" does not exist. sortMigrations now always puts the baseline first; existing databases are unaffected because their applied names are unchanged. Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Haiku 5.5
parent
2a33c0f290
commit
e7c9b7238f
@@ -0,0 +1,28 @@
|
||||
import { readdirSync } from 'fs';
|
||||
import { join } from 'path';
|
||||
import { sortMigrations } from './migrate';
|
||||
|
||||
describe('sortMigrations', () => {
|
||||
it('puts the baseline before 0002 so an empty database can boot', () => {
|
||||
const names = sortMigrations([
|
||||
{ name: '20260914165255_sync_schema_drift' },
|
||||
{ name: '0002_admin_schema.sql' },
|
||||
{ name: '20260910113720_first' },
|
||||
]).map((f) => f.name);
|
||||
|
||||
expect(names).toEqual([
|
||||
'20260910113720_first',
|
||||
'0002_admin_schema.sql',
|
||||
'20260914165255_sync_schema_drift',
|
||||
]);
|
||||
});
|
||||
|
||||
it('starts the real migrations folder with the baseline', () => {
|
||||
const dir = join(__dirname, '..', '..', 'prisma', 'migrations');
|
||||
const entries = readdirSync(dir)
|
||||
.filter((name) => name !== 'migration_lock.toml')
|
||||
.map((name) => ({ name }));
|
||||
|
||||
expect(sortMigrations(entries)[0].name).toBe('20260910113720_first');
|
||||
});
|
||||
});
|
||||
@@ -152,7 +152,23 @@ function discoverMigrationFiles(dir: string): MigrationFile[] {
|
||||
}
|
||||
}
|
||||
|
||||
return files.sort((a, b) => a.name.localeCompare(b.name));
|
||||
return sortMigrations(files);
|
||||
}
|
||||
|
||||
/**
|
||||
* The baseline creates every table, so it must run first on an empty database.
|
||||
* Plain name order put `0002_admin_schema.sql` ahead of `20260910113720_first`,
|
||||
* and a fresh boot died on `relation "City" does not exist`. Existing databases
|
||||
* never noticed because they already had the baseline applied.
|
||||
*/
|
||||
const BASELINE_MIGRATION = '20260910113720_first';
|
||||
|
||||
export function sortMigrations<T extends { name: string }>(files: T[]): T[] {
|
||||
return [...files].sort((a, b) => {
|
||||
if (a.name === BASELINE_MIGRATION) return -1;
|
||||
if (b.name === BASELINE_MIGRATION) return 1;
|
||||
return a.name.localeCompare(b.name);
|
||||
});
|
||||
}
|
||||
|
||||
export async function runMigrations(prisma: PrismaClient): Promise<MigrationResult> {
|
||||
|
||||
Reference in New Issue
Block a user