api: don't replay the baseline migration on pre-fix databases

The folder-discovery fix in the previous commit surfaced a second problem.
Databases migrated BEFORE that fix recorded the baseline under the name of
the hand-added flat duplicate that used to sit beside it
(prisma/migrations/0001_init.sql). Once the runner started discovering the
real folder (20260910113720_first), it saw a name it had never recorded and
tried to apply the baseline again — against a database that already had it:

  Raw query failed. Code: 42710.
  ERROR: type "AdminRole" already exists

The two files are identical SQL (verified byte-for-byte after normalising
line endings; they differ only by one trailing blank line), so the recorded
legacy name genuinely means that migration is applied. A LEGACY_NAME_ALIASES
map now treats '0001_init.sql' as an already-applied marker for
'20260910113720_first', so upgrading an existing database is a no-op instead
of a crash.

Verified against the local dev database this actually broke on
(postgresql://localhost:5432/gold_banking, which had recorded only the old
flat name): 'npm run dev' in apps/api now logs 'No pending migrations' and
'Nest application successfully started' instead of dying. That database's
tracking table was also reconciled to record both real migration names, and
it was confirmed to already contain both migrations' schema (AdminRole,
City.percent, user_type, CustomerKind all present) — nothing was re-run
against it. The dockerised database is unaffected: it already records the
real names, so the alias is inert there.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
s.esmaeili
2026-09-14 21:44:14 +03:30
co-authored by Claude Opus 5
parent 2b6795d007
commit a12fb0450e
2 changed files with 18 additions and 2 deletions
+5 -1
View File
@@ -93025,6 +93025,9 @@ var require_migrate = __commonJS({
statements.push(current.trim());
return statements;
}
var LEGACY_NAME_ALIASES = {
"20260910113720_first": "0001_init.sql"
};
function discoverMigrationFiles(dir) {
const entries = (0, fs_1.readdirSync)(dir);
const files = [];
@@ -93060,7 +93063,8 @@ var require_migrate = __commonJS({
const appliedNames = new Set(alreadyApplied.map((row) => row.name));
const applied = [];
for (const file2 of files) {
if (appliedNames.has(file2.name))
const legacyName = LEGACY_NAME_ALIASES[file2.name];
if (appliedNames.has(file2.name) || legacyName && appliedNames.has(legacyName))
continue;
const statements = splitSqlStatements((0, fs_1.readFileSync)(file2.path, "utf8"));
await prisma.$transaction(
+13 -1
View File
@@ -118,6 +118,17 @@ export function splitSqlStatements(sql: string): string[] {
*/
type MigrationFile = { name: string; path: string };
/**
* Databases migrated before the folder-discovery fix recorded the baseline
* under the name of the hand-added flat duplicate that used to sit alongside
* it (prisma/migrations/0001_init.sql, identical SQL bar a trailing newline).
* Without this, upgrading replays the baseline against a database that already
* has it and dies on `type "AdminRole" already exists`.
*/
const LEGACY_NAME_ALIASES: Record<string, string> = {
'20260910113720_first': '0001_init.sql',
};
function discoverMigrationFiles(dir: string): MigrationFile[] {
const entries = readdirSync(dir);
const files: MigrationFile[] = [];
@@ -171,7 +182,8 @@ export async function runMigrations(prisma: PrismaClient): Promise<MigrationResu
const applied: string[] = [];
for (const file of files) {
if (appliedNames.has(file.name)) continue;
const legacyName = LEGACY_NAME_ALIASES[file.name];
if (appliedNames.has(file.name) || (legacyName && appliedNames.has(legacyName))) continue;
const statements = splitSqlStatements(readFileSync(file.path, 'utf8'));
await prisma.$transaction(