From f7a3010dc9177ce8d0153c42fcb62f711ba765ab Mon Sep 17 00:00:00 2001 From: Edukpe David Date: Sat, 29 Aug 2026 15:05:02 +0100 Subject: [PATCH] fix: remove dead SchemaMigrationService and unused Migration entity MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SchemaMigrationService and the schema_migrations table were never wired up — no module registered the service, no migration created the table, and no code imported the Migration entity. They only sat in the migrations directory, where TypeORM's migration glob had to be explicitly configured to ignore them. Closes #1199 🤖 Generated with Codebuff Co-Authored-By: Codebuff --- src/config/datasource.ts | 10 +--- src/migrations/entities/migration.entity.ts | 55 ------------------- src/migrations/schema-migration.service.ts | 61 --------------------- 3 files changed, 3 insertions(+), 123 deletions(-) delete mode 100644 src/migrations/entities/migration.entity.ts delete mode 100644 src/migrations/schema-migration.service.ts diff --git a/src/config/datasource.ts b/src/config/datasource.ts index 238296e3..340d233e 100644 --- a/src/config/datasource.ts +++ b/src/config/datasource.ts @@ -6,14 +6,10 @@ export const AppDataSource = new DataSource({ synchronize: false, // Load all entity files so schema-aware operations (migration:run, // migration:generate, the drift check) can compare the database against the - // actual entity definitions. `!(migrations|modules)` excludes TypeORM - // helpers under src/migrations and the (non-compiling, unregistered) - // src/modules entities. + // actual entity definitions. `!(migrations|modules)` excludes the + // (non-compiling, unregistered) src/modules entities. entities: ['src/!(migrations|modules)/**/*.entity.ts'], - // Match only timestamp-prefixed migration files. This deliberately excludes - // non-migration helpers that live under src/migrations (e.g. - // schema-migration.service.ts and the entities/ subdir) which TypeORM would - // otherwise try to load as migrations and reject. + // Match only timestamp-prefixed migration files. migrations: ['src/migrations/[0-9]*.{ts,js}'], migrationsTableName: 'migrations', }); diff --git a/src/migrations/entities/migration.entity.ts b/src/migrations/entities/migration.entity.ts deleted file mode 100644 index 2e8851cf..00000000 --- a/src/migrations/entities/migration.entity.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { - Entity, - Column, - PrimaryGeneratedColumn, - CreateDateColumn, - UpdateDateColumn, - VersionColumn, -} from 'typeorm'; - -export enum MigrationStatus { - PENDING = 'pending', - COMPLETED = 'completed', - FAILED = 'failed', - ROLLED_BACK = 'rolled_back', -} - -/** - * Represents the migration entity. - */ -@Entity({ name: 'migrations' }) -export class Migration { - @PrimaryGeneratedColumn('uuid') - id: string; - - @VersionColumn() - lockVersion: number; - - @Column({ unique: true }) - name: string; - - @Column() - version: string; - - @Column({ - type: 'enum', - enum: MigrationStatus, - default: MigrationStatus.PENDING, - }) - status: MigrationStatus; - - @Column({ nullable: true }) - appliedAt?: Date; - - @Column({ nullable: true }) - rolledBackAt?: Date; - - @CreateDateColumn() - createdAt: Date; - - @UpdateDateColumn() - updatedAt: Date; - - @Column({ type: 'text', nullable: true }) - errorMessage?: string; -} diff --git a/src/migrations/schema-migration.service.ts b/src/migrations/schema-migration.service.ts deleted file mode 100644 index 7234cfb9..00000000 --- a/src/migrations/schema-migration.service.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { Injectable, Logger } from '@nestjs/common'; -import { DataSource } from 'typeorm'; - -export interface MigrationRecord { - version: number; - name: string; - appliedAt: Date; -} - -@Injectable() -export class SchemaMigrationService { - private readonly logger = new Logger(SchemaMigrationService.name); - - constructor(private readonly dataSource: DataSource) {} - - /** Returns all applied migrations ordered by version. */ - async getApplied(): Promise { - const result = await this.dataSource.query( - `SELECT version, name, applied_at AS "appliedAt" - FROM schema_migrations - ORDER BY version ASC`, - ); - return result; - } - - /** Runs pending migrations inside a transaction for zero-downtime apply. */ - async runPending( - migrations: Array<{ version: number; name: string; sql: string }>, - ): Promise { - const applied = await this.getApplied(); - const appliedVersions = new Set(applied.map((m) => m.version)); - - const pending = migrations.filter((m) => !appliedVersions.has(m.version)); - if (pending.length === 0) { - this.logger.log('No pending migrations.'); - return; - } - - await this.dataSource.transaction(async (em) => { - for (const migration of pending) { - this.logger.log(`Applying migration v${migration.version}: ${migration.name}`); - await em.query(migration.sql); - await em.query( - 'INSERT INTO schema_migrations (version, name, applied_at) VALUES ($1, $2, NOW())', - [migration.version, migration.name], - ); - } - }); - } - - /** Rolls back the last applied migration. */ - async rollbackLast(rollbackSql: string): Promise { - await this.dataSource.transaction(async (em) => { - await em.query(rollbackSql); - await em.query( - 'DELETE FROM schema_migrations WHERE version = (SELECT MAX(version) FROM schema_migrations)', - ); - }); - this.logger.log('Rolled back last migration.'); - } -}