GithubHelp home page GithubHelp logo

nestjs / config Goto Github PK

View Code? Open in Web Editor NEW
469.0 6.0 84.0 6.76 MB

Configuration module for Nest framework (node.js) πŸ“

Home Page: https://nestjs.com

License: MIT License

JavaScript 1.44% TypeScript 98.56%
nestjs nest javascript typescript configuration nodejs

config's Introduction

Nest Logo

A progressive Node.js framework for building efficient and scalable server-side applications.

NPM Version Package License NPM Downloads Coverage Discord Backers on Open Collective Sponsors on Open Collective

Description

Configuration module for Nest based on the dotenv (to load process environment variables) package.

Installation

$ npm i --save @nestjs/config

Quick Start

Overview & Tutorial

Support

Nest is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please read more here.

Stay in touch

License

Nest is MIT licensed.

config's People

Contributors

bejewel-kyoungmin avatar caucik avatar dariusj18 avatar dependabot[bot] avatar dzixxx avatar eyal-confetti avatar gperdomor avatar greenreign avatar jasonhk avatar jmcdo29 avatar jonahsnider avatar kamilmysliwiec avatar leoanesi avatar mansuralikoroglu avatar matthiaskunnen avatar micalevisk avatar muniftanjim avatar opportunityliu avatar prateekkathal avatar renovate-bot avatar renovate[bot] avatar seiwonpark avatar shaunek avatar sikora00 avatar swarthy avatar thematan avatar toilal avatar tony133 avatar wodcz avatar yharaskrik avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

config's Issues

object references cause a bug

I'm submitting a...


[ ] Regression 
[x ] Bug report
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead post your question on Stack Overflow.

Current behavior

export default registerAs('test', () => ({ var: 1 })); console.log(this.configService.get('test')) // { var:1 } good! console.log(this.configService.get('test.var')) // undefined ??wtf console.log(this.configService.get('test')) // { var: undefined }

the second and third calls return wrong value

Expected behavior

Environment


Nest version: 7.5.3

 
For Tooling issues:
- Node version: 15  
- Platform: Mac 

Others: @nestjs/config:0.6.0

Validation schema default values not working with ignoreEnvFile = true

I'm submitting a...


[ ] Regression 
[x] Bug report
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead post your question on Stack Overflow.

Current behavior

If ignoreEnvFile is true, seems validation schema default values are not handled

Expected behavior

If ignoreEnvFile is true, validation schema default values should be handled properly

Minimal reproduction of the problem with instructions

What is the motivation / use case for changing the behavior?

Environment


Nest version: X.Y.Z

 
For Tooling issues:
- Node version: XX  
- Platform:  

Others:

where can i decrypt the BD password?

hi,

i add an encrypted BD password in the config file and i want to decrypt the password at the runtime. i don't know how to achieve the target.

Add the validationSchema option to the forFeature

I'm submitting a...


[ ] Regression 
[ ] Bug report
[x] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead post your question on Stack Overflow.

Current behavior

I need to declare the validation schema for my feature config inside the forRoot execution.

Expected behavior

The forFeature method should have the validationSchema option.

What is the motivation / use case for changing the behavior?

If I can split the configuration between my features it should be possible to declare the validation of that configuration in the same place.
It could provide for us the possibility that forRoot doesn't know anything about the features.

Environment


@nestjs/config: 0.4.1

Passing validationOptions: { allowUnknown: false } causes errors for env values outside the schema

I'm submitting a...


[ ] Regression 
[x] Bug report
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead post your question on Stack Overflow.

Current behavior

Passing validationOptions: { allowUnknown: false } causes errors for environment values not in .env

Expected behavior

Only throw error if environment value is in .env file but not in validationSchema

Minimal reproduction of the problem with instructions

app.module.ts

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { ConfigModule } from '@nestjs/config';
import * as Joi from 'joi';

