Import statement breaks typeorm enitities when registered through config.json file

Viewed 11661

Following official docs, I created small koa/typeorm/postgres app. When I was using createConnection with config, importing entities in the same file, app was working fine, but typeorm cli coudn't find config file so I tried moving config to "ormconfig.json". Now I get this error:

SyntaxError: Cannot use import statement outside a module

It looks as if typeorm isn't able to use es6 features.

My ormconfig.json:

{
  "type": "postgres",
  "host": "localhost",
  "port": 5432,
  "username": ****,
  "password": ****,
  "database": ****,
  "synchronize": true,
  "entities": ["src/entity/**/*.ts"],
  "migrations": ["src/migration/**/*.ts"],
  "subscribers": ["src/subscriber/**/*.ts"],
  "cli": {
    "entitiesDir": "src/entity",
    "migrationsDir": "src/migration",
    "subscribersDir": "src/subscriber"
  }
}

My tsconfig.json:

{
  "compilerOptions": {
    "lib": ["es5", "es6"],
    "target": "es6",
    "module": "commonjs",
    "moduleResolution": "node",
    "outDir": "./dist",
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
  },
  "exclude": ["node_modules"]
}

File with error:

import {
  BaseEntity,
  Column,
  Entity,
  PrimaryGeneratedColumn,
  CreateDateColumn,
  ManyToOne
} from 'typeorm';
import { IsIn, IsPositive, IsNotEmpty } from 'class-validator';

import { LOAN_TYPE } from '../consts';
import { User } from './user';

@Entity('loans')
export class Loan extends BaseEntity {
  @PrimaryGeneratedColumn()
  public id: number;

  @CreateDateColumn({ type: 'timestamp' })
  public createdAt: Date;

  @Column()
  @IsNotEmpty()
  @IsPositive()
  public amount: number;

  @Column({ type: 'enum', enum: LOAN_TYPE })
  @IsNotEmpty()
  @IsIn(Object.values(LOAN_TYPE))
  public type: LOAN_TYPE;

  @Column({ default: false })
  public approvalStatus: boolean;

  @ManyToOne(type => User, user => user.loans)
  @IsNotEmpty()
  public user: User;
}

export default Loan;

4 Answers
  1. Make sure you have "module": "commonjs" in "compilerOptions" of tsconfig.json
  2. Run typeorm cli using ts-node: ts-node ./node_modules/typeorm/cli.js

See docs

Are you getting the error when trying to run the CLI, or when running the app?

You may need to change the "entities" entry in ormconfig.json to ["dist/entity/**/*.js"] or the "entitiesDir" to "dist/entity".

Problem is caused not just loading entities, but also for migrations and subscribers.

Your app are looking for entities, migrations and subscribers files on pre-compiled .ts files. So the files contains "imports" not understood by nodejs, it is the cause of your error.

When typescript compile the code it converts all the imports to requires (understood by node).

So to stop error at all you should make your configurations on your ormconfig.json:

{
  "type": "postgres",
  "host": "localhost",
  "port": 5432,
  "username": ****,
  "password": ****,
  "database": ****,
  "synchronize": true,
  "entities": ["dist/entity/**/*.js"],
  "migrations": ["dist/migration/**/*.js"],
  "subscribers": ["dist/subscriber/**/*.js"],
  "cli": {
    "entitiesDir": "src/entity",
    "migrationsDir": "src/migration",
    "subscribersDir": "src/subscriber"
  }
}

Use Auto-load entities, that answer fits to nestJS+typeOrm.

Manually adding entities to the entities array of the connection options can be tedious. In addition, referencing entities from the root module breaks application domain boundaries and causes leaking implementation details to other parts of the application. To solve this issue, static glob paths can be used (e.g., dist/**/*.entity{ .ts,.js}).

Note, however, that glob paths are not supported by webpack, so if you are building your application within a monorepo, you won't be able to use them. To address this issue, an alternative solution is provided. To automatically load entities, set the autoLoadEntities property of the configuration object (passed into the forRoot() method) to true, as shown below:

import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';

@Module({
  imports: [
    TypeOrmModule.forRoot({
      ...
      autoLoadEntities: true,
    }),
  ],
})
export class AppModule {}

With that option specified, every entity registered through the forFeature() method will be automatically added to the entities array of the configuration object.

And make sure that you use correct catalog path for entities dist/src. and latest NestJs and TypeOrm ver.

Related