mirror of
https://github.com/toddbluhm/env-cmd.git
synced 2025-12-08 18:23:33 +00:00
Fix the # comment in env var name issue
This commit is contained in:
parent
907bf640d9
commit
909df18ddb
65
README.md
65
README.md
@ -11,25 +11,44 @@ A simple node program for executing commands using an environment from an env fi
|
||||
## Install
|
||||
`npm install env-cmd` or `npm install -g env-cmd`
|
||||
|
||||
## Usage
|
||||
|
||||
### Environment File Usage
|
||||
|
||||
If the specified environment file can't be found, an error message is logged.
|
||||
If then `.env` fallback file can't be found too, an error is thrown.
|
||||
## Basic Usage
|
||||
|
||||
**Environment file `./test/.env`**
|
||||
```
|
||||
# This is a comment
|
||||
ENV1=THANKS # Yay inline comments support
|
||||
ENV1=THANKS
|
||||
ENV2=FOR ALL
|
||||
ENV3 THE FISH # This format is also accepted
|
||||
ENV3=THE FISH
|
||||
```
|
||||
|
||||
# Surround value in double quotes when using a # symbol in the value
|
||||
ENV4="ValueContains#Symbol"
|
||||
**Package.json**
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"test": "env-cmd ./test/.env mocha -R spec"
|
||||
}
|
||||
}
|
||||
```
|
||||
or
|
||||
|
||||
# If using double quotes as part of the value, you must surround the value in double quotes
|
||||
ENV5=""Value includes double quotes""
|
||||
**Terminal**
|
||||
```sh
|
||||
# uses ./test/.env
|
||||
./node_modules/.bin/env-cmd ./test/.env node index.js
|
||||
```
|
||||
|
||||
## Advanced Usage
|
||||
|
||||
### Fallback file usage
|
||||
|
||||
You can specify an `.env.local` (or any name) env file, add that to your `.gitignore` and use that in your local development environment. Then you can use a regular `.env` file in root directory with production configs that can get committed to a private/protected repo. When `env-cmd` cannot find the `.env.local` file it will fallback to looking for a regular `.env` file.
|
||||
|
||||
**Environment file `./.env.local`**
|
||||
```
|
||||
# This is a comment
|
||||
ENV1=THANKS
|
||||
ENV2=FOR ALL
|
||||
ENV3=THE FISH
|
||||
```
|
||||
**Fallback Environment file `./.env`**
|
||||
```
|
||||
@ -42,20 +61,11 @@ ENV5=gorge
|
||||
```
|
||||
|
||||
**Package.json**
|
||||
to use `./test/.env`
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"test": "env-cmd ./test/.env mocha -R spec"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
uses `./.env` as a fallback
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"test": "env-cmd ./test/.doesntExist mocha -R spec"
|
||||
"test": "env-cmd ./.env.local mocha -R spec"
|
||||
}
|
||||
}
|
||||
```
|
||||
@ -63,15 +73,14 @@ or
|
||||
|
||||
**Terminal**
|
||||
```sh
|
||||
# uses ./test/.env
|
||||
./node_modules/.bin/env-cmd ./test/.env node index.js
|
||||
# uses ./.env as a fallback, because i can't find `./test/.myEnv`
|
||||
./node_modules/.bin/env-cmd ./test/.myEnv node index.js
|
||||
# uses ./.env as a fallback, because it can't find `./.env.local`
|
||||
./node_modules/.bin/env-cmd ./.env.local node index.js
|
||||
```
|
||||
|
||||
|
||||
### .rc file usage
|
||||
|
||||
For more complex projects, a `.env-cmdrc` file can be defined in the root directory and supports as many environments as you want. Instead of passing the path to a `.env` file to `env-cmd`, simple pass the name of the environment you want use thats in your `.env-cmdrc` file.
|
||||
|
||||
**.rc file `.env-cmdrc`**
|
||||
|
||||
```json
|
||||
@ -95,7 +104,6 @@ or
|
||||
|
||||
These are the currently accepted environment file formats. If any other formats are desired please create an issue.
|
||||
- `key=value`
|
||||
- `key value`
|
||||
- Key/value pairs as JSON
|
||||
- JavaScript file exporting an object
|
||||
- `.env-cmdrc` file (as valid json) in execution directory
|
||||
@ -118,6 +126,7 @@ Special thanks to [`cross-env`](https://github.com/kentcdodds/cross-env) for ins
|
||||
|
||||
- Eric Lanehart
|
||||
- Jon Scheiding
|
||||
- Alexander Praetorius
|
||||
|
||||
## Contributing Guide
|
||||
I welcome all pull requests. Please make sure you add appropriate test cases for any features added. Before opening a PR please make sure to run the following scripts:
|
||||
|
||||
38
lib/index.js
38
lib/index.js
@ -56,11 +56,11 @@ function ParseArgs (args) {
|
||||
|
||||
// Strips out comments from env file string
|
||||
function StripComments (envString) {
|
||||
const commentsRegex = /("{1}.*"{1})*?([ ]*#.*$)/gim
|
||||
const commentsRegex = /(^#.*$)/gim
|
||||
let match = commentsRegex.exec(envString)
|
||||
let newString = envString
|
||||
while (match != null) {
|
||||
newString = newString.replace(match[2], '')
|
||||
newString = newString.replace(match[1], '')
|
||||
match = commentsRegex.exec(envString)
|
||||
}
|
||||
return newString
|
||||
@ -72,21 +72,9 @@ function StripEmptyLines (envString) {
|
||||
return envString.replace(emptyLinesRegex, '')
|
||||
}
|
||||
|
||||
// Stripes out double quotes to allow for usage for special # in values
|
||||
function StripDoubleQuotes (envString) {
|
||||
const doubleQuotesRegex = /"{1}(.*)"{1}/gim
|
||||
let match = doubleQuotesRegex.exec(envString)
|
||||
let newString = envString
|
||||
while (match != null) {
|
||||
newString = newString.replace(match[0], match[1])
|
||||
match = doubleQuotesRegex.exec(envString)
|
||||
}
|
||||
return newString
|
||||
}
|
||||
|
||||
// Parse out all env vars from an env file string
|
||||
function ParseEnvVars (envString) {
|
||||
const envParseRegex = /^((.+?)[ =](.*))$/gim
|
||||
const envParseRegex = /^((.+?)[=](.*))$/gim
|
||||
const matches = {}
|
||||
let match
|
||||
while ((match = envParseRegex.exec(envString)) !== null) {
|
||||
@ -104,9 +92,6 @@ function ParseEnvString (envFileString) {
|
||||
// Next we stripe out all the empty lines
|
||||
envFileString = StripEmptyLines(envFileString)
|
||||
|
||||
// Finally we stripe out all the double quotes for special charactes
|
||||
envFileString = StripDoubleQuotes(envFileString)
|
||||
|
||||
// Parse the envs vars out
|
||||
const envs = ParseEnvVars(envFileString)
|
||||
|
||||
@ -123,7 +108,16 @@ function ParseRCFile (fileData) {
|
||||
function UseRCFile (parsedArgs) {
|
||||
const fileData = fs.readFileSync(rcFileLocation, { encoding: 'utf8' })
|
||||
const parsedData = ParseRCFile(fileData)
|
||||
return parsedData[parsedArgs.envFile]
|
||||
const envVars = parsedData[parsedArgs.envFile]
|
||||
if (!envVars) {
|
||||
console.error(`Error:
|
||||
Could not find environment:
|
||||
${parsedArgs.envFile}
|
||||
in .rc file:
|
||||
${rcFileLocation}`)
|
||||
throw new Error(`Missing environment ${parsedArgs.envFile} in .env-cmdrc file.`)
|
||||
}
|
||||
return envVars
|
||||
}
|
||||
|
||||
// Uses the cli passed env file to get env vars
|
||||
@ -141,6 +135,10 @@ function UseCmdLine (parsedArgs) {
|
||||
Trying to fallback to read:
|
||||
${envFilePathDefault}
|
||||
`)
|
||||
}
|
||||
|
||||
// If we don't have a main file try the fallback file
|
||||
if (!file) {
|
||||
try {
|
||||
file = fs.readFileSync(envFilePathDefault)
|
||||
} catch (e) {
|
||||
@ -148,6 +146,7 @@ function UseCmdLine (parsedArgs) {
|
||||
}
|
||||
}
|
||||
|
||||
// Get the file extension
|
||||
const ext = path.extname(envFilePath).toLowerCase()
|
||||
|
||||
// Parse the env file string using the correct parser
|
||||
@ -188,7 +187,6 @@ module.exports = {
|
||||
HandleUncaughtExceptions,
|
||||
StripComments,
|
||||
StripEmptyLines,
|
||||
StripDoubleQuotes,
|
||||
ParseEnvVars,
|
||||
ParseRCFile,
|
||||
UseRCFile,
|
||||
|
||||
43
test/test.js
43
test/test.js
@ -40,7 +40,6 @@ const PrintHelp = lib.PrintHelp
|
||||
const HandleUncaughtExceptions = lib.HandleUncaughtExceptions
|
||||
const StripComments = lib.StripComments
|
||||
const StripEmptyLines = lib.StripEmptyLines
|
||||
const StripDoubleQuotes = lib.StripDoubleQuotes
|
||||
const ParseEnvVars = lib.ParseEnvVars
|
||||
|
||||
describe('env-cmd', function () {
|
||||
@ -90,16 +89,6 @@ describe('env-cmd', 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 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')
|
||||
})
|
||||
|
||||
it('should not strip out values that are surrouned in double quotes', 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 () {
|
||||
@ -109,13 +98,6 @@ describe('env-cmd', function () {
|
||||
})
|
||||
})
|
||||
|
||||
describe('StripDoubleQuotes', function () {
|
||||
it('should strip out single double quotes', function () {
|
||||
const envString = StripDoubleQuotes(`BOB="#COOL"\nNODE_ENV=dev\nANSWER="42 AND #COUNTING"\nCOOL=""quoted""\nAwesome="'singles'"`)
|
||||
assert(envString === `BOB=#COOL\nNODE_ENV=dev\nANSWER=42 AND #COUNTING\nCOOL="quoted"\nAwesome='singles'`)
|
||||
})
|
||||
})
|
||||
|
||||
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')
|
||||
@ -131,20 +113,6 @@ describe('env-cmd', function () {
|
||||
assert(envVars.ANSWER === '42 AND COUNTING')
|
||||
})
|
||||
|
||||
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)
|
||||
@ -218,6 +186,7 @@ describe('env-cmd', function () {
|
||||
assert(spawnStub.args[0][2].env.NODE_ENV === 'dev')
|
||||
assert(spawnStub.args[0][2].env.ANSWER === '42')
|
||||
})
|
||||
|
||||
it('should parse env vars from .env-cmdrc file using production env', function () {
|
||||
EnvCmd(['production', 'echo', '$BOB'])
|
||||
assert(spawnStub.args[0][0] === 'echo')
|
||||
@ -226,6 +195,16 @@ describe('env-cmd', function () {
|
||||
assert(spawnStub.args[0][2].env.NODE_ENV === 'prod')
|
||||
assert(spawnStub.args[0][2].env.ANSWER === '43')
|
||||
})
|
||||
|
||||
it('should throw error if env not in .rc file', function () {
|
||||
try {
|
||||
EnvCmd(['staging', 'echo', '$BOB'])
|
||||
assert(!'Should throw missing environment error.')
|
||||
} catch (e) {
|
||||
assert(e.message.includes('staging'))
|
||||
assert(e.message.includes(`.env-cmdrc`))
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('EnvCmd', function () {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user