@dotenvx/dotenvx 1.20.0 → 1.21.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,25 @@
|
|
|
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.21.0...main)
|
|
6
|
+
|
|
7
|
+
## 1.21.0
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
|
|
11
|
+
* treat single quotes literally ([#423](https://github.com/dotenvx/dotenvx/pull/423))
|
|
12
|
+
* respect user chosen quotes ([#423](https://github.com/dotenvx/dotenvx/pull/423) [#377](https://github.com/dotenvx/dotenvx/issues/377))
|
|
13
|
+
|
|
14
|
+
🎓 now if you choose to single quote, double quote, no quote, or backtick your value it will be respected - including for encrypted values. this more intuitively handles complex cases like escaped characters, literals, and json.
|
|
15
|
+
|
|
16
|
+
## 1.20.1
|
|
17
|
+
|
|
18
|
+
### Changed
|
|
19
|
+
|
|
20
|
+
* update [eciesjs](https://github.com/ecies/js/issues/802) ([#421](https://github.com/dotenvx/dotenvx/pull/421))
|
|
21
|
+
* remove default values for ts interface - no longer permitted by latest ts ([#419](https://github.com/dotenvx/dotenvx/pull/419))
|
|
22
|
+
|
|
23
|
+
## 1.20.0
|
|
6
24
|
|
|
7
25
|
### Changed
|
|
8
26
|
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "1.
|
|
2
|
+
"version": "1.21.0",
|
|
3
3
|
"name": "@dotenvx/dotenvx",
|
|
4
4
|
"description": "a better dotenv–from the creator of `dotenv`",
|
|
5
5
|
"author": "@motdotla",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"dependencies": {
|
|
39
39
|
"commander": "^11.1.0",
|
|
40
40
|
"dotenv": "^16.4.5",
|
|
41
|
-
"eciesjs": "^0.4.
|
|
41
|
+
"eciesjs": "^0.4.10",
|
|
42
42
|
"execa": "^5.1.1",
|
|
43
43
|
"fdir": "^6.2.0",
|
|
44
44
|
"ignore": "^5.3.0",
|
|
@@ -3,6 +3,7 @@ const dotenvEval = require('./dotenvEval')
|
|
|
3
3
|
const dotenvExpand = require('./dotenvExpand')
|
|
4
4
|
const decryptValue = require('./decryptValue')
|
|
5
5
|
const truncate = require('./truncate')
|
|
6
|
+
const quotes = require('./quotes')
|
|
6
7
|
|
|
7
8
|
function warning (e, key, privateKey = null) {
|
|
8
9
|
const warning = new Error(`[${e.code}] could not decrypt ${key} using private key '${truncate(privateKey)}'`)
|
|
@@ -15,8 +16,10 @@ function warning (e, key, privateKey = null) {
|
|
|
15
16
|
function parseDecryptEvalExpand (src, privateKey = null, processEnv = process.env) {
|
|
16
17
|
const warnings = []
|
|
17
18
|
|
|
18
|
-
// parse
|
|
19
|
+
// parse and quotes
|
|
19
20
|
const parsed = dotenv.parse(src)
|
|
21
|
+
const _quotes = quotes(src)
|
|
22
|
+
const originalParsed = { ...parsed }
|
|
20
23
|
for (const key in parsed) {
|
|
21
24
|
try {
|
|
22
25
|
const decryptedValue = decryptValue(parsed[key], privateKey)
|
|
@@ -39,7 +42,13 @@ function parseDecryptEvalExpand (src, privateKey = null, processEnv = process.en
|
|
|
39
42
|
parsed: evaled
|
|
40
43
|
}
|
|
41
44
|
const expanded = dotenvExpand.expand(inputEvaled)
|
|
45
|
+
|
|
42
46
|
for (const key in expanded.parsed) {
|
|
47
|
+
// unset eval and expansion for single quotes
|
|
48
|
+
if (_quotes[key] === "'") {
|
|
49
|
+
expanded.parsed[key] = originalParsed[key] // reset to original
|
|
50
|
+
}
|
|
51
|
+
|
|
43
52
|
try {
|
|
44
53
|
const decryptedValue = decryptValue(expanded.parsed[key], privateKey)
|
|
45
54
|
expanded.parsed[key] = decryptedValue
|
|
@@ -48,6 +57,11 @@ function parseDecryptEvalExpand (src, privateKey = null, processEnv = process.en
|
|
|
48
57
|
}
|
|
49
58
|
}
|
|
50
59
|
for (const key in processEnv) {
|
|
60
|
+
// unset eval and expansion for single quotes
|
|
61
|
+
if (_quotes[key] === "'") {
|
|
62
|
+
processEnv[key] = originalParsed[key] // reset to original
|
|
63
|
+
}
|
|
64
|
+
|
|
51
65
|
try {
|
|
52
66
|
const decryptedValue = decryptValue(processEnv[key], privateKey)
|
|
53
67
|
processEnv[key] = decryptedValue
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
const LINE = /(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|\s*`(?:\\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/mg
|
|
2
|
+
|
|
3
|
+
function quotes (src) {
|
|
4
|
+
const obj = {}
|
|
5
|
+
// Convert buffer to string
|
|
6
|
+
let lines = src.toString()
|
|
7
|
+
|
|
8
|
+
// Convert line breaks to same format
|
|
9
|
+
lines = lines.replace(/\r\n?/mg, '\n')
|
|
10
|
+
|
|
11
|
+
let match
|
|
12
|
+
while ((match = LINE.exec(lines)) != null) {
|
|
13
|
+
const key = match[1]
|
|
14
|
+
|
|
15
|
+
// Default undefined or null to empty string
|
|
16
|
+
let value = (match[2] || '')
|
|
17
|
+
|
|
18
|
+
// Remove whitespace
|
|
19
|
+
value = value.trim()
|
|
20
|
+
|
|
21
|
+
// Check if double quoted
|
|
22
|
+
const maybeQuote = value[0]
|
|
23
|
+
|
|
24
|
+
value = value.replace(/^(['"`])([\s\S]*)\1$/mg, '$2')
|
|
25
|
+
|
|
26
|
+
if (maybeQuote === value[0]) {
|
|
27
|
+
obj[key] = ''
|
|
28
|
+
} else {
|
|
29
|
+
obj[key] = maybeQuote
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return obj
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
module.exports = quotes
|
|
@@ -1,28 +1,19 @@
|
|
|
1
|
-
const util = require('util')
|
|
2
1
|
const dotenv = require('dotenv')
|
|
3
2
|
|
|
3
|
+
const quotes = require('./quotes')
|
|
4
4
|
const escapeForRegex = require('./escapeForRegex')
|
|
5
5
|
const escapeDollarSigns = require('./escapeDollarSigns')
|
|
6
6
|
|
|
7
7
|
function replace (src, key, replaceValue) {
|
|
8
8
|
let output
|
|
9
|
-
let
|
|
10
|
-
|
|
11
|
-
if (replaceValue.includes('\n')) {
|
|
12
|
-
escapedValue = JSON.stringify(replaceValue) // use JSON stringify if string contains newlines
|
|
13
|
-
escapedValue = escapedValue.replace(/\\n/g, '\n') // fix up newlines
|
|
14
|
-
escapedValue = escapedValue.replace(/\\r/g, '\r')
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
// prevents test\test (and similar) from becoming test\\test and then test\\\\test, etc recursively after each encrypt/decrypt combo
|
|
18
|
-
if (replaceValue.includes('\\')) {
|
|
19
|
-
escapedValue = escapedValue.replace(/\\\\/g, '\\')
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
let newPart = `${key}=${escapedValue}`
|
|
9
|
+
let newPart = ''
|
|
23
10
|
|
|
24
11
|
const parsed = dotenv.parse(src)
|
|
12
|
+
const _quotes = quotes(src)
|
|
25
13
|
if (Object.prototype.hasOwnProperty.call(parsed, key)) {
|
|
14
|
+
const quote = _quotes[key]
|
|
15
|
+
newPart += `${key}=${quote}${replaceValue}${quote}`
|
|
16
|
+
|
|
26
17
|
const originalValue = parsed[key]
|
|
27
18
|
const escapedOriginalValue = escapeForRegex(originalValue)
|
|
28
19
|
|
|
@@ -52,6 +43,8 @@ function replace (src, key, replaceValue) {
|
|
|
52
43
|
// $2 preserves export
|
|
53
44
|
output = src.replace(currentPart, `$1$2${saferInput}`)
|
|
54
45
|
} else {
|
|
46
|
+
newPart += `${key}="${replaceValue}"`
|
|
47
|
+
|
|
55
48
|
// append
|
|
56
49
|
if (src.endsWith('\n')) {
|
|
57
50
|
newPart = newPart + '\n'
|
package/src/lib/main.d.ts
CHANGED
|
@@ -203,10 +203,10 @@ export function ls(
|
|
|
203
203
|
*/
|
|
204
204
|
export function get(
|
|
205
205
|
key?: string,
|
|
206
|
-
envs
|
|
207
|
-
overload
|
|
208
|
-
DOTENV_KEY
|
|
209
|
-
all
|
|
206
|
+
envs?: string[],
|
|
207
|
+
overload?: boolean,
|
|
208
|
+
DOTENV_KEY?: string,
|
|
209
|
+
all?: boolean
|
|
210
210
|
): Record<string, string | undefined> | string | undefined;
|
|
211
211
|
|
|
212
212
|
export type SetOutput = {
|