TypeORMの設定ファイルが読み込めない


TypeORMの設定ファイル(ormconfig.json)を読み込めない!!
みたいな困りごとがあったので、解決策をメモしておきます

結論

TypeORMは「.env」「ormconfig.env」「ormconfig.xxx」の優先度で設定値を読み込む。今回はdotenv使っていたのでormconfig.jsonが読み込まれていなかった

ドキュメント

抜粋

From the environment variables. Typeorm will attempt to load the .env file using dotEnv if it exists. If the environment variables TYPEORM_CONNECTION or TYPEORM_URL are set, Typeorm will use this method.
From the ormconfig.env.
From the other ormconfig.[format] files, in this order: [js, ts, json, yml, yaml, xml].

状況を再現してみる

実験用ディレクトリを作ります

npm init
npx typeorm init

こんなプロジェクトができるはず

.
├── README.md
├── node_modules
├── ormconfig.json
├── package-lock.json
├── package.json
├── src
└── tsconfig.json

ormconfig.jsonを開いてみます

{
   "type": "mysql",
   "host": "localhost",
   "port": 3306, <-- ここに注目
   "username": "test",
   "password": "test",
   "database": "test",
   "synchronize": true,
   "logging": false,
   "entities": [
      "src/entity/**/*.ts"
   ],
   "migrations": [
      "src/migration/**/*.ts"
   ],
   "subscribers": [
      "src/subscriber/**/*.ts"
   ],
   "cli": {
      "entitiesDir": "src/entity",
      "migrationsDir": "src/migration",
      "subscribersDir": "src/subscriber"
   }
}

ポート3306を指定したので、この状態で npm start すれば...

  code: 'ECONNREFUSED',
  syscall: 'connect',
  address: '127.0.0.1',
  port: 3306, <-- ここに注目
  fatal: true

ちゃんと3306を目指します。

dotenvを使っている場合

が、仮にあなたのプロジェクトがdotenvを使って環境変数を管理していて、こんな.envファイルがルートに置いてあるとしましょう

TYPEORM_PORT=4000
TYPEORM_CONNECTION=mysql

この状態で npm start してみます

  code: 'ECONNREFUSED',
  syscall: 'connect',
  address: '127.0.0.1',
  port: 4000, <-- ここに注目
  fatal: true

ormconfig.jsonは無視されて.envが優先されました

この仕様を見落としていたため、今回僕はormconfig.jsonが無視されて困っていたワケです

ちなみに

.envの中身に左右されます

TYPEORM_CONNECTION、もしくはTYPEORM_URLのいずれかが.envに指定されている場合のみ、.envが優先されます。
なので試しにTYPEORM_CONNECTIONを外してみましょう

TYPEORM_PORT=4000
TYPEORM_CONNECTION=mysql <-- コイツを削除してみる
TYPEORM_PORT=4000

この状態で起動すると

  code: 'ECONNREFUSED',
  syscall: 'connect',
  address: '127.0.0.1',
  port: 3306, <-- ここに注目

.envではなく、ormconfig.jsonが優先されて3306に向かっていますね。

dotenvの有無は関係ねぇ!

dotenvをプロジェクト自身が使っていなくても、.envファイルが転がっていると、そちらormconfig.jsonより優先されます。
node_modules/typeorm/package.json を覗いてみると

  "dependencies": {
    "app-root-path": "^3.0.0",
    "buffer": "^5.1.0",
    "chalk": "^2.4.2",
    "cli-highlight": "^2.0.0",
    "debug": "^4.1.1",
    "dotenv": "^6.2.0", <-- いた!
    "glob": "^7.1.2",
    "js-yaml": "^3.13.1",

はい、dotenvが居りますね。
なので自分自身がdotenvを入れていなくても注意しましょう。

教訓

今後はドキュメントをちゃんと読むようにします...

関係ありそうなエラーメッセージ

Cannot find connection xxx because its not defined in any orm configuration files.
- ormconfig.jsonの中でconnectionの名前とか指定していた場合、.envが優先されてormconfig.jsonは無視されるので、名前付きconnectionが見つからず、こんなエラーが出る事があります

No migrations pending
- マイグレーション対象のDBをormconfig.jsonで定義していた場合、.envが優先されてormconfig.jsonは無視されるので、マイグレーション済みの別DBを参照して、こんなエラーが出る事があります