@Module({
  imports: [
    ConfigModule.forRoot({
      validationSchema: Joi.object({
        NODE_ENV: Joi.string()
          .valid('development', 'production', 'test', 'provision')
          .default('development'),
        PORT: Joi.number().default(3000),
      }),
      validationOptions: {
        allowUnknown: false,
      },
    }),
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

.env

NODE_ENV=development
PORT=3001

What is the motivation / use case for changing the behavior?

To prevent unnecessarily having to list ~227 default environment variables in the schema in addition to the ones in your .env.

Environment


Nest version: 8.0.2

 
For Tooling issues:
- Node version: 14.17.3
- Platform:  Mac

Others:

Related
#15

Feature Proposal: Allow for custom transformations of vars in getter

I'm submitting a...


[ ] Regression 
[ ] Bug report
[x] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead post your question on Stack Overflow.

What is the motivation / use case for changing the behavior?

Sometimes an environment variable is stored in a way that is not formatted for how it will actually be used in the application, my proposal would be to provide a map of transformations that are performed on a variable that is read in from process.env prior to it being returned in the getter.

I would be happy to implement this if it is something that others would find useful and the maintainers see value in.

calling ConfigService with default value causes ts(2589) - Type instantiation is excessively deep and possibly infinite

I'm submitting a...


[x] Regression 
[ ] Bug report
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead post your question on Stack Overflow.

Current behavior

The compile time error

const config = new ConfigService(...)
config.get('A_KEY', 'default')

>> Type instantiation is excessively deep and possibly infinite. ts(2589)

is shown, when using config.get() with a default value.

Expected behavior

Above code snippet should compile without any complains.

Minimal reproduction of the problem with instructions

Playground Example

What is the motivation / use case for changing the behavior?

nestjs/config v1.0.0 should work as v0.6.3 did

Environment


Nest version: 8.0.4
Nest config version: 1.0.0

Add dotenv-expand support so that env vars can contain other env vars

I'm submitting a...


[ ] Regression 
[ ] Bug report
[x] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead post your question on Stack Overflow.

I just noticed that you recently created a config package to replace the config module guide that was in the docs. I would love to replace my custom config module with this one, but one really useful feature I added which this config package is missing is variable expansion with dotenv-expand in order to have env files like this.

Here is a snippet of code that I used to implement it as an example:

import expand from "dotenv-expand"
import fs from "fs"
import { Injectable } from "@nestjs/common"
import { parse } from "dotenv"

@Injectable()
export class ConfigService {
  private readonly data: Record<string, string | undefined> = {}

  constructor(envFilePath: string) {
    if (fs.existsSync(envFilePath)) {
      const parsedVars = parse(fs.readFileSync(envFilePath))
      const expandedVars = expand({ parsed: parsedVars }).parsed
      if (!expandedVars) {
        throw new Error(
          `A problem was encountered while parsing "${envFilePath}".`,
        )
      }
      this.data = expandedVars
    }
    // Environment variables have higher priority than envFile.
    Object.assign(this.data, process.env)
  }

  get(key: string): string | undefined {
    return this.data[key]
  }
}

Add a direct export to ConfigModuleOptions interface and other interfaces

I'm submitting a...


[ ] Regression 
[ ] Bug report
[x] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead post your question on Stack Overflow.

Current behavior

At the moment, that is the only way I was able to import this type:


import { ConfigModuleOptions } from '@nestjs/config/dist/interfaces/config-module-options.interface';

const options: ConfigModuleOptions = { envFilePath: '...',  cache:true,  ... }

Expected behavior


import { ConfigModuleOptions } from '@nestjs/config';

const options: ConfigModuleOptions = { envFilePath: '...',  cache:true,  ... }

Environment


"@nestjs/common": "^7.5.1", 
"@nestjs/config": "^0.6.2",


Using `validationSchema` with namespaced configs is not possible?

I'm submitting a...


[ ] Regression 
[X] Bug report
[X] Feature request
[X] Documentation issue or request
[X] Support request => Please do not submit support request here, instead post your question on Stack Overflow.

Current behavior

I am importing ConfigModule into app.module.ts (root module) with those parameters:

ConfigModule.forRoot({
      expandVariables: true,
      validationSchema: ValidationSchema,
      validationOptions: {

      },
      load: [FooConfig],
    }),

ValidationSchema includes Joi validation schema and example of FooConfig is:

export default registerAs('foo', () => ({
  host: process.env.HOST,
  port: process.env.PORT
});

When I am using validationSchema parameter, my namespaced configs are not initialized at all (they are tested and working without it).

Does this means that Nest's config cannot do both? (validation and namespaced configs)?
Or it is just a bug?
How to make it work if yes?
This seems not properly documented.

Expected behavior

Joi should validate process.env (with added .env file) and then register namespaced configs.

Minimal reproduction of the problem with instructions

What is the motivation / use case for changing the behavior?

We should be able to validate .env file before we use it in namespaced configs

Environment


Nest version: 12,14

 
For Tooling issues:
- Node version: 12,14  
- Platform:  Win10

Others:

Config values from the environment are not validated

I'm submitting a...


[ ] Regression 
[x] Bug report
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead post your question on Stack Overflow.

Current behavior

Config values from the environment are not validate by the passed validationSchema.

The reason being: the forRoot method validates the loaded config and then assigns it to process.env without ever passing the environment values to be validated.

Expected behavior

Config values from the environment should be validated using the passed validationSchema

Minimal reproduction of the problem with instructions

Clone the following:

https://github.com/ozzywalsh/config-validation-error

Run it, specifying PORT from the environment.

PORT='invalid-value' npm start

No validation error is raised even though a schema is specified.

What is the motivation / use case for changing the behavior?

Environment

Nest version: 6.7.2

Cannot use ConfigModule as described in docs

I'm submitting a...


[ ] Regression 
[X] Bug report
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead post your question on Stack Overflow.

Current behavior

According to the docs after importing ConfigModule.forRoot() in my AppModule, I should be able to import ConifgModule in any FeatureModule and in FeatureService be able to inject ConfigService. Currently, the following error appears:

[Nest] 20030   - 02/17/2020, 4:28:04 PM   [NestFactory] Starting Nest application...
[Nest] 20030   - 02/17/2020, 4:28:04 PM   [InstanceLoader] ConfigModule dependencies initialized +24ms
[Nest] 20030   - 02/17/2020, 4:28:04 PM   [ExceptionHandler] Nest can't resolve dependencies of the BasicService (?). Please make sure that the argument ConfigService at index [0] is available in the BasicModule context.

Potential solutions:
- If ConfigService is a provider, is it part of the current BasicModule?
- If ConfigService is exported from a separate @Module, is that module imported within BasicModule?
  @Module({
    imports: [ /* the Module containing ConfigService */ ]
  })
 +1ms
Error: Nest can't resolve dependencies of the BasicService (?). Please make sure that the argument ConfigService at index [0] is available in the BasicModule context.

Potential solutions:
- If ConfigService is a provider, is it part of the current BasicModule?
- If ConfigService is exported from a separate @Module, is that module imported within BasicModule?
  @Module({
    imports: [ /* the Module containing ConfigService */ ]
  })

    at Injector.lookupComponentInParentModules (~/nest-config-test/node_modules/@nestjs/core/injector/injector.js:190:19)
    at processTicksAndRejections (internal/process/task_queues.js:97:5)
    at async Injector.resolveComponentInstance (~/nest-config-test/node_modules/@nestjs/core/injector/injector.js:146:33)
    at async resolveParam (~/nest-config-test/node_modules/@nestjs/core/injector/injector.js:100:38)
    at async Promise.all (index 0)
    at async Injector.resolveConstructorParams (~/nest-config-test/node_modules/@nestjs/core/injector/injector.js:115:27)
    at async Injector.loadInstance (~/nest-config-test/node_modules/@nestjs/core/injector/injector.js:79:9)
    at async Injector.loadProvider (~/nest-config-test/node_modules/@nestjs/core/injector/injector.js:36:9)
    at async Promise.all (index 3)
    at async InstanceLoader.createInstancesOfProviders (~/nest-config-test/node_modules/@nestjs/core/injector/instance-loader.js:41:9)

Expected behavior

As following the docs, it would be possible to just import ConfigModule.forRoot() and then use imports: [ConfigModule] in any feature module to have access to the ConfigService.

Minimal reproduction of the problem with instructions

Reproduction: https://github.com/jmcdo29/nest-config-test
Reproduction steps: In the readme but here as well:

  1. git clone https://github.com/jmcdo29/nest-config-test.git
  2. npm i
  3. npm run start:dev or npm build && npm start
  4. observe error

What is the motivation / use case for changing the behavior?

Mainly, I just see a lot of questions either on Discord or SO about using the ConfigModule as the docs show and the answer is always add isGlobal: true to make it work. While that works, it seems this kind of goes against the spirit of being explicit about what is being imported where.

Environment


Nest versions: 
Common: 6.11.7
Core: 6.11.7
Platform-Express: 6.11.7
Config: 0.2.2

 
For Tooling issues:
- Node version: 13.7.0
- Platform: Linux Mint 19.1

Other:
I know the workarounds for this are to set isGlobal: true in configuration, or to use a CommonModule format where ConfigModule.forRoot() is imported and ConfigModule is exported, which is fine if that is the final solution, but it should be documented that that's the correct way to manage the ConfigModule. E.g.

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

How to use validationSchema with something other than Joi?

I'm submitting a...


[ ] Regression 
[ ] Bug report
[ ] Feature request
[x] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead post your question on Stack Overflow.

What exactly is a validationSchema? How do I use it with something beside Joi? I want to use something more established, like JSON Schema (with ajv or something). Or even better - I wish it could be possible to supply my own validation function which should take a config as an argument and return/throw differently depending on the result.

If that's already supported somehow, then I apologize. VS Code suggests validationSchema takes any, and there are no comments on the interface, so I don't know what to do with this. The absence of API documentation in whole Nestjs infrastructure makes me sad sometimes.

ConfigService uses .env file values ONLY when schemaValidation is provided

Regression

Potential Commit/PR that introduced the regression**

f7c4da1#diff-

Describe the regression

Prior to the above commit the ConfigService would return values from environment variables as the last override regardless of schemaValidation

After the regression
schemaValidation provided: .env file takes precedence
schemaValidation not provided: environment variables will override .env file

Input Code

https://github.com/greenreign/nestjs-repros

run yarn start

Expected behavior/code

It should produce the console.log

configService.TEST_KEY value_from_env_var

BUT it produces

configService.TEST_KEY value_from_env_file

Environment


Nest version: 7+ - problem exists
Nest version: 6 - works as expected

Feature request: Caching of env variables

I'm submitting a...


[ ] Regression 
[ ] Bug report
[X] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead post your question on Stack Overflow.

Current behavior

Not sure if process values are cached.

Expected behavior

Provide flag to cache the values instead of accessing process.env everytime.

Minimal reproduction of the problem with instructions

ConfigModule.forRoot({
  enableCache: true
});

What is the motivation / use case for changing the behavior?

Accessing process.env is slow. We should provide support for caching.

Sources:
https://www.reddit.com/r/node/comments/7thtlv/performance_penalty_of_accessing_env_variables/

nodejs/node#3104

Environment


Nest version: latest

 
For Tooling issues:
- Node version: 12  
- Platform:  Mac 

Others:

ignoreEnvFile attribute doesn't work

I'm submitting a...


[ ] Regression 
[ ] Bug report
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead post your question on Stack Overflow.

Current behavior

When I set ignoreEnvFile to true to ignore local env file, but it still use local env file to get env vars.

Expected behavior

Ignore local env file when I set ignoreEnvFile to true.

Minimal reproduction of the problem with instructions

What is the motivation / use case for changing the behavior?

Environment


Nest version: X.Y.Z

 
For Tooling issues:
- Node version: XX  
- Platform:  

Others:

ConfigModule.forRoot() changes ConfigService singleton even if ConfigModule.forRoot() is not imported

The simple fact of calling ConfigModule.forRoot() changes the ConfigService singleton, even if ConfigModule.forRoot() result (a DynamicModule) is not imported by any dependent module.

Consider the following entry point index.ts:

import {INestMicroservice, Module} from "@nestjs/common";
import {NestFactory} from "@nestjs/core";
import {MicroserviceOptions, Transport} from "@nestjs/microservices";
import {ConfigModule, ConfigService} from "@nestjs/config";
import {strictEqual} from "assert";

@Module({
    providers: [
        ConfigService,
        {
            provide: 'Bar',
            useFactory: (config: ConfigService) => {
                strictEqual(config.get('FOO'), 'BAR'); // should throw since ConfigService is not "dot env enabled"
            },
            inject: [
                ConfigService
            ]
        }
    ]
})
class MainModule {

}

/**
 * Never imported by any module but still mutate ConfigService singleton.
 */
const forRootConfigModule = ConfigModule.forRoot();

export const bootstrap = (port: number): Promise<INestMicroservice> => {
    return NestFactory.createMicroservice<MicroserviceOptions>(
        MainModule,
        {
            transport: Transport.TCP,
            options: {
                port
            }
        },
    );
}

bootstrap(8888);

And the following .env file:

FOO=BAR

Executing index.ts would not throw an error, even though it should since ConfigService has not been configured as "dot env enabled" by any module imported by MainModule or by MainModule itself.

I understand where it is coming from: the simple fact of executing forRoot() mutate ConfigService, but I think this is a non-expected behavior: since the module returned by forRoot() is never imported by MainModule, it should not have any side effect on MainModule scope.

In other words, my interpretation of the issue is that forRoot() pollutes the scope of MainModule in an unexpected way.

How to double-check the issue

Commenting the line const forRootConfigModule = ConfigModule.forRoot(); and executing the script throws an AssertionError, as expected.

What do you think?

ignoreEnvVars is ignored

I'm submitting a...


[ ] Regression 
[x] Bug report
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead post your question on Stack Overflow.

Current behavior

When the ignoreEnvVars variable is set with no validation schema, the returned value is still the one from process.env. After some investigation, while ignoreEnvVars is taken into account in ConfigModule.forRoot() initialization, process.env is still directly accessed in ConfigService.

const processValue = get(process.env, propertyPath);

Expected behavior

The internal value should be accessed when ignoreEnvVars is set.

Minimal reproduction of the problem with instructions

Set environment variable DB_USER=root.

Create a minimum AppModule with:

const config = {
  DB_USER: 'db-user',
};

@Module({
  imports: [
    ConfigModule.forRoot({ load: [() => config], ignoreEnvVars: true })
  ],
  controllers: [AppController],
})
export class AppModule {
}

Access the variable from anywhere, and its value is root.

What is the motivation / use case for changing the behavior?

In CI environments, I set various environment variables which are also used in e2e tests. However, they interfere with unit tests that access a stub ConfigModule.

Environment


Nest version: 7.4.4
@nestjs/config version: 0.5.0
 
For Tooling issues:
- Node version: 14.8
- Platform: Windows

Some module not supply useFactory function

I'm submitting a...


[ ] Regression 
[ ] Bug report
[ ] Feature request
[ ] Documentation issue or request
[X] Support request => Please do not submit support request here, instead post your question on Stack Overflow.

Current behavior

If some module not support useFactory function to load configService, how do I use this library to get my config?

ConfigModule.forRoot Joi validation executed too early

I'm submitting a...


[ ] Regression 
[x] Bug report
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead post your question on Stack Overflow.

Current behavior

When using ConfigModule.forRoot and a validation schema, the validation schema appears to validate as soon as the module is imported (as in import { MyConfigModule } from '..../my-module.module.ts)

This breaks unit test flow because, even though I can override the config provider in the test, the fact that some files import something from the same index.ts that exports MyConfigModule, the validation gets executed. In JS, when we import something from a file, everything gets evaluated.

The reason why a file is importing something from the same index as MyConfigModule is that it needs to register MyConfigService in its constructor.
One workaround for this could be that I export types for my services separately, so that they are not in the same index.ts as their module, but I find this too awkward.
Another workaround is to import MyConfigService directly from its file instead of index.ts, but this breaks the feeling of modularity.

Expected behavior

I would expect the validation for a module which imports ConfigModule.forRoot({ with a validationSchema to happen when that module is instantiated, not when it is first imported from a typescript file.

Minimal reproduction of the problem with instructions

/////////////////////////
my-config/my-config.module.ts:
/////////////////////////

import * as Joi from 'joi'
import { Global, Module } from '@nestjs/common'
import { ConfigModule } from '@nestjs/config'
import { MyConfigService } from './my-config-service'

@Global()
@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true,
      validationSchema: Joi.object({
        MY_REQUIRED_VAR: Joi.string().required(),
      }),
    }),
  ],
  providers: [MyConfigService],
  exports: [MyConfigService],
})
export class MyConfigModule {}

/////////////////////////
my-config/my-config.service.ts:
/////////////////////////

import { isEnabled } from '@minka/flags'
import { Injectable } from '@nestjs/common'
import { ConfigService } from '@nestjs/config'

@Injectable()
export class BridgeConfigService {
  constructor(private readonly configService: ConfigService) {}

  get myRequiredVar(): string {
    return this.configService.get<string>('MY_REQUIRED_VAR')
  }
}

/////////////////////////
my-config/index.ts:
/////////////////////////

export * from './my-config.module.ts'
export * from './my-config.service.ts'

/////////////////////////
my-testable-module/testable-service.service.ts:
/////////////////////////

import { Injectable } from '@nestjs/common'
import { MyConfigService } from '~/my-config'

@LoggerConfig({ prefix: 'MyTestableService' })
@Injectable()
class MyTestableService {

  constructor(
    private readonly configService: MyConfigService,
  ) {
  }
}

export { MyTestableService }

/////////////////////////
my-testable-module/testable-service.service.spec.ts:
/////////////////////////

import { Test, TestingModule } from '@nestjs/testing'

describe('MyTestableService', () => {
  let myService: MyTestableService

  beforeEach(async () => {
    const module: TestingModule = await Test.createTestingModule({
      imports: [],
      providers: [
        MyTestableService,
      ],
    })
      .compile()

    myService = module.get<MyTestableService>(MyTestableService)
  })

  it('should be defined', async () => {
    expect(myService).toBeDefined()
  })
})

What is the motivation / use case for changing the behavior?

The issue made me awkwardly remove MyConfigModule from its own index.ts file and files from other modules now have to import it directly from the file.

Environment

Nest version: 7.4.4
@nestjs/config version: 0.5.0

Regression: .env takes priority over local environment variables

I'm submitting a...


[x] Regression 
[ ] Bug report
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead post your question on Stack Overflow.

Current behavior

With the changes in 6efcc5a the .env file takes precedence over the local environment variables. This was at least for our use case a breaking change, as we use environment variables in our docker container to override some local .env settings.

Expected behavior

This change should be either introduced as optional behaviour (e.g. using a flag in the options), explicitly mentioned as a breaking change or reverted to avoid causing issues in existing projects at least from my perspective.

If the changes are kept as default, the NestJS docs also need an update: https://docs.nestjs.com/techniques/configuration#getting-started

Minimal reproduction of the problem with instructions

Add a .env file with variable and declare the same variable in your CLI environment before starting the server.

What is the motivation / use case for changing the behavior?

Main intention behind this issue is ensuring that no other developers run into this issue. At least we were not expecting a change like this in a patch version.

Also I would reconsider this change. In my opinion the new behaviour is at least a bit uncommon and potentially unexpected, as other popular .env libraries (e.g. dotenv -> https://github.com/motdotla/dotenv#what-happens-to-environment-variables-that-were-already-set) implement this the other way around. There the .env file just acts as default values and not as overrides.

Environment


Nest version: 7.0.9

@nestjs/config version: 0.4.1

 
For Tooling issues:
- Node version: 12  
- Platform: Mac  

Others: -

Why Joi instead of class-validator

I'm submitting a...


[ ] Regression 
[ ] Bug report
[x] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead post your question on Stack Overflow.

Current behavior

Why using joi instead of class-validator, as the latter is more like a standard package for nest.

Expected behavior

Allow using class-validator.

ConfigModule from @nestjs/config isn't coming global

Bug Report

In docs I can see opportunity to make ConfigModule globally, but if I do everything like in docs I will receive error. But if I import ConfigModule directly to DatabaseModule, where I expect ConfigService, it works fine.

Current behavior

I'm getting an error if I specify code like below

[Nest] 23598   - 12/18/2019, 8:01:24 PM   [ExceptionHandler] Nest can't resolve dependencies of the DATABASE_CONNECTION (?). Please make sure that the argument ConfigService at index [0] is available in the DatabaseModule context.

Potential solutions:
- If ConfigService is a provider, is it part of the current DatabaseModule?
- If ConfigService is exported from a separate @Module, is that module imported within DatabaseModule?
  @Module({
    imports: [ /* the Module containing ConfigService */ ]
  })
 +3ms
Error: Nest can't resolve dependencies of the DATABASE_CONNECTION (?). Please make sure that the argument ConfigService at index [0] is available in the DatabaseModule context.

Potential solutions:
- If ConfigService is a provider, is it part of the current DatabaseModule?
- If ConfigService is exported from a separate @Module, is that module imported within DatabaseModule?
  @Module({
    imports: [ /* the Module containing ConfigService */ ]
  })

    at Injector.lookupComponentInParentModules (/Users/b.ponomarenko/Desktop/job/invest-admin-api/node_modules/@nestjs/core/injector/injector.js:190:19)
    at process._tickCallback (internal/process/next_tick.js:68:7)
    at Function.Module.runMain (internal/modules/cjs/loader.js:834:11)
    at startup (internal/bootstrap/node.js:283:19)
    at bootstrapNodeJSCore (internal/bootstrap/node.js:623:3)

Input Code

// app.module.ts
import { HttpModule, Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { DatabaseModule } from './database/database.module';
import { UsersController } from './users/users.controller';
import { RolesController } from './roles/roles.controller';
import { PermissionsController } from './permissions/permissions.controller';
import { ConfigModule } from '@nestjs/config';

@Module({
  imports: [DatabaseModule, HttpModule, ConfigModule.forRoot({ isGlobal: true })],
  controllers: [AppController, UsersController, RolesController, PermissionsController],
  providers: [AppService],
})
export class AppModule {}

// database.module.ts
import { Module } from '@nestjs/common';
import { databaseProviders } from './database.providers';

@Module({
  providers: [...databaseProviders],
  exports: [...databaseProviders],
})
export class DatabaseModule {}

// database.providers.ts
import { createConnection } from 'typeorm';
import { SnakeNamingStrategy } from 'typeorm-naming-strategies';
import { Assignment } from '../entity/Assignment.entity';
import { User } from '../entity/User.entity';
import { ConfigService } from '@nestjs/config';

export const databaseProviders = [
  {
    provide: 'DATABASE_CONNECTION',
    useFactory: async (configService: ConfigService) => await createConnection({
      namingStrategy: new SnakeNamingStrategy(),
      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_NAME'),
      entities: [Assignment, User],
      synchronize: false,
      logging: true,
    }),
    inject: [ConfigService],
  },
];

Expected behavior

ConfigService injected to useFactory function

Environment


"@nestjs/common": "^6.7.2",
"@nestjs/config": "0.0.7"
 
For Tooling issues:
- Node version: 10.17.0
- Platform:  Mac

Handle envFilePath options properly

I'm submitting a...


[ ] Regression 
[x] Bug report
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead post your question on Stack Overflow.

Current behavior

If use envFilePath, and the file not exists, the app fails

Expected behavior

When you don't use envFilePath, the default value is .env, and the app is bootstrapped even when the .env file not exist... The behavior should be the same for the envFilePathparameter

Minimal reproduction of the problem with instructions

What is the motivation / use case for changing the behavior?

Environment


Nest version: X.Y.Z

 
For Tooling issues:
- Node version: XX  
- Platform:  

Others:

How to catch @nest/config (Joi) exceptions?

I'm submitting a...


[ ] Regression 
[ ] Bug report
[ ] Feature request
[X] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead post your question on Stack Overflow.

Current behavior

I setuped configuration validation as described in documentation of NestJS: https://docs.nestjs.com/techniques/configuration#schema-validation

Validation works as expected, but when my .env file is not valid, I am getting plain error, for example:

Error: Config validation error: "FOO_BAR" is required at Function.forRoot (@nestjs\config\dist\config.module.js:44:27)

This error is not thrown by Nest so approach with globalFilter what can catch every Nest error not work: https://docs.nestjs.com/websockets/exception-filters#exception-filters

Can this be described in documentation?

Using class-validator for ConfigModule validation

Feature Request

Is your feature request related to a problem? Please describe.

Why i should install additional dependency for only one call?

Describe the solution you'd like

Can you add an option to validate enviroment variables via class-validator instead of @hapi/joi?

What is the motivation / use case for changing the behavior?

Well, for example my docker container will be smaller an its building faster. The chance of getting a dependency with a vulnerability is less.

Cast configuration variable to the provided type

I'm submitting a...


[ ] Regression
[ ] Bug report
[x] Feature request
[ ] Documentation issue or request
[ ] Support request

Current behavior

When fetching configuration values via config service there is no type conversion although I pass in a desired type.

Expected behavior

I would expect the config service to cast the configuration value to the type that I passed in. If that fails, it throws an exception.

Minimal reproduction of the problem with instructions

Create a new application via NestJs CLI.

$ nest new application

Install the config module

$ npm i --save @nestjs/config

Create a .env file in the root directory with the content

PORT = 3000

Update the app.module.ts to

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

@Module({
  imports: [ConfigModule.forRoot()]
})
export class AppModule {}

Update the main.ts file to

import { NestFactory } from "@nestjs/core";
import { ConfigService } from "@nestjs/config";
import { AppModule } from "./app.module";

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  const config: ConfigService = app.get(ConfigService);
  const port: number = config.get<number>("PORT");

  console.log(port); // 3000
  console.log(typeof port); // string
  console.log(typeof port === "number"); // false

  await app.listen(port);
}
bootstrap();

Start the application via

$ npm run start:dev

You should see the following console logs

  • 3000
  • string
  • false

What is the motivation / use case for changing the behavior?

So the config service usage is described in the docs

https://docs.nestjs.com/techniques/configuration#using-the-configservice

I read something about "type hinting". To me, this is a bit confusing / misleading. If I pass in the type I would expect a numeric cast.

const port: number = config.get<number>("PORT");

You will still receive a string. I found the current code implementation here

https://github.com/nestjs/config/blob/master/lib/config.service.ts

To solve the current example I could do

const port: number = Number(config.get("PORT"));

but a cast would be awesome :)

Environment


Nest common version: 6.7.2
Nest config version: 0.0.7
 
For Tooling issues:
- Node version: 10.16.3
- Platform:  Windows

ConfigService::get is not type-hinting correctly its return value

Consider the following use case:

const configuration = new ConfigService<{
    FOO: number
}<();

const foo = configuration.get('FOO');

foo?.bar; // should fail; doesn't because foo is inferred as any | undefined

It is expected that foo is resolved by TypeScript type checker as a number. But it is actually resolved as any | undefined.

get should have the following signature:

    get<P extends keyof K>(propertyPath: P): K[P];

NestJs Config Module incompatible with Typescript 4

I'm submitting a...


[ ] Regression 
[x] Bug report
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead post your question on Stack Overflow.

Current behavior

NestJs config module is not compatible with Typescript 4.
When trying to import the ConfigModule, its not available in IDE quick assist. Forcefully trying to import ConfigModule from @nestjs/config gives an error - Cannot find module '@nestjs/config' or its corresponding type declarations

Expected behavior

ConfigModule should be available after installing @nestjs/config

Minimal reproduction of the problem with instructions

Installed typescript and nestjs cli
Initialise a project, and then install @nestjs/config.
Try to import ConfigModule in AppModule, and it throws an error.

I compared with one of my old projects, and rollbacked the Typescript version to 3, after which the error goes away.

What is the motivation / use case for changing the behavior?

Not as per expectations from the documentation.

Environment


Nest version: 7.5.1

 
For Tooling issues:
- Node version: 14.15.0  
- Platform:  Mac 

Others:

Typescript version: ^4.0.5

[Q] Using config

Sorry for posting here but i dont known where to put this, there is not gist channel?
if this is not a place for these question please send me where i should ask.

I have app.module.ts:

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { ConfigModule } from '@nestjs/config';
import configuration from './config/configuration';
import { TypeOrmModule } from '@nestjs/typeorm';

@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true,
      load: [configuration],
    }),
    TypeOrmModule.forRoot({
      type: 'mysql',
      host: 'localhost',
      port: 3306,
      username: 'root',
      password: 'root',
      database: 'test',
      autoLoadEntities: true,
      synchronize: true,
    }),
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

