Skip to content

Commit

Permalink
fix(validations): fix schema validations
Browse files Browse the repository at this point in the history
  • Loading branch information
gperdomor committed Mar 27, 2020
1 parent 1a5a34c commit 96406f1
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 29 deletions.
60 changes: 32 additions & 28 deletions lib/config.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,39 +38,40 @@ export class ConfigModule {
*/
static forRoot(options: ConfigModuleOptions = {}): DynamicModule {
let validatedEnvConfig: Record<string, any> | undefined = undefined;
if (!options.ignoreEnvFile) {
if (options.validationSchema) {
let config = this.loadEnvFile(options);
if (!options.ignoreEnvVars) {
config = {
...process.env,
...config,
};
}
const validationOptions = this.getSchemaValidationOptions(options);
const {
error,
value: validatedConfig,
} = options.validationSchema.validate(config, validationOptions);

if (error) {
throw new Error(`Config validation error: ${error.message}`);
}
validatedEnvConfig = validatedConfig;
this.assignVariablesToProcess(validatedConfig);
} else {
const config = this.loadEnvFile(options);
this.assignVariablesToProcess(config);

let config = this.loadEnvFile(options);

if (!options.ignoreEnvVars) {
config = {
...process.env,
...config,
};
}

if (options.validationSchema) {
const validationOptions = this.getSchemaValidationOptions(options);
const {
error,
value: validatedConfig,
} = options.validationSchema.validate(config, validationOptions);

if (error) {
throw new Error(`Config validation error: ${error.message}`);
}
validatedEnvConfig = validatedConfig;
this.assignVariablesToProcess(validatedConfig);
} else {
this.assignVariablesToProcess(config);
}

const isConfigToLoad = options.load && options.load.length;
const providers = (options.load || [])
.map(factory =>
.map((factory) =>
createConfigProvider(factory as ConfigFactory & ConfigFactoryKeyHost),
)
.filter(item => item) as FactoryProvider[];
.filter((item) => item) as FactoryProvider[];

const configProviderTokens = providers.map(item => item.provide);
const configProviderTokens = providers.map((item) => item.provide);
const configServiceProvider = {
provide: ConfigService,
useFactory: (configService: ConfigService) => configService,
Expand Down Expand Up @@ -150,6 +151,9 @@ export class ConfigModule {
private static loadEnvFile(
options: ConfigModuleOptions,
): Record<string, any> {
if (options.ignoreEnvFile) {
return {};
}
const envFilePaths = Array.isArray(options.envFilePath)
? options.envFilePath
: [options.envFilePath || resolve(process.cwd(), '.env')];
Expand All @@ -173,8 +177,8 @@ export class ConfigModule {
if (!isObject(config)) {
return;
}
const keys = Object.keys(config).filter(key => !(key in process.env));
keys.forEach(key => (process.env[key] = config[key]));
const keys = Object.keys(config).filter((key) => !(key in process.env));
keys.forEach((key) => (process.env[key] = config[key]));
}

private static mergePartial(
Expand Down
15 changes: 15 additions & 0 deletions tests/e2e/validation-schema.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,21 @@ describe('Schema validation', () => {
}
});

it(`should validate env variables even when ignoreEnvFile is true`, async () => {
try {
const module = await Test.createTestingModule({
imports: [AppModule.withSchemaValidation(undefined, true)],
}).compile();

app = module.createNestApplication();
await app.init();
} catch (err) {
expect(err.message).toEqual(
'Config validation error: "PORT" is required. "DATABASE_NAME" is required',
);
}
});

it(`should parse loaded env variables`, async () => {
const module = await Test.createTestingModule({
imports: [AppModule.withSchemaValidation(join(__dirname, '.env.valid'))],
Expand Down
6 changes: 5 additions & 1 deletion tests/src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,12 +72,16 @@ export class AppModule {
};
}

static withSchemaValidation(envFilePath?: string): DynamicModule {
static withSchemaValidation(
envFilePath?: string,
ignoreEnvFile?: boolean,
): DynamicModule {
return {
module: AppModule,
imports: [
ConfigModule.forRoot({
envFilePath,
ignoreEnvFile,
validationSchema: Joi.object({
PORT: Joi.number().required(),
DATABASE_NAME: Joi.string().required(),
Expand Down

0 comments on commit 96406f1

Please sign in to comment.