@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.23.0...main)
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 -f .env -- node index.js
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
- Note 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.
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 -f .env --overload -- node index.js
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 `-f` flags</summary><br>
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 -f .env -- node index.js
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
- Note 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.
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 -f .env --overload -- node index.js
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 -f .env.production
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.23.0",
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": "^2.2.0",
56
+ "@dotenvx/primitives": "^3.0.2",
57
57
  "@dotenvx/tooling": "^1.0.3",
58
58
  "yocto-spinner": "^1.2.1"
59
59
  },
@@ -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('-p, --plain', 'store value as plain text', false)
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
- // ensure the first command is expanded
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 parse(src, options)
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 parse(src, parseOptionsWithoutProvider(options))
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 parse(result.src, parseOptionsWithoutProvider(options))
50
+ return await parser(result.src, parseOptionsWithoutProvider(options))
43
51
  } catch (decryptorError) {
44
- const result = await parse(src, parseOptionsWithoutProvider(options))
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, array: true, provider, decryptor })
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])