nestjs / nest

A progressive Node.js framework for building efficient, scalable, and enterprise-grade server-side applications with TypeScript/JavaScript 🚀
https://nestjs.com
MIT License
67.89k stars 7.66k forks source link

The property synchronize (TypeOrmModule.forRootAsync) cannot be customized #11955

Closed jocafi closed 1 year ago

jocafi commented 1 year ago

Is there an existing issue for this?

Current behavior

I want customize the behaviour of the TypeOrm property "synchronize" using a defined environment variable in the '.env' file.

However using the ConfigService to get the boolean value does not work, although I could read and use all the other environment variables to configure TypeOrm.

If I set "synchronize" explicitly to true or false, it works well.

Minimum reproduction code

I put the code in the field "Steps to reproduce"

Steps to reproduce

1) Create a Postgresl database using docker 1.5) Double Check that you dropped the table user in the database. 2) Create .env in your root directory and set the following variables:

production=false
server_port = 3000

DB_HOST = localhost
DB_PORT = 5432
DB_USERNAME = usertest
DB_PASSWORD = userpwd
DB_DATABASE = usertest
DB_SYNCRONIZE = false

3) Change your AppModule to the following code:

import { Logger, Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { HttpModule } from '@nestjs/axios';
import { TypeOrmModule } from '@nestjs/typeorm';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { UserModule } from './user/user.module';

@Module({
  imports: [
    ConfigModule.forRoot({
      cache: true,
    }),
    HttpModule,
    TypeOrmModule.forRootAsync({
      imports: [ConfigModule],
      useFactory: (configService: ConfigService) => ({
        type: 'postgres',
        host: configService.get('DB_HOST'),
        port: +configService.get('DB_PORT'),
        username: configService.get('DB_USERNAME'),
        password: configService.get('DB_PASSWORD'),
        database: configService.get('DB_DATABASE'),
        entities: [],
        synchronize: configService.get<boolean>('DB_SYNCRONIZE'),
        autoLoadEntities: true,
      }),
      inject: [ConfigService],
    }),
    UserModule,
  ],
  controllers: [AppController],
  providers: [Logger, AppService],
})
export class AppModule {
  private readonly logger = new Logger(AppModule.name);
  constructor(configService: ConfigService) {
     this.logger.log('(AppModule) Syncronize: ' + configService.get<boolean>('DB_SYNCRONIZE'));
  }
}

4) Create the user.entity.ts using the code below:

import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';

@Entity()
export class User {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  firstName: string;

  @Column()
  lastName: string;

  @Column({ default: true })
  active: boolean;
}

5) Add your entity class to the module user.module.ts:

import { Module } from '@nestjs/common';
import { User } from './user.entity';
import { TypeOrmModule } from '@nestjs/typeorm';
import { UserService } from './user.service';
import { UserController } from './user.controller';

@Module({
  imports: [TypeOrmModule.forFeature([User])],
  providers: [UserService],
  controllers: [UserController],
})
export class UserModule {}

6) Run the program. 7) Check the logs to see the message: "(AppModule) Syncronize: false" 8) Check that the table user was created, although "DB_SYNCRONIZE = false" is defined in the .env

If you drop the table again and set explicitly "synchronize: false" and run it again, you will see that the table user was NOT created and this is the expected behaviour for the case above.

Expected behavior

The table user should not be created.

1) Check that "DB_SYNCRONIZE = false" is defined in the .env 2) Check that you dropped the table user before starting the program.

Package

Other package

@nestjs/config or @nestjs/typeorm

NestJS version

10.0.0

Packages versions

  "dependencies": {
    "@aws-sdk/signature-v4-crt": "^3.354.0",
    "@nestjs/axios": "^3.0.0",
    "@nestjs/common": "^10.0.0",
    "@nestjs/config": "^3.0.0",
    "@nestjs/core": "^10.0.0",
    "@nestjs/platform-express": "^10.0.0",
    "@nestjs/typeorm": "^10.0.0",
    "aws-crt": "^1.15.18",
    "nest-winston": "^1.9.3",
    "pg": "^8.11.1",
    "reflect-metadata": "^0.1.13",
    "rxjs": "^7.8.1",
    "typeorm": "^0.3.17",
    "winston": "^3.9.0",
    "winston-daily-rotate-file": "^4.7.1"
  },

Node.js version

v18.16.0

In which operating systems have you tested?

Other

No response

jmcdo29 commented 1 year ago

dotenv (what @nestjs/config uses to parse the env file) possessed everything to strings and the !!'false' value is true so synchronize will always be ran. The <boolean> is just a type hint to Typescript, not an actual runtime conversion. This is not a bug, but the expected behavior of JavaScript based on the libraries being used.

jocafi commented 1 year ago

@jmcdo29 Thx Jay. I changed the line below and it worked !

synchronize: configService.get('DB_SYNCRONIZE') === 'true',