👋

EntityMetadataNotFoundError: No metadata for "*" was found.

2024/08/11に公開

Nestjs × TypeORMでアプリを作っておりまして、かなりハマったポイントがあったため、残しておきます。

Entities直接指定は問題ないのに、パス指定だとエラー

database.config.tsというファイルで、TypeORMのオプションを指定していました。

下記のように、entitiesフィールドにImportしてきたクラスを直接指定すると、ちゃんと動作します。

database.config.ts
import { Injectable } from "@nestjs/common";
import { ConfigService } from "@nestjs/config";
import { TypeOrmOptionsFactory, TypeOrmModuleOptions } from "@nestjs/typeorm";
import { User } from "src/domain/entities/user";

@Injectable()
export class TypeOrmConfigService implements TypeOrmOptionsFactory {
  createTypeOrmOptions(): TypeOrmModuleOptions {
    const configService = new ConfigService();
    return {
      type: "postgres",
      host: configService.get("DATABASE_HOST"),
      port: configService.get("DATABASE_PORT"),
      username: configService.get("DATABASE_USER"),
      password: configService.get("DATABASE_PASSWORD"),
      database: configService.get("DATABASE_DB"),
      schema: configService.get("DATABASE_SCHEMA"),
      entities: [User],
      synchronize: false,
    };
  }
}

しかし、下記のように、パス指定だと、エラーになってしまいました。(パスは間違っていないものとします)

database.config.ts
import { Injectable } from "@nestjs/common";
import { ConfigService } from "@nestjs/config";
import { TypeOrmOptionsFactory, TypeOrmModuleOptions } from "@nestjs/typeorm";

@Injectable()
export class TypeOrmConfigService implements TypeOrmOptionsFactory {
  createTypeOrmOptions(): TypeOrmModuleOptions {
    const configService = new ConfigService();
    return {
      type: "postgres",
      host: configService.get("DATABASE_HOST"),
      port: configService.get("DATABASE_PORT"),
      username: configService.get("DATABASE_USER"),
      password: configService.get("DATABASE_PASSWORD"),
      database: configService.get("DATABASE_DB"),
      schema: configService.get("DATABASE_SCHEMA"),
      entities: [__dirname + "/../../domain/entities/*.ts"], // ← 相対パス指定
      synchronize: false,
    };
  }
}

一度テーブルをすべて消してMigrationし直してみたりと、色々試してみたのですが、一向に解消されません。
調べてみると、こちらの記事で同様の事象に悩まされている人がいました。
https://stackoverflow.com/questions/51562162/no-metadata-for-user-was-found-using-typeorm

.jsで指定しなさい

__dirname + "/../../domain/entities/*.ts"をconsole.logで吐き出してみると分かるのですが、/dist配下のディレクトリを指してるんですね

なので、トランスパイル後の.jsで指定すれば、正しく動きました。

database.config.ts
import { Injectable } from "@nestjs/common";
import { ConfigService } from "@nestjs/config";
import { TypeOrmOptionsFactory, TypeOrmModuleOptions } from "@nestjs/typeorm";

@Injectable()
export class TypeOrmConfigService implements TypeOrmOptionsFactory {
  createTypeOrmOptions(): TypeOrmModuleOptions {
    const configService = new ConfigService();
    return {
      type: "postgres",
      host: configService.get("DATABASE_HOST"),
      port: configService.get("DATABASE_PORT"),
      username: configService.get("DATABASE_USER"),
      password: configService.get("DATABASE_PASSWORD"),
      database: configService.get("DATABASE_DB"),
      schema: configService.get("DATABASE_SCHEMA"),
      entities: [__dirname + "/../../domain/entities/*.js"],
      synchronize: false,
    };
  }
}

めでたしめでたし

Discussion