Миграции баз данных в TypeScript: полный обзор инструментов и практическое руководство
Миграции баз данных — это способ версионирования и последовательного применения изменений схемы базы данных (создание, изменение или удаление таблиц, индексов и ограничений). В экосистеме TypeScript существует несколько мощных инструментов для управления миграциями. В этой статье мы подробно разберём три самых популярных решения: TypeORM, Prisma и Drizzle ORM.
Зачем нужны миграции?
Без миграций разработчики часто вносят изменения вручную через SQL-консоль или админку, что приводит к:
- Потере синхронизации между средой разработки и продакшеном;
- Ошибкам из-за человеческого фактора;
- Сложностям при откате изменений.
Миграции решают эти проблемы, позволяя автоматически применять и откатывать изменения, а также хранить историю всех изменений схемы в коде.
1. TypeORM — классический подход с ActiveRecord и Data Mapper
TypeORM — один из самых зрелых ORM для TypeScript и JavaScript. Он поддерживает как паттерн ActiveRecord, так и Data Mapper, и имеет встроенную систему миграций.
Установка и настройка
npm install typeorm reflect-metadata @types/node
npm install pg # для PostgreSQL
Создайте файл конфигурации ormconfig.json или используйте data-source.ts:
import { DataSource } from "typeorm";
export const AppDataSource = new DataSource({
type: "postgres",
host: "localhost",
port: 5432,
username: "user",
password: "password",
database: "mydb",
entities: ["src/entity/*.ts"],
migrations: ["src/migration/*.ts"],
synchronize: false, // отключаем автосинхронизацию
});
Создание и выполнение миграции
Сначала сгенерируем миграцию на основе изменений в сущностях:
npx typeorm migration:generate src/migration/AddUserTable -d src/data-source.ts
Пример сгенерированной миграции:
import { MigrationInterface, QueryRunner, Table } from "typeorm";
export class AddUserTable1234567890 implements MigrationInterface {
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.createTable(
new Table({
name: "user",
columns: [
{ name: "id", type: "int", isPrimary: true, isGenerated: true, generationStrategy: "increment" },
{ name: "name", type: "varchar", length: "255" },
{ name: "email", type: "varchar", isUnique: true },
],
})
);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.dropTable("user");
}
}
Примените миграцию:
npx typeorm migration:run -d src/data-source.ts
Плюсы и минусы TypeORM
- Плюсы: большая экосистема, множество БД (PostgreSQL, MySQL, SQLite, MSSQL), генерация миграций из сущностей.
- Минусы: сложная конфигурация, медленная скорость работы при большом количестве сущностей, устаревшая кодовая база.
2. Prisma — современный ORM с автоматическими миграциями
Prisma — это новый стандарт в TypeScript ORM. Он использует декларативную схему (schema.prisma) и автоматически генерирует миграции.
Установка и инициализация
npm install prisma @prisma/client
npx prisma init
Определите модель в prisma/schema.prisma:
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model User {
id Int @id @default(autoincrement())
name String
email String @unique
}
Создание и выполнение миграции
npx prisma migrate dev --name add_user_table
Эта команда создаст SQL-файл миграции в папке prisma/migrations и применит его к базе данных. Пример сгенерированного SQL:
-- CreateTable
CREATE TABLE "User" (
"id" SERIAL NOT NULL,
"name" TEXT NOT NULL,
"email" TEXT NOT NULL,
CONSTRAINT "User_pkey" PRIMARY KEY ("id")
);
-- CreateIndex
CREATE UNIQUE INDEX "User_email_key" ON "User"("email");
Для продакшена используйте:
npx prisma migrate