@dotenvx/dotenvx 1.37.0 → 1.38.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/CHANGELOG.md CHANGED
@@ -2,7 +2,14 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
- [Unreleased](https://github.com/dotenvx/dotenvx/compare/v1.37.0...main)
5
+ [Unreleased](https://github.com/dotenvx/dotenvx/compare/v1.38.0...main)
6
+
7
+ ## [1.38.0](https://github.com/dotenvx/dotenvx/compare/v1.37.0...v1.38.0)
8
+
9
+ ### Changed
10
+
11
+ * Command substitution failures no longer halt further processing of keys in a .env file ([#533](https://github.com/dotenvx/dotenvx/pull/533))
12
+ * A more helpful error is raised if a command substitution failure occurs ([#533](https://github.com/dotenvx/dotenvx/pull/533))
6
13
 
7
14
  ## [1.37.0](https://github.com/dotenvx/dotenvx/compare/v1.36.0...v1.37.0)
8
15
 
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.37.0",
2
+ "version": "1.38.0",
3
3
  "name": "@dotenvx/dotenvx",
4
4
  "description": "a better dotenv–from the creator of `dotenv`",
5
5
  "author": "@motdotla",
@@ -8,6 +8,7 @@ class Errors {
8
8
  this.key = options.key
9
9
  this.privateKey = options.privateKey
10
10
  this.privateKeyName = options.privateKeyName
11
+ this.command = options.command
11
12
 
12
13
  this.message = options.message
13
14
  }
@@ -84,6 +85,17 @@ class Errors {
84
85
  e.code = code
85
86
  return e
86
87
  }
88
+
89
+ commandSubstitutionFailed () {
90
+ const code = 'COMMAND_SUBSTITUTION_FAILED'
91
+ const message = `[${code}] could not eval ${this.key} containing command '${this.command}': ${this.message}`
92
+ const help = `[${code}] https://github.com/dotenvx/dotenvx/issues/532`
93
+
94
+ const e = new Error(message)
95
+ e.code = code
96
+ e.help = help
97
+ return e
98
+ }
87
99
  }
88
100
 
89
101
  module.exports = Errors
@@ -0,0 +1,23 @@
1
+ const { execSync } = require('child_process')
2
+ const chomp = require('./chomp')
3
+ const Errors = require('./errors')
4
+
5
+ function evalKeyValue (key, value, processEnv, runningParsed) {
6
+ // Match everything between the outermost $() using a regex with non-capturing groups
7
+ const matches = value.match(/\$\(([^)]+(?:\)[^(]*)*)\)/g) || []
8
+ return matches.reduce((newValue, match) => {
9
+ const command = match.slice(2, -1) // Extract command by removing $() wrapper
10
+ let result
11
+
12
+ try {
13
+ result = execSync(command, { env: { ...processEnv, ...runningParsed } }).toString() // execute command (including runningParsed)
14
+ } catch (e) {
15
+ throw new Errors({ key, command, message: e.message.trim() }).commandSubstitutionFailed()
16
+ }
17
+
18
+ result = chomp(result) // chomp it
19
+ return newValue.replace(match, result) // Replace match with result
20
+ }, value)
21
+ }
22
+
23
+ module.exports = evalKeyValue
@@ -1,7 +1,6 @@
1
- const chomp = require('./chomp')
2
1
  const decryptKeyValue = require('./decryptKeyValue')
2
+ const evalKeyValue = require('./evalKeyValue')
3
3
  const resolveEscapeSequences = require('./resolveEscapeSequences')
4
- const { execSync } = require('child_process')
5
4
 
6
5
  class Parse {
7
6
  static LINE = /(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|\s*`(?:\\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/mg
@@ -49,7 +48,12 @@ class Parse {
49
48
  let evaled = false
50
49
  if (quote !== "'" && (!this.inProcessEnv(key) || this.processEnv[key] === this.parsed[key])) {
51
50
  const priorEvaled = this.parsed[key]
52
- this.parsed[key] = this.eval(priorEvaled)
51
+ // eval
52
+ try {
53
+ this.parsed[key] = this.eval(key, priorEvaled)
54
+ } catch (e) {
55
+ this.errors.push(e)
56
+ }
53
57
  if (priorEvaled !== this.parsed[key]) {
54
58
  evaled = true
55
59
  }
@@ -133,14 +137,8 @@ class Parse {
133
137
  return decryptKeyValue(key, value, this.privateKeyName, this.privateKey)
134
138
  }
135
139
 
136
- eval (value) {
137
- // Match everything between the outermost $() using a regex with non-capturing groups
138
- const matches = value.match(/\$\(([^)]+(?:\)[^(]*)*)\)/g) || []
139
- return matches.reduce((newValue, match) => {
140
- const command = match.slice(2, -1) // Extract command by removing $() wrapper
141
- const result = chomp(execSync(command, { env: { ...this.processEnv, ...this.runningParsed } }).toString()) // execute command (including runningParsed)
142
- return newValue.replace(match, result) // Replace match with result
143
- }, value)
140
+ eval (key, value) {
141
+ return evalKeyValue(key, value, this.processEnv, this.runningParsed)
144
142
  }
145
143
 
146
144
  expand (value) {