@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 +13 -1
- package/package.json +1 -1
- package/src/cli/actions/decrypt.js +2 -0
- package/src/cli/actions/encrypt.js +8 -29
- package/src/cli/actions/get.js +1 -0
- package/src/cli/actions/keypair.js +1 -0
- package/src/cli/actions/rotate.js +2 -0
- package/src/cli/actions/run.js +2 -6
- package/src/cli/actions/set.js +1 -0
- package/src/lib/extensions/armor.js +3 -14
- package/src/lib/helpers/cryptography/armorKeypair.js +1 -11
- package/src/lib/helpers/cryptography/provision.js +3 -2
- package/src/lib/helpers/keyResolution/keyValues.js +1 -1
- package/src/lib/services/encrypt.js +1 -4
- package/src/lib/services/run.js +1 -3
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.
|
|
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
|
@@ -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
|
|
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 (
|
|
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(
|
|
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(
|
|
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(
|
|
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})`)
|
package/src/cli/actions/get.js
CHANGED
|
@@ -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,
|
package/src/cli/actions/run.js
CHANGED
|
@@ -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) {
|
package/src/cli/actions/set.js
CHANGED
|
@@ -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
|
|
114
|
+
_execInteractive (binary, args) {
|
|
117
115
|
return new Promise((resolve, reject) => {
|
|
118
116
|
const spawnOptions = {
|
|
119
|
-
stdio: ['inherit', '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
|
-
|
|
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,
|
|
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
|
|
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
|
|
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
|
package/src/lib/services/run.js
CHANGED
|
@@ -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 {
|