@dotenvx/dotenvx 1.71.3 → 1.73.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.
Files changed (72) hide show
  1. package/CHANGELOG.md +17 -1
  2. package/README.md +3 -3
  3. package/package.json +8 -4
  4. package/src/cli/actions/armor/down.js +37 -0
  5. package/src/cli/actions/armor/move.js +42 -0
  6. package/src/cli/actions/armor/pull.js +37 -0
  7. package/src/cli/actions/armor/push.js +37 -0
  8. package/src/cli/actions/armor/up.js +37 -0
  9. package/src/cli/actions/decrypt.js +1 -1
  10. package/src/cli/actions/encrypt.js +1 -1
  11. package/src/cli/actions/login.js +63 -0
  12. package/src/cli/actions/logout.js +36 -0
  13. package/src/cli/actions/normalizeArmorOptions.js +1 -2
  14. package/src/cli/actions/set.js +1 -1
  15. package/src/cli/commands/armor.js +72 -0
  16. package/src/cli/dotenvx.js +17 -19
  17. package/src/db/device.js +73 -0
  18. package/src/db/session.js +187 -4
  19. package/src/lib/api/getAccount.js +32 -0
  20. package/src/lib/api/postArmorDown.js +48 -0
  21. package/src/lib/api/postArmorMove.js +48 -0
  22. package/src/lib/api/postArmorPull.js +48 -0
  23. package/src/lib/api/postArmorPush.js +48 -0
  24. package/src/lib/api/postArmorUp.js +51 -0
  25. package/src/lib/api/postKeypair.js +60 -0
  26. package/src/lib/api/postLogout.js +34 -0
  27. package/src/lib/api/postOauthDeviceCode.js +38 -0
  28. package/src/lib/api/postOauthToken.js +35 -0
  29. package/src/lib/helpers/armoredKeyDisplay.js +10 -0
  30. package/src/lib/helpers/buildApiError.js +16 -0
  31. package/src/lib/helpers/buildOauthError.js +14 -0
  32. package/src/lib/helpers/createSpinner.js +1 -1
  33. package/src/lib/helpers/cryptography/armorKeypair.js +32 -11
  34. package/src/lib/helpers/cryptography/armorKeypairSync.js +48 -7
  35. package/src/lib/helpers/cryptography/provision.js +2 -2
  36. package/src/lib/helpers/cryptography/provisionSync.js +2 -2
  37. package/src/lib/helpers/decryptDeviceValue.js +10 -0
  38. package/src/lib/helpers/encryptDeviceValue.js +9 -0
  39. package/src/lib/helpers/formatCode.js +11 -0
  40. package/src/lib/helpers/http.js +7 -0
  41. package/src/lib/helpers/jsonToEnv.js +7 -0
  42. package/src/lib/helpers/keyResolution/index.js +1 -1
  43. package/src/lib/helpers/keyResolution/{keyNames.js → keyNamesForEnvFile.js} +2 -2
  44. package/src/lib/helpers/keyResolution/keyValues.js +2 -2
  45. package/src/lib/helpers/keyResolution/keyValuesSync.js +2 -2
  46. package/src/lib/helpers/keypairMetadata.js +77 -0
  47. package/src/lib/helpers/listenForOpenKey.js +46 -0
  48. package/src/lib/helpers/normalizeToken.js +5 -0
  49. package/src/lib/helpers/openUrl.js +7 -0
  50. package/src/lib/helpers/readEnvKey.js +31 -0
  51. package/src/lib/helpers/removeEnvKey.js +50 -0
  52. package/src/lib/helpers/sanitizeCommandForMetadata.js +64 -0
  53. package/src/lib/helpers/teamChoicesFromMeta.js +8 -0
  54. package/src/lib/helpers/upsertEnvKey.js +61 -0
  55. package/src/lib/main.d.ts +0 -24
  56. package/src/lib/main.js +1 -1
  57. package/src/lib/services/armorDown.js +71 -0
  58. package/src/lib/services/armorKeypair.js +156 -0
  59. package/src/lib/services/armorMove.js +54 -0
  60. package/src/lib/services/armorPull.js +71 -0
  61. package/src/lib/services/armorPush.js +76 -0
  62. package/src/lib/services/armorUp.js +73 -0
  63. package/src/lib/services/decrypt.js +2 -2
  64. package/src/lib/services/encrypt.js +2 -2
  65. package/src/lib/services/keypair.js +5 -7
  66. package/src/lib/services/login.js +26 -0
  67. package/src/lib/services/loginPoll.js +35 -0
  68. package/src/lib/services/logout.js +26 -0
  69. package/src/lib/services/rotate.js +2 -2
  70. package/src/lib/services/run.js +3 -3
  71. package/src/lib/services/sets.js +3 -3
  72. package/src/lib/extensions/armor.js +0 -204
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/v1.71.3...main)
5
+ [Unreleased](https://github.com/dotenvx/dotenvx/compare/v1.73.0...main)
6
+
7
+ ## [1.73.0](https://github.com/dotenvx/dotenvx/compare/v1.72.0...v1.73.0) (2026-06-16)
8
+
9
+ ### Added
10
+
11
+ * Add `dotenvx armor` commands directly inside dotenvx ([#839](https://github.com/dotenvx/dotenvx/pull/839))
12
+
13
+ > `dotenvx` remains local-first: `armor` commands are optional under professional security section
14
+
15
+ ## [1.72.0](https://github.com/dotenvx/dotenvx/compare/v1.71.3...v1.72.0) (2026-06-15)
16
+
17
+ ### Added
18
+
19
+ * Move `armor login` command to first class `dotenvx login` command. ([#836](https://github.com/dotenvx/dotenvx/pull/836))
20
+ * `dotenvx` remains local-first: login is optional and only needed when you want Armor features like moving keys off-device, team sharing, and audit access.
21
+ * Patch 2 high severity dependencies ([#837](https://github.com/dotenvx/dotenvx/pull/837))
6
22
 
7
23
  ## [1.71.3](https://github.com/dotenvx/dotenvx/compare/v1.71.2...v1.71.3) (2026-06-11)
8
24
 
package/README.md CHANGED
@@ -11,7 +11,7 @@
11
11
   
12
12
 
13
13
 
14
- ### Quickstart [![npm version](https://img.shields.io/npm/v/@dotenvx/dotenvx.svg)](https://www.npmjs.com/package/@dotenvx/dotenvx) [![downloads](https://img.shields.io/npm/dw/@dotenvx/dotenvx)](https://www.npmjs.com/package/@dotenvx/dotenvx) [![test suite](https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/motdotenv/bb76445765a9731e7d824a6efdf53524/raw/dotenvxTestCount.json)](https://github.com/dotenvx/dotenvx/tree/main/tests)
14
+ ### Quickstart [![npm version](https://img.shields.io/npm/v/@dotenvx/dotenvx.svg)](https://www.npmjs.com/package/@dotenvx/dotenvx) [![downloads](https://img.shields.io/npm/dw/@dotenvx/dotenvx)](https://www.npmjs.com/package/@dotenvx/dotenvx)
15
15
 
16
16
  Install and use it in code just like `dotenv`.
17
17
 
@@ -2119,8 +2119,8 @@ Commands:
2119
2119
  run inject env at runtime [dotenvx run -- yourcommand]
2120
2120
  get [KEY] return a single environment variable
2121
2121
  set <KEY> <value> set a single environment variable
2122
- encrypt convert .env file(s) to encrypted .env file(s)
2123
- decrypt convert encrypted .env file(s) to plain .env file(s)
2122
+ encrypt encrypt .env file(s)
2123
+ decrypt decrypt .env file(s)
2124
2124
  keypair [KEY] print public/private keys for .env file(s)
2125
2125
  ls [directory] print all .env files in a tree structure
2126
2126
 
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.71.3",
2
+ "version": "1.73.0",
3
3
  "name": "@dotenvx/dotenvx",
4
4
  "description": "a secure dotenv–from the creator of `dotenv`",
5
5
  "author": "@motdotla",
@@ -36,7 +36,6 @@
36
36
  "standard": "standard",
37
37
  "standard:fix": "standard --fix",
38
38
  "test": "tap run --test-env=DOTENVX_NO_ARMOR=true --allow-empty-coverage --disable-coverage --timeout=60000",
39
- "test-coverage": "tap run --test-env=DOTENVX_NO_ARMOR=true --show-full-coverage --timeout=60000",
40
39
  "testshell": "bash shellspec",
41
40
  "release:check": "npm test && npm run testshell",
42
41
  "prerelease": "npm run release:check",
@@ -45,21 +44,26 @@
45
44
  "funding": "https://dotenvx.com",
46
45
  "dependencies": {
47
46
  "commander": "^11.1.0",
47
+ "conf": "^10.2.0",
48
48
  "dotenv": "^17.2.1",
49
49
  "eciesjs": "^0.4.10",
50
50
  "enquirer": "^2.4.1",
51
+ "env-paths": "^2.2.1",
51
52
  "execa": "^5.1.1",
52
53
  "fdir": "^6.2.0",
53
54
  "ignore": "^5.3.0",
54
55
  "object-treeify": "1.1.33",
56
+ "open": "^8.4.2",
55
57
  "picomatch": "^4.0.4",
58
+ "systeminformation": "^5.22.11",
59
+ "undici": "^7.11.0",
56
60
  "which": "^4.0.0",
57
61
  "yocto-spinner": "^1.1.0"
58
62
  },
59
63
  "devDependencies": {
60
- "@yao-pkg/pkg": "^6.14.2",
64
+ "@yao-pkg/pkg": "^6.12.0",
61
65
  "capture-console": "^1.0.2",
62
- "esbuild": "^0.25.8",
66
+ "esbuild": "^0.28.1",
63
67
  "proxyquire": "^2.1.3",
64
68
  "sinon": "^14.0.1",
65
69
  "standard": "^17.1.0",
@@ -0,0 +1,37 @@
1
+ const { logger } = require('../../../shared/logger')
2
+ const Session = require('./../../../db/session')
3
+ const ArmorDown = require('./../../../lib/services/armorDown')
4
+ const createSpinner = require('../../../lib/helpers/createSpinner')
5
+ const armoredKeyDisplay = require('../../../lib/helpers/armoredKeyDisplay')
6
+
7
+ async function down () {
8
+ const options = this.opts()
9
+ const spinner = await createSpinner({ ...options, text: 'dearmoring' })
10
+
11
+ logger.debug(`options: ${JSON.stringify(options)}`)
12
+
13
+ const sesh = new Session()
14
+ await sesh.notifyUpdate()
15
+ const hostname = options.hostname || sesh.hostname()
16
+ const token = options.token || sesh.token()
17
+
18
+ try {
19
+ const devicePublicKey = sesh.devicePublicKey()
20
+
21
+ const { changed, privateKeyName, publicKeyValue } = await new ArmorDown(hostname, token, devicePublicKey, options.envFile, options.team).run()
22
+ const keyDisplay = armoredKeyDisplay(publicKeyValue) || privateKeyName
23
+
24
+ if (spinner) spinner.stop()
25
+ if (changed) {
26
+ logger.success(`◇ dearmored to .env.keys (${keyDisplay})`)
27
+ } else {
28
+ logger.info(`○ no change (${keyDisplay})`)
29
+ }
30
+ } catch (error) {
31
+ if (spinner) spinner.stop()
32
+ logger.error(error.message)
33
+ process.exit(1)
34
+ }
35
+ }
36
+
37
+ module.exports = down
@@ -0,0 +1,42 @@
1
+ const { logger } = require('../../../shared/logger')
2
+ const Session = require('./../../../db/session')
3
+ const ArmorMove = require('./../../../lib/services/armorMove')
4
+ const createSpinner = require('../../../lib/helpers/createSpinner')
5
+ const armoredKeyDisplay = require('../../../lib/helpers/armoredKeyDisplay')
6
+
7
+ async function move () {
8
+ const options = this.opts()
9
+ const spinner = await createSpinner({ ...options, text: 'moving' })
10
+
11
+ logger.debug(`options: ${JSON.stringify(options)}`)
12
+
13
+ const sesh = new Session()
14
+ await sesh.notifyUpdate()
15
+ const hostname = options.hostname || sesh.hostname()
16
+ const token = options.token || sesh.token()
17
+
18
+ try {
19
+ const devicePublicKey = sesh.devicePublicKey()
20
+
21
+ const {
22
+ changed,
23
+ privateKeyName,
24
+ publicKeyValue,
25
+ team
26
+ } = await new ArmorMove(hostname, token, devicePublicKey, options.envFile).run()
27
+ const keyDisplay = armoredKeyDisplay(publicKeyValue) || privateKeyName
28
+
29
+ if (spinner) spinner.stop()
30
+ if (changed) {
31
+ logger.success(`⛨ moved to ${team} (${keyDisplay})`)
32
+ } else {
33
+ logger.info(`○ no change (${keyDisplay})`)
34
+ }
35
+ } catch (error) {
36
+ if (spinner) spinner.stop()
37
+ logger.error(error.message)
38
+ process.exit(1)
39
+ }
40
+ }
41
+
42
+ module.exports = move
@@ -0,0 +1,37 @@
1
+ const { logger } = require('../../../shared/logger')
2
+ const Session = require('./../../../db/session')
3
+ const ArmorPull = require('./../../../lib/services/armorPull')
4
+ const createSpinner = require('../../../lib/helpers/createSpinner')
5
+ const armoredKeyDisplay = require('../../../lib/helpers/armoredKeyDisplay')
6
+
7
+ async function pull () {
8
+ const options = this.opts()
9
+ const spinner = await createSpinner({ ...options, text: 'pulling' })
10
+
11
+ logger.debug(`options: ${JSON.stringify(options)}`)
12
+
13
+ const sesh = new Session()
14
+ await sesh.notifyUpdate()
15
+ const hostname = options.hostname || sesh.hostname()
16
+ const token = options.token || sesh.token()
17
+
18
+ try {
19
+ const devicePublicKey = sesh.devicePublicKey()
20
+
21
+ const { changed, privateKeyName, publicKeyValue } = await new ArmorPull(hostname, token, devicePublicKey, options.envFile, options.team).run()
22
+ const keyDisplay = armoredKeyDisplay(publicKeyValue) || privateKeyName
23
+
24
+ if (spinner) spinner.stop()
25
+ if (changed) {
26
+ logger.success(`◇ pulled to .env.keys (${keyDisplay})`)
27
+ } else {
28
+ logger.info(`○ no change (${keyDisplay})`)
29
+ }
30
+ } catch (error) {
31
+ if (spinner) spinner.stop()
32
+ logger.error(error.message)
33
+ process.exit(1)
34
+ }
35
+ }
36
+
37
+ module.exports = pull
@@ -0,0 +1,37 @@
1
+ const { logger } = require('../../../shared/logger')
2
+ const Session = require('./../../../db/session')
3
+ const ArmorPush = require('./../../../lib/services/armorPush')
4
+ const createSpinner = require('../../../lib/helpers/createSpinner')
5
+ const armoredKeyDisplay = require('../../../lib/helpers/armoredKeyDisplay')
6
+
7
+ async function push () {
8
+ const options = this.opts()
9
+ const spinner = await createSpinner({ ...options, text: 'pushing' })
10
+
11
+ logger.debug(`options: ${JSON.stringify(options)}`)
12
+
13
+ const sesh = new Session()
14
+ await sesh.notifyUpdate()
15
+ const hostname = options.hostname || sesh.hostname()
16
+ const token = options.token || sesh.token()
17
+
18
+ try {
19
+ const devicePublicKey = sesh.devicePublicKey()
20
+
21
+ const { changed, privateKeyName, publicKeyValue } = await new ArmorPush(hostname, token, devicePublicKey, options.envFile, options.team).run()
22
+ const keyDisplay = armoredKeyDisplay(publicKeyValue) || privateKeyName
23
+
24
+ if (spinner) spinner.stop()
25
+ if (changed) {
26
+ logger.success(`⛨ pushed (${keyDisplay})`)
27
+ } else {
28
+ logger.info(`○ no change (${keyDisplay})`)
29
+ }
30
+ } catch (error) {
31
+ if (spinner) spinner.stop()
32
+ logger.error(error.message)
33
+ process.exit(1)
34
+ }
35
+ }
36
+
37
+ module.exports = push
@@ -0,0 +1,37 @@
1
+ const { logger } = require('../../../shared/logger')
2
+ const Session = require('./../../../db/session')
3
+ const ArmorUp = require('./../../../lib/services/armorUp')
4
+ const createSpinner = require('../../../lib/helpers/createSpinner')
5
+ const armoredKeyDisplay = require('../../../lib/helpers/armoredKeyDisplay')
6
+
7
+ async function up () {
8
+ const options = this.opts()
9
+ const spinner = await createSpinner({ ...options, text: 'armoring' })
10
+
11
+ logger.debug(`options: ${JSON.stringify(options)}`)
12
+
13
+ const sesh = new Session()
14
+ await sesh.notifyUpdate()
15
+ const hostname = options.hostname || sesh.hostname()
16
+ const token = options.token || sesh.token()
17
+
18
+ try {
19
+ const devicePublicKey = sesh.devicePublicKey()
20
+
21
+ const { changed, privateKeyName, publicKeyValue } = await new ArmorUp(hostname, token, devicePublicKey, options.envFile, options.team).run()
22
+ const keyDisplay = armoredKeyDisplay(publicKeyValue) || privateKeyName
23
+
24
+ if (spinner) spinner.stop()
25
+ if (changed) {
26
+ logger.success(`⛨ armored (${keyDisplay})`)
27
+ } else {
28
+ logger.info(`○ no change (${keyDisplay})`)
29
+ }
30
+ } catch (error) {
31
+ if (spinner) spinner.stop()
32
+ logger.error(error.message)
33
+ process.exit(1)
34
+ }
35
+ }
36
+
37
+ module.exports = up
@@ -13,8 +13,8 @@ async function decrypt () {
13
13
 
14
14
  logger.debug(`options: ${JSON.stringify(options)}`)
15
15
 
16
- const sesh = new Session()
17
16
  const envs = this.envs
17
+ const sesh = new Session()
18
18
  const noArmor = options.armor === false || (await sesh.noArmor())
19
19
 
20
20
  let errorCount = 0
@@ -46,8 +46,8 @@ async function encrypt () {
46
46
 
47
47
  logger.debug(`options: ${JSON.stringify(options)}`)
48
48
 
49
- const sesh = new Session()
50
49
  const envs = this.envs
50
+ const sesh = new Session()
51
51
  const noArmor = options.armor === false || (!options.token && (await sesh.noArmor()))
52
52
  const noCreate = options.create === false
53
53
 
@@ -0,0 +1,63 @@
1
+ const { logger } = require('../../shared/logger')
2
+
3
+ const Session = require('../../db/session')
4
+ const Login = require('../../lib/services/login')
5
+ const LoginPoll = require('../../lib/services/loginPoll')
6
+
7
+ const createSpinner = require('../../lib/helpers/createSpinner')
8
+ const formatCode = require('../../lib/helpers/formatCode')
9
+ const listenForOpenKey = require('../../lib/helpers/listenForOpenKey')
10
+ const openUrl = require('../../lib/helpers/openUrl')
11
+
12
+ const FRAMES = ['◐', '◓', '◑', '◒']
13
+
14
+ async function login () {
15
+ const options = this.opts()
16
+ const spinner = await createSpinner({ ...options, text: 'logging in', frames: FRAMES })
17
+
18
+ logger.debug(`options: ${JSON.stringify(options)}`)
19
+
20
+ const sesh = new Session()
21
+ await sesh.notifyUpdate()
22
+ const hostname = options.hostname || sesh.hostname()
23
+ let cleanupOpenKeyListener = () => {}
24
+
25
+ try {
26
+ const {
27
+ deviceCode,
28
+ userCode,
29
+ verificationUri,
30
+ verificationUriComplete,
31
+ interval
32
+ } = await new Login(hostname).run()
33
+
34
+ const promptMessage = `◌ press Enter to open [${verificationUri}] and enter code [${formatCode(userCode)}]...`
35
+
36
+ logger.debug(`POST ${hostname} with deviceCode ${deviceCode} at interval ${interval}`)
37
+ logger.info(promptMessage)
38
+
39
+ // begin polling
40
+ const pollPromise = new LoginPoll(hostname, deviceCode, interval).run()
41
+ cleanupOpenKeyListener = listenForOpenKey(() => openUrl(verificationUriComplete))
42
+ const data = await pollPromise
43
+
44
+ cleanupOpenKeyListener()
45
+ if (spinner) spinner.stop()
46
+ logger.success(`◉ logged in (${data.username})`)
47
+ process.exit(0)
48
+ } catch (error) {
49
+ cleanupOpenKeyListener()
50
+ if (spinner) spinner.stop()
51
+ if (error.message) {
52
+ logger.error(error.message)
53
+ } else {
54
+ logger.error(error)
55
+ }
56
+ if (error.stack) {
57
+ logger.debug(error.stack)
58
+ }
59
+ process.exit(1)
60
+ }
61
+ }
62
+
63
+ module.exports = login
@@ -0,0 +1,36 @@
1
+ const { logger } = require('../../shared/logger')
2
+
3
+ const Session = require('../../db/session')
4
+ const Logout = require('../../lib/services/logout')
5
+ const createSpinner = require('../../lib/helpers/createSpinner')
6
+
7
+ const FRAMES = ['◐', '◓', '◑', '◒']
8
+
9
+ async function logout () {
10
+ const options = this.opts()
11
+ const spinner = await createSpinner({ ...options, text: 'logging out', frames: FRAMES })
12
+
13
+ logger.debug(`options: ${JSON.stringify(options)}`)
14
+
15
+ const sesh = new Session()
16
+ const hostname = options.hostname || sesh.hostname()
17
+
18
+ try {
19
+ const data = await new Logout(hostname).run()
20
+ if (spinner) spinner.stop()
21
+ logger.success(`◌ logged out (${data.username})`)
22
+ } catch (error) {
23
+ if (spinner) spinner.stop()
24
+ if (error.message) {
25
+ logger.error(error.message)
26
+ } else {
27
+ logger.error(error)
28
+ }
29
+ if (error.stack) {
30
+ logger.debug(error.stack)
31
+ }
32
+ process.exit(1)
33
+ }
34
+ }
35
+
36
+ module.exports = logout
@@ -1,8 +1,7 @@
1
1
  function normalizeArmorOptions (options) {
2
- if (options.armor === false || options.ops === false || options.vlt === false) {
2
+ if (options.armor === false || options.ops === false) {
3
3
  options.armor = false
4
4
  options.ops = false
5
- options.vlt = false
6
5
  }
7
6
 
8
7
  return options
@@ -24,9 +24,9 @@ async function set (key, value) {
24
24
  logger.debug(`options: ${JSON.stringify(options)}`)
25
25
 
26
26
  try {
27
- const sesh = new Session()
28
27
  const envs = this.envs
29
28
  const envKeysFilepath = options.envKeysFile
29
+ const sesh = new Session()
30
30
  const noArmor = options.armor === false || (await sesh.noArmor())
31
31
  const noCreate = options.create === false
32
32
 
@@ -0,0 +1,72 @@
1
+ const Session = require('./../../db/session')
2
+ const executeDynamic = require('./../../lib/helpers/executeDynamic')
3
+
4
+ function configureArmorCommand (armor) {
5
+ armor
6
+ .description('move private keys off-device')
7
+ .allowUnknownOption()
8
+ .argument('[command]', 'dotenvx-armor command')
9
+ .argument('[args...]', 'dotenvx-armor command arguments')
10
+ .action(async function (command, args) {
11
+ if (command) {
12
+ return executeDynamic(armor, 'armor', [command, ...(args || [])])
13
+ }
14
+
15
+ const sesh = new Session()
16
+ await sesh.notifyUpdate()
17
+ this.help()
18
+ })
19
+
20
+ // dotenvx armor up
21
+ const upAction = require('./../actions/armor/up')
22
+ armor
23
+ .command('up')
24
+ .description('armor key')
25
+ .option('-f, --env-file <path>', 'path to your env file')
26
+ .option('--token <token>', 'set token')
27
+ .option('--team <team>', 'team to armor private key for')
28
+ .action(upAction)
29
+
30
+ // dotenvx armor down
31
+ const downAction = require('./../actions/armor/down')
32
+ armor
33
+ .command('down')
34
+ .description('dearmor key')
35
+ .option('-f, --env-file <path>', 'path to your env file')
36
+ .option('--token <token>', 'set token')
37
+ .option('--team <team>', 'team to dearmor private key from')
38
+ .action(downAction)
39
+
40
+ // dotenvx armor push
41
+ const pushAction = require('./../actions/armor/push')
42
+ armor
43
+ .command('push')
44
+ .description('push armored key (from .env.keys)')
45
+ .option('-f, --env-file <path>', 'path to your env file')
46
+ .option('--token <token>', 'set token')
47
+ .option('--team <team>', 'team to push armored private key for')
48
+ .action(pushAction)
49
+
50
+ // dotenvx armor pull
51
+ const pullAction = require('./../actions/armor/pull')
52
+ armor
53
+ .command('pull')
54
+ .description('pull armored key (into .env.keys)')
55
+ .option('-f, --env-file <path>', 'path to your env file')
56
+ .option('--token <token>', 'set token')
57
+ .option('--team <team>', 'team to pull armored private key from')
58
+ .action(pullAction)
59
+
60
+ // dotenvx armor move
61
+ const moveAction = require('./../actions/armor/move')
62
+ armor
63
+ .command('move')
64
+ .description('move armored key (to other team)')
65
+ .option('-f, --env-file <path>', 'path to your env file')
66
+ .option('--token <token>', 'set token')
67
+ .action(moveAction)
68
+
69
+ return armor
70
+ }
71
+
72
+ module.exports = configureArmorCommand
@@ -72,7 +72,6 @@ program.command('run')
72
72
  .option('--ignore <errorCodes...>', 'error code(s) to ignore (example: --ignore=MISSING_ENV_FILE)')
73
73
  .option('--token <token>', 'set Armor ⛨ token')
74
74
  .option('--no-armor', 'disable dotenvx-armor features')
75
- .addOption(new Option('--no-vlt', 'disable dotenvx-vlt features (deprecated. use --no-armor)').hideHelp())
76
75
  .addOption(new Option('--no-ops', 'disable dotenvx-ops features (deprecated. use --no-armor)').hideHelp())
77
76
  .action(function (...args) {
78
77
  this.envs = envs
@@ -96,7 +95,6 @@ program.command('get')
96
95
  .option('--pp', 'pretty print output (alias)')
97
96
  .option('--format <type>', 'format of the output (json, shell, colon, eval)', 'json')
98
97
  .option('--no-armor', 'disable dotenvx-armor features')
99
- .addOption(new Option('--no-vlt', 'disable dotenvx-vlt features (deprecated. use --no-armor)').hideHelp())
100
98
  .addOption(new Option('--no-ops', 'disable dotenvx-ops features (deprecated. use --no-armor)').hideHelp())
101
99
  .action(function (...args) {
102
100
  this.envs = envs
@@ -117,7 +115,6 @@ program.command('set')
117
115
  .option('-p, --plain', 'store value as plain text', false)
118
116
  .option('--no-create', 'do not create .env file(s) when missing')
119
117
  .option('--no-armor', 'disable dotenvx-armor features')
120
- .addOption(new Option('--no-vlt', 'disable dotenvx-vlt features (deprecated. use --no-armor)').hideHelp())
121
118
  .addOption(new Option('--no-ops', 'disable dotenvx-ops features (deprecated. use --no-armor)').hideHelp())
122
119
  .action(function (...args) {
123
120
  this.envs = envs
@@ -126,7 +123,7 @@ program.command('set')
126
123
 
127
124
  // dotenvx encrypt
128
125
  program.command('encrypt')
129
- .description('convert .env file(s) to encrypted .env file(s)')
126
+ .description('encrypt .env file(s)')
130
127
  .option('-f, --env-file <paths...>', 'path(s) to your env file(s)', collectEnvs('envFile'), [])
131
128
  .option('-fk, --env-keys-file <path>', 'path to your .env.keys file (default: same path as your env file)')
132
129
  .option('-k, --key <keys...>', 'keys(s) to encrypt (default: all keys in file)')
@@ -135,7 +132,6 @@ program.command('encrypt')
135
132
  .option('--token <token>', 'set Armor ⛨ token')
136
133
  .option('--no-create', 'do not create .env file(s) when missing')
137
134
  .option('--no-armor', 'disable dotenvx-armor features')
138
- .addOption(new Option('--no-vlt', 'disable dotenvx-vlt features (deprecated. use --no-armor)').hideHelp())
139
135
  .addOption(new Option('--no-ops', 'disable dotenvx-ops features (deprecated. use --no-armor)').hideHelp())
140
136
  .action(function (...args) {
141
137
  this.envs = envs
@@ -144,13 +140,12 @@ program.command('encrypt')
144
140
 
145
141
  // dotenvx decrypt
146
142
  program.command('decrypt')
147
- .description('convert encrypted .env file(s) to plain .env file(s)')
143
+ .description('decrypt .env file(s)')
148
144
  .option('-f, --env-file <paths...>', 'path(s) to your env file(s)', collectEnvs('envFile'), [])
149
145
  .option('-fk, --env-keys-file <path>', 'path to your .env.keys file (default: same path as your env file)')
150
146
  .option('-k, --key <keys...>', 'keys(s) to decrypt (default: all keys in file)')
151
147
  .option('-ek, --exclude-key <excludeKeys...>', 'keys(s) to exclude from decryption (default: none)')
152
148
  .option('--no-armor', 'disable dotenvx-armor features')
153
- .addOption(new Option('--no-vlt', 'disable dotenvx-vlt features (deprecated. use --no-armor)').hideHelp())
154
149
  .addOption(new Option('--no-ops', 'disable dotenvx-ops features (deprecated. use --no-armor)').hideHelp())
155
150
  .option('--stdout', 'send to stdout')
156
151
  .action(function (...args) {
@@ -166,7 +161,6 @@ program.command('rotate')
166
161
  .option('-k, --key <keys...>', 'keys(s) to encrypt (default: all keys in file)')
167
162
  .option('-ek, --exclude-key <excludeKeys...>', 'keys(s) to exclude from encryption (default: none)')
168
163
  .option('--no-armor', 'disable dotenvx-armor features')
169
- .addOption(new Option('--no-vlt', 'disable dotenvx-vlt features (deprecated. use --no-armor)').hideHelp())
170
164
  .addOption(new Option('--no-ops', 'disable dotenvx-ops features (deprecated. use --no-armor)').hideHelp())
171
165
  .option('--stdout', 'send to stdout')
172
166
  .action(function (...args) {
@@ -182,7 +176,6 @@ program.command('keypair')
182
176
  .option('-f, --env-file <paths...>', 'path(s) to your env file(s)')
183
177
  .option('-fk, --env-keys-file <path>', 'path to your .env.keys file (default: same path as your env file)')
184
178
  .option('--no-armor', 'disable dotenvx-armor features')
185
- .addOption(new Option('--no-vlt', 'disable dotenvx-vlt features (deprecated. use --no-armor)').hideHelp())
186
179
  .addOption(new Option('--no-ops', 'disable dotenvx-ops features (deprecated. use --no-armor)').hideHelp())
187
180
  .option('-pp, --pretty-print', 'pretty print output')
188
181
  .option('--pp', 'pretty print output (alias)')
@@ -211,20 +204,20 @@ program.command('doctor', { hidden: true })
211
204
 
212
205
  // dotenvx login
213
206
  program.command('login', { hidden: true })
214
- .description('')
207
+ .description('log in to move keys off-device, share with your team, and audit access')
215
208
  .allowUnknownOption()
216
- .action(() => {
217
- const rawArgs = ['armor', 'login', ...process.argv.slice(3)]
218
- executeDynamic(program, 'armor', rawArgs)
209
+ .option('--hostname <hostname>', 'set Armor ⛨ hostname')
210
+ .action(function (...args) {
211
+ return require('./actions/login').apply(this, args)
219
212
  })
220
213
 
221
214
  // dotenvx logout
222
215
  program.command('logout', { hidden: true })
223
- .description('log out of your dotenvx account')
216
+ .description('log out of connected security features')
224
217
  .allowUnknownOption()
225
- .action(() => {
226
- const rawArgs = ['armor', 'logout', ...process.argv.slice(3)]
227
- executeDynamic(program, 'armor', rawArgs)
218
+ .option('--hostname <hostname>', 'set Armor ⛨ hostname')
219
+ .action(function (...args) {
220
+ return require('./actions/logout').apply(this, args)
228
221
  })
229
222
 
230
223
  // dotenvx help
@@ -245,10 +238,15 @@ program.command('help [command]')
245
238
 
246
239
  // dotenvx armor
247
240
  program.addHelpText('after', ' ')
248
- program.addHelpText('after', 'Advanced: ')
249
- program.addHelpText('after', ' armor ARMORED KEYS [www.dotenvx.com/armor]')
241
+ program.addHelpText('after', 'Professional Security: ')
242
+ program.addHelpText('after', ' login log in to move keys off-device, share with your team, and audit access')
243
+ program.addHelpText('after', ' logout log out of connected security features')
244
+ program.addHelpText('after', ' armor ⛨ move private keys off-device [www.dotenvx.com/armor]')
250
245
  program.addHelpText('after', ' ext ⊕ extensions')
251
246
 
247
+ // dotenvx armor
248
+ require('./commands/armor')(program.command('armor', { hidden: true }))
249
+
252
250
  // dotenvx ext
253
251
  program.addCommand(require('./commands/ext'))
254
252