How can i use a configService to pass username and other to TypeOrmModule? or many others module in this file.

config.get<boolean> return unexpected value

I'm submitting a...


[ ] Regression 
[x] Bug report
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead post your question on Stack Overflow.

Current behavior

From the documentation

@Injectable()
export class ApiConfigService {
  constructor(private configService: ConfigService) {}

  get isAuthEnabled(): boolean {
    return Boolean(this.configService.get('AUTH_ENABLED'));  // if `AUTH_ENABLED=false` in .env it might get true with `Boolean('false')`
  }
}

Expected behavior

when .env file contains boolean value
such as

DATABASE_SYNC=false

and ConfigModule options contains Joi Schema validation
like Joi.boolean().default(false).

the validatedConfig from joi validate(config, validateOptions) will return a boolean value.

// now typeof validatedConfig['DATABASE_SYNC'] === 'boolean'

after assignVariablesToProcess, we can not get boolean value which has been validated and perform expected type cast behavior.

suppose config.get<boolean>('DATABASE_SYNC') return same value from validatedConfig?

Minimal reproduction of the problem with instructions

You might run below unittest code (append test case in validation-schema.spec.ts)

it(`should validate loaded env with boolean variables`, async () => {
    const withBooleanSchemaValidationModule = (): DynamicModule => {
      return {
        module: AppModule,
        imports: [
          ConfigModule.forRoot({
            validationSchema: Joi.object({
              DATABASE_SYNC: Joi.boolean().default(false),
            }),
          }),
        ],
      };
    };

    const module = await Test.createTestingModule({
      imports: [withBooleanSchemaValidationModule()],
    }).compile();

    app = module.createNestApplication();
    await app.init();
    const config = app.get(ConfigService);

    const isDatabaseSync = config.get<boolean>('DATABASE_SYNC');

    expect(typeof isDatabaseSync).toBe('boolean'); // Received: 'string'
    expect(Boolean(isDatabaseSync)).toBeFalsy(); // Received: true  from `Boolean('false')`

    await app.close();
  });

