NestJS

[TypeORM] TypeORMError: Migration class name should have a JavaScript timestamp appended.

sihanni 2025. 8. 31. 05:50
const mod = await import(pathToFileURL(abs).href);
const Mig = mod.default ?? Object.values(mod)[0];
if (typeof Mig === 'function') migrations.push(Mig);

에러

❌ TypeORMError: ReactionsAndComments_20250830 migration name is wrong.
   Migration class name should have a JavaScript timestamp appended.

 

TypeORM 0.3.x는 마이그레이션을 기록할 때 클래스명 끝의 숫자를 뽑아 timestamp 로 사용한다.

이 값은 JS 타임스탬프(ms) 여야 해서 최소 13자리가 필요하다.

 

해결

처음 마이그레이션을 위해 생성한 클래스 명이 ReactionsAndComments_20250830 의 형태여서 발생한 에러이다.

즉 ReactionsAndComments_20250830은 8자리라서 “JS timestamp가 없다”고 보고 바로 에러를 낸 것이다.

클래스명 끝의 숫자만은 13자리(ms)여야하기 때문에 클래스 내에서 이름을 ReactionsAndComments_1725062400000 형태로 바꿔주면 되고,

 

개선

타임스탬프를 매번 구하기 힘든 부분이 있기 때문에, 스크립트를 동적 import 해서 직접 migrations 배열에 주입한다.

async function loadMigrationClasses(): Promise<any[]> {
  const files = readdirSync(scriptsDir)
    .filter(f => f.endsWith('.ts') || f.endsWith('.js'))
    .sort(); // 파일명(타임스탬프) 기준 정렬

  const migrations: any[] = [];
  for (const f of files) {
    const abs = join(scriptsDir, f);
    const mod = await import(pathToFileURL(abs).href);
    const Mig = mod.default ?? Object.values(mod)[0];
    if (typeof Mig === 'function') migrations.push(Mig);
  }
  return migrations;
}

 

migrations 스크립트 파일을 읽어서, 그 안에 있는 마이그레이션 클래스들을 배열로 반환하는 함수이다.

ts나 js 파일만 가져와서, 하나씩 동적으로 import -> default export 클래스를 찾아서 배열에 담아 반환한다.

그리고 이것들을 DataSource({migrations})에 담아 TypeORM이 인식하도록 했다.

이렇게 해서 클래스명에 타임스탬프 13자리를 붙이지 않아도 우회해서 실행할 수 있도록 했다.