1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

tscでトランスパイル後のTypeORMのパス問題に対処する

Last updated at Posted at 2020-12-05

TypeScriptを用いたサーバーサイドの開発で、ORMとしてTypeORMを使っている人も多いと思います。TypeORMはモデルを設定ファイルや環境変数で指定されたパスから動的に読み込むことから、ts-nodeやts-node-devなどでTypeScriptのまま動かす場合とtscでJavaScriptにトランスパイルしてから動かす場合で、パスに差異が出て困ることがあります。

問題となるケース

ormconfig.jsに設定を書く運用の場合を考えます。最初は公式ドキュメントを真似して以下のように書いていました。

ormconfig.js
module.exports = [{
  name: 'default',
  type: 'mysql',
  host: process.env.MYSQL_SERVER,
  port: process.env.MYSQL_PORT,
  username: process.env.MYSQL_USER,
  password: process.env.MYSQL_PASSWORD,
  database: process.env.MYSQL_DATABASE,
  synchronize: true,
  logging: false,
  entities: ['src/entity/**/*.ts'],
  migrations: ['src/migration/**/*.ts'],
  subscribers: ['src/subscriber/**/*.ts']
}];

開発中はずっとts-node-devでTypeScriptのまま動かしていたのでこれで何の問題もなかったのですが、いざ本番環境向けにtscでトランスパイルしてみると、Repository Not Foundとかで全然動かない。

原因はすぐ察しがつく通り、entitiesmigrationssubscribersの指定が拡張子.tsになっていること。トランスパイル後は.jsになるので、TypeORMはモデルを読み込むことができません。またtsconfig.jsonの内容次第ではディレクトリ構成も変わったりすることもあり得ます。

解決策

本番運用をts-nodeにする

正直これが一番手っ取り早い気がしています。起動さえしてしまえばトランスパイルする場合とパフォーマンスに大差はないという話もありますし。一応、今回の本題はこれではありません。

ormconfig.jsの設定値を実行環境に応じて切り換える

こっちが本題です。まず、ormconfig.jsをこんな感じにします。

ormconfig.js
const commonConfig = {
  name: 'default',
  type: 'mysql',
  host: process.env.MYSQL_SERVER,
  port: process.env.MYSQL_PORT,
  username: process.env.MYSQL_USER,
  password: process.env.MYSQL_PASSWORD,
  database: process.env.MYSQL_DATABASE,
  synchronize: true,
  logging: false
};

const tsConfig = {
  entities: ['src/entity/**/*.ts'],
  migrations: ['src/migration/**/*.ts'],
  subscribers: ['src/subscriber/**/*.ts']
};

const jsConfig = {
  entities: ['dist/entity/**/*.js'],
  migrations: ['dist/migration/**/*.js'],
  subscribers: ['dist/subscriber/**/*.js']
}

if (process.env.TS_NODE) {
  module.exports = [{...commonConfig, ...tsConfig}];
} else {
  module.exports = [{...commonConfig, ...jsConfig}];
}

package.jsonscriptsをこうします。

package.json
  "scripts": {
    "dev": "TS_NODE=true ts-node ./src/index.ts",
    "dev:watch": "TS_NODE=true ts-node-dev ./src/index.ts",
    "build": "npm-run-all clean tsc",
    "clean": "rimraf dist/*",
    "tsc": "tsc",
    "start": "TS_NODE= node ./dist/index.js"
  },

ts-nodeやts-node-devで動かす場合はTS_NODEに適当な値を設定して、nodeで動かす場合はTS_NODEを空にします。ormconfig.jsではTS_NODEを見てモデルのロードパスを切り換えます。

ormconfigはJSONやYAMLなどで書くこともできますが、その場合ロジックが書けないのでJavaScriptで書く方が何かと便利です。

これを応用すると、例えば開発・ステージング・本番でDB周りの設定値を切り換えるといったことも比較的シンプルに実現できます。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?