What is the motivation / use case for changing the behavior?

I want to migrate my application code configuration module to @nestjs/config, and found boolean value in .env file can not load correctly.

Environment


Nest version: 6.11.8

 
For Tooling issues:
- Node version: v12.6.0  
- Platform:  Mac 

Others:

Possible to use config service inside model classes?

Currently we are using https://github.com/nestjsx/nestjs-config but have been looking at moving to use this package instead.

With the current package being used, we could access the config service using static get method, which meant we were able to use the confing service inside model files as part of validation conditions.

e.g.

export class AuthenticateUser {
  @ValidateIf((_obj: AuthenticateUser) => ConfigService.get('app').isFeatureEnabled('recaptcha'))
  @IsNotEmpty()
  @IsString()
  @MaxLength(1000)
  recaptchaCode: string;
}

Is this also possible with this package, to have access to the config service inside a model file without having to resort to making the class injectable and using DI?

I'm submitting a...


[ ] Regression 
[ ] Bug report
[x] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead post your question on Stack Overflow.

share configs

I'm submitting a...


[ ] Regression 
[ ] Bug report
[x] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead post your question on Stack Overflow.

like registerAs, if there has includeAs(or other name)

registerAs('a',()=>{
  return {a:'a'}
})

registerAs('b',()=>{
  return {a:includeAs('a') , b:'b'}
})

