@dotenvx/dotenvx 0.23.0 → 0.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.23.0",
2
+ "version": "0.24.0",
3
3
  "name": "@dotenvx/dotenvx",
4
4
  "description": "a better dotenv–from the creator of `dotenv`",
5
5
  "author": "@motdotla",
@@ -0,0 +1,54 @@
1
+ const { execSync } = require('child_process')
2
+
3
+ function _chomp (value) {
4
+ return value.replace(/\r?\n|\r/, '')
5
+ }
6
+
7
+ function interpolate (value, processEnv, parsed) {
8
+ const matches = value.match(/\$\([^()]+\)/) || []
9
+
10
+ return matches.reduce(function (newValue, match) {
11
+ // get command
12
+ const command = match.substring(2, match.length - 1)
13
+ // execute command
14
+ const value = _chomp(execSync(command).toString())
15
+ // replace with command value
16
+ return newValue.replace(match, value)
17
+ }, value)
18
+ }
19
+
20
+ function evaluate (options) {
21
+ let processEnv = process.env
22
+ if (options && options.processEnv != null) {
23
+ processEnv = options.processEnv
24
+ }
25
+
26
+ for (const key in options.parsed) {
27
+ let value = options.parsed[key]
28
+
29
+ const inProcessEnv = Object.prototype.hasOwnProperty.call(processEnv, key)
30
+
31
+ if (inProcessEnv) {
32
+ if (processEnv[key] === options.parsed[key]) {
33
+ // assume was set to processEnv from the .env file if the values match and therefore interpolate
34
+ value = interpolate(value, processEnv, options.parsed)
35
+ } else {
36
+ // do not interpolate - assume processEnv had the intended value even if containing a $.
37
+ value = processEnv[key]
38
+ }
39
+ } else {
40
+ // not inProcessEnv so assume interpolation for this .env key
41
+ value = interpolate(value, processEnv, options.parsed)
42
+ }
43
+
44
+ options.parsed[key] = value
45
+ }
46
+
47
+ for (const processKey in options.parsed) {
48
+ processEnv[processKey] = options.parsed[processKey]
49
+ }
50
+
51
+ return options
52
+ }
53
+
54
+ module.exports.eval = evaluate
@@ -1,7 +1,8 @@
1
1
  const dotenv = require('dotenv')
2
2
  const dotenvExpand = require('dotenv-expand')
3
+ const dotenvEval = require('./dotenvEval')
3
4
 
4
- function parseExpand (src, overload) {
5
+ function parseExpandAndEval (src, overload) {
5
6
  const parsed = dotenv.parse(src)
6
7
 
7
8
  // consider moving this logic straight into dotenv-expand
@@ -18,13 +19,26 @@ function parseExpand (src, overload) {
18
19
  }
19
20
  const expanded = dotenvExpand.expand(expandPlease).parsed
20
21
 
22
+ let inputExpanded = {}
23
+ if (overload) {
24
+ inputExpanded = { ...process.env, ...expanded }
25
+ } else {
26
+ inputExpanded = { ...expanded, ...process.env }
27
+ }
28
+
29
+ const evaluatePlease = {
30
+ processEnv: {},
31
+ parsed: inputExpanded
32
+ }
33
+ const evaluated = dotenvEval.eval(evaluatePlease).parsed
34
+
21
35
  // but then for logging only log the original keys existing in parsed. this feels unnecessarily complex - like dotenv-expand should support the ability to inject additional `process.env` or objects as it sees fit to the object it wants to expand
22
36
  const result = {}
23
37
  for (const key in parsed) {
24
- result[key] = expanded[key]
38
+ result[key] = evaluated[key]
25
39
  }
26
40
 
27
41
  return result
28
42
  }
29
43
 
30
- module.exports = parseExpand
44
+ module.exports = parseExpandAndEval
package/src/lib/main.js CHANGED
@@ -8,6 +8,9 @@ const Ls = require('./services/ls')
8
8
  const Get = require('./services/get')
9
9
  const Genexample = require('./services/genexample')
10
10
 
11
+ // helpers
12
+ const dotenvEval = require('./helpers/dotenvEval')
13
+
11
14
  // proxies to dotenv
12
15
  const config = function (options) {
13
16
  const env = dotenv.config(options)
@@ -18,7 +21,13 @@ const config = function (options) {
18
21
  }
19
22
  const expanded = dotenvExpand.expand(env)
20
23
 
21
- return expanded
24
+ // if processEnv passed also pass to eval
25
+ if (options && options.processEnv) {
26
+ expanded.processEnv = options.processEnv
27
+ }
28
+ const evaluated = dotenvEval.eval(expanded)
29
+
30
+ return evaluated
22
31
  }
23
32
 
24
33
  const configDotenv = function (options) {
@@ -4,7 +4,7 @@ const path = require('path')
4
4
  const ENCODING = 'utf8'
5
5
 
6
6
  const inject = require('./../helpers/inject')
7
- const parseExpand = require('./../helpers/parseExpand')
7
+ const parseExpandAndEval = require('./../helpers/parseExpandAndEval')
8
8
 
9
9
  class RunDefault {
10
10
  constructor (envFile = '.env', env = [], overload = false) {
@@ -25,7 +25,7 @@ class RunDefault {
25
25
  row.string = env
26
26
 
27
27
  try {
28
- const parsed = parseExpand(env, this.overload)
28
+ const parsed = parseExpandAndEval(env, this.overload)
29
29
  row.parsed = parsed
30
30
 
31
31
  const { injected, preExisted } = inject(process.env, parsed, this.overload)
@@ -52,7 +52,7 @@ class RunDefault {
52
52
  const src = fs.readFileSync(filepath, { encoding: ENCODING })
53
53
  readableFilepaths.add(envFilepath)
54
54
 
55
- const parsed = parseExpand(src, this.overload)
55
+ const parsed = parseExpandAndEval(src, this.overload)
56
56
  row.parsed = parsed
57
57
 
58
58
  const { injected, preExisted } = inject(process.env, parsed, this.overload)
@@ -4,7 +4,7 @@ const dotenv = require('dotenv')
4
4
 
5
5
  const inject = require('./../helpers/inject')
6
6
  const decrypt = require('./../helpers/decrypt')
7
- const parseExpand = require('./../helpers/parseExpand')
7
+ const parseExpandAndEval = require('./../helpers/parseExpandAndEval')
8
8
  const parseEnvironmentFromDotenvKey = require('./../helpers/parseEnvironmentFromDotenvKey')
9
9
 
10
10
  const ENCODING = 'utf8'
@@ -43,7 +43,7 @@ class RunVault {
43
43
  const row = {}
44
44
  row.string = env
45
45
 
46
- const parsed = parseExpand(env, this.overload)
46
+ const parsed = parseExpandAndEval(env, this.overload)
47
47
  row.parsed = parsed
48
48
 
49
49
  const { injected, preExisted } = inject(process.env, parsed, this.overload)
@@ -77,7 +77,7 @@ class RunVault {
77
77
  }
78
78
 
79
79
  // parse this. it's the equivalent of the .env file
80
- const parsed = parseExpand(decrypted, this.overload)
80
+ const parsed = parseExpandAndEval(decrypted, this.overload)
81
81
  const { injected, preExisted } = inject(process.env, parsed, this.overload)
82
82
 
83
83
  for (const key of Object.keys(injected)) {