env-cmd
Advanced tools
Comparing version 5.1.0 to 6.0.0
# Changelog | ||
## 6.0.0 | ||
- ***BREAKING***: Fallback to default `.env` file behavior is no longer the default behavior. You must specify `--fallback` option for that behavior now. | ||
- ***BREAKING***: A specific node version has been set in package.json. Current minimum version is `>=4.0.0`. *Note: the implied minimum version | ||
before this release was always `4.0.0`, but now it is explicitly set and could produce warnings by npm if included in projects that utilizes a | ||
node version that is less than `4.0.0`.* | ||
- **Feature**: Added `--fallback` option to allow for falling back to the default `.env` file if the provided `.env` file is not found. | ||
- **Feature**: Added ability to select multiple environments from the `.env-cmdrc` file. The environments override each other like this: | ||
`development,production` where `production` vars override `development` vars if they share the same vars. | ||
- **Bug**: `env-cmd` no longer crashes when it cannot find the provided `.env` file. Instead, it will execute as normal, but without included any custom env vars. *Note: it will still include system and shell vars.* | ||
## 5.1.0 | ||
@@ -4,0 +14,0 @@ - **Feature**: Added new option `--no-override` that when passed will make it so that the env file |
160
lib/index.js
@@ -9,2 +9,8 @@ 'use strict' | ||
/** | ||
* The main process for reading, parsing, applying and then running the process with env vars | ||
* @param {Array<String>} args And array if strings representing cli args | ||
* | ||
* @return {Object} The child process | ||
*/ | ||
function EnvCmd (args) { | ||
@@ -15,10 +21,17 @@ // First Parse the args from the command line | ||
// If a .rc file was found then use that | ||
let parsedEnv = fs.existsSync(rcFileLocation) ? UseRCFile(parsedArgs) : UseCmdLine(parsedArgs) | ||
let parsedEnv | ||
if (fs.existsSync(rcFileLocation)) { | ||
parsedEnv = UseRCFile({ envFile: parsedArgs.envFile }) | ||
} else { | ||
// Try to use a .env file | ||
parsedEnv = UseCmdLine({ envFile: parsedArgs.envFile, useFallback: parsedArgs.useFallback }) | ||
} | ||
// Add in the system environment variables to our environment list | ||
let env = Object.assign({}, process.env, parsedEnv) | ||
let env | ||
// Override the merge order if --no-override flag set | ||
if (parsedArgs.noOverride) { | ||
env = Object.assign({}, parsedEnv, process.env) | ||
} else { | ||
// Add in the system environment variables to our environment list | ||
env = Object.assign({}, process.env, parsedEnv) | ||
} | ||
@@ -36,3 +49,8 @@ | ||
// Parses the arguments passed into the cli | ||
/** | ||
* Parses the arguments passed into the cli | ||
* @param {Array<String>} args An array of strings to parse the options out of | ||
* | ||
* @return {Object} An object containing cli options and commands | ||
*/ | ||
function ParseArgs (args) { | ||
@@ -46,5 +64,10 @@ if (args.length < 2) { | ||
let noOverride | ||
let useFallback | ||
let commandArgs = args.slice() | ||
while (commandArgs.length) { | ||
const arg = commandArgs.shift() | ||
if (arg === '--fallback') { | ||
useFallback = true | ||
continue | ||
} | ||
if (arg === '--no-override') { | ||
@@ -67,7 +90,13 @@ noOverride = true | ||
commandArgs, | ||
noOverride | ||
noOverride, | ||
useFallback | ||
} | ||
} | ||
// Strips out comments from env file string | ||
/** | ||
* Strips out comments from env file string | ||
* @param {String} envString The .env file string | ||
* | ||
* @return {String} The .env file string with comments stripped out | ||
*/ | ||
function StripComments (envString) { | ||
@@ -84,3 +113,8 @@ const commentsRegex = /(^#.*$)/gim | ||
// Strips out newlines from env file string | ||
/** | ||
* Strips out newlines from env file string | ||
* @param {String} envString The .env file string | ||
* | ||
* @return {String} The .env file string with newlines stripped out | ||
*/ | ||
function StripEmptyLines (envString) { | ||
@@ -91,3 +125,8 @@ const emptyLinesRegex = /(^\n)/gim | ||
// Parse out all env vars from an env file string | ||
/** | ||
* Parse out all env vars from an env file string | ||
* @param {String} envString The .env file string | ||
* | ||
* @return {Object} Key/Value pairs corresponding to the .env file data | ||
*/ | ||
function ParseEnvVars (envString) { | ||
@@ -104,3 +143,8 @@ const envParseRegex = /^((.+?)[=](.*))$/gim | ||
// Parse out all env vars from a given env file string and return an object | ||
/** | ||
* Parse out all env vars from a given env file string and return an object | ||
* @param {String} envString The .env file string | ||
* | ||
* @return {Object} Key/Value pairs of all env vars parsed from files | ||
*/ | ||
function ParseEnvString (envFileString) { | ||
@@ -113,33 +157,66 @@ // First thing we do is stripe out all comments | ||
// 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) | ||
return ParseEnvVars(envFileString) | ||
} | ||
// Reads and parses the .env-cmdrc file | ||
/** | ||
* Reads and parses the .env-cmdrc file | ||
* @param {String} fileData the .env-cmdrc file data (which should be a valid json string) | ||
* | ||
* @return {Object} The .env-cmdrc as a parsed JSON object | ||
*/ | ||
function ParseRCFile (fileData) { | ||
return JSON.parse(fileData) | ||
let data | ||
try { | ||
data = JSON.parse(fileData) | ||
} catch (e) { | ||
console.error(`Error: | ||
Could not parse the .env-cmdrc file. | ||
Please make sure its in a valid JSON format.`) | ||
throw new Error(`Unable to parse JSON in .env-cmdrc file.`) | ||
} | ||
return data | ||
} | ||
// Uses the rc file to get env vars | ||
function UseRCFile (parsedArgs) { | ||
/** | ||
* Uses the rc file to get env vars | ||
* @param {Object} options | ||
* @param {String} options.envFile The .env-cmdrc file environment to use | ||
* | ||
* @return {Object} Key/Value pair of env vars from the .env-cmdrc file | ||
*/ | ||
function UseRCFile (options) { | ||
const fileData = fs.readFileSync(rcFileLocation, { encoding: 'utf8' }) | ||
const parsedData = ParseRCFile(fileData) | ||
const envVars = parsedData[parsedArgs.envFile] | ||
if (!envVars) { | ||
let result = {} | ||
const envNames = options.envFile.split(',') | ||
if (envNames.length === 1 && !parsedData[envNames[0]]) { | ||
console.error(`Error: | ||
Could not find environment: | ||
${parsedArgs.envFile} | ||
in .rc file: | ||
${rcFileLocation}`) | ||
throw new Error(`Missing environment ${parsedArgs.envFile} in .env-cmdrc file.`) | ||
Could not find environment: | ||
${options.envFile} | ||
in .rc file: | ||
${rcFileLocation}`) | ||
throw new Error(`Missing environment ${options.envFile} in .env-cmdrc file.`) | ||
} | ||
return envVars | ||
envNames.forEach(function (name) { | ||
const envVars = parsedData[name] | ||
if (envVars) { | ||
result = Object.assign(result, envVars) | ||
} | ||
}) | ||
return result | ||
} | ||
// Uses the cli passed env file to get env vars | ||
function UseCmdLine (parsedArgs) { | ||
const envFilePath = path.join(process.cwd(), parsedArgs.envFile) | ||
/** | ||
* Uses the cli passed env file to get env vars | ||
* @param {Object} options | ||
* @param {String} options.envFile The .env file name/relative path | ||
* @param {Boolean} options.useFallback Should we attempt to find a fallback file | ||
* | ||
* @return {Object} Key/Value pairing of env vars found in .env file | ||
*/ | ||
function UseCmdLine (options) { | ||
const envFilePath = path.join(process.cwd(), options.envFile) | ||
@@ -151,16 +228,13 @@ // Attempt to open the provided file | ||
} catch (err) { | ||
console.error(`WARNING: | ||
Could not find or read file at: | ||
${envFilePath} | ||
Trying to fallback to read: | ||
${envFilePathDefault} | ||
`) | ||
if (!options.useFallback) { | ||
return {} | ||
} | ||
} | ||
// If we don't have a main file try the fallback file | ||
if (!file) { | ||
if (!file && options.useFallback) { | ||
try { | ||
file = fs.readFileSync(envFilePathDefault) | ||
} catch (e) { | ||
throw new Error(`Error! Could not fallback to find or read file at ${envFilePathDefault}`) | ||
throw new Error(`Error! Could not find fallback file or read env file at ${envFilePathDefault}`) | ||
} | ||
@@ -180,6 +254,9 @@ } | ||
// Prints out some minor help text | ||
/** | ||
* Prints out some minor help text | ||
* @return {String} Help text | ||
*/ | ||
function PrintHelp () { | ||
return ` | ||
Usage: env-cmd [option] [env_file | env_name] command [command options] | ||
Usage: env-cmd [options] [env_file | env_name] command [command options] | ||
@@ -193,5 +270,10 @@ A simple utility for running a cli application using an env config file. | ||
--no-override - do not override existing process env vars with file env vars | ||
--fallback - if provided env file does not exist, attempt to use fallback .env file in root dir | ||
` | ||
} | ||
/** | ||
* General exception handler | ||
* @param {Error} e The exception error to handle | ||
*/ | ||
function HandleUncaughtExceptions (e) { | ||
@@ -198,0 +280,0 @@ if (e.message.match(/passed/gi)) { |
{ | ||
"name": "env-cmd", | ||
"version": "5.1.0", | ||
"version": "6.0.0", | ||
"description": "Executes a command using the envs in the provided env file", | ||
"main": "lib/index.js", | ||
"engines" : { | ||
"node" : ">=4.0.0" | ||
}, | ||
"bin": { | ||
@@ -49,5 +52,5 @@ "env-cmd": "bin/env-cmd.js" | ||
"proxyquire": "^1.7.10", | ||
"sinon": "^2.0.0", | ||
"sinon": "^3.3.0", | ||
"standard": "^10.0.0" | ||
} | ||
} |
@@ -41,3 +41,3 @@ [![Travis](https://img.shields.io/travis/toddbluhm/env-cmd.svg)](https://travis-ci.org/toddbluhm/env-cmd) | ||
### Fallback file usage | ||
### `--fallback` file usage option | ||
@@ -68,3 +68,3 @@ 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. | ||
"scripts": { | ||
"test": "env-cmd ./.env.local mocha -R spec" | ||
"test": "env-cmd --fallback ./.env.local mocha -R spec" | ||
} | ||
@@ -81,5 +81,5 @@ } | ||
### .rc file usage | ||
### `.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`, simply pass the name of the environment you want to use thats in your `.env-cmdrc` file. | ||
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`, simply pass the name of the environment you want to use thats in your `.env-cmdrc` file. You may also use multiple environment names to merge env vars together. | ||
@@ -94,2 +94,6 @@ **.rc file `.env-cmdrc`** | ||
}, | ||
"test": { | ||
"ENV1": "No Thanks", | ||
"ENV3": "!" | ||
}, | ||
"production": { | ||
@@ -104,7 +108,11 @@ "ENV1": "The Fish" | ||
./node_modules/.bin/env-cmd production node index.js | ||
# Or for multiple environments (where `production` vars override `test` vars, | ||
# but both are included) | ||
./node_modules/.bin/env-cmd test,production node index.js | ||
``` | ||
### --no-override option | ||
Sometimes you want to set env variables from a file without overriding existing process env vars. | ||
### `--no-override` option | ||
Sometimes you want to set env variables from a file without overriding existing process env vars or shell env vars. | ||
**Terminal** | ||
@@ -111,0 +119,0 @@ ```sh |
19022
260
152
4
6