// config.get('b.a') // 'a'

Current behavior

config define separately

Expected behavior

include from other config

for example, there are 3 configs A,B and C. but B and C have the same part like A

Minimal reproduction of the problem with instructions

What is the motivation / use case for changing the behavior?

Environment


Nest version: X.Y.Z

 
For Tooling issues:
- Node version: XX  
- Platform:  

Others:

Action Required: Fix Renovate Configuration

There is an error with this repository's Renovate configuration that needs to be fixed. As a precaution, Renovate will stop PRs until it is resolved.

Error type: undefined. Note: this is a nested preset so please contact the preset author if you are unable to fix it yourself.

@hapi/joi moved to joi

I'm submitting a...


[ ] Regression 
[ ] Bug report
[ ] Feature request
[x] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead post your question on Stack Overflow.

@hapi/joi is now deprecated as the package has been renamed joi. Although the same cannot be said for its types (the author claims that there is going to be a future native Typescript support), and the best up-to-date types are those of the old package, I think that the current NestJS docs should be updated to reflect the change.

Modify type signature for `ConfigService.get()` so that types are automatically inferred

I'm submitting a...


[ ] Regression 
[ ] Bug report
[x] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead post your question on Stack Overflow.

Current behavior

If you provide an initial argument to the generic when you declare ConfigService, like ConfigService<EnvironmentVariables>, when you call .get() it will provide all the possible key strings, but the return type isn't automatically inferred, it must be manually stated with .get<type>().

