【TypeORM】tsファイルにて定義した接続環境と、テーブル定義を表現したEntityファイルにもとづいたマイグレーションファイル自動生成を行う


上記の続編。上記ではsyncronizeによるテーブル自動生成を行っていた。
今回は上記Entityファイルおよび接続設定によるマイグレーションファイル自動作成を行う。

前提

上記のTypeORMを導入していること。本記事にて用いているバージョンは以下。

    "mysql2": "^2.3.0",
    "typeorm": "^0.2.37",

    "@types/node": "^16.7.10",

参考記事

書き始めようとしたら見つけた先駆者様。より全体的な実装例を書いてくださっている。

--config なるオプションがあり、そこからconfigファイルを指定できるらしい。

躓いたところ+解決法

躓いたところ:ormconfig.jsonじゃないファイルを個別に指定してできないの?

→できた。migrateコマンドにconfigファイルを指定するオプションがあるのでソレを指定する。

実際にやってみる

package.json

  "scripts": {
    "migrate:generate:training": "ts-node ./node_modules/typeorm/cli.js migration:generate  --config ./server/typeorm/togoconfig.ts -n",
    "migrate:up:training": "ts-node ./node_modules/typeorm/cli.js migration:run  --config ./server/typeorm/togoconfig.ts",
    "migrate:down:training": "ts-node ./node_modules/typeorm/cli.js migration:revert  --config ./server/typeorm/togoconfig.ts"
  }

migrate:generate部分の末尾にはファイル名オプションの-nを付けてあるので、
yarn migrate:generate:training filenameのようなイメージでマイグレーションファイルを自動生成できる。
この"migrate:generate:training"部分はコマンドのエイリアス(別名)に過ぎないので、お好みでいいと思う。

ガチャガチャ組み込んだ接続設定、server/typeorm/togoconfig.ts

import connectConfig from './index'

export = connectConfig.tougouConfig

上記ファイルの親玉、server/typeorm/index.ts(一部)

各設定などは公式ページなどを参照。


import dotenv from 'dotenv'
import { ConnectionOptions } from "typeorm";
import { Log4jsLogger } from "./common/logger"

// nuxt.js v14.12なので.envを有効活用している。
// 接続設定を環境変数process.env.~にすることで他環境へも適用できるようにする。
dotenv.config({ path: __dirname + '/.env' });

// https://typeorm.io/#/connection-options
const tougouConfig: ConnectionOptions = {
    type: "mysql",
    host: process.env.CONNECT_HOST,
    port: Number(process.env.CONNECT_PORT),
    username: process.env.CONNECT_USER,
    password: process.env.CONNECT_PASS,
    database: process.env.CONNECT_DATABASE,
    // 指定したフォルダ内の@Entityを認識してくれる。
    // Nuxt.jsのservermiddlewareにて動かしてる扱いなので以下のようなフォルダ階層としている。
    entities: [
        "server/typeorm/models/*.*"
    ],
    // migrate時に確認するファイル。
    migrations: [
        "migration/tougou/*.ts"
    ],
    // cli起動時に生成するmigrationファイルのフォルダ位置
    cli: {
        migrationsDir: 'migration/tougou',
    },
    // synchronize: trueの時、上記entityを正としてスキーマに接続、同期させる。
    // デバッグや開発時に役立つ。

    // 公式ドキュメントに書いてあるが、本番環境では絶対にfalseにしておくこと。
    synchronize: false,
    logging: true,
    // https://typeorm.io/#/logging
    // カスタムしてるので割愛。
    // Visual Code Studio + typescriptのクイックフィックスで編集必要なメソッドはわかる。
    logger: new Log4jsLogger(),
    timezone: "+09:00"
}

export default {
    tougouConfig: tougouConfig
}

上記exportによって複数の接続設定がtsファイルによって可能。その中から一つを選んでCLI利用migrationをするという選択肢を取ることができる。

躓いたところ:バージョン管理としてEntityを保存・更新してmigrate:generateしたら変更した箇所のデータが消える

→列定義変更箇所は、MODIFYで済む変更もDROP+ADDを行ってしまっている。仕方がないのでヒトの手で直す

変更例

列のlengthを変更する

  @Column({ nullable: false, type: "varchar", length: 12, comment: "グループコードID" })
  codeGroupId!: string;

to

  @Column({ nullable: false, type: "varchar", length: 24, comment: "グループコードID" })
  codeGroupId!: string;

できあがったマイグレーションファイル一部

    public async up(queryRunner: QueryRunner): Promise<void> {
        await queryRunner.query(`ALTER TABLE \`nuxt_typescript_training\`.\`m_code\` DROP COLUMN \`codeGroupId\``);
        await queryRunner.query(`ALTER TABLE \`nuxt_typescript_training\`.\`m_code\` ADD \`codeGroupId\` varchar(24) NOT NULL COMMENT 'グループコードID'`);

DROP COLUMN+ADD をしている。
これだとアップデート・ダウングレード時にカラムデータが抜けてしまう…。
仕方がないのでヒトの手で直す。

        // await queryRunner.query(`ALTER TABLE \`nuxt_typescript_training\`.\`m_code\` DROP COLUMN \`codeGroupId\``);
        // await queryRunner.query(`ALTER TABLE \`nuxt_typescript_training\`.\`m_code\` ADD \`codeGroupId\` varchar(24) NOT NULL COMMENT 'グループコードID'`);
        await queryRunner.query(`ALTER TABLE \`nuxt_typescript_training\`.\`m_code\` MODIFY \`codeGroupId\` varchar(24) NOT NULL COMMENT 'グループコードID'`);

マイグレーションファイルのdown側も同じなので、同じく書き直す。
もっと良い方法があればいいなと思っている。