@dotenvx/dotenvx 1.75.1 → 2.0.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 (85) hide show
  1. package/CHANGELOG.md +24 -1
  2. package/README.md +4 -114
  3. package/package.json +8 -7
  4. package/src/cli/actions/decrypt.js +35 -17
  5. package/src/cli/actions/doctor.js +2 -2
  6. package/src/cli/actions/encrypt.js +64 -85
  7. package/src/cli/actions/ext/genexample.js +2 -2
  8. package/src/cli/actions/get.js +16 -7
  9. package/src/cli/actions/keypair.js +55 -42
  10. package/src/cli/actions/login.js +4 -3
  11. package/src/cli/actions/normalizeArmorAliases.js +9 -0
  12. package/src/cli/actions/run.js +65 -22
  13. package/src/cli/actions/set.js +51 -37
  14. package/src/cli/dotenvx.js +6 -21
  15. package/src/lib/api/{postKeypair.js → postArmorKeyring.js} +4 -14
  16. package/src/lib/{helpers/envResolution → conventions}/environment.js +1 -1
  17. package/src/lib/conventions/filepaths.js +9 -0
  18. package/src/lib/conventions/keynames.js +38 -0
  19. package/src/lib/helpers/catchAndLog.js +4 -1
  20. package/src/lib/helpers/cryptography/index.js +0 -8
  21. package/src/lib/helpers/cryptography/mutateKeysSrc.js +5 -21
  22. package/src/lib/helpers/envResolution/index.js +1 -1
  23. package/src/lib/helpers/errors.js +13 -0
  24. package/src/lib/helpers/keypairMetadata.js +1 -1
  25. package/src/lib/main.d.ts +2 -39
  26. package/src/lib/main.js +82 -45
  27. package/src/lib/providers/armor/index.js +29 -0
  28. package/src/lib/providers/index.js +46 -0
  29. package/src/lib/providers/worker.js +6 -0
  30. package/src/lib/resolvers/envs.js +302 -0
  31. package/src/lib/resolvers/get.js +69 -0
  32. package/src/lib/resolvers/keypair.js +81 -0
  33. package/src/lib/resolvers/ls.js +41 -0
  34. package/src/lib/services/armorDown.js +2 -2
  35. package/src/lib/services/{armorKeypair.js → armorKeyring.js} +14 -51
  36. package/src/lib/services/armorMove.js +2 -2
  37. package/src/lib/services/armorPull.js +2 -2
  38. package/src/lib/services/armorPush.js +2 -2
  39. package/src/lib/services/armorUp.js +2 -2
  40. package/src/lib/services/genexample.js +5 -6
  41. package/src/lib/services/login.js +25 -0
  42. package/src/lib/services/prebuild.js +9 -3
  43. package/src/lib/services/precommit.js +9 -3
  44. package/src/lib/transforms/decrypt.js +83 -0
  45. package/src/lib/transforms/encrypt.js +179 -0
  46. package/src/lib/transforms/set.js +179 -0
  47. package/src/shared/logger.js +5 -0
  48. package/src/cli/actions/normalizeArmorOptions.js +0 -10
  49. package/src/cli/actions/rotate.js +0 -87
  50. package/src/lib/helpers/append.js +0 -62
  51. package/src/lib/helpers/cryptography/armorKeypair.js +0 -42
  52. package/src/lib/helpers/cryptography/armorKeypairSync.js +0 -55
  53. package/src/lib/helpers/cryptography/encryptValue.js +0 -7
  54. package/src/lib/helpers/cryptography/localKeypair.js +0 -14
  55. package/src/lib/helpers/cryptography/mutateKeysSrcSync.js +0 -38
  56. package/src/lib/helpers/cryptography/provision.js +0 -56
  57. package/src/lib/helpers/cryptography/provisionSync.js +0 -51
  58. package/src/lib/helpers/cryptography/provisionWithPrivateKey.js +0 -26
  59. package/src/lib/helpers/escapeDollarSigns.js +0 -5
  60. package/src/lib/helpers/escapeForRegex.js +0 -5
  61. package/src/lib/helpers/evalKeyValue.js +0 -23
  62. package/src/lib/helpers/isIgnoringDotenvKeys.js +0 -19
  63. package/src/lib/helpers/keyResolution/index.js +0 -16
  64. package/src/lib/helpers/keyResolution/keyNamesForEnvFile.js +0 -24
  65. package/src/lib/helpers/keyResolution/keyValues.js +0 -99
  66. package/src/lib/helpers/keyResolution/keyValuesFromEnvSrc.js +0 -85
  67. package/src/lib/helpers/keyResolution/keyValuesSync.js +0 -103
  68. package/src/lib/helpers/keyResolution/readFileKey.js +0 -19
  69. package/src/lib/helpers/keyResolution/readFileKeySync.js +0 -17
  70. package/src/lib/helpers/keyResolution/readProcessKey.js +0 -7
  71. package/src/lib/helpers/localDisplayPath.js +0 -11
  72. package/src/lib/helpers/parse.js +0 -214
  73. package/src/lib/helpers/pluralize.js +0 -10
  74. package/src/lib/helpers/quotes.js +0 -36
  75. package/src/lib/helpers/replace.js +0 -82
  76. package/src/lib/helpers/resolveEscapeSequences.js +0 -5
  77. package/src/lib/services/decrypt.js +0 -156
  78. package/src/lib/services/encrypt.js +0 -213
  79. package/src/lib/services/get.js +0 -76
  80. package/src/lib/services/keypair.js +0 -60
  81. package/src/lib/services/loginPoll.js +0 -36
  82. package/src/lib/services/ls.js +0 -57
  83. package/src/lib/services/rotate.js +0 -197
  84. package/src/lib/services/run.js +0 -255
  85. package/src/lib/services/sets.js +0 -328