Expected behavior

Types should be automatically inferred from the object/argument provided to new ConfigService(), in addition to having values be manually typed if a generic to ConfigService<T> is provided.

What is the motivation / use case for changing the behavior?

Better developer experience, it's an easy change, and improves safety + quality-of-life.

Draft

I tried to remain completely backwards-compatible with behavior here, even when that includes allowing people to pass the wrong types manually:

Typescript playground demo

There may also be someone better at TS that might offer suggestions or a cleaner approach here.

Custom config files validation via Joi or another validator

I'm submitting a...


[ ] Regression 
[ ] Bug report
[x ] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead post your question on Stack Overflow.

Current behavior

Currently, in the @nestjs/config package, we have the possibility to validate env variables at application startup. I would like to be able to do this for the custom configuration files that Nest allows us to create

Expected behavior

I would like to be able to pass a validator, much like what is done now for the env variables but for the custom config files, and have them be validated just like the env variables are.

Minimal reproduction of the problem with instructions

What is the motivation/use case for changing the behavior?

The motivation is that in the project I'm working on the configuration elements are quite complex, we have a lot of custom configuration files that take care of different aspects of the application configuration (TypeORM, Elasticsearch, Rabbitmq, Sentry, etc...). We would like to validate the values that we get from those configuration files, one simple example being when we expect a number from an env var and somehow we forget to cast the var to a number in Javascript. As the config module is built right now, from my understanding we never once dispose of an aggregate object that would contain all the computed values from the custom files that we could validate which was the approach I wanted to implement when looking through the codebase. I'd be happy to submit a pull request if you could point me in the right direction for this.

Environment


Nest version: latest
For Tooling issues:
- Node version: 14.4.0
- Platform:  Mac

Others:

Loading of custom config files should be validated


[ ] Regression 
[ ] Bug report
[x] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead post your question on Stack Overflow.

Current behavior

If I have a custom configuration file that gets included via the load property, the config file is not validated.
The validation runs and fails before the custom configuration files are added and the combined config object is established.

Expected behavior

I would expect that if I have custom configs that are to be loaded that the config validation functionality not be run until all configs are loaded and merged together.

Minimal reproduction of the problem with instructions

Create a project
Create a config file to load
Create a custom validation function
run app and see that validation fails because the variables aren't available yet.

What is the motivation / use case for changing the behavior?

The use case seems like a common one. I want to load a custom config file and would like to validate the entire config after all variables have been loaded up.

Environment


Nest version: X.Y.Z

 
For Tooling issues:
- Node version: XX  
- Platform:  

Others:

Error: No valid exports main found for 'node_modules/uuid'

I'm submitting an issue with NestJS Config and UUID


[ ] Regression 
[x] Bug report
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead post your question on Stack Overflow.

Current behavior

I have just installed NestJS Config package and after running the npm run start:dev I get the below error:

4:14:18 PM - Found 0 errors. Watching for file changes.
internal/modules/cjs/loader.js:625
  throw e;
  ^

Error: No valid exports main found for '/Users/thang/Projects/backend/node_modules/uuid'
    at resolveExportsTarget (internal/modules/cjs/loader.js:622:9)
    at applyExports (internal/modules/cjs/loader.js:499:14)
    at resolveExports (internal/modules/cjs/loader.js:548:12)
    at Function.Module._findPath (internal/modules/cjs/loader.js:654:22)
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:953:27)
    at Function.Module._load (internal/modules/cjs/loader.js:859:27)
    at Module.require (internal/modules/cjs/loader.js:1028:19)
    at require (internal/modules/cjs/helpers.js:72:18)
    at Object.<anonymous> (/Users/thang/Projects/bell-health-backend/node_modules/@nestjs/config/dist/utils/create-config-factory.util.js:3:16)
    at Module._compile (internal/modules/cjs/loader.js:1139:30) {
  code: 'MODULE_NOT_FOUND'
}

Environment


  "dependencies": {
    "@nestjs/common": "^7.0.0",
    "@nestjs/config": "^0.4.0",
    "@nestjs/core": "^7.0.0",
    "@nestjs/platform-express": "^6.10.14",
    "aws-amplify": "^3.0.10",
    "reflect-metadata": "^0.1.13",
    "rimraf": "^3.0.0",
    "rxjs": "^6.5.4"
  },
 
For Tooling issues:
- Node version: 13.5.0
- Platform:  MAC

Feature idea: support for .env.*.local by default

Hi, I want to propose this feature.

I see it's a common practice for frameworks to support multiple .env files by default, with specific order of precedence between them.

For example, a regular web app could contain

.env
.env.production
.env.development

The 3 files are versioned on git, and on each environment (local, prod, etc...) there's an extra *.local file. E.g.

.env.local
.env.production.local
.env.developoment.local

The order of precedence is

.env.{ENV}.local > .env.{ENV} > .env.local > .env

