@dotenvx/dotenvx 1.37.0 → 1.38.1
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 +16 -1
- package/package.json +1 -1
- package/src/lib/helpers/append.js +1 -1
- package/src/lib/helpers/dotenvParse.js +4 -2
- package/src/lib/helpers/errors.js +12 -0
- package/src/lib/helpers/evalKeyValue.js +23 -0
- package/src/lib/helpers/parse.js +9 -11
- package/src/lib/helpers/replace.js +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,7 +2,22 @@
|
|
|
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.
|
|
5
|
+
[Unreleased](https://github.com/dotenvx/dotenvx/compare/v1.38.1...main)
|
|
6
|
+
|
|
7
|
+
## [1.38.1](https://github.com/dotenvx/dotenvx/compare/v1.38.0...v1.38.1)
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
|
|
11
|
+
* Support `encrypt` when mutliline contains windows `CRLF` (`\\r\\n`) ([#534](https://github.com/dotenvx/dotenvx/pull/534))
|
|
12
|
+
|
|
13
|
+
Note: dotenvx will convert these `\\r\\n` newlines to `\\n`. Our recommendation is to stop using CRLF - its origin is from typewriter days. Instead, set your editor or gitattributes to use LF.
|
|
14
|
+
|
|
15
|
+
## [1.38.0](https://github.com/dotenvx/dotenvx/compare/v1.37.0...v1.38.0)
|
|
16
|
+
|
|
17
|
+
### Changed
|
|
18
|
+
|
|
19
|
+
* Command substitution failures no longer halt further processing of keys in a .env file ([#533](https://github.com/dotenvx/dotenvx/pull/533))
|
|
20
|
+
* A more helpful error is raised if a command substitution failure occurs ([#533](https://github.com/dotenvx/dotenvx/pull/533))
|
|
6
21
|
|
|
7
22
|
## [1.37.0](https://github.com/dotenvx/dotenvx/compare/v1.36.0...v1.37.0)
|
|
8
23
|
|
package/package.json
CHANGED
|
@@ -7,7 +7,7 @@ function append (src, key, appendValue) {
|
|
|
7
7
|
let output
|
|
8
8
|
let newPart = ''
|
|
9
9
|
|
|
10
|
-
const parsed = dotenvParse(src, true) // skip expanding \n
|
|
10
|
+
const parsed = dotenvParse(src, true, true) // skip expanding \n and skip converting \r\n
|
|
11
11
|
const _quotes = quotes(src)
|
|
12
12
|
if (Object.prototype.hasOwnProperty.call(parsed, key)) {
|
|
13
13
|
const quote = _quotes[key]
|
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
// historical dotenv.parse - https://github.com/motdotla/dotenv)
|
|
2
2
|
const LINE = /(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|\s*`(?:\\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/mg
|
|
3
3
|
|
|
4
|
-
function dotenvParse (src, skipExpandForDoubleQuotes = false) {
|
|
4
|
+
function dotenvParse (src, skipExpandForDoubleQuotes = false, skipConvertingWindowsNewlines = false) {
|
|
5
5
|
const obj = {}
|
|
6
6
|
|
|
7
7
|
// Convert buffer to string
|
|
8
8
|
let lines = src.toString()
|
|
9
9
|
|
|
10
10
|
// Convert line breaks to same format
|
|
11
|
-
|
|
11
|
+
if (!skipConvertingWindowsNewlines) {
|
|
12
|
+
lines = lines.replace(/\r\n?/mg, '\n')
|
|
13
|
+
}
|
|
12
14
|
|
|
13
15
|
let match
|
|
14
16
|
while ((match = LINE.exec(lines)) != null) {
|
|
@@ -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
|
package/src/lib/helpers/parse.js
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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) {
|
|
@@ -7,7 +7,7 @@ function replace (src, key, replaceValue) {
|
|
|
7
7
|
let output
|
|
8
8
|
let newPart = ''
|
|
9
9
|
|
|
10
|
-
const parsed = dotenvParse(src, true) // skip expanding \n
|
|
10
|
+
const parsed = dotenvParse(src, true, true) // skip expanding \n and skip converting \r\n
|
|
11
11
|
const _quotes = quotes(src)
|
|
12
12
|
if (Object.prototype.hasOwnProperty.call(parsed, key)) {
|
|
13
13
|
const quote = _quotes[key]
|