From 28bd3845e76aa582579bad8a562f3b89e5570874 Mon Sep 17 00:00:00 2001 From: Todd Bluhm Date: Mon, 25 Sep 2017 13:39:06 -0500 Subject: [PATCH] Allow for using absolute pathing, ~ pathing, and relative pathing (#30) * Allow for using absolute pathing, ~ pathing, and relative pathing * Add test cases for `./` and `../` pathing * Update Readme file with new path rules --- README.md | 15 +++++++++++++++ lib/index.js | 20 ++++++++++++++++++-- test/test.js | 44 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 77 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 880e997..dfbd2e3 100644 --- a/README.md +++ b/README.md @@ -122,6 +122,21 @@ These are the currently accepted environment file formats. If any other formats - JavaScript file exporting an object - `.env-cmdrc` file (as valid json) in execution directory +## Path Rules + +This lib attempts to follow standard `bash` path rules. The rules are as followed: + +Home Directory = `/Users/test` + +Working Directory = `/Users/test/Development/app` + +| Type | Input Path | Expanded Path | +| -- | -- | ------------- | +| Absolute | `/some/absolute/path.env` | `/some/absolute/path.env` | +| Home Directory with `~` | `~/starts/on/homedir/path.env` | `/Users/test/starts/on/homedir/path.env` | +| Relative | `./some/relative/path.env` or `some/relative/path.env` | `/Users/test/Development/app/some/relative/path.env` | +| Relative with parent dir | `../some/relative/path.env` | `/Users/test/Development/some/relative/path.env` | + ## 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. diff --git a/lib/index.js b/lib/index.js index bcccebc..475cc64 100644 --- a/lib/index.js +++ b/lib/index.js @@ -3,6 +3,7 @@ const spawn = require('cross-spawn').spawn const path = require('path') const fs = require('fs') +const os = require('os') const rcFileLocation = path.join(process.cwd(), '.env-cmdrc') const envFilePathDefault = path.join(process.cwd(), '.env') @@ -209,7 +210,7 @@ function UseRCFile (options) { * @return {Object} Key/Value pairing of env vars found in .env file */ function UseCmdLine (options) { - const envFilePath = path.join(process.cwd(), options.envFile) + const envFilePath = ResolveEnvFilePath(options.envFile) // Attempt to open the provided file let file @@ -272,6 +273,20 @@ function HandleUncaughtExceptions (e) { process.exit(1) } +/** + * A simple function for resolving the path the user entered + * @param {String} userPath A path + * @return {String} The fully qualified absolute path + */ +function ResolveEnvFilePath (userPath) { + // Make sure a home directory exist + const home = os.homedir() + if (home) { + userPath = userPath.replace(/^~($|\/|\\)/, `${home}$1`) + } + return path.resolve(process.cwd(), userPath) +} + process.on('uncaughtException', HandleUncaughtExceptions) module.exports = { @@ -285,5 +300,6 @@ module.exports = { ParseEnvVars, ParseRCFile, UseRCFile, - UseCmdLine + UseCmdLine, + ResolveEnvFilePath } diff --git a/test/test.js b/test/test.js index 34a86d9..239a5be 100644 --- a/test/test.js +++ b/test/test.js @@ -11,6 +11,7 @@ const path = require('path') const proxyquire = require('proxyquire') const sinon = require('sinon') const fs = require('fs') +let userHomeDir = '/Users/hitchhikers-guide-to-the-galaxy' const spawnStub = sinon.spy(() => ({ on: sinon.stub(), @@ -31,6 +32,9 @@ const lib = proxyquire('../lib', { BOB: 'COOL', NODE_ENV: 'dev', ANSWER: '42' + }, + 'os': { + homedir: () => userHomeDir } }) const EnvCmd = lib.EnvCmd @@ -41,6 +45,7 @@ const HandleUncaughtExceptions = lib.HandleUncaughtExceptions const StripComments = lib.StripComments const StripEmptyLines = lib.StripEmptyLines const ParseEnvVars = lib.ParseEnvVars +const ResolveEnvFilePath = lib.ResolveEnvFilePath describe('env-cmd', function () { describe('ParseArgs', function () { @@ -357,4 +362,43 @@ describe('env-cmd', function () { this.logStub.restore() // restore here so test success logs get printed }) }) + + describe('ResolveEnvFilePath', function () { + beforeEach(function () { + this.cwdStub = sinon.stub(process, 'cwd') + this.cwdStub.returns('/Users/hitchhikers-guide-to-the-galaxy/Thanks') + }) + afterEach(function () { + this.cwdStub.restore() + }) + it('should add "fish.env" to the end of the current directory', function () { + const abPath = ResolveEnvFilePath('fish.env') + assert(abPath === '/Users/hitchhikers-guide-to-the-galaxy/Thanks/fish.env') + }) + it('should add "./fish.env" to the end of the current directory', function () { + const abPath = ResolveEnvFilePath('./fish.env') + assert(abPath === '/Users/hitchhikers-guide-to-the-galaxy/Thanks/fish.env') + }) + it('should add "../fish.env" to the end of the current directory', function () { + const abPath = ResolveEnvFilePath('../fish.env') + assert(abPath === '/Users/hitchhikers-guide-to-the-galaxy/fish.env') + }) + it('should add "for-all-the/fish.env" to the end of the current directory', function () { + const abPath = ResolveEnvFilePath('for-all-the/fish.env') + assert(abPath === '/Users/hitchhikers-guide-to-the-galaxy/Thanks/for-all-the/fish.env') + }) + it('should set the absolute path to "/thanks/for-all-the/fish.env"', function () { + const abPath = ResolveEnvFilePath('/thanks/for-all-the/fish.env') + assert(abPath === '/thanks/for-all-the/fish.env') + }) + it('should use "~" to add "fish.env" to the end of user directory', function () { + const abPath = ResolveEnvFilePath('~/fish.env') + assert(abPath === '/Users/hitchhikers-guide-to-the-galaxy/fish.env') + }) + it('should leave "~" in path if no user home directory found', function () { + userHomeDir = '' + const abPath = ResolveEnvFilePath('~/fish.env') + assert(abPath === '/Users/hitchhikers-guide-to-the-galaxy/Thanks/~/fish.env') + }) + }) })