Example nextjs:
https://nextjs.org/docs/basic-features/environment-variables
https://github.com/vercel/next.js/blob/canary/packages/next-env/index.ts#L82

Example symfony:
https://symfony.com/doc/current/configuration.html#overriding-environment-values-via-env-local
https://github.com/symfony/symfony/blob/46ca50fd843b71ed5fc4517f5d87e04fdfb87768/src/Symfony/Component/Dotenv/Dotenv.php#L109

I'll be happy to implement this on the @nestjs/config package

ValidationSchema does not respect configuration provided to `load`

I'm submitting a...


[ ] Regression 
[x] Bug report
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead post your question on Stack Overflow.

Current behavior

Given the following code:

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

const configuration = () => ({
  foo: 'bar',
});

@Module({
  imports: [
    ConfigModule.forRoot({
      validationSchema: Joi.object({
        foo: Joi.string().required(),
      }),
      load: [configuration],
    }),
  ],
})
export class AppModule {}

The following error is produced

Error: Config validation error: "foo" is required
    at Function.forRoot (/dev/playground/node_modules/@nestjs/config/dist/config.module.js:43:23)
    at /dev/playground/src/app.module.ts:11:18
    at Object.<anonymous> (/dev/playground/src/app.module.ts:44:3)
    at Module._compile (internal/modules/cjs/loader.js:1200:30)
    at Module.m._compile (/Users/stevensilvestri/.config/yarn/global/node_modules/ts-node/src/index.ts:473:23)
    at Module._extensions..js (internal/modules/cjs/loader.js:1220:10)
    at Object.require.extensions.<computed> [as .ts] (/Users/stevensilvestri/.config/yarn/global/node_modules/ts-node/src/index.ts:476:12)
    at Module.load (internal/modules/cjs/loader.js:1049:32)
    at Function.Module._load (internal/modules/cjs/loader.js:937:14)
    at Module.require (internal/modules/cjs/loader.js:1089:19)

Expected behavior

No error should be thrown

Minimal reproduction of the problem with instructions

see snippet above

What is the motivation / use case for changing the behavior?

The configuration is providing the value, it should not fail validation when it is provided.

Environment


Nest version: 7.0.13

 
For Tooling issues:
- Node version: XX  
- Platform:  

Others:

Types

Screen Shot 2021-05-13 at 12 43 00 AM

How can I fix this. Thanks

How does it support multiple env files?

I am looking through this instruction: https://docs.nestjs.com/techniques/configuration to setup env file for my nestjs application.

I see it supports creating multiple config files: envFilePath: ['.env.development.local', '.env.development'], but I wonder how it supports dynamically choose environment file based on NODE_ENV.

I have three env files: .env.dev, .dev.staging, .dev.prod. And I usually use NODE_ENV=dev env to set the current environment. How does nestjs/dev work with NODE_ENV. Can it pick one based on its value?

Export getConfigToken from the root of the package

I'm submitting a...


[ ] Regression 
[ ] Bug report
[x] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead post your question on Stack Overflow.

Current behavior

If I would like to test service with directly injected specific config type, fe:

@Inject(awsConfig.KEY)
        private readonly configAws: ConfigType<typeof awsConfig>,

Then in spec file I need to import it like this:

import { getConfigToken } from "@nestjs/config/dist/utils/get-config-token.util";

Expected behavior

I should be able to import getConfigToken directly from @nestjs/config

Minimal reproduction of the problem with instructions

What is the motivation / use case for changing the behavior?

Some eslint configuration across projects might be different, fe adding rule like: import/no-internal-modules which make sense more or less prints out an error here.

I was not able to figure out other way to mock this injection other than using this getConfigToken function.

Environment


Nest version: 0.6.1

 
For Tooling issues:
- Node version: 15.0.1  
- Platform: Linux  

Others:
I love Nest <3

Error in INJECT namespace - Nest can't resolve dependencies

I'm submitting a...


[ ] Regression 
[X] Bug report
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead post your question on Stack Overflow.

Current behavior

I'm using the SequielizeModule and ConfigModule, I have my database configurations created with registerAs and loaded with the forRoot method in my ApplicationModule.

In my database module, I import the Sequelize module using the forRootAsync, importing ConfigModule, injecting the ConfigService, and using useClass for Sequelize configurations.

In my configuration class if I use the config service everything works as expected but if I use the @INJECT decorator with the KEY of the configuration, Nest can't resolve the dependency. (if the ConfigModule is global, using the isGlobal flag, the inject decorator works)

Error:

my_awesome_project_dev_1        | [Nest] 96   - 07/10/2020, 9:54:52 PM   [ExceptionHandler] Nest can't resolve dependencies of the SequelizeConfig (?). Please make sure that the argument CONFIGURATION(database) at index [0] is available in the SequelizeCoreModule context.
my_awesome_project_dev_1        | 
my_awesome_project_dev_1        | Potential solutions:
my_awesome_project_dev_1        | - If CONFIGURATION(database) is a provider, is it part of the current SequelizeCoreModule?
my_awesome_project_dev_1        | - If CONFIGURATION(database) is exported from a separate @Module, is that module imported within SequelizeCoreModule?
my_awesome_project_dev_1        |   @Module({
my_awesome_project_dev_1        |     imports: [ /* the Module containing CONFIGURATION(database) */ ]
my_awesome_project_dev_1        |   })
my_awesome_project_dev_1        |  +5ms
my_awesome_project_dev_1        | Error: Nest can't resolve dependencies of the SequelizeConfig (?). Please make sure that the argument CONFIGURATION(database) at index [0] is available in the SequelizeCoreModule context.
my_awesome_project_dev_1        | 
my_awesome_project_dev_1        | Potential solutions:
my_awesome_project_dev_1        | - If CONFIGURATION(database) is a provider, is it part of the current SequelizeCoreModule?
my_awesome_project_dev_1        | - If CONFIGURATION(database) is exported from a separate @Module, is that module imported within SequelizeCoreModule?
my_awesome_project_dev_1        |   @Module({
my_awesome_project_dev_1        |     imports: [ /* the Module containing CONFIGURATION(database) */ ]
my_awesome_project_dev_1        |   })

Expected behavior

NestJs must be able to resolve the namespace dependency.

Minimal reproduction of the problem with instructions

  1. Create a configuration file with registerAs:
import { registerAs } from '@nestjs/config';
import { Dialect } from 'sequelize';

export default registerAs('database', () => {
  const { NODE_ENV } = process.env;

  return {
    dialect: (process.env.DATABASE_DIALECT || 'mysql') as Dialect,
    host: process.env.DATABASE_HOST,
    port: parseInt(process.env.DATABASE_PORT || '3306', 10),
    username: process.env.DATABASE_USERNAME,
    password: process.env.DATABASE_PASSWORD,
    database: NODE_ENV === 'test' ? 'e2e' : process.env.DATABASE_NAME,
    logging: NODE_ENV === 'development',
  };
});
  1. Import the config module in App:
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { databaseConfig } from './config';
import { DatabaseModule } from './database/database.module';

@Module({
  imports: [
    ConfigModule.forRoot({
      load: [databaseConfig],
      ignoreEnvFile: true,
    }),
    DatabaseModule,
  ],
})
export class AppModule {}
  1. Import sequelize module in database module:
