Миграции баз данных в TypeScript: TypeORM, Prisma и Drizzle

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Миграции баз данных в 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                    

Рекомендаций