@@ -1,12 +1,12 @@
1
1
  const { logger } = require('./../../shared/logger')
2
2
 
3
- const Keypair = require('./../../lib/services/keypair')
3
+ const keypairResolver = require('./../../lib/resolvers/keypair')
4
+ const catchAndLog = require('./../../lib/helpers/catchAndLog')
4
5
  const createSpinner = require('../../lib/helpers/createSpinner')
5
- const Session = require('../../db/session')
6
- const normalizeArmorOptions = require('./normalizeArmorOptions')
6
+ const normalizeArmorAliases = require('./normalizeArmorAliases')
7
7
 
8
8
  async function keypair (key) {
9
- const options = normalizeArmorOptions(this.opts())
9
+ const options = normalizeArmorAliases(this.opts())
10
10
  const spinner = await createSpinner({ ...options, text: 'retrieving' })
11
11
 
12
12
  logger.debug(`options: ${JSON.stringify(options)}`)
@@ -16,50 +16,63 @@ async function keypair (key) {
16
16
 
17
17
  const prettyPrint = options.prettyPrint || options.pp
18
18
 
19
- const sesh = new Session()
20
- const noArmor = options.armor === false || await sesh.noArmor()
21
- if (spinner) spinner.stop()
22
- const keypairs = await new Keypair(options.envFile, options.envKeysFile, noArmor, {
23
- command: process.argv.slice(2)
24
- }).run()
25
- const results = key ? keypairs[key] : keypairs
26
-
27
- if (spinner) spinner.stop()
28
- if (typeof results === 'object' && results !== null) {
29
- if (options.format === 'shell') {
30
- let inline = ''
31
- for (const [keyName, value] of Object.entries(results)) {
32
- inline += `${keyName}=${value || ''} `
19
+ try {
20
+ const keypairs = await keypairResolver({
21
+ envFile: options.envFile,
22
+ envKeysFile: options.envKeysFile,
23
+ armor: options.armor,
24
+ token: options.token,
25
+ command: process.argv.slice(2),
26
+ onStatus: (text) => {
27
+ if (spinner && text) {
28
+ spinner.text = text
29
+ }
33
30
  }
34
- inline = inline.trim()
31
+ })
35
32
 
36
- console.log(inline)
37
- } else if (options.format === 'colon') {
38
- let inline = ''
39
- for (const [keyName, value] of Object.entries(results)) {
40
- inline += `${keyName}:${value || ''} `
41
- }
42
- inline = inline.trim()
33
+ const results = key ? keypairs[key] : keypairs
43
34
 
44
- console.log(inline)
45
- // json format
46
- } else {
47
- let space = 0
48
- if (prettyPrint) {
49
- space = 2
50
- }
35
+ if (spinner) spinner.stop()
36
+ if (typeof results === 'object' && results !== null) {
37
+ if (options.format === 'shell') {
38
+ let inline = ''
39
+ for (const [keyName, value] of Object.entries(results)) {
40
+ inline += `${keyName}=${value || ''} `
41
+ }
42
+ inline = inline.trim()
51
43
 
52
- console.log(JSON.stringify(results, null, space))
53
- }
54
- } else {
55
- if (results === undefined) {
56
- console.log('')
57
- process.exit(1)
58
- } else if (options.format === 'colon' && key) {
59
- console.log(`${key}:${results}`)
44
+ console.log(inline)
45
+ } else if (options.format === 'colon') {
46
+ let inline = ''
47
+ for (const [keyName, value] of Object.entries(results)) {
48
+ inline += `${keyName}:${value || ''} `
49
+ }
50
+ inline = inline.trim()
51
+
52
+ console.log(inline)
53
+ // json format
54
+ } else {
55
+ let space = 0
56
+ if (prettyPrint) {
57
+ space = 2
58
+ }
59
+
60
+ console.log(JSON.stringify(results, null, space))
61
+ }
60
62
  } else {
61
- console.log(results)
63
+ if (results === undefined) {
64
+ console.log('')
65
+ process.exit(1)
66
+ } else if (options.format === 'colon' && key) {
67
+ console.log(`${key}:${results}`)
68
+ } else {
69
+ console.log(results)
70
+ }
62
71
  }
72
+ } catch (error) {
73
+ if (spinner) spinner.stop()
74
+ catchAndLog(error)
75
+ process.exit(1)
63
76
  }
64
77
  }
65
78
 
@@ -2,7 +2,6 @@ const { logger } = require('../../shared/logger')
2
2
 
3
3
  const Session = require('../../db/session')
4
4
  const Login = require('../../lib/services/login')
5
- const LoginPoll = require('../../lib/services/loginPoll')
6
5
 
7
6
  const createSpinner = require('../../lib/helpers/createSpinner')
8
7
  const formatCode = require('../../lib/helpers/formatCode')
@@ -20,15 +19,17 @@ async function login () {
20
19
  const sesh = new Session()
21
20
  const hostname = options.hostname || sesh.hostname()
22
21
  let cleanupOpenKeyListener = () => {}
22
+ let loginService
23
23
 
24
24
  try {
25
+ loginService = new Login(hostname)
25
26
  const {
26
27
  deviceCode,
27
28
  userCode,
28
29
  verificationUri,
29
30
  verificationUriComplete,
30
31
  interval
31
- } = await new Login(hostname).run()
32
+ } = await loginService.run()
32
33
 
33
34
  const promptMessage = `◌ press Enter to open [${verificationUri}] and enter code [${formatCode(userCode)}]...`
34
35
 
@@ -36,7 +37,7 @@ async function login () {
36
37
  logger.info(promptMessage)
37
38
 
38
39
  // begin polling
39
- const pollPromise = new LoginPoll(hostname, deviceCode, interval).run()
40
+ const pollPromise = loginService.poll(deviceCode, interval)
40
41
  cleanupOpenKeyListener = listenForOpenKey(() => openUrl(verificationUriComplete))
41
42
  const data = await pollPromise
42
43
 
@@ -0,0 +1,9 @@
1
+ function normalizeArmorAliases (options) {
2
+ if (options.ops === false) {
3
+ options.armor = false
4
+ }
5
+
6
+ return options
7
+ }
8
+
9
+ module.exports = normalizeArmorAliases
@@ -2,18 +2,56 @@ const path = require('path')
2
2
  const { logger } = require('./../../shared/logger')
3
3
 
4
4
  const executeCommand = require('./../../lib/helpers/executeCommand')
5
- const Run = require('./../../lib/services/run')
5
+ const envsResolver = require('./../../lib/resolvers/envs')
6
6
  const catchAndLog = require('./../../lib/helpers/catchAndLog')
7
7
  const createSpinner = require('../../lib/helpers/createSpinner')
8
8
  const Session = require('../../db/session')
9
- const normalizeArmorOptions = require('./normalizeArmorOptions')
9
+ const normalizeArmorAliases = require('./normalizeArmorAliases')
10
10
 
11
11
  const conventions = require('./../../lib/helpers/conventions')
12
12
  const { determine } = require('./../../lib/helpers/envResolution')
13
13
 
14
+ function inferCommandArgsFromProcessArgv (argv) {
15
+ const runIndex = argv.indexOf('run')
16
+ if (runIndex === -1) return []
17
+
18
+ const args = argv.slice(runIndex + 1)
19
+
20
+ const separatorIndex = args.indexOf('--')
21
+ if (separatorIndex !== -1) return args.slice(separatorIndex + 1)
22
+
23
+ for (let i = 0; i < args.length; i++) {
24
+ if (args[i] === '-f' || args[i] === '--env-file') {
25
+ i++
26
+ continue
27
+ }
28
+
29
+ if (args[i].startsWith('-')) continue
30
+
31
+ return args.slice(i)
32
+ }
33
+
34
+ return []
35
+ }
36
+
37
+ function uniqueInjectedKeys (processedEnvs) {
38
+ const result = new Set()
39
+ for (const processedEnv of processedEnvs) {
40
+ for (const key of Object.keys(processedEnv.injected || {})) {
41
+ result.add(key)
42
+ }
43
+ }
44
+ return result
45
+ }
46
+
14
47
  async function run () {
15
- const options = normalizeArmorOptions(this.opts())
16
- const commandArgs = this.args
48
+ const options = normalizeArmorAliases(this.opts())
49
+
50
+ let commandArgs = this.args
51
+ if (commandArgs.length < 1) {
52
+ commandArgs = inferCommandArgsFromProcessArgv(process.argv)
53
+ }
54
+
17
55
  const spinner = await createSpinner({ ...options, text: 'injecting' })
18
56
 
19
57
  logger.debug(`options: ${JSON.stringify(options)}`)
@@ -48,17 +86,24 @@ async function run () {
48
86
  envs = this.envs
49
87
  }
50
88
  envs = determine(envs, process.env)
51
- if (spinner) spinner.stop()
52
89
 
53
90
  const {
54
91
  processedEnvs,
55
- readableStrings,
56
- readableFilepaths,
57
- uniqueInjectedKeys
58
- } = await new Run(envs, options.overload, process.env, options.envKeysFile, noArmor, {
92
+ readableFilepaths
93
+ } = await envsResolver({
94
+ envs,
95
+ overload: options.overload,
96
+ processEnv: process.env,
97
+ envKeysFile: options.envKeysFile,
98
+ noArmor,
59
99
  token: options.token,
60
- command: commandArgs
61
- }).run()
100
+ command: commandArgs,
101
+ onStatus: (text) => {
102
+ if (spinner && text) {
103
+ spinner.text = text
104
+ }
105
+ }
106
+ })
62
107
 
63
108
  for (const processedEnv of processedEnvs) {
64
109
  if (processedEnv.type === 'envFile') {
@@ -93,27 +138,25 @@ async function run () {
93
138
  logger.debug(`${key} set to ${value}`)
94
139
  }
95
140
 
96
- // verbose/debug preExisted key/value
97
- for (const [key, value] of Object.entries(processedEnv.preExisted || {})) {
141
+ // verbose/debug existed key/value
142
+ for (const [key, value] of Object.entries(processedEnv.existed || {})) {
98
143
  logger.verbose(`${key} pre-exists (protip: use --overload to override)`)
99
144
  logger.debug(`${key} pre-exists as ${value} (protip: use --overload to override)`)
100
145
  }
101
146
  }
102
147
 
103
- let msg = `injected env (${uniqueInjectedKeys.length})`
104
- if (readableFilepaths.length > 0 && readableStrings.length > 0) {
105
- msg += ` from ${readableFilepaths.join(', ')}, and --env flag${readableStrings.length > 1 ? 's' : ''}`
148
+ let msg = `injected env (${uniqueInjectedKeys(processedEnvs).size})`
149
+ const envStringCount = processedEnvs.filter((processedEnv) => processedEnv.type === 'env' && processedEnv.parsed).length
150
+ if (readableFilepaths.length > 0 && envStringCount > 0) {
151
+ msg += ` from ${readableFilepaths.join(', ')}, and --env flag${envStringCount > 1 ? 's' : ''}`
106
152
  } else if (readableFilepaths.length > 0) {
107
153
  msg += ` from ${readableFilepaths.join(', ')}`
108
- } else if (readableStrings.length > 0) {
109
- msg += ` from --env flag${readableStrings.length > 1 ? 's' : ''}`
154
+ } else if (envStringCount > 0) {
155
+ msg += ` from --env flag${envStringCount > 1 ? 's' : ''}`
110
156
  }
111
157
 
112
- const armoredPrivateKeyUsed = processedEnvs.some((processedEnv) => processedEnv.armoredPrivateKeyUsed)
113
- const keyUsedSuffix = armoredPrivateKeyUsed ? ' · armored ⛨' : ''
114
-
115
158
  if (spinner) spinner.stop()
116
- logger.success(`⟐ ${msg}${keyUsedSuffix}`)
159
+ logger.success(`⟐ ${msg}`)
117
160
  } catch (error) {
118
161
  if (spinner) spinner.stop()
119
162
  catchAndLog(error)
@@ -1,14 +1,15 @@
1
1
  const fsx = require('./../../lib/helpers/fsx')
2
2
  const { logger } = require('./../../shared/logger')
3
3
 
4
+ const setTransform = require('./../../lib/transforms/set')
5
+
4
6
  const catchAndLog = require('../../lib/helpers/catchAndLog')
5
7
  const createSpinner = require('../../lib/helpers/createSpinner')
6
8
  const Session = require('../../db/session')
7
- const Sets = require('./../../lib/services/sets')
8
- const normalizeArmorOptions = require('./normalizeArmorOptions')
9
+ const normalizeArmorAliases = require('./normalizeArmorAliases')
9
10
 
10
11
  async function set (key, value) {
11
- const options = normalizeArmorOptions(this.opts())
12
+ const options = normalizeArmorAliases(this.opts())
12
13
 
13
14
  let encrypt = true
14
15
  let settingMessage = 'encrypting'
@@ -18,70 +19,83 @@ async function set (key, value) {
18
19
  }
19
20
 
20
21
  const spinner = await createSpinner({ ...options, text: settingMessage })
22
+ const sesh = new Session()
21
23
 
22
24
  logger.debug(`key: ${key}`)
23
25
  logger.debug(`value: ${value}`)
24
26
  logger.debug(`options: ${JSON.stringify(options)}`)
25
27
 
28
+ const envs = this.envs || []
29
+ const fk = options.envKeysFile || '.env.keys'
30
+ const noCreate = options.create === false
31
+ const noArmor = options.armor === false || (!options.token && (await sesh.noArmor()))
32
+
33
+ let errorCount = 0
34
+
26
35
  try {
27
- const envs = this.envs
28
- const envKeysFilepath = options.envKeysFile
29
- const sesh = new Session()
30
- const noArmor = options.armor === false || (await sesh.noArmor())
31
- const noCreate = options.create === false
36
+ const { keysSrc, processedEnvs, changedFilepaths, unchangedFilepaths } = await setTransform({ envs, key, value, fk, noArmor, noCreate, encrypt })
32
37
 
33
- if (spinner) spinner.stop()
34
- const {
35
- processedEnvs,
36
- changedFilepaths,
37
- unchangedFilepaths
38
- } = await new Sets(key, value, envs, encrypt, envKeysFilepath, noArmor, noCreate, {
39
- command: process.argv.slice(2)
40
- }).run()
38
+ if (keysSrc) {
39
+ await fsx.writeFileX(fk, keysSrc)
40
+ }
41
41
 
42
42
  let withEncryption = ''
43
-
44
43
  if (encrypt) {
45
44
  withEncryption = ' with encryption'
46
45
  }
47
46
 
47
+ if (spinner) spinner.stop()
48
48
  for (const processedEnv of processedEnvs) {
49
49
  logger.verbose(`setting for ${processedEnv.envFilepath}`)
50
-
51
50
  if (processedEnv.error) {
52
- logger.warn(processedEnv.error.messageWithHelp)
53
- } else {
51
+ errorCount += 1
52
+ logger.error(processedEnv.error.messageWithHelp || processedEnv.error.message)
53
+ } else if (processedEnv.changed) {
54
54
  await fsx.writeFileX(processedEnv.filepath, processedEnv.envSrc)
55
-
56
55
  logger.verbose(`${processedEnv.key} set${withEncryption} (${processedEnv.envFilepath})`)
57
- logger.debug(`${processedEnv.key} set${withEncryption} to ${processedEnv.value} (${processedEnv.envFilepath})`)
56
+ } else {
57
+ logger.verbose(`no change ${processedEnv.envFilepath} (${processedEnv.filepath})`)
58
58
  }
59
59
  }
60
60
 
61
- const localKeyAddedEnv = processedEnvs.find((processedEnv) => processedEnv.localPrivateKeyAdded)
62
- const remoteKeyAddedEnv = processedEnvs.find((processedEnv) => processedEnv.remotePrivateKeyAdded)
63
- let keyAddedSuffix = ''
64
- if (remoteKeyAddedEnv) {
65
- keyAddedSuffix = ' · armored ⛨'
66
- }
61
+ // const localKeyAddedEnv = processedEnvs.find((processedEnv) => processedEnv.localPrivateKeyAdded)
62
+ // const remoteKeyAddedEnv = processedEnvs.find((processedEnv) => processedEnv.remotePrivateKeyAdded)
63
+ // let keyAddedSuffix = ''
64
+ // if (remoteKeyAddedEnv) {
65
+ // keyAddedSuffix = ' · armored ⛨'
66
+ // }
67
67
 
68
- if (spinner) spinner.stop()
69
68
  if (changedFilepaths.length > 0) {
69
+ let msg = `◇ set ${key} (${changedFilepaths.join(',')})`
70
70
  if (encrypt) {
71
- logger.success(`◈ encrypted ${key} (${changedFilepaths.join(',')})${keyAddedSuffix}`)
72
- } else {
73
- logger.success(`◇ set ${key} (${changedFilepaths.join(',')})`)
71
+ msg = `◈ encrypted ${key} (${changedFilepaths.join(',')})`
74
72
  }
75
- } else if (encrypt && localKeyAddedEnv) {
76
- const localKeyAddedEnvFilepath = localKeyAddedEnv.envFilepath || changedFilepaths[0] || '.env'
77
- logger.success(`◈ encrypted ${key} (${localKeyAddedEnvFilepath})${keyAddedSuffix}`)
73
+
74
+ logger.success(msg)
75
+
76
+ // if (encrypt) {
77
+ // logger.success(`◈ encrypted ${key} (${changedFilepaths.join(',')})${keyAddedSuffix}`)
78
+ // } else {
79
+ // logger.success(`◇ set ${key} (${changedFilepaths.join(',')})`)
80
+ // }
78
81
  } else if (unchangedFilepaths.length > 0) {
79
82
  logger.info(`○ no change (${unchangedFilepaths})`)
80
83
  } else {
81
- // do nothing
84
+ // do nothing - scenario when no .env files found
82
85
  }
83
86
 
84
- // intentionally quiet: success line communicates key creation
87
+ // } else if (encrypt && localKeyAddedEnv) {
88
+ // const localKeyAddedEnvFilepath = localKeyAddedEnv.envFilepath || changedFilepaths[0] || '.env'
89
+ // logger.success(`◈ encrypted ${key} (${localKeyAddedEnvFilepath})${keyAddedSuffix}`)
90
+ // } else if (unchangedFilepaths.length > 0) {
91
+ // logger.info(`○ no change (${unchangedFilepaths})`)
92
+ // } else {
93
+ // // do nothing
94
+ // }
95
+
96
+ if (errorCount > 0) {
97
+ process.exit(1)
98
+ }
85
99
  } catch (error) {
86
100
  if (spinner) spinner.stop()
87
101
  catchAndLog(error)
@@ -64,7 +64,7 @@ program.command('run')
64
64
  .description('inject env at runtime [dotenvx run -- yourcommand]')
65
65
  .addHelpText('after', examples.run)
66
66
  .option('-e, --env <strings...>', 'environment variable(s) set as string (example: "HELLO=World")', collectEnvs('env'), [])
67
- .option('-f, --env-file <paths...>', 'path(s) to your env file(s)', collectEnvs('envFile'), [])
67
+ .option('-f, --env-file <path>', 'path(s) to your env file(s)', collectEnvs('envFile'), [])
68
68
  .option('-fk, --env-keys-file <path>', 'path to your .env.keys file (default: same path as your env file)')
69
69
  .option('-o, --overload', 'override existing env variables (by default, existing env vars take precedence over .env files)')
70
70
  .option('--strict', 'process.exit(1) on any errors', false)
@@ -84,7 +84,7 @@ program.command('get')
84
84
  .description('return a single environment variable')
85
85
  .argument('[KEY]', 'environment variable name')
86
86
  .option('-e, --env <strings...>', 'environment variable(s) set as string (example: "HELLO=World")', collectEnvs('env'), [])
87
- .option('-f, --env-file <paths...>', 'path(s) to your env file(s)', collectEnvs('envFile'), [])
87
+ .option('-f, --env-file <path>', 'path(s) to your env file(s)', collectEnvs('envFile'), [])
88
88
  .option('-fk, --env-keys-file <path>', 'path to your .env.keys file (default: same path as your env file)')
89
89
  .option('-o, --overload', 'override existing env variables (by default, existing env vars take precedence over .env files)')
90
90
  .option('--strict', 'process.exit(1) on any errors', false)
@@ -109,7 +109,7 @@ program.command('set')
109
109
  .allowUnknownOption()
110
110
  .argument('KEY', 'KEY')
111
111
  .argument('value', 'value')
112
- .option('-f, --env-file <paths...>', 'path(s) to your env file(s)', collectEnvs('envFile'), [])
112
+ .option('-f, --env-file <path>', 'path(s) to your env file(s)', collectEnvs('envFile'), [])
113
113
  .option('-fk, --env-keys-file <path>', 'path to your .env.keys file (default: same path as your env file)')
114
114
  .option('-c, --encrypt', 'encrypt value', true)
115
115
  .option('-p, --plain', 'store value as plain text', false)
@@ -124,7 +124,7 @@ program.command('set')
124
124
  // dotenvx encrypt
125
125
  program.command('encrypt')
126
126
  .description('encrypt .env file(s)')
127
- .option('-f, --env-file <paths...>', 'path(s) to your env file(s)', collectEnvs('envFile'), [])
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('-k, --key <keys...>', 'keys(s) to encrypt (default: all keys in file)')
130
130
  .option('-ek, --exclude-key <excludeKeys...>', 'keys(s) to exclude from encryption (default: none)')
@@ -141,7 +141,7 @@ program.command('encrypt')
141
141
  // dotenvx decrypt
142
142
  program.command('decrypt')
143
143
  .description('decrypt .env file(s)')
144
- .option('-f, --env-file <paths...>', 'path(s) to your env file(s)', collectEnvs('envFile'), [])
144
+ .option('-f, --env-file <path>', 'path(s) to your env file(s)', collectEnvs('envFile'), [])
145
145
  .option('-fk, --env-keys-file <path>', 'path to your .env.keys file (default: same path as your env file)')
146
146
  .option('-k, --key <keys...>', 'keys(s) to decrypt (default: all keys in file)')
147
147
  .option('-ek, --exclude-key <excludeKeys...>', 'keys(s) to exclude from decryption (default: none)')
@@ -153,27 +153,12 @@ program.command('decrypt')
153
153
  return require('./actions/decrypt').apply(this, args)
154
154
  })
155
155
 
156
- // dotenvx rotate
157
- program.command('rotate')
158
- .description('rotate keypair(s) and re-encrypt .env file(s)')
159
- .option('-f, --env-file <paths...>', 'path(s) to your env file(s)', collectEnvs('envFile'), [])
160
- .option('-fk, --env-keys-file <path>', 'path to your .env.keys file (default: same path as your env file)')
161
- .option('-k, --key <keys...>', 'keys(s) to encrypt (default: all keys in file)')
162
- .option('-ek, --exclude-key <excludeKeys...>', 'keys(s) to exclude from encryption (default: none)')
163
- .option('--no-armor', 'disable dotenvx-armor features')
164
- .addOption(new Option('--no-ops', 'disable dotenvx-ops features (deprecated. use --no-armor)').hideHelp())
165
- .option('--stdout', 'send to stdout')
166
- .action(function (...args) {
167
- this.envs = envs
168
- return require('./actions/rotate').apply(this, args)
169
- })
170
-
171
156
  // dotenvx keypair
172
157
  program.command('keypair')
173
158
  .usage('[KEY] [options]')
174
159
  .description('print public/private keys for .env file(s)')
175
160
  .argument('[KEY]', 'environment variable key name')
176
- .option('-f, --env-file <paths...>', 'path(s) to your env file(s)')
161
+ .option('-f, --env-file <path>', 'path(s) to your env file(s)')
177
162
  .option('-fk, --env-keys-file <path>', 'path to your .env.keys file (default: same path as your env file)')
178
163
  .option('--no-armor', 'disable dotenvx-armor features')
179
164
  .addOption(new Option('--no-ops', 'disable dotenvx-ops features (deprecated. use --no-armor)').hideHelp())
@@ -3,20 +3,18 @@ const buildApiError = require('../helpers/buildApiError')
3
3
  const packageJson = require('../helpers/packageJson')
4
4
  const normalizeToken = require('../helpers/normalizeToken')
5
5
 
6
- class PostKeypair {
7
- constructor (hostname, token, devicePublicKey, publicKey, team, metadata, grantToken) {
6
+ class PostArmorKeyring {
7
+ constructor (hostname, token, devicePublicKey, publicKey, grantToken) {
8
8
  this.hostname = hostname || 'https://armor.dotenvx.com'
9
9
  this.token = token
10
10
  this.devicePublicKey = devicePublicKey
11
11
  this.publicKey = publicKey
12
- this.team = team
13
- this.metadata = metadata
14
12
  this.grantToken = grantToken
15
13
  }
16
14
 
17
15
  async run () {
18
16
  const token = normalizeToken(this.token)
19
- const url = `${this.hostname}/api/keypair`
17
+ const url = `${this.hostname}/api/armor/keyring`
20
18
  const body = {
21
19
  device_public_key: this.devicePublicKey,
22
20
  cli_version: packageJson.version
@@ -26,14 +24,6 @@ class PostKeypair {
26
24
  body.public_key = this.publicKey
27
25
  }
28
26
 
29
- if (this.team) {
30
- body.team = this.team
31
- }
32
-
33
- if (this.metadata && Object.keys(this.metadata).length > 0) {
34
- body.metadata = this.metadata
35
- }
36
-
37
27
  if (this.grantToken) {
38
28
  body.grant_token = this.grantToken
39
29
  }
@@ -57,4 +47,4 @@ class PostKeypair {
57
47
  }
58
48
  }
59
49
 
60
- module.exports = PostKeypair
50
+ module.exports = PostArmorKeyring
@@ -1,4 +1,4 @@
1
- const canonicalEnvFilename = require('./../canonicalEnvFilename')
1
+ const canonicalEnvFilename = require('../helpers/canonicalEnvFilename')
2
2
 
3
3
  function environment (filepath) {
4
4
  const filename = canonicalEnvFilename(filepath)
@@ -0,0 +1,9 @@
1
+ function filepaths (envFile = '.env') {
2
+ if (!Array.isArray(envFile)) {
3
+ return [envFile]
4
+ }
5
+
6
+ return envFile
7
+ }
8
+
9
+ module.exports = filepaths
@@ -0,0 +1,38 @@
1
+ const { scan } = require('@dotenvx/primitives')
2
+ const canonicalEnvFilename = require('../helpers/canonicalEnvFilename')
3
+ const environment = require('./environment')
4
+
5
+ function keynames (filepath = '.env', src = '') {
6
+ const { parsed } = scan(src)
7
+
8
+ // src public key name wins
9
+ for (const publicKeyName in parsed) {
10
+ if (publicKeyName.startsWith('DOTENV_PUBLIC_KEY')) {
11
+ return {
12
+ publicKeyName,
13
+ privateKeyName: publicKeyName.replace('DOTENV_PUBLIC_KEY', 'DOTENV_PRIVATE_KEY')
14
+ }
15
+ }
16
+ }
17
+
18
+ const filename = canonicalEnvFilename(filepath)
19
+
20
+ // .env
21
+ if (filename === '.env') {
22
+ return {
23
+ publicKeyName: 'DOTENV_PUBLIC_KEY',
24
+ privateKeyName: 'DOTENV_PRIVATE_KEY'
25
+ }
26
+ }
27
+
28
+ // .env.ENVIRONMENT
29
+ const resolvedEnvironment = environment(filename).toUpperCase()
30
+
31
+ return {
32
+ publicKeyName: `DOTENV_PUBLIC_KEY_${resolvedEnvironment}`,
33
+ privateKeyName: `DOTENV_PRIVATE_KEY_${resolvedEnvironment}`
34
+ }
35
+ }
36
+
37
+ module.exports = keynames
38
+ module.exports.keynames = keynames
@@ -1,7 +1,10 @@
1
1
  const { logger } = require('./../../shared/logger')
2
2
 
3
3
  function catchAndLog (error) {
4
- logger.error(error.messageWithHelp || error.message)
4
+ const msg = error.messageWithHelp || error.message
5
+ if (msg) {
6
+ logger.error(msg)
7
+ }
5
8
  if (error.debug) {
6
9
  logger.debug(error.debug)
7
10
  }
@@ -1,14 +1,6 @@
1
1
  module.exports = {
2
- armorKeypair: require('./armorKeypair'),
3
- armorKeypairSync: require('./armorKeypairSync'),
4
- localKeypair: require('./localKeypair'),
5
- encryptValue: require('./encryptValue'),
6
2
  decryptKeyValue: require('./decryptKeyValue'),
7
3
  isPublicKey: require('./isPublicKey'),
8
4
  mutateKeysSrc: require('./mutateKeysSrc'),
9
- mutateKeysSrcSync: require('./mutateKeysSrcSync'),
10
- provision: require('./provision'),
11
- provisionSync: require('./provisionSync'),
12
- provisionWithPrivateKey: require('./provisionWithPrivateKey'),
13
5
  mutateSrc: require('./mutateSrc')
14
6
  }