@dotenvx/dotenvx 2.23.0 → 2.24.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
CHANGED
|
@@ -2,7 +2,23 @@
|
|
|
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/v2.
|
|
5
|
+
[Unreleased](https://github.com/dotenvx/dotenvx/compare/v2.24.1...main)
|
|
6
|
+
|
|
7
|
+
## [2.24.1](https://github.com/dotenvx/dotenvx/compare/v2.24.0...v2.24.1) (2026-09-11)
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
|
|
11
|
+
* Upgraded to latest [@dotenvx/primitives](https://www.npmjs.com/package/@dotenvx/primitives)
|
|
12
|
+
|
|
13
|
+
## [2.24.0](https://github.com/dotenvx/dotenvx/compare/v2.23.0...v2.24.0) (2026-09-10)
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
|
|
17
|
+
* Do not expand nested commands ([#965](https://github.com/dotenvx/dotenvx/pull/965))
|
|
18
|
+
|
|
19
|
+
### Removed
|
|
20
|
+
|
|
21
|
+
* BREAKING: Remove the `-p` shorthand for `--plain`; use `--plain` instead
|
|
6
22
|
|
|
7
23
|
## [2.23.0](https://github.com/dotenvx/dotenvx/compare/v2.22.0...v2.23.0) (2026-08-31)
|
|
8
24
|
|
package/README.md
CHANGED
|
@@ -747,12 +747,12 @@ $ echo "HELLO=local" > .env.local
|
|
|
747
747
|
|
|
748
748
|
$ echo "HELLO=World" > .env
|
|
749
749
|
|
|
750
|
-
$ dotenvx run -f .env.local
|
|
750
|
+
$ dotenvx run -f .env.local,.env -- node index.js
|
|
751
751
|
[dotenvx@1.X.X] injecting env (1) from .env.local,.env
|
|
752
752
|
Hello local
|
|
753
753
|
```
|
|
754
754
|
|
|
755
|
-
|
|
755
|
+
Comma-separate multiple files after a single `-f`. Subsequent files do NOT override pre-existing variables defined in previous files or env. This follows historic principle. For example, above `local` wins – from the first file.
|
|
756
756
|
|
|
757
757
|
</details>
|
|
758
758
|
|
|
@@ -763,7 +763,7 @@ $ echo "HELLO=local" > .env.local
|
|
|
763
763
|
|
|
764
764
|
$ echo "HELLO=World" > .env
|
|
765
765
|
|
|
766
|
-
$ dotenvx run -f .env.local
|
|
766
|
+
$ dotenvx run -f .env.local,.env --overload -- node index.js
|
|
767
767
|
[dotenvx@1.X.X] injecting env (1) from .env.local,.env
|
|
768
768
|
Hello World
|
|
769
769
|
```
|
|
@@ -1267,7 +1267,7 @@ Hello World
|
|
|
1267
1267
|
```
|
|
1268
1268
|
|
|
1269
1269
|
</details>
|
|
1270
|
-
<details><summary>`run` - multiple
|
|
1270
|
+
<details><summary>`run -f` - multiple files</summary><br>
|
|
1271
1271
|
|
|
1272
1272
|
Compose multiple `.env` files for environment variables loading, as you need.
|
|
1273
1273
|
|
|
@@ -1276,12 +1276,12 @@ $ echo "HELLO=local" > .env.local
|
|
|
1276
1276
|
$ echo "HELLO=World" > .env
|
|
1277
1277
|
$ echo "console.log('Hello ' + process.env.HELLO)" > index.js
|
|
1278
1278
|
|
|
1279
|
-
$ dotenvx run -f .env.local
|
|
1279
|
+
$ dotenvx run -f .env.local,.env -- node index.js
|
|
1280
1280
|
[dotenvx@1.X.X] injecting env (1) from .env.local, .env
|
|
1281
1281
|
Hello local
|
|
1282
1282
|
```
|
|
1283
1283
|
|
|
1284
|
-
|
|
1284
|
+
Comma-separate multiple files after a single `-f`. Subsequent files do NOT override pre-existing variables defined in previous files or env. This follows historic principle. For example, above `local` wins – from the first file.
|
|
1285
1285
|
|
|
1286
1286
|
</details>
|
|
1287
1287
|
<details><summary>`run --env HELLO=String`</summary><br>
|
|
@@ -1371,7 +1371,7 @@ $ echo "HELLO=local" > .env.local
|
|
|
1371
1371
|
$ echo "HELLO=World" > .env
|
|
1372
1372
|
$ echo "console.log('Hello ' + process.env.HELLO)" > index.js
|
|
1373
1373
|
|
|
1374
|
-
$ dotenvx run -f .env.local
|
|
1374
|
+
$ dotenvx run -f .env.local,.env --overload -- node index.js
|
|
1375
1375
|
[dotenvx@1.X.X] injecting env (1) from .env.local, .env
|
|
1376
1376
|
Hello World
|
|
1377
1377
|
```
|
|
@@ -2833,7 +2833,7 @@ Pass multiple `.env` files to generate your `.env.example` file from the combina
|
|
|
2833
2833
|
$ echo "HELLO=World" > .env
|
|
2834
2834
|
$ echo "DB_HOST=example.com" > .env.production
|
|
2835
2835
|
|
|
2836
|
-
$ dotenvx genexample -f .env
|
|
2836
|
+
$ dotenvx genexample -f .env,.env.production
|
|
2837
2837
|
▣ generated (.env.example)
|
|
2838
2838
|
```
|
|
2839
2839
|
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "2.
|
|
2
|
+
"version": "2.24.1",
|
|
3
3
|
"name": "@dotenvx/dotenvx",
|
|
4
4
|
"description": "a secure dotenv–from the creator of `dotenv`",
|
|
5
5
|
"author": "@motdotla",
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
},
|
|
54
54
|
"funding": "https://dotenvx.com",
|
|
55
55
|
"dependencies": {
|
|
56
|
-
"@dotenvx/primitives": "^
|
|
56
|
+
"@dotenvx/primitives": "^3.0.2",
|
|
57
57
|
"@dotenvx/tooling": "^1.0.3",
|
|
58
58
|
"yocto-spinner": "^1.2.1"
|
|
59
59
|
},
|
package/src/cli/dotenvx.js
CHANGED
|
@@ -127,7 +127,7 @@ program.command('set')
|
|
|
127
127
|
.option('-f, --env-file <path>', 'path(s) to your env file(s)', collectEnvs('envFile'), [])
|
|
128
128
|
.option('-fk, --env-keys-file <path>', 'path to your .env.keys file (default: same path as your env file)')
|
|
129
129
|
.option('-c, --encrypt', 'encrypt value', true)
|
|
130
|
-
.option('
|
|
130
|
+
.option('--plain', 'store value as plain text', false)
|
|
131
131
|
.option('--no-create', 'do not create .env file(s) when missing')
|
|
132
132
|
.option('--no-armor', 'disable Dotenvx Armor features')
|
|
133
133
|
.option('--no-native', 'disable OS secret store features')
|
|
@@ -108,7 +108,7 @@ async function executeCommand (commandArgs, env, sensitiveValues = []) {
|
|
|
108
108
|
/* c8 ignore stop */
|
|
109
109
|
|
|
110
110
|
try {
|
|
111
|
-
//
|
|
111
|
+
// Expand only the executable; child arguments and separators pass through unchanged.
|
|
112
112
|
try {
|
|
113
113
|
commandArgs[0] = path.resolve(which.sync(`${commandArgs[0]}`))
|
|
114
114
|
logger.debug(`expanding process command to [${commandArgs.join(' ')}]`)
|
|
@@ -116,22 +116,6 @@ async function executeCommand (commandArgs, env, sensitiveValues = []) {
|
|
|
116
116
|
logger.debug(`could not expand process command. using [${commandArgs.join(' ')}]`)
|
|
117
117
|
}
|
|
118
118
|
|
|
119
|
-
// expand any other commands that follow a --
|
|
120
|
-
let expandNext = false
|
|
121
|
-
for (let i = 0; i < commandArgs.length; i++) {
|
|
122
|
-
if (commandArgs[i] === '--') {
|
|
123
|
-
expandNext = true
|
|
124
|
-
} else if (expandNext) {
|
|
125
|
-
try {
|
|
126
|
-
commandArgs[i] = path.resolve(which.sync(`${commandArgs[i]}`))
|
|
127
|
-
logger.debug(`expanding process command to [${commandArgs.join(' ')}]`)
|
|
128
|
-
} catch (e) {
|
|
129
|
-
logger.debug(`could not expand process command. using [${commandArgs.join(' ')}]`)
|
|
130
|
-
}
|
|
131
|
-
expandNext = false
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
119
|
const redactStdout = sensitiveValues.length > 0
|
|
136
120
|
const redactStderr = sensitiveValues.length > 0
|
|
137
121
|
const usePty = redactStdout && Boolean(
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const { parse, parseSync } = require('@dotenvx/primitives')
|
|
1
|
+
const { parse, parseSync, parsearrays } = require('@dotenvx/primitives')
|
|
2
2
|
const SERVER_SIDE_DECRYPTION_REQUIRED = 'SERVER_SIDE_DECRYPTION_REQUIRED'
|
|
3
3
|
|
|
4
4
|
function decryptOptions (error) {
|
|
@@ -27,21 +27,29 @@ function failedKeyAccessFallback (result, error) {
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
async function parseWithDecryptor (src, options = {}) {
|
|
30
|
+
return parseWith(src, options, parse)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
parseWithDecryptor.arrays = async function parsearraysWithDecryptor (src, options = {}) {
|
|
34
|
+
return parseWith(src, options, parsearrays)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
async function parseWith (src, options, parser) {
|
|
30
38
|
try {
|
|
31
|
-
return await
|
|
39
|
+
return await parser(src, options)
|
|
32
40
|
} catch (error) {
|
|
33
41
|
if (error.code !== SERVER_SIDE_DECRYPTION_REQUIRED || typeof options.decryptor !== 'function') {
|
|
34
42
|
if (typeof options.provider !== 'function') throw error
|
|
35
43
|
|
|
36
|
-
const result = await
|
|
44
|
+
const result = await parser(src, parseOptionsWithoutProvider(options))
|
|
37
45
|
return failedKeyAccessFallback(result, error)
|
|
38
46
|
}
|
|
39
47
|
|
|
40
48
|
try {
|
|
41
49
|
const result = await options.decryptor(src, decryptOptions(error))
|
|
42
|
-
return await
|
|
50
|
+
return await parser(result.src, parseOptionsWithoutProvider(options))
|
|
43
51
|
} catch (decryptorError) {
|
|
44
|
-
const result = await
|
|
52
|
+
const result = await parser(src, parseOptionsWithoutProvider(options))
|
|
45
53
|
return failedKeyAccessFallback(result, decryptorError)
|
|
46
54
|
}
|
|
47
55
|
}
|
|
@@ -44,7 +44,7 @@ async function decrypt (options = {}) {
|
|
|
44
44
|
const encoding = await detectEncoding(filepath)
|
|
45
45
|
row.envSrc = await fsx.readFileX(filepath, { encoding })
|
|
46
46
|
|
|
47
|
-
const { parsed, errors } = await parseWithDecryptor(row.envSrc, { fk, ik, ek,
|
|
47
|
+
const { parsed, errors } = await parseWithDecryptor.arrays(row.envSrc, { fk, ik, ek, provider, decryptor })
|
|
48
48
|
|
|
49
49
|
if (errors.length > 0) {
|
|
50
50
|
row.error = parseError(errors[0])
|