mirror of
https://github.com/toddbluhm/env-cmd.git
synced 2026-02-01 14:54:41 +00:00
Merge pull request #3 from toddbluhm/2.1.0
Regex for parsing, support inline comments, support `key value` format
This commit is contained in:
commit
8fd41397d6
@ -1,5 +1,13 @@
|
||||
# Changelog
|
||||
|
||||
## 2.1.0
|
||||
- **Feature**: Added support for `key value` mapping in env vars file
|
||||
- **Feature**: Added support for inline comments `ENV=VALUE # inline comment`
|
||||
- **Change**: Will now ignore invalid lines in env vars file instead of throwing an error
|
||||
- **Change**: Migrated all the parsing over to regex since the file format is simple enough right
|
||||
now to support that
|
||||
- **Bug**: Removed old test cases for the `-e/--env` flags that were not needed anymore
|
||||
|
||||
## 2.0.0
|
||||
- ***BREAKING***: Removed the `-e` and `--env` flags. Now it just expects the first arg to `env-cmd` to be the relative path to the env file: `env-cmd env_file command carg1 carg2`
|
||||
- **Change:** `ParseEnvFile` is now more properly named `ParseEnvString`
|
||||
|
||||
19
README.md
19
README.md
@ -5,7 +5,7 @@
|
||||
[](https://www.npmjs.com/package/env-cmd)
|
||||
|
||||
# env-cmd
|
||||
A simple node program for executing commands using an environment from an env file
|
||||
A simple node program for executing commands using an environment from an env file.
|
||||
|
||||
## Install
|
||||
`npm install env-cmd`
|
||||
@ -14,14 +14,13 @@ A simple node program for executing commands using an environment from an env fi
|
||||
**Environment file `./test/.env`**
|
||||
```
|
||||
# This is a comment
|
||||
ENV1=THANKS
|
||||
ENV2=FORALL
|
||||
ENV4=THEFISH
|
||||
ENV1=THANKS # Yay inline comments support
|
||||
ENV2=FOR ALL
|
||||
ENV3 THE FISH # This format is also accepted
|
||||
```
|
||||
*This is the only accepted format for an environment file. If other formats are desired please create an issue*
|
||||
|
||||
**Package.json**
|
||||
```js
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"test": "env-cmd ./test/.env mocha -R spec"
|
||||
@ -35,11 +34,17 @@ or
|
||||
./node_modules/.bin/env-cmd ./test/.env node index.js
|
||||
```
|
||||
|
||||
## Environment File Formats
|
||||
|
||||
These are the currently accepted environment file formats. If any other formats are desired please create an issue.
|
||||
- `key=value`
|
||||
- `key value`
|
||||
|
||||
## Why
|
||||
|
||||
Because sometimes its just too cumbersome passing lots of environment variables to scripts. Its usually just easier to have a file with all the vars in them, especially for development and testing.
|
||||
|
||||
**Do not commit sensitive env data to a public git repo!**
|
||||
**Do not commit sensitive environment data to a public git repo!**
|
||||
|
||||
## Related Projects
|
||||
|
||||
|
||||
63
lib/index.js
63
lib/index.js
@ -58,37 +58,39 @@ function ParseArgs (args) {
|
||||
}
|
||||
}
|
||||
|
||||
function ParseEnvString (envFileString) {
|
||||
const envs = Object.assign({}, process.env)
|
||||
while (envFileString.length) {
|
||||
// The the last index of the line using the newline delimiter
|
||||
let endOfLineIndex = envFileString.indexOf('\n')
|
||||
function StripComments (envString) {
|
||||
const commentsRegex = /[ ]*(#.*$)/gim
|
||||
return envString.replace(commentsRegex, '')
|
||||
}
|
||||
|
||||
// If no newline, then assume end of file
|
||||
if (endOfLineIndex === -1) {
|
||||
endOfLineIndex = envFileString.length
|
||||
}
|
||||
function StripEmptyLines (envString) {
|
||||
const emptyLinesRegex = /(^\n)/gim
|
||||
return envString.replace(emptyLinesRegex, '')
|
||||
}
|
||||
|
||||
// Get the full line
|
||||
const line = envFileString.slice(0, endOfLineIndex + 1)
|
||||
|
||||
// Shrink the file by 1 line
|
||||
envFileString = envFileString.slice(line.length)
|
||||
|
||||
// Only parse lines that are not empty and don't begin with #
|
||||
if (line.length > 1 && line[0] !== '#') {
|
||||
// Parse the line
|
||||
const equalSign = line.indexOf('=')
|
||||
|
||||
if (equalSign === -1) {
|
||||
throw new Error('Error! Malformed line in env file.')
|
||||
}
|
||||
|
||||
// Set then new env var
|
||||
envs[line.slice(0, equalSign)] = line.slice(equalSign + 1, endOfLineIndex)
|
||||
}
|
||||
function ParseEnvVars (envString) {
|
||||
const envParseRegex = /^((.+?)[ =](.*))$/gim
|
||||
const matches = {}
|
||||
let match
|
||||
while ((match = envParseRegex.exec(envString)) !== null) {
|
||||
// Note: match[1] is the full env=var line
|
||||
matches[match[2]] = match[3]
|
||||
}
|
||||
return envs
|
||||
return matches
|
||||
}
|
||||
|
||||
function ParseEnvString (envFileString) {
|
||||
// First thing we do is stripe out all comments
|
||||
envFileString = StripComments(envFileString)
|
||||
|
||||
// Next we stripe out all the empty lines
|
||||
envFileString = StripEmptyLines(envFileString)
|
||||
|
||||
// Parse the envs vars out
|
||||
const envs = ParseEnvVars(envFileString)
|
||||
|
||||
// Merge the file env vars with the current process env vars (the file vars overwrite process vars)
|
||||
return Object.assign({}, process.env, envs)
|
||||
}
|
||||
|
||||
function PrintHelp () {
|
||||
@ -114,5 +116,8 @@ module.exports = {
|
||||
ParseArgs,
|
||||
ParseEnvString,
|
||||
PrintHelp,
|
||||
HandleUncaughtExceptions
|
||||
HandleUncaughtExceptions,
|
||||
StripComments,
|
||||
StripEmptyLines,
|
||||
ParseEnvVars
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "env-cmd",
|
||||
"version": "2.0.0",
|
||||
"version": "2.1.0",
|
||||
"description": "Executes a command using the envs in the provided env file",
|
||||
"main": "lib/index.js",
|
||||
"bin": {
|
||||
|
||||
83
test/test.js
83
test/test.js
@ -27,15 +27,13 @@ const ParseArgs = lib.ParseArgs
|
||||
const ParseEnvString = lib.ParseEnvString
|
||||
const PrintHelp = lib.PrintHelp
|
||||
const HandleUncaughtExceptions = lib.HandleUncaughtExceptions
|
||||
const StripComments = lib.StripComments
|
||||
const StripEmptyLines = lib.StripEmptyLines
|
||||
const ParseEnvVars = lib.ParseEnvVars
|
||||
|
||||
describe('env-cmd', function () {
|
||||
describe('ParseArgs', function () {
|
||||
it('should parse out the -e envfile path', function () {
|
||||
const parsedArgs = ParseArgs(['./test/envFile', 'command', 'cmda1', 'cmda2'])
|
||||
assert(parsedArgs.envFilePath === path.join(__dirname, 'envFile'))
|
||||
})
|
||||
|
||||
it('should parse out the --env envfile path', function () {
|
||||
it('should parse out the envfile path', function () {
|
||||
const parsedArgs = ParseArgs(['./test/envFile', 'command', 'cmda1', 'cmda2'])
|
||||
assert(parsedArgs.envFilePath === path.join(__dirname, 'envFile'))
|
||||
})
|
||||
@ -64,35 +62,70 @@ describe('env-cmd', function () {
|
||||
})
|
||||
|
||||
describe('ParseEnvString', function () {
|
||||
it('should parse out vars in the environment variable string', function () {
|
||||
it('should parse env vars and merge (overwrite) with process.env vars', function () {
|
||||
process.env.TEST = 'SOME TEST VAR'
|
||||
process.env.NODE_ENV = 'development'
|
||||
const env = ParseEnvString('BOB=COOL\nNODE_ENV=dev\nANSWER=42\n')
|
||||
assert(env.BOB === 'COOL')
|
||||
assert(env.NODE_ENV === 'dev')
|
||||
assert(env.ANSWER === '42')
|
||||
assert(env.TEST === 'SOME TEST VAR')
|
||||
})
|
||||
})
|
||||
|
||||
describe('StripComments', function () {
|
||||
it('should strip out all full line comments', function () {
|
||||
const envString = StripComments('#BOB=COOL\nNODE_ENV=dev\nANSWER=42 AND COUNTING\n#AnotherComment\n')
|
||||
assert(envString === '\nNODE_ENV=dev\nANSWER=42 AND COUNTING\n\n')
|
||||
})
|
||||
|
||||
it('should ignore comment lines (starting with \'#\') and empty lines', function () {
|
||||
const env = ParseEnvString('#BOB=COOL\nNODE_ENV=dev\n\n#ANSWER=42\n')
|
||||
assert(env.BOB === undefined)
|
||||
assert(env.NODE_ENV === 'dev')
|
||||
assert(env.ANSWER === undefined)
|
||||
it('should strip out all inline comments and preceding spaces', function () {
|
||||
const envString = StripComments('BOB=COOL#inline1\nNODE_ENV=dev #cool\nANSWER=42 AND COUNTING #multiple-spaces\n')
|
||||
assert(envString === 'BOB=COOL\nNODE_ENV=dev\nANSWER=42 AND COUNTING\n')
|
||||
})
|
||||
})
|
||||
|
||||
describe('StripEmptyLines', function () {
|
||||
it('should strip out all empty lines', function () {
|
||||
const envString = StripEmptyLines('\nBOB=COOL\n\nNODE_ENV=dev\n\nANSWER=42 AND COUNTING\n\n')
|
||||
assert(envString === 'BOB=COOL\nNODE_ENV=dev\nANSWER=42 AND COUNTING\n')
|
||||
})
|
||||
})
|
||||
|
||||
describe('ParseEnvVars', function () {
|
||||
it('should parse out all env vars in string when not ending with \'\\n\'', function () {
|
||||
const envVars = ParseEnvVars('BOB=COOL\nNODE_ENV=dev\nANSWER=42 AND COUNTING')
|
||||
assert(envVars.BOB === 'COOL')
|
||||
assert(envVars.NODE_ENV === 'dev')
|
||||
assert(envVars.ANSWER === '42 AND COUNTING')
|
||||
})
|
||||
|
||||
it('should parse out env vars even if string does not end in \'\\n\'', function () {
|
||||
const env = ParseEnvString('BOB=COOL\nNODE_ENV=dev\nANSWER=42')
|
||||
assert(env.BOB === 'COOL')
|
||||
assert(env.NODE_ENV === 'dev')
|
||||
assert(env.ANSWER === '42')
|
||||
it('should parse out all env vars in string with format \'key=value\'', function () {
|
||||
const envVars = ParseEnvVars('BOB=COOL\nNODE_ENV=dev\nANSWER=42 AND COUNTING\n')
|
||||
assert(envVars.BOB === 'COOL')
|
||||
assert(envVars.NODE_ENV === 'dev')
|
||||
assert(envVars.ANSWER === '42 AND COUNTING')
|
||||
})
|
||||
|
||||
it('should throw parse error due to malformed env var string', function () {
|
||||
try {
|
||||
ParseEnvString('BOB=COOL\nNODE_ENV dev\nANSWER=42\n')
|
||||
} catch (e) {
|
||||
assert(e.message === 'Error! Malformed line in env file.')
|
||||
return
|
||||
}
|
||||
assert(!'No exception thrown')
|
||||
it('should parse out all env vars in string with format \'key value\'', function () {
|
||||
const envVars = ParseEnvVars('BOB COOL\nNODE_ENV dev\nANSWER 42 AND COUNTING\n')
|
||||
assert(envVars.BOB === 'COOL')
|
||||
assert(envVars.NODE_ENV === 'dev')
|
||||
assert(envVars.ANSWER === '42 AND COUNTING')
|
||||
})
|
||||
|
||||
it('should parse out all env vars in string with mixed format \'key=value\' & \'key value\'', function () {
|
||||
const envVars = ParseEnvVars('BOB=COOL\nNODE_ENV dev\nANSWER=42 AND COUNTING\n')
|
||||
assert(envVars.BOB === 'COOL')
|
||||
assert(envVars.NODE_ENV === 'dev')
|
||||
assert(envVars.ANSWER === '42 AND COUNTING')
|
||||
})
|
||||
|
||||
it('should ignore invalid lines', function () {
|
||||
const envVars = ParseEnvVars('BOB=COOL\nTHISIS$ANDINVALIDLINE\nANSWER=42 AND COUNTING\n')
|
||||
assert(Object.keys(envVars).length === 2)
|
||||
assert(envVars.BOB === 'COOL')
|
||||
assert(envVars.ANSWER === '42 AND COUNTING')
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user