@dotenvx/dotenvx 1.71.0 → 1.71.2

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,19 @@
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.71.0...main)
5
+ [Unreleased](https://github.com/dotenvx/dotenvx/compare/v1.71.2...main)
6
+
7
+ ## [1.71.2](https://github.com/dotenvx/dotenvx/compare/v1.71.1...v1.71.2) (2026-06-08)
8
+
9
+ ### Changed
10
+
11
+ * touch up `get`, `set`, and `decrypt` when armor installed ([#834](https://github.com/dotenvx/dotenvx/pull/834))
12
+
13
+ ## [1.71.1](https://github.com/dotenvx/dotenvx/compare/v1.71.0...v1.71.1) (2026-06-08)
14
+
15
+ ### Changed
16
+
17
+ * stderr changed to `inherit` for dotenvx-armor integration ([#833](https://github.com/dotenvx/dotenvx/pull/833))
6
18
 
7
19
  ## [1.71.0](https://github.com/dotenvx/dotenvx/compare/v1.70.0...v1.71.0) (2026-06-01)
8
20
 
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.71.0",
2
+ "version": "1.71.2",
3
3
  "name": "@dotenvx/dotenvx",
4
4
  "description": "a secure dotenv–from the creator of `dotenv`",
5
5
  "author": "@motdotla",
@@ -21,6 +21,7 @@ async function decrypt () {
21
21
 
22
22
  // stdout - should not have a try so that exit codes can surface to stdout
23
23
  if (options.stdout) {
24
+ if (spinner) spinner.stop()
24
25
  const {
25
26
  processedEnvs
26
27
  } = await new Decrypt(envs, options.key, options.excludeKey, options.envKeysFile, noArmor).run()
@@ -41,6 +42,7 @@ async function decrypt () {
41
42
  }
42
43
  } else {
43
44
  try {
45
+ if (spinner) spinner.stop()
44
46
  const {
45
47
  processedEnvs,
46
48
  changedFilepaths,
@@ -9,32 +9,12 @@ const prompts = require('../../lib/helpers/prompts')
9
9
  const Session = require('../../db/session')
10
10
  const normalizeArmorOptions = require('./normalizeArmorOptions')
11
11
 
12
- function keypairSpinnerHooks (spinner) {
13
- let stoppedForArmor = false
14
-
15
- return {
16
- onStderr: () => {
17
- if (spinner && !stoppedForArmor) {
18
- spinner.stop()
19
- stoppedForArmor = true
20
- }
21
- },
22
- after: () => {
23
- if (spinner && stoppedForArmor) {
24
- spinner.start('encrypting')
25
- stoppedForArmor = false
26
- }
27
- }
28
- }
29
- }
30
-
31
- function keyStorageSelector (spinner) {
12
+ function keyStorageSelector () {
32
13
  let selected
33
14
 
34
15
  return async function selectKeyStorage () {
35
16
  if (selected) return selected
36
17
 
37
- if (spinner) spinner.stop()
38
18
  selected = await prompts.select({
39
19
  message: 'Choose private key storage',
40
20
  choices: [
@@ -45,19 +25,16 @@ function keyStorageSelector (spinner) {
45
25
  input: process.stdin,
46
26
  output: process.stderr
47
27
  })
48
- if (spinner) spinner.start('encrypting')
49
28
 
50
29
  return selected
51
30
  }
52
31
  }
53
32
 
54
- function encryptOptions (spinner, noArmor) {
55
- const options = {
56
- keypairHooks: keypairSpinnerHooks(spinner)
57
- }
33
+ function encryptOptions (noArmor) {
34
+ const options = {}
58
35
 
59
36
  if (!noArmor) {
60
- options.selectKeyStorage = keyStorageSelector(spinner)
37
+ options.selectKeyStorage = keyStorageSelector()
61
38
  }
62
39
 
63
40
  return options
@@ -76,9 +53,10 @@ async function encrypt () {
76
53
 
77
54
  // stdout - should not have a try so that exit codes can surface to stdout
78
55
  if (options.stdout) {
56
+ if (spinner) spinner.stop()
79
57
  const {
80
58
  processedEnvs
81
- } = await new Encrypt(envs, options.key, options.excludeKey, options.envKeysFile, noArmor, noCreate, options.token, encryptOptions(spinner, noArmor)).run()
59
+ } = await new Encrypt(envs, options.key, options.excludeKey, options.envKeysFile, noArmor, noCreate, options.token, encryptOptions(noArmor)).run()
82
60
  if (spinner) spinner.stop()
83
61
  for (const processedEnv of processedEnvs) {
84
62
  console.log(processedEnv.envSrc)
@@ -86,11 +64,12 @@ async function encrypt () {
86
64
  process.exit(0) // exit early
87
65
  } else {
88
66
  try {
67
+ if (spinner) spinner.stop()
89
68
  const {
90
69
  processedEnvs,
91
70
  changedFilepaths,
92
71
  unchangedFilepaths
93
- } = await new Encrypt(envs, options.key, options.excludeKey, options.envKeysFile, noArmor, noCreate, options.token, encryptOptions(spinner, noArmor)).run()
72
+ } = await new Encrypt(envs, options.key, options.excludeKey, options.envKeysFile, noArmor, noCreate, options.token, encryptOptions(noArmor)).run()
94
73
 
95
74
  for (const processedEnv of processedEnvs) {
96
75
  logger.verbose(`encrypting ${processedEnv.envFilepath} (${processedEnv.filepath})`)
@@ -31,6 +31,7 @@ async function get (key) {
31
31
  try {
32
32
  const sesh = new Session()
33
33
  const noArmor = options.armor === false || (await sesh.noArmor())
34
+ if (spinner) spinner.stop()
34
35
  const { parsed, errors } = await new Get(key, envs, options.overload, options.all, options.envKeysFile, noArmor).run()
35
36
 
36
37
  for (const error of errors || []) {
@@ -18,6 +18,7 @@ async function keypair (key) {
18
18
 
19
19
  const sesh = new Session()
20
20
  const noArmor = options.armor === false || await sesh.noArmor()
21
+ if (spinner) spinner.stop()
21
22
  const keypairs = await new Keypair(options.envFile, options.envKeysFile, noArmor).run()
22
23
  const results = key ? keypairs[key] : keypairs
23
24
 
@@ -20,6 +20,7 @@ async function rotate () {
20
20
 
21
21
  // stdout - should not have a try so that exit codes can surface to stdout
22
22
  if (options.stdout) {
23
+ if (spinner) spinner.stop()
23
24
  const {
24
25
  processedEnvs
25
26
  } = await new Rotate(envs, options.key, options.excludeKey, options.envKeysFile, noArmor).run()
@@ -34,6 +35,7 @@ async function rotate () {
34
35
  process.exit(0) // exit early
35
36
  } else {
36
37
  try {
38
+ if (spinner) spinner.stop()
37
39
  const {
38
40
  processedEnvs,
39
41
  changedFilepaths,
@@ -48,6 +48,7 @@ async function run () {
48
48
  envs = this.envs
49
49
  }
50
50
  envs = determine(envs, process.env)
51
+ if (spinner) spinner.stop()
51
52
 
52
53
  const {
53
54
  processedEnvs,
@@ -55,12 +56,7 @@ async function run () {
55
56
  readableFilepaths,
56
57
  uniqueInjectedKeys
57
58
  } = await new Run(envs, options.overload, process.env, options.envKeysFile, noArmor, {
58
- token: options.token,
59
- keypairHooks: {
60
- after: () => {
61
- if (spinner) spinner.start('injecting')
62
- }
63
- }
59
+ token: options.token
64
60
  }).run()
65
61
 
66
62
  for (const processedEnv of processedEnvs) {
@@ -30,6 +30,7 @@ async function set (key, value) {
30
30
  const noArmor = options.armor === false || (await sesh.noArmor())
31
31
  const noCreate = options.create === false
32
32
 
33
+ if (spinner) spinner.stop()
33
34
  const {
34
35
  processedEnvs,
35
36
  changedFilepaths,
@@ -46,9 +46,7 @@ class Armor {
46
46
  if (publicKey) args.push(publicKey)
47
47
 
48
48
  try {
49
- return JSON.parse(await this._execInteractive(binary, args, {
50
- onStderr: options.onStderr
51
- }))
49
+ return JSON.parse(await this._execInteractive(binary, args))
52
50
  } catch (_e) {
53
51
  return {}
54
52
  }
@@ -113,26 +111,17 @@ class Armor {
113
111
  return childProcess.execFileSync(binary, args).toString().trim()
114
112
  }
115
113
 
116
- _execInteractive (binary, args, options = {}) {
114
+ _execInteractive (binary, args) {
117
115
  return new Promise((resolve, reject) => {
118
116
  const spawnOptions = {
119
- stdio: ['inherit', 'pipe', 'pipe']
117
+ stdio: ['inherit', 'pipe', 'inherit']
120
118
  }
121
119
  const subprocess = childProcess.spawn(binary, args, spawnOptions)
122
120
  let stdout = ''
123
- let sawStderr = false
124
121
 
125
122
  subprocess.stdout.on('data', (data) => {
126
123
  stdout += data.toString()
127
124
  })
128
- subprocess.stderr.on('data', (data) => {
129
- if (!sawStderr) {
130
- sawStderr = true
131
- if (options.onStderr) options.onStderr()
132
- }
133
-
134
- process.stderr.write(data)
135
- })
136
125
  subprocess.on('error', reject)
137
126
  subprocess.on('close', (code) => {
138
127
  if (code !== 0) {
@@ -1,22 +1,12 @@
1
1
  const Armor = require('../../extensions/armor')
2
2
 
3
3
  async function armorKeypair (existingPublicKey, options = {}) {
4
- const hooks = options.hooks || {}
5
- if (hooks.before) await hooks.before()
6
-
7
4
  const keypairOptions = {
8
5
  token: options.token,
9
6
  envFilepath: options.envFilepath
10
7
  }
11
- if (hooks.onStderr) keypairOptions.onStderr = hooks.onStderr
12
- if (hooks.before || hooks.onStderr || hooks.after) keypairOptions.noSpinner = true
13
8
 
14
- let kp
15
- try {
16
- kp = await new Armor().keypair(existingPublicKey, keypairOptions)
17
- } finally {
18
- if (hooks.after) await hooks.after()
19
- }
9
+ const kp = await new Armor().keypair(existingPublicKey, keypairOptions)
20
10
 
21
11
  const publicKey = kp.public_key
22
12
  const privateKey = kp.private_key
@@ -4,7 +4,7 @@ const armorKeypair = require('./armorKeypair')
4
4
  const localKeypair = require('./localKeypair')
5
5
  const { keyNames } = require('../keyResolution')
6
6
 
7
- async function provision ({ envSrc, envFilepath, keysFilepath, noArmor, token, keypairHooks, selectKeyStorage }) {
7
+ async function provision ({ envSrc, envFilepath, keysFilepath, noArmor, token, selectKeyStorage }) {
8
8
  noArmor = noArmor !== false
9
9
  if (!noArmor && selectKeyStorage) {
10
10
  noArmor = await selectKeyStorage() !== 'armored'
@@ -24,7 +24,8 @@ async function provision ({ envSrc, envFilepath, keysFilepath, noArmor, token, k
24
24
  publicKey = kp.publicKey
25
25
  privateKey = kp.privateKey
26
26
  } else {
27
- const kp = await armorKeypair(undefined, { token, envFilepath, hooks: keypairHooks })
27
+ const armorOptions = { token, envFilepath }
28
+ const kp = await armorKeypair(undefined, armorOptions)
28
29
  publicKey = kp.publicKey
29
30
  privateKey = kp.privateKey
30
31
  }
@@ -73,7 +73,7 @@ async function keyValues (filepath, opts = {}) {
73
73
 
74
74
  // armor
75
75
  if (!noArmor && !privateKey && publicKey && publicKey.length > 0) {
76
- const armorOptions = { envFilepath: filepath, hooks: opts.keypairHooks }
76
+ const armorOptions = { envFilepath: filepath }
77
77
  if (opts.token) {
78
78
  armorOptions.token = opts.token
79
79
  }
@@ -37,7 +37,6 @@ class Encrypt {
37
37
  this.noArmor = noArmor
38
38
  this.noCreate = noCreate
39
39
  this.token = token
40
- this.keypairHooks = options.keypairHooks
41
40
  this.selectKeyStorage = options.selectKeyStorage
42
41
 
43
42
  this.processedEnvs = []
@@ -105,8 +104,7 @@ class Encrypt {
105
104
  const { publicKeyName, privateKeyName } = keyNames(envFilepath)
106
105
  const { publicKeyValue, privateKeyValue } = await keyValues(envFilepath, {
107
106
  keysFilepath: this.envKeysFilepath,
108
- noArmor: this.noArmor,
109
- keypairHooks: this.keypairHooks
107
+ noArmor: this.noArmor
110
108
  })
111
109
 
112
110
  // first pass - provision
@@ -117,7 +115,6 @@ class Encrypt {
117
115
  keysFilepath: this.envKeysFilepath,
118
116
  noArmor: this.noArmor,
119
117
  token: this.token,
120
- keypairHooks: this.keypairHooks,
121
118
  selectKeyStorage: this.selectKeyStorage
122
119
  })
123
120
  envSrc = prov.envSrc
@@ -25,7 +25,6 @@ class Run {
25
25
  this.noArmor = noArmor
26
26
  this.noSpinner = options.noSpinner
27
27
  this.token = options.token
28
- this.keypairHooks = options.keypairHooks
29
28
 
30
29
  this.processedEnvs = []
31
30
  this.readableFilepaths = new Set()
@@ -199,8 +198,7 @@ class Run {
199
198
  const { privateKeyValue, privateKeySource } = await keyValues(filepath, {
200
199
  keysFilepath: this.envKeysFilepath,
201
200
  noArmor: this.noArmor,
202
- token: this.token,
203
- keypairHooks: this.keypairHooks
201
+ token: this.token
204
202
  })
205
203
 
206
204
  const {