Migrations

Geração e execução de migrations TypeORM no Koala Nest.

Migrations ficam em src/infra/database/migrations/ e são gerenciadas pelos scripts do projeto gerado. Pendentes são aplicadas automaticamente ao subir a API (dataSourceFactoryrunMigrations()).

bash
bun run migration:generate # gera migration a partir das entidades
bun run migration:run      # aplica migrations pendentes (fallback / CI)
bun run migration:revert   # reverte a última migration

O script generate-migration.ts encapsula a CLI do TypeORM:

typescript
const isAutoName = !process.argv[2];
const timestamp = String(Date.now());
const name = process.argv[2] ?? `Migration-${timestamp}`;

const migrationPath = path.join('src/infra/database/migrations', name);
const command = [
  './node_modules/typeorm/cli.js',
  'migration:generate',
  migrationPath,
  '-d',
  './src/infra/database/migrations/migration-datasource.ts',
];

if (isAutoName) {
  command.push('-t', timestamp);
}

const result = spawnSync(process.execPath, command, {
  stdio: 'inherit',
  cwd: process.cwd(),
});

process.exit(result.status ?? 1);
bash
# nome automático com timestamp
bun run migration:generate

# nome explícito
bun run migration:generate AddProductTable

Migrations usam um datasource dedicado em migration-datasource.ts, separado do factory de runtime. Ambos leem entidades do DbContext:

typescript
import { DbContext } from '@/core/database/db-context';
import 'dotenv/config';
import './load-all-entities';
import path from 'node:path';
import { DataSource } from 'typeorm';

const root = process.cwd();
const schema = process.env.DATABASE_SCHEMA;

export default new DataSource({
  type: 'postgres',
  url: process.env.DATABASE_URL,
  ...(schema
    ? {
        schema,
        extra: { options: `-c search_path=${schema},public` },
      }
    : {}),
  entities: Array.from(DbContext.entities.values()),
  migrations: [path.join(root, 'src/infra/database/migrations/[0-9]*.{js,ts}')],
  migrationsTableName: 'migrations',
  migrationsTransactionMode: 'all',
});

O load-all-entities.ts importa todos os arquivos em src/domain/entities/ (exceto enums) para popular o DbContext fora do Nest — necessário porque o CLI não carrega os módulos da aplicação. No runtime, o Nest importa repositórios/entidades e o mesmo DbContext alimenta o dataSourceFactory.

  1. Altere ou crie entidades em src/domain/entities/ com @Entity de @/core/database/entity.
  2. Execute bun run migration:generate.
  3. Revise o arquivo gerado em src/infra/database/migrations/.
  4. Suba a API (aplica pendentes automaticamente) ou use bun run migration:run.

O template Person inclui uma migration inicial consolidada:

  • 1781281330533-Init.ts — schema completo (person, person_address, person_contact, users) e usuário demo

Serve como referência de nomenclatura e estrutura. Novas alterações de schema devem gerar migrations incrementais com migration:generate.