Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add support for parameter expansion #342

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,22 @@ or in `package.json` (use `\\` to insert a literal backslash)
}
```

It will also work with parameter expansion

```sh
./node_modules/.bin/env-cmd -x echo "Hello ${WHO}!"
```

or in `package.json`:

```json
{
"script": {
"hello": "env-cmd -x echo \"Hello ${WHO}!\""
}
}
```


### `--silent` suppresses env-cmd errors

Expand Down
1 change: 1 addition & 0 deletions dist/env-cmd.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.EnvCmd = exports.CLI = void 0;
const spawn_1 = require("./spawn");
const signal_termination_1 = require("./signal-termination");
const parse_args_1 = require("./parse-args");
Expand Down
7 changes: 4 additions & 3 deletions dist/expand-envs.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.expandEnvs = void 0;
/**
* expandEnvs Replaces $var in args and command with environment variables
* the environment variable doesn't exist, it leaves it as is.
*/
function expandEnvs(str, envs) {
return str.replace(/(?<!\\)\$[a-zA-Z0-9_]+/g, varName => {
const varValue = envs[varName.slice(1)];
return varValue === undefined ? varName : varValue;
return str.replace(/(?<!\\)\$\{?([a-zA-Z0-9_]+)\}?/g, (_, varName) => {
const varValue = envs[varName];
return varValue === undefined ? `$${varName}` : varValue;
});
}
exports.expandEnvs = expandEnvs;
1 change: 1 addition & 0 deletions dist/get-env-vars.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getRCFile = exports.getEnvFile = exports.getEnvVars = void 0;
const parse_rc_file_1 = require("./parse-rc-file");
const parse_env_file_1 = require("./parse-env-file");
const RC_FILE_DEFAULT_LOCATIONS = ['./.env-cmdrc', './.env-cmdrc.js', './.env-cmdrc.json'];
Expand Down
18 changes: 14 additions & 4 deletions dist/index.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,18 @@
"use strict";
function __export(m) {
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
}
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !exports.hasOwnProperty(p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.GetEnvVars = void 0;
const get_env_vars_1 = require("./get-env-vars");
__export(require("./env-cmd"));
// Export the core env-cmd API
__exportStar(require("./types"), exports);
__exportStar(require("./env-cmd"), exports);
exports.GetEnvVars = get_env_vars_1.getEnvVars;
1 change: 1 addition & 0 deletions dist/parse-args.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseArgsUsingCommander = exports.parseArgs = void 0;
const commander = require("commander");
const utils_1 = require("./utils");
// Use commonjs require to prevent a weird folder hierarchy in dist
Expand Down
1 change: 1 addition & 0 deletions dist/parse-env-file.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.stripEmptyLines = exports.stripComments = exports.parseEnvVars = exports.parseEnvString = exports.getEnvFileVars = void 0;
const fs = require("fs");
const path = require("path");
const utils_1 = require("./utils");
Expand Down
1 change: 1 addition & 0 deletions dist/parse-rc-file.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getRCFileVars = void 0;
const fs_1 = require("fs");
const util_1 = require("util");
const path_1 = require("path");
Expand Down
4 changes: 3 additions & 1 deletion dist/signal-termination.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.TermSignals = void 0;
const SIGNALS_TO_HANDLE = [
'SIGINT', 'SIGTERM', 'SIGHUP'
];
Expand Down Expand Up @@ -82,7 +83,8 @@ class TermSignals {
*/
_terminateProcess(code, signal) {
if (signal !== undefined) {
return process.kill(process.pid, signal);
process.kill(process.pid, signal);
return;
}
if (code !== undefined) {
return process.exit(code);
Expand Down
1 change: 1 addition & 0 deletions dist/spawn.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.spawn = void 0;
const spawn = require("cross-spawn");
exports.spawn = spawn;
1 change: 1 addition & 0 deletions dist/utils.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.isPromise = exports.parseArgList = exports.resolveEnvFilePath = void 0;
const path = require("path");
const os = require("os");
/**
Expand Down
6 changes: 3 additions & 3 deletions src/expand-envs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
* the environment variable doesn't exist, it leaves it as is.
*/
export function expandEnvs (str: string, envs: { [key: string]: any }): string {
return str.replace(/(?<!\\)\$[a-zA-Z0-9_]+/g, varName => {
const varValue = envs[varName.slice(1)]
return varValue === undefined ? varName : varValue
return str.replace(/(?<!\\)\$\{?([a-zA-Z0-9_]+)\}?/g, (_, varName: string) => {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The current implementation does not check, if the pattern is contained in a string. That would make the regex way more complex.

Currently something like env-cmd -x ${WHO} would also be expanded. I don’t think that is a big deal, but if so we could use something like ((?<="[^"]*)\${([a-zA-Z0-9_]+)}(?=[^"]*")|(?<!\\)\$([a-zA-Z0-9_]+)).

const varValue = envs[varName]
return varValue === undefined ? `$${varName}` : varValue
})
}
3 changes: 2 additions & 1 deletion src/signal-termination.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,8 @@ export class TermSignals {
*/
public _terminateProcess (code?: number, signal?: NodeJS.Signals): void {
if (signal !== undefined) {
return process.kill(process.pid, signal)
process.kill(process.pid, signal)
return
Comment on lines +92 to +93
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

linting was failing for me on this one, because process.kill seems to return a boolean, but the function expects the return value to be void.

}
if (code !== undefined) {
return process.exit(code)
Expand Down
11 changes: 7 additions & 4 deletions test/expand-envs.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,15 @@ describe('expandEnvs', (): void => {
notvar: 'this is not used',
dollar: 'money',
PING: 'PONG',
IP1: '127.0.0.1'
IP1: '127.0.0.1',
WHO: 'World'
}
const args = ['notvar', '$dollar', '\\$notvar', '-4', '$PING', '$IP1', '\\$IP1', '$NONEXIST']
const argsExpanded = ['notvar', 'money', '\\$notvar', '-4', 'PONG', '127.0.0.1', '\\$IP1', '$NONEXIST']

it('should replace environment variables in args', (): void => {
// eslint-disable-next-line no-template-curly-in-string
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I needed to disable the rule for this line, otherwise I could not commit my test string.

const args = ['notvar', '$dollar', '\\$notvar', '-4', '$PING', '$IP1', '\\$IP1', '$NONEXIST', '"Hello ${WHO}"']
const argsExpanded = ['notvar', 'money', '\\$notvar', '-4', 'PONG', '127.0.0.1', '\\$IP1', '$NONEXIST', '"Hello World"']

it.only('should replace environment variables in args', (): void => {
const res = args.map(arg => expandEnvs(arg, envs))
assert.sameOrderedMembers(res, argsExpanded)
})
Expand Down