import { Module } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { SequelizeModule } from '@nestjs/sequelize';
import { SequelizeConfig } from './config';

@Module({
  imports: [
    SequelizeModule.forRootAsync({
      imports: [ConfigModule],
      useClass: SequelizeConfig,
      inject: [ConfigService],
    }),
  ],
})
export class DatabaseModule {}
  1. Create the SequelizeConfig class
import { Injectable, Logger, Inject } from '@nestjs/common';
import { ConfigType } from '@nestjs/config';
import {
  SequelizeOptionsFactory,
  SequelizeModuleOptions,
} from '@nestjs/sequelize';
import { databaseConfig } from '../../config';

@Injectable()
export class SequelizeConfig implements SequelizeOptionsFactory {
  constructor(
    @Inject(databaseConfig.KEY)
    private readonly config: ConfigType<typeof databaseConfig>,
  ) {}

  createSequelizeOptions(): SequelizeModuleOptions {
    return {
      dialect: this.config.dialect,
      host: this.config.host,
      port: this.config.port,
      username: this.config.username,
      password: this.config.password,
      database: this.config.database,
      logging: this.config.logging
        ? (sql) => Logger.log(sql, 'Database')
        : false,
      autoLoadModels: true,
      synchronize: false,
    };
  }
}

What is the motivation / use case for changing the behavior?

Inject namespaces in other modules.

Environment


Nest version: 7.3.1

 
For Tooling issues:
- Node version: 12.18.1
- Platform:  Linux

Others:
    "@nestjs/config": "^0.5.0",
    "@nestjs/sequelize": "^0.1.0",

Use dotenv-expand instead of dotenv

I'm submitting feature request

We should use dotenv-expand instead of dotenv.

Instead of this:

import { config } from 'dotenv';
config();

We should do this:

import { config } from 'dotenv';
import dotenvExpand from 'dotenv-expand';
dotenvExpand(config());

Current behavior

We use dotenv to fetch configuration from the .env file

Expected behavior

We should switch to using dotenv-expand

What is the motivation / use case for changing the behavior?

Using dotenv-expand, we can do this:

DB_PROVIDER = "my-database-provider"
DB_USER = "my-database-user"
DB_PASSWORD = "my-database-password"
DB_HOST = "my-database-host"
DB_POST = 3306
DB_NAME = "my-database-name"
DATABASE_URL = "${DB_PROVIDER}://${DB_USER}:${DB_PASSWORD}@${DB_HOST}:${DB_POST}/${DB_NAME}"

Currently, we'd have to specify the full DATABASE_URL.

Error in loading configuration

I'm submitting a...


[ ] Regression 
[ ] Bug report
[ ] Feature request
[X] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead post your question on Stack Overflow.

Current behavior

I do everything according to the documentation at https://docs.nestjs.com/techniques/configuration
but I am getting an error:
app.module.ts
image
configuration.ts
image

What im doing wrong?

Unable to properly encapsulate `ConfigService` from `process.env` in tests

I'm submitting a...


[ ] Regression 
[x] Bug report
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead post your question on Stack Overflow.

Current behavior

When testing different configurations for services in our nest.js application, we would like to separate the process.env of the actual test runtime from the simulated environment inside the test. I don't want the tested application to know that e.g. process.env.NODE_ENV is set to test in general, and I want to be able to change it into something else without globally mutating process.env.
I tried using ConfigModule.forRoot({ ignoreEnvValues: true, ignoreEnvFile: true, load: [() => myTestConfig] }) for that purpose.

This doesn't suffice though because the evaluation order of different config sources inside ConfigService#get doesn't respect this configuration. It will still use this order (see source):

  1. validated configuration values set on initialization
  2. lazily evaluated process.env
  3. internalConfig - this is where myTestConfig ends up

Unfortunately, this results in the ConfigService still picking up process.env.NODE_ENV from the outer process before it would use myTestConfig.NODE_ENV.

There is a weird workaround: I can specify a validation schema, which will put myTestConfig into the internalConfig[VALIDATED_ENV_PROPNAME], which is evaluated first. I find this even more confusing.

Expected behavior

ConfigService#get respects the module configuration and doesn't fall back to process.env if ignoreEnvVars is set to true.
I also think that the order of preference should be changed and the ConfigService should always check internalConfig before it falls back to process.env. I don't understand what's the motivation to do it the other way around.

Minimal reproduction of the problem with instructions

const module: TestingModule = await Test.createTestingModule({
    imports: [
        ConfigModule.forRoot({
            ignoreEnvVars: true,
            ignoreEnvFile: true,
            load: [() => ({ NODE_ENV: 'some_encapsulated_value' })],
        }),
    ],
}).compile();

const configService = module.get(ConfigService);
expect(configService.get('NODE_ENV')).toEqual('some_encapsulated_value');
// actual value: 'test' from the outer test runtime: `process.env.NODE_ENV`

What is the motivation / use case for changing the behavior?

This issue made me now mock the entire ConfigService and replace it with a different class entirely which I have under full control. I don't think this should be what nest.js requires us to do. After all, one of the big arguments for having a DI-powered configuration is that you can easily replace configuration with different values by creating a new ConfigService with a different underlying data source. Right now, we need to replace the whole ConfigService though.

Environment


Nest version: 7.1.0
@nestjs/config version: 0.5.0

configService.get<T> returns string

I'm submitting a...


[ ] Regression 
[x] Bug report
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead post your question on Stack Overflow.

Current behavior

Given the following .env.local file,

KEY1=3000
KEY2=false

When doing:

const confValue = this.configService.get<number>("KEY1", 5000);

... then confValue is actually a string, which is confirmed by typeof confValue

... which gets worse when dealing with booleans:

const confValue = this.configService.get<boolean>("KEY2", false);
if (confValue) {
  // truthy expression which always returns true:  if "false" => true
}

Expected behavior

When performing this:

const confValue1 = this.configService.get<number>("KEY1", 5000);
const confValue2 = this.configService.get<number>("KEY2", false);

then confValue1's type should be a number and confValue2 a boolean. At least that's what the get method's signature suggests and that's great.

Minimal reproduction of the problem with instructions

@Module({
  imports: [
    ConfigModule.forRoot({ envFilePath: ['.env.local'], cache: true })
  ],
  controllers: [ ],
  providers: [MyManager],
})
export class AppModule { }
@Injectable()
export class MyManager {

    @Inject()
    private configService: ConfigService;

    public async doStuff(): Promise<void> {
        const confValue1 = this.configService.get<number>("KEY1", 5000);
        const confValue2 = this.configService.get<boolean>("KEY2", false);
    }
}

## What is the motivation / use case for changing the behavior?
Maybe I missed something with configuration validation of some sort, but there's no point typing a function (get<T>) if it always returns a string. Or is it ?

## Environment

<pre><code>
Nest version: 7.5.1
Nest config version: 0.6.1
 
For Tooling issues:
- Node version: 13.13
- Platform:  Linux

Others:
<!-- Anything else relevant?  Operating system version, IDE, package manager, ... -->
</code></pre>

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.