Skip to main content
Skip to main content

How to Create Migrations

In this document, you’ll learn how to create a Migration using Typeorm in Medusa.

Step 1: Create Migration File

There are two ways to create a migration file: create and write its content manually, or create and generate its content.

If you're creating a custom entity, then it's recommended to generate the migration file. However, if you're extending an entity from Medusa's core, then you should create and write the migration manually.

Option 1: Generate Migration File

Warning

Generating migration files for extended entities may cause unexpected errors. It's highly recommended to write them manually instead.

Typeorm provides a migration:generate command that allows you to pass it a Typeorm DataSource. The DataSource includes database connection details, as well as the path to your custom entities.

Start by creating the file datasource.js in the root of your Medusa backend project with the following content:

const { DataSource } = require("typeorm")

const AppDataSource = new DataSource({
type: "postgres",
port: 5432,
username: "<YOUR_DB_USERNAME>",
password: "<YOUR_DB_PASSWORD>",
database: "<YOUR_DB_NAME>",
entities: [
"dist/models/*.js",
],
migrations: [
"dist/migrations/*.js",
],
})

module.exports = {
datasource: AppDataSource,
}

Make sure to replace <YOUR_DB_USERNAME>, <YOUR_DB_PASSWORD>, and <YOUR_DB_NAME> with the necessary values for your database connection.

Then, after creating your entity, run the build command:

npm run build

Finally, run the following command to generate a migration for your custom entity:

npx typeorm migration:generate -d datasource.js src/migrations/PostCreate

This will generate the migration file in the path you specify, where PostCreate is just an example of the name of the migration to create. The migration file must be inside the src/migrations directory. When you run the build command, it will be transpiled into the dist/migrations directory.

The migrations run command can only pick up migrations under the dist/migrations directory on a Medusa backend. This applies to migrations created in a Medusa backend, and not in a Medusa plugin. For plugins, check out the Plugin's Structure section.

You can now continue to step 2 of this guide.

Option 2: Write Migration File

With this option, you'll use Typeorm's CLI tool to create the migration file, but you'll write the content yourself.

Run the following command in the root directory of your Medusa backend project:

npx typeorm migration:create src/migrations/PostCreate

This will create the migration file in the path you specify, where PostCreate is just an example of the name of the migration to create. The migration file must be inside the src/migrations directory. When you run the build command, it will be transpiled into the dist/migrations directory.

The migrations run command can only pick up migrations under the dist/migrations directory on a Medusa backend. This applies to migrations created in a Medusa backend, and not in a Medusa plugin. For plugins, check out the Plugin's Structure section.

If you open the file, you'll find up and down methods. The up method is used to reflect the changes on the database. The down method is used to revert the changes, which will be executed if the npx medusa migrations revert command is used.

In each of the up and down methods, you can write the migration either with SQL syntax, or using the migration API.

For example:

import { MigrationInterface, QueryRunner } from "typeorm"

export class AddAuthorsAndPosts1690876698954 implements MigrationInterface {
name = "AddAuthorsAndPosts1690876698954"

public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`CREATE TABLE "post" ("id" character varying NOT NULL, "created_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "updated_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "title" character varying NOT NULL, "author_id" character varying NOT NULL, "authorId" character varying, CONSTRAINT "PK_be5fda3aac270b134ff9c21cdee" PRIMARY KEY ("id"))`)
await queryRunner.query(`CREATE TABLE "author" ("id" character varying NOT NULL, "created_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "updated_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "name" character varying NOT NULL, "image" character varying, CONSTRAINT "PK_5a0e79799d372fe56f2f3fa6871" PRIMARY KEY ("id"))`)
await queryRunner.query(`ALTER TABLE "post" ADD CONSTRAINT "FK_c6fb082a3114f35d0cc27c518e0" FOREIGN KEY ("authorId") REFERENCES "author"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`)
}

public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE "post" DROP CONSTRAINT "FK_c6fb082a3114f35d0cc27c518e0"`)
await queryRunner.query(`DROP TABLE "author"`)
await queryRunner.query(`DROP TABLE "post"`)
}
}

Migration Name

If the name attribute isn't available in the generated migration, an error may occur while running the migration. To avoid this, make sure to add it manually and set its value to the class's name:

export class AddAuthorsAndPosts1690876698954 implements MigrationInterface {
name = "AddAuthorsAndPosts1690876698954"

// ...
}

Step 2: Build Files

Before you can run the migrations, you need to run the build command to transpile the TypeScript files to JavaScript files:

npm run build

Step 3: Run Migration

The last step is to run the migration with the command detailed earlier

npx medusa migrations run

If you check your database now you should see that the change defined by the migration has been applied successfully.


See Also

Was this section helpful?