diff --git a/README.md b/README.md index 2c359b9..a4476d7 100644 --- a/README.md +++ b/README.md @@ -49,8 +49,9 @@ const S = require('fluent-schema') const config = envSchema({ schema: S.object().prop('port', S.string().default('3000').required()), - data: data // optional, default: process.env - dotenv: true // load .env if it's there, default: false + data: data, // optional, default: process.env + dotenv: true, // load .env if it's there, default: false + expandEnv: true, // use dotenv-expand, default: false }) console.log(config) diff --git a/index.js b/index.js index 3cc6e13..99ba6d0 100644 --- a/index.js +++ b/index.js @@ -30,7 +30,8 @@ const optsSchema = { default: {} }, env: { type: 'boolean', default: true }, - dotenv: { type: ['boolean', 'object'], default: false } + dotenv: { type: ['boolean', 'object'], default: false }, + expandEnv: { type: ['boolean'], default: false } } } const optsSchemaValidator = ajv.compile(optsSchema) @@ -62,6 +63,9 @@ function loadAndValidateEnvironment (_opts) { } if (opts.env) { + if (opts.expandEnv) { + require('dotenv-expand')({ parsed: process.env }) + } data.unshift(process.env) } diff --git a/package.json b/package.json index 7cd3727..e03fe91 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,8 @@ }, "dependencies": { "ajv": "^6.10.2", - "dotenv": "^8.2.0" + "dotenv": "^8.2.0", + "dotenv-expand": "^5.1.0" }, "tsd": { "directory": "test/types" diff --git a/test/.env b/test/.env index c2e04ae..cddaa49 100644 --- a/test/.env +++ b/test/.env @@ -1 +1,2 @@ VALUE_FROM_DOTENV=look ma +EXPANDED_VALUE_FROM_DOTENV=the password is $PASSWORD! \ No newline at end of file diff --git a/test/expand.test.js b/test/expand.test.js new file mode 100644 index 0000000..6f20000 --- /dev/null +++ b/test/expand.test.js @@ -0,0 +1,64 @@ +'use strict' + +const t = require('tap') +const makeTest = require('./make-test') +const { join } = require('path') + +process.env.K8S_NAMESPACE = 'pippo' +process.env.K8S_CLUSTERID = 'pluto' +process.env.URL = 'https://prefix.$K8S_NAMESPACE.$K8S_CLUSTERID.my.domain.com' +process.env.PASSWORD = 'password' + +const tests = [ + { + name: 'simple object - ok - expandEnv', + schema: { + type: 'object', + properties: { + URL: { + type: 'string' + }, + K8S_NAMESPACE: { + type: 'string' + } + } + }, + expandEnv: true, + isOk: true, + confExpected: { + URL: 'https://prefix.pippo.pluto.my.domain.com', + K8S_NAMESPACE: 'pippo' + } + }, + { + name: 'simple object - ok - expandEnv use dotenv', + schema: { + type: 'object', + properties: { + EXPANDED_VALUE_FROM_DOTENV: { + type: 'string' + } + } + }, + expandEnv: true, + isOk: true, + dotenv: { path: join(__dirname, '.env') }, + confExpected: { + EXPANDED_VALUE_FROM_DOTENV: 'the password is password!' + } + } +] + +tests.forEach(function (testConf) { + t.test(testConf.name, t => { + const options = { + schema: testConf.schema, + data: testConf.data, + dotenv: testConf.dotenv, + dotenvConfig: testConf.dotenvConfig, + expandEnv: testConf.expandEnv + } + + makeTest(t, options, testConf.isOk, testConf.confExpected, testConf.errorMessage) + }) +})