NestJS: cómo usar variables .env en el archivo del módulo de la aplicación principal para la conexión de la base de datos

7 minutos de lectura

Avatar de usuario de Mohit Bhardwaj
Mohit Bhardwaj

Estoy trabajando en mi primera aplicación NestJS, que funcionaba bien con la cadena de conexión de la base de datos codificada en app.module.ts.

Pero luego, según nuestros requisitos, tuve que elegir los valores de configuración de la base de datos de los archivos de entorno. Para eso, seguí la documentación de configuración en el sitio web de documentación de nestjs: https://docs.nestjs.com/techniques/configuration

Pero el problema es que necesito usar las variables .env dentro del mismo archivo para la conexión a la base de datos, lo cual está fallando.

Aquí está mi código original que funcionaba bien:

@Module({
  imports: [
    MongooseModule.forRoot(`mongodb+srv://myusername:mypassword@myhost.net?retryWrites=true&w=majority&db=dbname`, { useNewUrlParser: true, dbName: 'dbname' }),
    ProductModule,
    CategoryModule,
  ],
  controllers: [
    AppController,
    HealthCheckController,
  ],
  providers: [AppService, CustomLogger],
})

Ahora, quería elegir esos valores DB de archivos .env que son como local.env, dev.env etc. dependiendo del entorno. Ahora, mi este código no funciona:

@Module({
  imports: [
    ConfigModule.forRoot({ envFilePath: `${process.env.NODE_ENV}.env` }),
    MongooseModule.forRoot(`mongodb+srv://${ConfigModule.get('DB_USER')}:${ConfigModule.get('DB_PASS')}@myhost.net?retryWrites=true&w=majority&db=dbname`, { useNewUrlParser: true, dbName: 'dbname' }),
    ProductModule,
    CategoryModule,
  ],
  controllers: [
    AppController,
    HealthCheckController,
  ],
  providers: [AppService, CustomLogger],
})

  • ConfigModule.consigue ser this.configService.get(‘database.host’)

    – yusung lee

    10 de marzo de 2021 a las 7:38

avatar de usuario de swedge218
swedge218

De los documentos de Nestjs aquí: https://docs.nestjs.com/techniques/configuration

Estos pasos me funcionaron con MySQL y TypeORM.

  1. Instale el módulo de configuración de Nestjs – npm i --save @nestjs/config. Se basa en dotenv

  2. Crear un .env archivo en su carpeta raíz y agregue sus pares clave/valor, por ejemplo DATABASE_USER=myusername

  3. Abra app.module.ts e importe el módulo de configuración

    import { ConfigModule } from '@nestjs/config';
  1. Agregue la siguiente línea a la sección de importaciones de app.module.ts. Lo agregué en la primera importación. Cargará el contenido del archivo .env automáticamente.
    ConfigModule.forRoot(),
  1. Luego puede comenzar a usar las variables env según el proceso habitual.env. en la sección de configuración de la base de datos, por ejemplo
    process.env.DATABASE_USER

Para obtener más información sobre la configuración de ConfigModule, consulte el enlace anterior. Puede usar un archivo/ruta personalizado y configurar el módulo visible globalmente.

  • Intenté hacer esto con el módulo “@nestjs/dotenv” pero no funcionó. Funcionó perfectamente con “@nestjs/config”. ¡Gracias!

    –José Manuel Blasco

    22 de octubre de 2021 a las 9:46

  • Esto ES lo que recomiendan los documentos de Nest.js y el curso pagado de Nest.js. Sin embargo, a partir de mediados de 2022, esto no está funcionando. Seguí los pasos en la documentación y el curso exactamente, y obtengo “la contraseña del cliente debe ser una cadena”. Obtengo dependencias de ConfigModule y luego aparece ese error.

    – Michael Jay

    8 de junio de 2022 a las 23:49


  • también puede simplemente llamar a ConfigModule.forRoot() como una función normal fuera de la importación y solicitar datos de process.env, gracias

    – Alexy

    30 de junio de 2022 a las 14:02

  • @MichaelJay Me encontré con el mismo problema y tuve que usar la función de inicialización asíncrona: JwtModule.registerAsync({ useFactory: async () => ({ secretOrPrivateKey: process.env.JWT_SECRET_KEY, signOptions: { expiresIn: process.env.JWT_EXPIRATION_TIME, }, }), }),

    – rami

    21 de enero a las 18:21


Avatar de usuario de Acebee
acebee

1. Seguir usando ConfigModule

Necesitas configurar NODE_ENV en scripts npm para que pueda usarse para cargar un archivo env basado en el env.

"scripts": {
  "start:local": "NODE_ENV=local npm run start"
  "start:dev": "NODE_ENV=dev npm run start"
}

Ahora solo puedes usar el ConfigModule:

