Skip to content

Commit

Permalink
feat: recursive embedding of env vars in env vars
Browse files Browse the repository at this point in the history
  • Loading branch information
nkrul committed Mar 10, 2021
1 parent fa50d02 commit 65d2198
Show file tree
Hide file tree
Showing 9 changed files with 63 additions and 2 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -5,6 +5,7 @@
- **Upgrade**: Upgraded dependency `commander` to `5.x`
- **Upgrade**: Upgraded devDependencies `ts-standard`, `sinon`
- **Feature**: support both `$var` and `${var}` when expanding vars
- **Feature**: Added support for nested env variables with the `--recursive` flag

## 10.1.0

Expand Down
5 changes: 5 additions & 0 deletions dist/env-cmd.js
Expand Up @@ -52,6 +52,11 @@ async function EnvCmd({ command, commandArgs, envFile, rc, options = {} }) {
// Add in the system environment variables to our environment list
env = Object.assign({}, process.env, env);
}
if (options.recursive === true) {
for (const key of Object.keys(env)) {
env[key] = expand_envs_1.expandEnvs(env[key], env);
}
}
if (options.expandEnvs === true) {
command = expand_envs_1.expandEnvs(command, env);
commandArgs = commandArgs.map(arg => expand_envs_1.expandEnvs(arg, env));
Expand Down
8 changes: 7 additions & 1 deletion dist/parse-args.js
Expand Up @@ -31,6 +31,10 @@ function parseArgs(args) {
if (program.expandEnvs === true) {
expandEnvs = true;
}
let recursive = false;
if (program.recursive === true) {
recursive = true;
}
let verbose = false;
if (program.verbose === true) {
verbose = true;
Expand Down Expand Up @@ -60,6 +64,7 @@ function parseArgs(args) {
rc,
options: {
expandEnvs,
recursive,
noOverride,
silent,
useShell,
Expand All @@ -85,7 +90,8 @@ function parseArgsUsingCommander(args) {
.option('--silent', 'Ignore any env-cmd errors and only fail on executed program failure.')
.option('--use-shell', 'Execute the command in a new shell with the given environment')
.option('--verbose', 'Print helpful debugging information')
.option('-x, --expand-envs', 'Replace $var in args and command with environment variables')
.option('-x, --expand-envs', 'Replace $var and $\\{var\\} in args and command with environment variables')
.option('--recursive', 'Replace $var and $\\{var\\} in env file with the referenced environment variable')
.allowUnknownOption(true)
.parse(['_', '_', ...args]);
}
Expand Down
1 change: 1 addition & 0 deletions dist/types.d.ts
Expand Up @@ -14,6 +14,7 @@ export interface EnvCmdOptions extends Pick<GetEnvVarOptions, 'envFile' | 'rc'>
commandArgs: string[];
options?: {
expandEnvs?: boolean;
recursive?: boolean;
noOverride?: boolean;
silent?: boolean;
useShell?: boolean;
Expand Down
6 changes: 6 additions & 0 deletions src/env-cmd.ts
Expand Up @@ -57,6 +57,12 @@ export async function EnvCmd (
env = Object.assign({}, process.env, env)
}

if (options.recursive === true) {
for (const key of Object.keys(env)) {
env[key] = expandEnvs(env[key], env)
}
}

if (options.expandEnvs === true) {
command = expandEnvs(command, env)
commandArgs = commandArgs.map(arg => expandEnvs(arg, env))
Expand Down
8 changes: 7 additions & 1 deletion src/parse-args.ts
Expand Up @@ -33,6 +33,10 @@ export function parseArgs (args: string[]): EnvCmdOptions {
if (program.expandEnvs === true) {
expandEnvs = true
}
let recursive = false
if (program.recursive === true) {
recursive = true
}
let verbose = false
if (program.verbose === true) {
verbose = true
Expand Down Expand Up @@ -65,6 +69,7 @@ export function parseArgs (args: string[]): EnvCmdOptions {
rc,
options: {
expandEnvs,
recursive,
noOverride,
silent,
useShell,
Expand All @@ -90,7 +95,8 @@ export function parseArgsUsingCommander (args: string[]): commander.Command {
.option('--silent', 'Ignore any env-cmd errors and only fail on executed program failure.')
.option('--use-shell', 'Execute the command in a new shell with the given environment')
.option('--verbose', 'Print helpful debugging information')
.option('-x, --expand-envs', 'Replace $var in args and command with environment variables')
.option('-x, --expand-envs', 'Replace $var and $\\{var\\} in args and command with environment variables')
.option('--recursive', 'Replace $var and $\\{var\\} in env file with the referenced environment variable')
.allowUnknownOption(true)
.parse(['_', '_', ...args])
}
1 change: 1 addition & 0 deletions src/types.ts
Expand Up @@ -15,6 +15,7 @@ export interface EnvCmdOptions extends Pick<GetEnvVarOptions, 'envFile' | 'rc'>
commandArgs: string[]
options?: {
expandEnvs?: boolean
recursive?: boolean
noOverride?: boolean
silent?: boolean
useShell?: boolean
Expand Down
29 changes: 29 additions & 0 deletions test/env-cmd.spec.ts
Expand Up @@ -193,6 +193,35 @@ describe('EnvCmd', (): void => {
}
)

it('should spawn process with args expanded if recursive option is true',
async (): Promise<void> => {
getEnvVarsStub.returns({ PING: 'PONG', recursive: 'PING ${PING}' }) /* eslint-disable-line */
await envCmdLib.EnvCmd({
command: 'node',
commandArgs: [],
envFile: {
filePath: './.env',
fallback: true
},
rc: {
environments: ['dev'],
filePath: './.rc'
},
options: {
recursive: true
}
})

const spawnArgs = spawnStub.args[0]

assert.equal(getEnvVarsStub.callCount, 1, 'getEnvVars must be called once')
assert.equal(spawnStub.callCount, 1)
assert.isAtLeast(expandEnvsSpy.callCount, 3, 'total number of env args')
assert.equal(spawnArgs[0], 'node')
assert.equal(spawnArgs[2].env.recursive, 'PING PONG')
}
)

it('should ignore errors if silent flag provided',
async (): Promise<void> => {
delete process.env.BOB
Expand Down
6 changes: 6 additions & 0 deletions test/parse-args.spec.ts
Expand Up @@ -98,6 +98,12 @@ describe('parseArgs', (): void => {
assert.isTrue(res.options!.expandEnvs)
})

it('should parse recursive option', (): void => {
const res = parseArgs(['-f', envFilePath, '--recursive', command, ...commandArgs])
assert.exists(res.envFile)
assert.isTrue(res.options!.recursive)
})

it('should parse silent option', (): void => {
const res = parseArgs(['-f', envFilePath, '--silent', command, ...commandArgs])
assert.exists(res.envFile)
Expand Down

0 comments on commit 65d2198

Please sign in to comment.