docs: collect all migrations documentation in one place (#11674)

* docs: collect all migrations documentation in one place

* links

* vite

* fic

* link to vite project

* Apply suggestions from code review

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* ai review suggestions

* docs: collect all migrations documentation in one place

* links

* vite

* fic

* link to vite project

* ai review suggestions

* Apply suggestions from code review

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* format

* single redirect

* fix bad merge

* auto-run

* restore cli

* add migration create

* fix postgresql syntax

---------

Co-authored-by: Giorgio Boa <35845425+gioboa@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
This commit is contained in:
Piotr Kuczynski 2025-11-09 12:34:28 +01:00 committed by GitHub
parent 3ac605359d
commit b639d33aee
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
19 changed files with 508 additions and 506 deletions

View File

@ -148,7 +148,7 @@ For more information see the [Postgres documentation](https://www.postgresql.org
TypeORM does not support some index options and definitions (e.g. `lower`, `pg_trgm`) due to many database-specific differences and multiple
issues with getting information about existing database indices and synchronizing them automatically. In such cases you should create the index manually
(for example, in migrations) with any index signature you want. To make TypeORM ignore these indices during synchronization, use `synchronize: false`
(for example, in [the migrations](../migrations/01-why.md)) with any index signature you want. To make TypeORM ignore these indices during synchronization, use `synchronize: false`
option on the `@Index` decorator.
For example, you create an index with case-insensitive comparison:

View File

@ -124,66 +124,15 @@ typeorm subscriber:create path-to-subscriber-dir/subscriber
Learn more about [Subscribers](./4-listeners-and-subscribers.md).
## Create a new migration
## Manage migrations
You can create a new migration using CLI:
* `typeorm migration:create` - [create](../migrations/03-creating.md) empty migration
* `typeorm migration:generate` - [generate](../migrations/04-generating.md) migration comparing entities with actual database schema
* `typeorm migration:run` - [execute](../migrations/05-executing.md) all migrations
* `typeorm migration:revert` - [revert](../migrations/06-reverting.md) last migration
* `typeorm migration:show` - [list](../migrations/07-status.md) all migrations with their execution status
```shell
typeorm migration:create path-to-migrations-dir/migrationName
```
Learn more about [Migrations](./1-migrations.md).
## Generate a migration from existing table schema
Automatic migration generation creates a new migration file
and writes all sql queries that must be executed to update the database.
If no there were no changes generated, the command will exit with code 1.
```shell
typeorm migration:generate path/to/Migration -d path/to/datasource
```
The rule of thumb is to generate a migration after each entity change.
the -d argument value should specify the path where your DataSource instance is defined.
You can specify the path and name of the migration with the first argument.
Learn more about [Migrations](./1-migrations.md).
## Run migrations
To execute all pending migrations use following command:
```shell
typeorm migration:run -- -d path-to-datasource-config
```
Learn more about [Migrations](./1-migrations.md).
## Revert migrations
To revert the most recently executed migration use the following command:
```shell
typeorm migration:revert -- -d path-to-datasource-config
```
This command will undo only the last executed migration.
You can execute this command multiple times to revert multiple migrations.
Learn more about [Migrations](./1-migrations.md).
## Show migrations
To show all migrations and whether they've been run or not use following command:
```shell
typeorm migration:show -- -d path-to-datasource-config
```
[X] = Migration has been ran
[ ] = Migration is pending/unapplied
Learn more about [Migrations](../migrations/01-why.md).
## Sync database schema

View File

@ -28,12 +28,6 @@ Different RDBMS-es have their own specific options.
Example: `subscribers: [PostSubscriber, AppSubscriber, "subscriber/*.js", "modules/**/subscriber/*.js"]`.
Learn more about [Subscribers](../advanced-topics/4-listeners-and-subscribers.md).
- `migrations` - Migrations to be loaded and used for this data source.
It accepts both migration classes and directories from which to load.
Directories support glob patterns.
Example: `migrations: [FirstMigration, SecondMigration, "migration/*.js", "modules/**/migration/*.js"]`.
Learn more about [Migrations](../advanced-topics/1-migrations.md).
- `logging` - Indicates if logging is enabled or not.
If set to `true` then query and error logging will be enabled.
You can also specify different types of logging to be enabled, for example `["query", "error", "schema"]`.
@ -67,13 +61,13 @@ Different RDBMS-es have their own specific options.
Note that for MongoDB database it does not create schema, because MongoDB is schemaless.
Instead, it syncs just by creating indices.
- `migrationsRun` - Indicates if migrations should be auto run on every application launch.
As an alternative, you can use CLI and run migration:run command.
- `migrations` - [Migrations](../migrations/01-why.md) to be loaded and used for this data source
- `migrationsTableName` - Name of the table in the database which is going to contain information about executed migrations.
By default, this table is called "migrations".
- `migrationsRun` - Indicates if [migrations](../migrations/01-why.md) should be auto-run on every application launch.
- `migrationsTransactionMode` - Control transactions for migrations (default: `all`), can be one of `all` | `none` | `each`
- `migrationsTableName` - Name of the table in the database which is going to contain information about executed [migrations](../migrations/01-why.md).
- `migrationsTransactionMode` - Controls transaction mode when running [migrations](../migrations/01-why.md).
- `metadataTableName` - Name of the table in the database which is going to contain information about table metadata.
By default, this table is called "typeorm_metadata".
@ -85,7 +79,7 @@ Different RDBMS-es have their own specific options.
eg. `.where("user.firstName = :search OR user.lastName = :search")` becomes `WHERE (user.firstName = ? OR user.lastName = ?)` instead of `WHERE user.firstName = ? OR user.lastName = ?`
- `invalidWhereValuesBehavior` - Controls how null and undefined values are handled in where conditions across all TypeORM operations (find operations, query builders, repository methods).
- `null` behavior options:
- `'ignore'` (default) - skips null properties
- `'sql-null'` - transforms null to SQL NULL

View File

@ -11,7 +11,7 @@ You can create a view entity by defining a new class and mark it with `@ViewEnti
- `database` - database name in selected DB server.
- `schema` - schema name.
- `expression` - view definition. **Required parameter**.
- `dependsOn` - List of other views on which the current views depends. If your view uses another view in its definition, you can add it here so that migrations are generated in the correct order.
- `dependsOn` - List of other views on which the current views depends. If your view uses another view in its definition, you can add it here so that [migrations](../migrations/01-why.md) are generated in the correct order.
`expression` can be string with properly escaped columns and tables, depend on database used (postgres in example):

View File

@ -34,7 +34,7 @@ TypeORM is highly influenced by other ORMs, such as [Hibernate](http://hibernate
- Cascades.
- Indices.
- Transactions.
- Migrations and automatic migrations generation.
- [Migrations](../migrations/01-why.md) with automatic generation.
- Connection pooling.
- Replication.
- Using multiple database instances.
@ -1195,7 +1195,7 @@ There are several extensions that simplify working with TypeORM and integrating
- ER Diagram generator - [typeorm-uml](https://github.com/eugene-manuilov/typeorm-uml/)
- another ER Diagram generator - [erdia](https://www.npmjs.com/package/erdia/)
- Create, drop and seed database - [typeorm-extension](https://github.com/tada5hi/typeorm-extension)
- Automatically update `data-source.ts` after generating migrations/entities - [typeorm-codebase-sync](https://www.npmjs.com/package/typeorm-codebase-sync)
- Automatically update `data-source.ts` after generating [migrations](../migrations/01-why.md)/entities - [typeorm-codebase-sync](https://www.npmjs.com/package/typeorm-codebase-sync)
- Easy manipulation of `relations` objects - [typeorm-relations](https://npmjs.com/package/typeorm-relations)
- Automatically generate `relations` based on a GraphQL query - [typeorm-relations-graphql](https://npmjs.com/package/typeorm-relations-graphql)

View File

@ -178,7 +178,7 @@ module.exports = {
### Bundling Migration Files
By default Webpack tries to bundle everything into one file. This can be problematic when your project has migration files which are meant to be executed after bundled code is deployed to production. To make sure all your migrations can be recognized and executed by TypeORM, you may need to use "Object Syntax" for the `entry` configuration for the migration files only.
By default Webpack tries to bundle everything into one file. This can be problematic when your project has migration files which are meant to be executed after bundled code is deployed to production. To make sure all your [migrations](../migrations/01-why.md) can be recognized and executed by TypeORM, you may need to use "Object Syntax" for the `entry` configuration for the migration files only.
```javascript
const glob = require("glob")
@ -210,7 +210,7 @@ module.exports = {
}
```
Also, since Webpack 4, when using `mode: 'production'`, files are optimized by default which includes mangling your code in order to minimize file sizes. This breaks the migrations because TypeORM relies on their names to determine which has already been executed. You may disable minimization completely by adding:
Also, since Webpack 4, when using `mode: 'production'`, files are optimized by default which includes mangling your code in order to minimize file sizes. This breaks the [migrations](../migrations/01-why.md) because TypeORM relies on their names to determine which has already been executed. You may disable minimization completely by adding:
```javascript
module.exports = {
@ -256,93 +256,6 @@ module.exports = {
}
```
## How to use Vite for the backend?
Using TypeORM in a Vite project is pretty straight forward. However, when you use migrations, you will run into "...migration name is wrong. Migration class name should have a
JavaScript timestamp appended." errors when running the production build.
On production builds, files are [optimized by default](https://vite.dev/config/build-options#build-minify) which includes mangling your code in order to minimize file sizes.
You have 3 options to mitigate this. The 3 options are shown belown as diff to this basic "vite.config.ts"
```typescript
import legacy from "@vitejs/plugin-legacy"
import vue from "@vitejs/plugin-vue"
import path from "path"
import { defineConfig } from "vite"
// https://vitejs.dev/config/
export default defineConfig({
build: {
sourcemap: true,
},
plugins: [vue(), legacy()],
resolve: {
alias: {
"@": path.resolve(__dirname, "./src"),
},
},
})
```
### Option 1: Disable minify
This is the most crude option and will result in significantly larger files. Add `build.minify = false` to your config.
```diff
--- basic vite.config.ts
+++ disable minify vite.config.ts
@@ -7,6 +7,7 @@
export default defineConfig({
build: {
sourcemap: true,
+ minify: false,
},
plugins: [vue(), legacy()],
resolve: {
```
### Option 2: Disable esbuild minify identifiers
Vite uses esbuild as the default minifier. You can disable mangling of identifiers by adding `esbuild.minifyIdentifiers = false` to your config.
This will result in smaller file sizes, but depending on your code base you will get diminishing returns as all identifiers will be kept at full length.
```diff
--- basic vite.config.ts
+++ disable esbuild minify identifiers vite.config.ts
@@ -8,6 +8,7 @@
build: {
sourcemap: true,
},
+ esbuild: { minifyIdentifiers: false },
plugins: [vue(), legacy()],
resolve: {
```
### Option 3: Use terser as minifier while keeping only the migration class names
Vite supports using terser as minifier. Terser is slower then esbuild, but offers more fine grained control over what to minify.
Add `minify: 'terser'` with `terserOptions.mangle.keep_classnames: /^Migrations\d+$/` and `terserOptions.compress.keep_classnames: /^Migrations\d+$/` to your config.
These options will make sure classnames that start with "Migrations" and end with numbers are not renamed during minification.
Make sure terser is available as dev dependency in your project: `npm add -D terser`.
```diff
--- basic vite.config.ts
+++ terser keep migration class names vite.config.ts
@@ -7,6 +7,11 @@
export default defineConfig({
build: {
sourcemap: true,
+ minify: 'terser',
+ terserOptions: {
+ mangle: { keep_classnames: /^Migrations\d+$/ },
+ compress: { keep_classnames: /^Migrations\d+$/ },
+ },
},
plugins: [vue(), legacy()],
resolve: {
```
## How to use TypeORM in ESM projects?
Make sure to add `"type": "module"` in the `package.json` of your project so TypeORM will know to use `import( ... )` on files.

View File

@ -0,0 +1,42 @@
# How migrations work?
Once you get into production you'll need to synchronize model changes into the database.
Typically, it is unsafe to use `synchronize: true` for schema synchronization on production once
you get data in your database. Here is where migrations come to help.
A migration is just a single file with SQL queries to update a database schema
and apply new changes to an existing database.
Let's say you already have a database and a `Post` entity:
```typescript
import { Entity, Column, PrimaryGeneratedColumn } from "typeorm"
@Entity()
export class Post {
@PrimaryGeneratedColumn()
id: number
@Column()
title: string
@Column()
text: string
}
```
And your entity worked in production for months without any changes.
You have thousands of posts in your database.
Now you need to make a new release and rename `title` to `name`.
What would you do?
You need to create a new migration with the following SQL query (PostgreSQL dialect):
```sql
ALTER TABLE "post" RENAME COLUMN "title" TO "name";
```
Once you run this SQL query your database schema is ready to work with your new codebase.
TypeORM provides a place where you can write such sql queries and run them when needed.
This place is called "migrations".

View File

@ -0,0 +1,71 @@
# Setup
Before working with migrations you need to setup your [DataSource](../data-source/1-data-source.md) options properly:
```ts
export default new DataSource({
// basic setup
synchronize: false,
migrations: [ /*...*/ ],
// optional
migrationsRun: false,
migrationsTableName: 'migrations',
migrationsTransactionMode: 'all'
// other options...
})
```
## `synchronise`
Turning off automatic schema synchronisation is essential for working with migrations. Otherwise they would make no sense.
## `migrations`
Defines list of migrations that need to be loaded by TypeORM. It accepts both migration classes and directories from which to load.
The easiest is to specify the directory where your migration files are located (glob patterns are supported):
```ts
migrations: [__dirname + '/migration/**/*{.js,.ts}']
```
Defining both `.js` and `.ts` extensions would allow you to run migrations in development and from compiled to JavaScript for production (eg. from Docker image).
Alternatively you could also specify exact classes to get more fine grained control:
```ts
import FirstMigration from 'migrations/TIMESTAMP-first-migration'
import SecondMigration from 'migrations/TIMESTAMP-second-migration'
export default new DataSource({
migrations: [FirstMigration, SecondMigration]
})
```
but it also requires more manual work and can be error prone.
- `migrationsRun` - Indicates if [migrations](../migrations/01-why.md) should be auto-run on every application launch.
## Optional settings
### `migrationsRun`
Indicates if migrations should be auto-run on every application launch. Default: `false`
### `migrationsTableName`
You might want to specify the name of the table that will store information about executed migrations. By default it is called `'migrations'`.
```ts
migrationsTableName: 'some_custom_migrations_table'
```
### `migrationsTransactionMode`
Controls transaction mode when running migrations. Possible options are:
- `all` (_default_) - wraps migrations run into a single transaction
- `none`
- `each`

View File

@ -0,0 +1,56 @@
# Creating manually
You can create a new migration using CLI by specifying the name and location of the migration:
```shell
npx typeorm migration:create <path/to/migrations>/<migration-name>
```
For example:
```shell
npx typeorm migration:create src/db/migrations/post-refactoring
```
After you run the command you can see a new file generated in the `src/db/migrations` directory named `{TIMESTAMP}-post-refactoring.ts` where `{TIMESTAMP}` is the current timestamp when the migration was generated.
Now you can open the file and add your migration sql queries there. You should see the following content inside your migration:
```typescript
import { MigrationInterface, QueryRunner } from "typeorm"
export class PostRefactoringTIMESTAMP implements MigrationInterface {
async up(queryRunner: QueryRunner): Promise<void> {}
async down(queryRunner: QueryRunner): Promise<void> {}
}
```
There are two methods you must fill with your migration code: `up` and `down`.
`up` has to contain the code you need to perform the migration.
`down` has to revert whatever `up` changed.
`down` method is used to revert the last migration.
Inside both `up` and `down` you have a `QueryRunner` object.
All database operations are executed using this object.
Learn more about [query runner](../query-runner.md).
Let's see what the migration looks like with our `Post` changes:
```typescript
import { MigrationInterface, QueryRunner } from "typeorm"
export class PostRefactoringTIMESTAMP implements MigrationInterface {
async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "post" RENAME COLUMN "title" TO "name"`,
)
}
async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "post" RENAME COLUMN "name" TO "title"`,
) // reverts things made in "up" method
}
}
```

View File

@ -0,0 +1,117 @@
# Generating
TypeORM is able to automatically generate migration files based on the changes you made to the entities, comparing them with existing database schema on the server.
Automatic migration generation creates a new migration file and writes all sql queries that must be executed to update the database. If no changes are detected, the command will exit with code `1`.
Let's say you have a `Post` entity with a `title` column, and you have changed the name `title` to `name`.
You can generate migration with of the following command:
```shell
typeorm migration:generate -d <path/to/datasource> <migration-name>
```
The `-d` argument value should specify the path where your [DataSource](../data-source/1-data-source.md) instance is defined.
Alternatively you can also specify name with `--name` param
```shell
typeorm migration:generate -- -d <path/to/datasource> --name=<migration-name>
```
or use a full path:
```shell
typeorm migration:generate -d <path/to/datasource> <path/to/migrations>/<migration-name>
```
Assuming you used `post-refactoring` as a name, it will generate a new file called `{TIMESTAMP}-post-refactoring.ts` with the following content:
```typescript
import { MigrationInterface, QueryRunner } from "typeorm"
export class PostRefactoringTIMESTAMP implements MigrationInterface {
async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "post" ALTER COLUMN "title" RENAME TO "name"`,
)
}
async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "post" ALTER COLUMN "name" RENAME TO "title"`,
)
}
}
```
Alternatively, you can also output your migrations as Javascript files using the `o` (alias for `--outputJs`) flag. This is useful for Javascript only projects in which TypeScript additional packages are not installed. This command, will generate a new migration file `{TIMESTAMP}-PostRefactoring.js` with the following content:
```javascript
/**
* @typedef {import('typeorm').MigrationInterface} MigrationInterface
* @typedef {import('typeorm').QueryRunner} QueryRunner
*/
/**
* @class
* @implements {MigrationInterface}
*/
module.exports = class PostRefactoringTIMESTAMP {
/**
* @param {QueryRunner} queryRunner
*/
async up(queryRunner) {
await queryRunner.query(
`ALTER TABLE "post" ALTER COLUMN "title" RENAME TO "name"`,
)
}
/**
* @param {QueryRunner} queryRunner
*/
async down(queryRunner) {
await queryRunner.query(
`ALTER TABLE "post" ALTER COLUMN "name" RENAME TO "title"`,
)
}
}
```
By default, it generates CommonJS JavaScript code with the `o` (alias for `--outputJs`) flag, but you can also generate ESM code with the `esm` flag. This is useful for Javascript projects that use ESM:
```javascript
/**
* @typedef {import('typeorm').MigrationInterface} MigrationInterface
* @typedef {import('typeorm').QueryRunner} QueryRunner
*/
/**
* @class
* @implements {MigrationInterface}
*/
export class PostRefactoringTIMESTAMP {
/**
* @param {QueryRunner} queryRunner
*/
async up(queryRunner) {
await queryRunner.query(
`ALTER TABLE "post" ALTER COLUMN "title" RENAME TO "name"`,
)
}
/**
* @param {QueryRunner} queryRunner
*/
async down(queryRunner) {
await queryRunner.query(
`ALTER TABLE "post" ALTER COLUMN "name" RENAME TO "title"`,
)
}
}
```
See, you don't need to write the queries on your own.
The rule of thumb for generating migrations is that you generate them after **each** change you made to your models. To apply multi-line formatting to your generated migration queries, use the `p` (alias for `--pretty`) flag.

View File

@ -0,0 +1,29 @@
# Executing and reverting
Once you have a migration to run on production, you can run them using a CLI command:
```shell
typeorm migration:run -- -d path-to-datasource-config
```
**`typeorm migration:create` and `typeorm migration:generate` will create `.ts` files, unless you use the `o` flag (see more in [Generating migrations](04-generating.md)). The `migration:run` and `migration:revert` commands only work on `.js` files. Thus the typescript files need to be compiled before running the commands.** Alternatively, you can use `ts-node` with `typeorm` to run `.ts` migration files.
Example with `ts-node`:
```shell
npx typeorm-ts-node-commonjs migration:run -- -d path-to-datasource-config
```
Example with `ts-node` in ESM projects:
```shell
npx typeorm-ts-node-esm migration:run -- -d path-to-datasource-config
```
```shell
npx typeorm-ts-node-esm migration:generate ./src/migrations/update-post-table -d ./src/data-source.ts
```
This command will execute all pending migrations and run them in a sequence ordered by their timestamps.
This means all sql queries written in the `up` methods of your created migrations will be executed.
That's all! Now you have your database schema up-to-date.

View File

@ -0,0 +1,11 @@
# Reverting
If for some reason you want to revert the changes, you can run:
```shell
typeorm migration:revert -- -d path-to-datasource-config
```
This command will execute `down` in the latest executed migration.
If you need to revert multiple migrations you must call this command multiple times.

View File

@ -0,0 +1,11 @@
# Status
To show all migrations and whether they've been run or not use following command:
```shell
typeorm migration:show -- -d path-to-datasource-config
```
[X] = Migration has been ran
[ ] = Migration is pending/unapplied

View File

@ -0,0 +1,42 @@
# Faking Migrations and Rollbacks
You can also fake run a migration using the `--fake` flag (`-f` for short). This will add the migration
to the migrations table without running it. This is useful for migrations created after manual changes
have already been made to the database or when migrations have been run externally
(e.g. by another tool or application), and you still would like to keep a consistent migration history.
```shell
typeorm migration:run -d path-to-datasource-config --fake
```
This is also possible with rollbacks.
```shell
typeorm migration:revert -d path-to-datasource-config --fake
```
### Transaction modes
By default, TypeORM will run all your migrations within a single wrapping transaction.
This corresponds to the `--transaction all` flag.
If you require more fine grained transaction control, you can use the `--transaction each` flag to wrap every migration individually, or the `--transaction none` flag to opt out of wrapping the migrations in transactions altogether.
In addition to these flags, you can also override the transaction behavior on a per-migration basis by setting the `transaction` property on the `MigrationInterface` to `true` or `false`. This only works in the `each` or `none` transaction mode.
```typescript
import { MigrationInterface, QueryRunner } from "typeorm"
export class AddIndexTIMESTAMP implements MigrationInterface {
transaction = false
async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`CREATE INDEX CONCURRENTLY post_names_idx ON post(name)`,
)
}
async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`DROP INDEX CONCURRENTLY post_names_idx`)
}
}
```

View File

@ -1,348 +1,7 @@
# Migrations
## How migrations work?
Once you get into production you'll need to synchronize model changes into the database.
Typically, it is unsafe to use `synchronize: true` for schema synchronization on production once
you get data in your database. Here is where migrations come to help.
A migration is just a single file with sql queries to update a database schema
and apply new changes to an existing database.
Let's say you already have a database and a post entity:
```typescript
import { Entity, Column, PrimaryGeneratedColumn } from "typeorm"
@Entity()
export class Post {
@PrimaryGeneratedColumn()
id: number
@Column()
title: string
@Column()
text: string
}
```
And your entity worked in production for months without any changes.
You have thousands of posts in your database.
Now you need to make a new release and rename `title` to `name`.
What would you do?
You need to create a new migration with the following SQL query (postgres dialect):
```sql
ALTER TABLE "post" ALTER COLUMN "title" RENAME TO "name";
```
Once you run this SQL query your database schema is ready to work with your new codebase.
TypeORM provides a place where you can write such sql queries and run them when needed.
This place is called "migrations".
## Creating a new migration
**Pre-requisites**: [Installing CLI](./6-using-cli.md#installing-cli)
Before creating a new migration you need to setup your data source options properly:
```ts
import { DataSource } from "typeorm"
export default new DataSource({
type: "mysql",
host: "localhost",
port: 3306,
username: "test",
password: "test",
database: "test",
entities: [
/*...*/
],
migrations: [
/*...*/
],
migrationsTableName: "custom_migration_table",
})
```
Here we setup two options:
- `"migrationsTableName": "migrations"` - Specify this option only if you need the migration table name to be different from `"migrations"`.
- `"migrations": [/*...*/]` - list of migrations that need to be loaded by TypeORM
Once you setup the connection options you can create a new migration using CLI:
```shell
typeorm migration:create ./path-to-migrations-dir/PostRefactoring
```
Here, `PostRefactoring` is the name of the migration - you can specify any name you want.
After you run the command you can see a new file generated in the "migration" directory
named `{TIMESTAMP}-PostRefactoring.ts` where `{TIMESTAMP}` is the current timestamp when the migration was generated.
Now you can open the file and add your migration sql queries there.
You should see the following content inside your migration:
```typescript
import { MigrationInterface, QueryRunner } from "typeorm"
export class PostRefactoringTIMESTAMP implements MigrationInterface {
async up(queryRunner: QueryRunner): Promise<void> {}
async down(queryRunner: QueryRunner): Promise<void> {}
}
```
There are two methods you must fill with your migration code: `up` and `down`.
`up` has to contain the code you need to perform the migration.
`down` has to revert whatever `up` changed.
`down` method is used to revert the last migration.
Inside both `up` and `down` you have a `QueryRunner` object.
All database operations are executed using this object.
Learn more about [query runner](../query-runner.md).
Let's see what the migration looks like with our `Post` changes:
```typescript
import { MigrationInterface, QueryRunner } from "typeorm"
export class PostRefactoringTIMESTAMP implements MigrationInterface {
async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "post" RENAME COLUMN "title" TO "name"`,
)
}
async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "post" RENAME COLUMN "name" TO "title"`,
) // reverts things made in "up" method
}
}
```
## Running and reverting migrations
Once you have a migration to run on production, you can run them using a CLI command:
```shell
typeorm migration:run -- -d path-to-datasource-config
```
**`typeorm migration:create` and `typeorm migration:generate` will create `.ts` files, unless you use the `o` flag (see more in [Generating migrations](#generating-migrations)). The `migration:run` and `migration:revert` commands only work on `.js` files. Thus the typescript files need to be compiled before running the commands.** Alternatively, you can use `ts-node` with `typeorm` to run `.ts` migration files.
Example with `ts-node`:
```shell
npx typeorm-ts-node-commonjs migration:run -- -d path-to-datasource-config
```
Example with `ts-node` in ESM projects:
```shell
npx typeorm-ts-node-esm migration:run -- -d path-to-datasource-config
```
```shell
npx typeorm-ts-node-esm migration:generate ./src/migrations/update-post-table -d ./src/data-source.ts
```
This command will execute all pending migrations and run them in a sequence ordered by their timestamps.
This means all sql queries written in the `up` methods of your created migrations will be executed.
That's all! Now you have your database schema up-to-date.
If for some reason you want to revert the changes, you can run:
```shell
typeorm migration:revert -- -d path-to-datasource-config
```
This command will execute `down` in the latest executed migration.
If you need to revert multiple migrations you must call this command multiple times.
### Faking Migrations and Rollbacks
You can also fake run a migration using the `--fake` flag (`-f` for short). This will add the migration
to the migrations table without running it. This is useful for migrations created after manual changes
have already been made to the database or when migrations have been run externally
(e.g. by another tool or application), and you still would like to keep a consistent migration history.
```shell
typeorm migration:run -d path-to-datasource-config --fake
```
This is also possible with rollbacks.
```shell
typeorm migration:revert -d path-to-datasource-config --fake
```
### Transaction modes
By default, TypeORM will run all your migrations within a single wrapping transaction.
This corresponds to the `--transaction all` flag.
If you require more fine grained transaction control, you can use the `--transaction each` flag to wrap every migration individually, or the `--transaction none` flag to opt out of wrapping the migrations in transactions altogether.
In addition to these flags, you can also override the transaction behavior on a per-migration basis by setting the `transaction` property on the `MigrationInterface` to `true` or `false`. This only works in the `each` or `none` transaction mode.
```typescript
import { MigrationInterface, QueryRunner } from "typeorm"
export class AddIndexTIMESTAMP implements MigrationInterface {
transaction = false
async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`CREATE INDEX CONCURRENTLY post_names_idx ON post(name)`,
)
}
async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`DROP INDEX CONCURRENTLY post_names_idx`)
}
}
```
## Generating migrations
TypeORM is able to automatically generate migration files with schema changes you made.
Let's say you have a `Post` entity with a `title` column, and you have changed the name `title` to `name`.
You can run following command:
```shell
typeorm migration:generate PostRefactoring -d path-to-datasource-config
```
If you encounter any error, it require you have the path to migration name and data source. You can try this option
```shell
typeorm migration:generate -d <path/to/datasource> path/to/migrations/<migration-name>
```
And it will generate a new migration called `{TIMESTAMP}-PostRefactoring.ts` with the following content:
```typescript
import { MigrationInterface, QueryRunner } from "typeorm"
export class PostRefactoringTIMESTAMP implements MigrationInterface {
async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "post" ALTER COLUMN "title" RENAME TO "name"`,
)
}
async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "post" ALTER COLUMN "name" RENAME TO "title"`,
)
}
}
```
Alternatively, you can also output your migrations as Javascript files using the `o` (alias for `--outputJs`) flag. This is useful for Javascript only projects in which TypeScript additional packages are not installed. This command, will generate a new migration file `{TIMESTAMP}-PostRefactoring.js` with the following content:
```javascript
/**
* @typedef {import('typeorm').MigrationInterface} MigrationInterface
* @typedef {import('typeorm').QueryRunner} QueryRunner
*/
/**
* @class
* @implements {MigrationInterface}
*/
module.exports = class PostRefactoringTIMESTAMP {
/**
* @param {QueryRunner} queryRunner
*/
async up(queryRunner) {
await queryRunner.query(
`ALTER TABLE "post" ALTER COLUMN "title" RENAME TO "name"`,
)
}
/**
* @param {QueryRunner} queryRunner
*/
async down(queryRunner) {
await queryRunner.query(
`ALTER TABLE "post" ALTER COLUMN "name" RENAME TO "title"`,
)
}
}
```
By default, it generates CommonJS JavaScript code with the `o` (alias for `--outputJs`) flag, but you can also generate ESM code with the `esm` flag. This is useful for Javascript projects that use ESM:
```javascript
/**
* @typedef {import('typeorm').MigrationInterface} MigrationInterface
* @typedef {import('typeorm').QueryRunner} QueryRunner
*/
/**
* @class
* @implements {MigrationInterface}
*/
export class PostRefactoringTIMESTAMP {
/**
* @param {QueryRunner} queryRunner
*/
async up(queryRunner) {
await queryRunner.query(
`ALTER TABLE "post" ALTER COLUMN "title" RENAME TO "name"`,
)
}
/**
* @param {QueryRunner} queryRunner
*/
async down(queryRunner) {
await queryRunner.query(
`ALTER TABLE "post" ALTER COLUMN "name" RENAME TO "title"`,
)
}
}
```
See, you don't need to write the queries on your own.
The rule of thumb for generating migrations is that you generate them after **each** change you made to your models. To apply multi-line formatting to your generated migration queries, use the `p` (alias for `--pretty`) flag.
## DataSource option
If you need to run/revert/generate/show your migrations use the `-d` (alias for `--dataSource`) and pass the path to the file where your DataSource instance is defined as an argument
```shell
typeorm -d <your-data-source-path> migration:{run|revert}
```
## Timestamp option
If you need to specify a timestamp for the migration name, use the `-t` (alias for `--timestamp`) and pass the timestamp (should be a non-negative number)
```shell
typeorm -t <specific-timestamp> migration:{create|generate}
```
You can get a timestamp from:
```js
Date.now()
/* OR */ new Date().getTime()
```
## Using migration API to write migrations
# Query Runner API
In order to use an API to change a database schema you can use `QueryRunner`.
Example:
```ts
import {
MigrationInterface,

View File

@ -0,0 +1,16 @@
# Extra options
## Timestamp
If you need to specify a timestamp for the migration name, use the `-t` (alias for `--timestamp`) and pass the timestamp (should be a non-negative number)
```shell
typeorm -t <specific-timestamp> migration:{create|generate}
```
You can get a timestamp from:
```js
Date.now()
/* OR */ new Date().getTime()
```

View File

@ -0,0 +1,86 @@
# Vite
Using TypeORM in a [Vite](https://vite.dev) project is pretty straight forward. However, when you use [migrations](../migrations/01-why.md), you will run into "...migration name is wrong. Migration class name should have a
JavaScript timestamp appended." errors when running the production build.
On production builds, files are [optimized by default](https://vite.dev/config/build-options#build-minify) which includes mangling your code in order to minimize file sizes.
You have 3 options to mitigate this. The 3 options are shown below as diff to this basic `vite.config.ts`
```typescript
import legacy from "@vitejs/plugin-legacy"
import vue from "@vitejs/plugin-vue"
import path from "path"
import { defineConfig } from "vite"
// https://vitejs.dev/config/
export default defineConfig({
build: {
sourcemap: true,
},
plugins: [vue(), legacy()],
resolve: {
alias: {
"@": path.resolve(__dirname, "./src"),
},
},
})
```
## Option 1: Disable minify
This is the most crude option and will result in significantly larger files. Add `build.minify = false` to your config.
```diff
--- basic vite.config.ts
+++ disable minify vite.config.ts
@@ -7,6 +7,7 @@
export default defineConfig({
build: {
sourcemap: true,
+ minify: false,
},
plugins: [vue(), legacy()],
resolve: {
```
## Option 2: Disable esbuild minify identifiers
Vite uses esbuild as the default minifier. You can disable mangling of identifiers by adding `esbuild.minifyIdentifiers = false` to your config.
This will result in smaller file sizes, but depending on your code base you will get diminishing returns as all identifiers will be kept at full length.
```diff
--- basic vite.config.ts
+++ disable esbuild minify identifiers vite.config.ts
@@ -8,6 +8,7 @@
build: {
sourcemap: true,
},
+ esbuild: { minifyIdentifiers: false },
plugins: [vue(), legacy()],
resolve: {
```
## Option 3: Use terser as minifier while keeping only the migration class names
Vite supports using terser as minifier. Terser is slower then esbuild, but offers more fine grained control over what to minify.
Add `minify: 'terser'` with `terserOptions.mangle.keep_classnames: /^Migrations\d+$/` and `terserOptions.compress.keep_classnames: /^Migrations\d+$/` to your config.
These options will make sure classnames that start with "Migrations" and end with numbers are not renamed during minification.
Make sure terser is available as dev dependency in your project: `npm add -D terser`.
```diff
--- basic vite.config.ts
+++ terser keep migration class names vite.config.ts
@@ -7,6 +7,11 @@
export default defineConfig({
build: {
sourcemap: true,
+ minify: 'terser',
+ terserOptions: {
+ mangle: { keep_classnames: /^Migrations\d+$/ },
+ compress: { keep_classnames: /^Migrations\d+$/ },
+ },
},
plugins: [vue(), legacy()],
resolve: {
```

View File

@ -101,7 +101,7 @@ export const redirects = [
},
{ from: "/data-source-api", to: "/docs/data-source/data-source-api" },
{ from: "/migrations", to: "/docs/advanced-topics/migrations" },
{ from: "/migrations", to: "/docs/migrations" },
{ from: "/transactions", to: "/docs/advanced-topics/transactions" },
{ from: "/indices", to: "/docs/advanced-topics/indices" },
{
@ -123,4 +123,5 @@ export const redirects = [
{ from: "/getting-started", to: "/docs/getting-started" },
{ from: "/future-of-typeorm", to: "/docs/future-of-typeorm" },
{ from: "/query-runner", to: "/docs/query-runner" },
{ from: "/docs/advanced-topics/migrations", to: "/docs/migrations" },
]

View File

@ -35,6 +35,11 @@ const sidebars: SidebarsConfig = {
label: "Relations",
items: [{ type: "autogenerated", dirName: "relations" }],
},
{
type: "category",
label: "Migrations",
items: [{ type: "autogenerated", dirName: "migrations" }],
},
{
type: "category",
label: "Working with Entity Manager",