@Module({ importaciones: [
    ConfigModule.forRoot({ envFilePath: `${process.env.NODE_ENV}.env` }), 
MongooseModule.forRoot(`mongodb+srv://${process.env.DB_USER}:${process.env.DB_PASS}@myhost.net?retryWrites=true&w=majority&db=dbname`, { useNewUrlParser: true, dbName: 'dbname' })
    ...
})

2. Using dotenv

npm install dotenv

Add some scripts to your package.json to set what env you are in.

"scripts": {
  ...
  "start:local": "NODE_ENV=local npm run start"
  "start:dev": "NODE_ENV=dev npm run start"
}

Import dotenv in main.ts file. Make sure you do it at the top of the file.

require('dotenv').config({ path: `../${process.env.NODE_ENV}.env` });

3. Using env-cmd

You can use env-cmd npm package.

npm install env-cmd

And add some commands for different envs in package.json, for example:

"scripts": {
  ...
  "start:local": "env-cmd -f local.env npm run start"
  "start:dev": "env-cmd -f dev.env npm run start"
}
...

Now you can use the env variables, for example:

MongooseModule.forRoot(`mongodb+srv://${process.env.DB_USER}:${process.env.DB_PASS}@myhost.net?retryWrites=true&w=majority&db=dbname`, { useNewUrlParser: true, dbName: 'dbname' })

process.env.MONGO_CONNECTION_STRING

Update:

To overcome the env set command problem in different platforms, you can install cross-env package.

npm install -D cross-env

And update the scripts:

"scripts": {
  "start:local": "cross-env NODE_ENV=local npm run start"
  "start:dev": "cross-env NODE_ENV=dev npm run start"
}

  • Thanks. I tried your first suggestion and it worked fine for me (the only thing was that the require(‘dotenv’) line had to come before the import of AppModule). This solution is simple and quick 🙂

    – Mohit Bhardwaj

    Aug 6, 2020 at 15:05

  • can you show me the main.ts and app module where you wrote this working code ?

    – Anmol Jain

    Mar 23, 2021 at 5:55

  • you can just put the require('dotenv').config({ path: ../${process.env.NODE_ENV}.env` });` at the top of your main.ts.

    – Acebee

    Mar 23, 2021 at 10:45

  • Nest config service already has ‘dotenv’ under the hood

    – kosiakMD

    Apr 27, 2021 at 23:33

  • I am facing an issue with this method then env file is not loading although NODE_ENV is set it can’t read the env

    – Shashank Dubey

    Oct 6, 2021 at 11:22

MongooseModule.forRootAsync({
  imports: [ConfigModule]useFactory: async (configService: ConfigService) => ({ uri: configService.get('MONGODB_URI'), }), inyecte: [ConfigService]});

  • tanx, a menudo se olvidan de “inyectar: [Configervice ] 🙂

    – Mojtaba Pourmirzaei

    6 sep 2022 a las 10:07

  • Esta es la forma correcta de hacerlo. Suponiendo que desea ejecutar todo a través del módulo de configuración que puede ejecutar la validación en vars antes de que se transfieran.

    – aaronmbmorse

    21 oct 2022 a las 18:11

Usando el paquete nestjs/config:

npm instalar @nestjs/config

Después de instalar el paquete, en el módulo de la aplicación (archivo app.module.ts):

import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';

@Module({
  imports: [ConfigModule.forRoot()],
})

export class AppModule {}

Después de eso, se puede acceder a los archivos .env en toda la aplicación. Suponga que su archivo .env se ve así.

DB_USER=mohit

para acceder a la variable DB_USER utilice process.env.DB_USER

Necesitas usar el MongooseModule.forRootAsync(() => {...}) en lugar de MongooseModule.forRoot(...)

Esto hace que MongooseModule espere sus dependencias IOC.

Ver: https://docs.nestjs.com/techniques/mongodb#async-configuration

  • Actualicé mi código como usted sugirió. Pero ahora estoy recibiendo un error – Nest cannot export a module that is not part of the currently processed module. Esto es lo que actualicé: MongooseModule.forRootAsync({ imports: [ConfigModule], useFactory: async (configService: ConfigService) => ({ uri: 'mongodb+srv://db_username:db_pass@myhost.net?retryWrites=true&w=majority', options: { useNewUrlParser: true, dbName: 'dbname' }, }), inject: [ConfigModule], }),

    – Mohit Bhardwaj

    6 de agosto de 2020 a las 14:43

  • arreglar la inyección de ConfigModule a ConfigService (Siga los documentos de NestJS)

    – Daniel

    9 de agosto de 2020 a las 11:21


Para usar la configuración de NestJS (dot-env) en el propio app.module.ts, use MongooseModule.forRootAsync({}). Aquí está mi código.

  @Module({
  imports: [
    MongooseModule.forRootAsync({
      useFactory: () => ({
        uri: process.env.CONNECTION_STRING,
      }),
    }),
    ConfigModule.forRoot(
      {
        isGlobal: true
      }
    )
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule { }

  • Actualicé mi código como usted sugirió. Pero ahora estoy recibiendo un error – Nest cannot export a module that is not part of the currently processed module. Esto es lo que actualicé: MongooseModule.forRootAsync({ imports: [ConfigModule], useFactory: async (configService: ConfigService) => ({ uri: 'mongodb+srv://db_username:db_pass@myhost.net?retryWrites=true&w=majority', options: { useNewUrlParser: true, dbName: 'dbname' }, }), inject: [ConfigModule], }),

    – Mohit Bhardwaj

    6 de agosto de 2020 a las 14:43

  • arreglar la inyección de ConfigModule a ConfigService (Siga los documentos de NestJS)

    – Daniel

    9 de agosto de 2020 a las 11:21


¿Ha sido útil esta solución?