Skip to content

Commit

Permalink
Smart vaultFilepath selection if passed as array
Browse files Browse the repository at this point in the history
  • Loading branch information
motdotla committed Nov 19, 2023
1 parent dfaa11d commit 2a88fff
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 8 deletions.
6 changes: 4 additions & 2 deletions lib/main.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// TypeScript Version: 3.0
/// <reference types="node" />
import type { URL } from 'node:url';
import type { URL } from 'url';

export interface DotenvParseOutput {
[name: string]: string;
Expand All @@ -24,10 +24,12 @@ export interface DotenvConfigOptions {
* Default: `path.resolve(process.cwd(), '.env')`
*
* Specify a custom path if your file containing environment variables is located elsewhere.
* Can also be an array of strings, specifying multiple paths.
*
* example: `require('dotenv').config({ path: '/custom/path/to/.env' })`
* example: `require('dotenv').config({ path: ['/path/to/first.env', '/path/to/second.env'] })`
*/
path?: string | URL;
path?: string | string[] | URL;

/**
* Default: `utf8`
Expand Down
23 changes: 18 additions & 5 deletions lib/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -150,14 +150,27 @@ function _instructions (result, dotenvKey) {
}

function _vaultPath (options) {
let dotenvPath = path.resolve(process.cwd(), '.env')
let possibleVaultPath = null

if (options && options.path && options.path.length > 0) {
dotenvPath = options.path
if (Array.isArray(options.path)) {
for (const filepath of options.path) {
if (fs.existsSync(filepath)) {
possibleVaultPath = filepath.endsWith('.vault') ? filepath : `${filepath}.vault`
}
}
} else {
possibleVaultPath = options.path.endsWith('.vault') ? options.path : `${options.path}.vault`
}
} else {
possibleVaultPath = path.resolve(process.cwd(), '.env.vault')
}

if (fs.existsSync(possibleVaultPath)) {
return possibleVaultPath
}

// Locate .env.vault
return dotenvPath.endsWith('.vault') ? dotenvPath : `${dotenvPath}.vault`
return null
}

function _resolveHome (envPath) {
Expand Down Expand Up @@ -224,7 +237,7 @@ function config (options) {
}

// dotenvKey exists but .env.vault file does not exist
if (!fs.existsSync(vaultPath)) {
if (!vaultPath) {
_warn(`You set DOTENV_KEY but you are missing a .env.vault file at ${vaultPath}. Did you forget to build it?`)

return DotenvModule.configDotenv(options)
Expand Down
42 changes: 41 additions & 1 deletion tests/test-config-vault.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,15 @@ t.afterEach(() => {
}
})

t.test('logs when no path is set', ct => {
ct.plan(1)

logStub = sinon.stub(console, 'log')

dotenv.config()
ct.ok(logStub.called)
})

t.test('logs', ct => {
ct.plan(1)

Expand All @@ -43,7 +52,7 @@ t.test('logs when testPath calls to .env.vault directly (interpret what the user
ct.ok(logStub.called)
})

t.test('warns if DOTENV_KEY exists but .env.vault does not', ct => {
t.test('warns if DOTENV_KEY exists but .env.vault does not exist', ct => {
ct.plan(1)

logStub = sinon.stub(console, 'log')
Expand All @@ -56,6 +65,19 @@ t.test('warns if DOTENV_KEY exists but .env.vault does not', ct => {
ct.end()
})

t.test('warns if DOTENV_KEY exists but .env.vault does not exist (set as array)', ct => {
ct.plan(1)

logStub = sinon.stub(console, 'log')

const existsSync = sinon.stub(fs, 'existsSync').returns(false) // make .env.vault not exist
dotenv.config({ path: [testPath] })
ct.ok(logStub.called)
existsSync.restore()

ct.end()
})

t.test('returns parsed object', ct => {
ct.plan(1)

Expand All @@ -65,6 +87,24 @@ t.test('returns parsed object', ct => {
ct.end()
})

t.test('returns parsed object (set path as array)', ct => {
ct.plan(1)

const env = dotenv.config({ path: [testPath] })
ct.same(env.parsed, { ALPHA: 'zeta' })

ct.end()
})

t.test('returns parsed object (set path as array with .vault extension)', ct => {
ct.plan(1)

const env = dotenv.config({ path: [`${testPath}.vault`] })
ct.same(env.parsed, { ALPHA: 'zeta' })

ct.end()
})

t.test('throws not found if .env.vault is empty', ct => {
ct.plan(1)

Expand Down
9 changes: 9 additions & 0 deletions tests/test-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,15 @@ t.test('takes string for path option', ct => {
ct.equal(readFileSyncStub.args[0][0], testPath)
})

t.test('takes string for path option', ct => {
ct.plan(1)

const testPath = 'tests/.env'
dotenv.config({ path: testPath })

ct.equal(readFileSyncStub.args[0][0], testPath)
})

t.test('takes array for path option', ct => {
ct.plan(1)

Expand Down

0 comments on commit 2a88fff

Please sign in to comment.