@dotenvx/dotenvx 1.55.1 → 1.57.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 (71) hide show
  1. package/CHANGELOG.md +18 -1
  2. package/README.md +43 -45
  3. package/package.json +3 -3
  4. package/src/cli/actions/decrypt.js +2 -2
  5. package/src/cli/actions/encrypt.js +10 -14
  6. package/src/cli/actions/ext/genexample.js +3 -2
  7. package/src/cli/actions/ext/gitignore.js +2 -2
  8. package/src/cli/actions/get.js +4 -2
  9. package/src/cli/actions/keypair.js +3 -2
  10. package/src/cli/actions/rotate.js +19 -21
  11. package/src/cli/actions/run.js +1 -14
  12. package/src/cli/actions/set.js +16 -16
  13. package/src/cli/commands/ext.js +0 -3
  14. package/src/cli/dotenvx.js +29 -25
  15. package/src/cli/examples.js +2 -2
  16. package/src/db/session.js +21 -0
  17. package/src/lib/extensions/ops.js +98 -0
  18. package/src/lib/helpers/buildEnvs.js +2 -15
  19. package/src/lib/helpers/{decryptKeyValue.js → cryptography/decryptKeyValue.js} +1 -1
  20. package/src/lib/helpers/cryptography/index.js +14 -0
  21. package/src/lib/helpers/{isPublicKey.js → cryptography/isPublicKey.js} +1 -1
  22. package/src/lib/helpers/{keypair.js → cryptography/localKeypair.js} +2 -2
  23. package/src/lib/helpers/cryptography/mutateKeysSrc.js +38 -0
  24. package/src/lib/helpers/cryptography/mutateSrc.js +24 -0
  25. package/src/lib/helpers/cryptography/opsKeypair.js +14 -0
  26. package/src/lib/helpers/cryptography/provision.js +47 -0
  27. package/src/lib/helpers/cryptography/provisionWithPrivateKey.js +26 -0
  28. package/src/lib/helpers/envResolution/determine.js +46 -0
  29. package/src/lib/helpers/{guessEnvironment.js → envResolution/environment.js} +4 -6
  30. package/src/lib/helpers/envResolution/index.js +8 -0
  31. package/src/lib/helpers/errors.js +13 -0
  32. package/src/lib/helpers/executeDynamic.js +11 -14
  33. package/src/lib/helpers/findEnvFiles.js +1 -1
  34. package/src/lib/helpers/isFullyEncrypted.js +3 -3
  35. package/src/lib/helpers/keyResolution/index.js +13 -0
  36. package/src/lib/helpers/keyResolution/keyNames.js +24 -0
  37. package/src/lib/helpers/keyResolution/keyValues.js +85 -0
  38. package/src/lib/helpers/keyResolution/readFileKey.js +15 -0
  39. package/src/lib/helpers/keyResolution/readProcessKey.js +7 -0
  40. package/src/lib/helpers/localDisplayPath.js +11 -0
  41. package/src/lib/helpers/parse.js +1 -1
  42. package/src/lib/helpers/prependPublicKey.js +17 -0
  43. package/src/lib/helpers/preserveShebang.js +16 -0
  44. package/src/lib/main.d.ts +19 -3
  45. package/src/lib/main.js +23 -32
  46. package/src/lib/services/decrypt.js +23 -19
  47. package/src/lib/services/encrypt.js +41 -136
  48. package/src/lib/services/get.js +3 -3
  49. package/src/lib/services/keypair.js +12 -16
  50. package/src/lib/services/prebuild.js +2 -2
  51. package/src/lib/services/precommit.js +2 -2
  52. package/src/lib/services/rotate.js +59 -42
  53. package/src/lib/services/run.js +29 -112
  54. package/src/lib/services/sets.js +40 -124
  55. package/src/shared/colors.js +10 -0
  56. package/src/shared/logger.js +4 -3
  57. package/src/lib/helpers/decrypt.js +0 -31
  58. package/src/lib/helpers/deprecationNotice.js +0 -17
  59. package/src/lib/helpers/determineEnvs.js +0 -65
  60. package/src/lib/helpers/encrypt.js +0 -29
  61. package/src/lib/helpers/findPrivateKey.js +0 -25
  62. package/src/lib/helpers/findPublicKey.js +0 -15
  63. package/src/lib/helpers/guessPrivateKeyName.js +0 -18
  64. package/src/lib/helpers/guessPublicKeyName.js +0 -18
  65. package/src/lib/helpers/parseEncryptionKeyFromDotenvKey.js +0 -19
  66. package/src/lib/helpers/parseEnvironmentFromDotenvKey.js +0 -19
  67. package/src/lib/helpers/smartDotenvPrivateKey.js +0 -89
  68. package/src/lib/helpers/smartDotenvPublicKey.js +0 -42
  69. package/src/lib/services/ops.js +0 -136
  70. /package/src/lib/helpers/{encryptValue.js → cryptography/encryptValue.js} +0 -0
  71. /package/src/lib/helpers/{isEncrypted.js → cryptography/isEncrypted.js} +0 -0
@@ -13,6 +13,9 @@ const executeDynamic = require('./../lib/helpers/executeDynamic')
13
13
  const removeDynamicHelpSection = require('./../lib/helpers/removeDynamicHelpSection')
14
14
  const removeOptionsHelpParts = require('./../lib/helpers/removeOptionsHelpParts')
15
15
 
16
+ const Session = require('./../db/session')
17
+ const sesh = new Session()
18
+
16
19
  // for use with run
17
20
  const envs = []
18
21
  function collectEnvs (type) {
@@ -68,12 +71,11 @@ program.command('run')
68
71
  .option('-e, --env <strings...>', 'environment variable(s) set as string (example: "HELLO=World")', collectEnvs('env'), [])
69
72
  .option('-f, --env-file <paths...>', 'path(s) to your env file(s)', collectEnvs('envFile'), [])
70
73
  .option('-fk, --env-keys-file <path>', 'path to your .env.keys file (default: same path as your env file)')
71
- .option('-fv, --env-vault-file <paths...>', 'path(s) to your .env.vault file(s)', collectEnvs('envVaultFile'), [])
72
74
  .option('-o, --overload', 'override existing env variables (by default, existing env vars take precedence over .env files)')
73
75
  .option('--strict', 'process.exit(1) on any errors', false)
74
76
  .option('--convention <name>', 'load a .env convention (available conventions: [\'nextjs\', \'flow\'])')
75
77
  .option('--ignore <errorCodes...>', 'error code(s) to ignore (example: --ignore=MISSING_ENV_FILE)')
76
- .option('--ops-off', 'disable dotenvx-ops features', false)
78
+ .option('--ops-off', 'disable dotenvx-ops features', sesh.opsOff())
77
79
  .action(function (...args) {
78
80
  this.envs = envs
79
81
  runAction.apply(this, args)
@@ -88,15 +90,15 @@ program.command('get')
88
90
  .option('-e, --env <strings...>', 'environment variable(s) set as string (example: "HELLO=World")', collectEnvs('env'), [])
89
91
  .option('-f, --env-file <paths...>', 'path(s) to your env file(s)', collectEnvs('envFile'), [])
90
92
  .option('-fk, --env-keys-file <path>', 'path to your .env.keys file (default: same path as your env file)')
91
- .option('-fv, --env-vault-file <paths...>', 'path(s) to your .env.vault file(s)', collectEnvs('envVaultFile'), [])
92
93
  .option('-o, --overload', 'override existing env variables (by default, existing env vars take precedence over .env files)')
93
94
  .option('--strict', 'process.exit(1) on any errors', false)
94
95
  .option('--convention <name>', 'load a .env convention (available conventions: [\'nextjs\', \'flow\'])')
95
96
  .option('--ignore <errorCodes...>', 'error code(s) to ignore (example: --ignore=MISSING_ENV_FILE)')
96
97
  .option('-a, --all', 'include all machine envs as well')
97
98
  .option('-pp, --pretty-print', 'pretty print output')
99
+ .option('--pp', 'pretty print output (alias)')
98
100
  .option('--format <type>', 'format of the output (json, shell, eval)', 'json')
99
- .option('--ops-off', 'disable dotenvx-ops features', false)
101
+ .option('--ops-off', 'disable dotenvx-ops features', sesh.opsOff())
100
102
  .action(function (...args) {
101
103
  this.envs = envs
102
104
  getAction.apply(this, args)
@@ -106,7 +108,7 @@ program.command('get')
106
108
  const setAction = require('./actions/set')
107
109
  program.command('set')
108
110
  .usage('<KEY> <value> [options]')
109
- .description('set a single environment variable')
111
+ .description('encrypt a single environment variable')
110
112
  .addHelpText('after', examples.set)
111
113
  .allowUnknownOption()
112
114
  .argument('KEY', 'KEY')
@@ -115,7 +117,7 @@ program.command('set')
115
117
  .option('-fk, --env-keys-file <path>', 'path to your .env.keys file (default: same path as your env file)')
116
118
  .option('-c, --encrypt', 'encrypt value', true)
117
119
  .option('-p, --plain', 'store value as plain text', false)
118
- .option('--ops-off', 'disable dotenvx-ops features', false)
120
+ .option('--ops-off', 'disable dotenvx-ops features', sesh.opsOff())
119
121
  .action(function (...args) {
120
122
  this.envs = envs
121
123
  setAction.apply(this, args)
@@ -129,7 +131,7 @@ program.command('encrypt')
129
131
  .option('-fk, --env-keys-file <path>', 'path to your .env.keys file (default: same path as your env file)')
130
132
  .option('-k, --key <keys...>', 'keys(s) to encrypt (default: all keys in file)')
131
133
  .option('-ek, --exclude-key <excludeKeys...>', 'keys(s) to exclude from encryption (default: none)')
132
- .option('--ops-off', 'disable dotenvx-ops features', false)
134
+ .option('--ops-off', 'disable dotenvx-ops features', sesh.opsOff())
133
135
  .option('--stdout', 'send to stdout')
134
136
  .action(function (...args) {
135
137
  this.envs = envs
@@ -144,13 +146,28 @@ program.command('decrypt')
144
146
  .option('-fk, --env-keys-file <path>', 'path to your .env.keys file (default: same path as your env file)')
145
147
  .option('-k, --key <keys...>', 'keys(s) to decrypt (default: all keys in file)')
146
148
  .option('-ek, --exclude-key <excludeKeys...>', 'keys(s) to exclude from decryption (default: none)')
147
- .option('--ops-off', 'disable dotenvx-ops features', false)
149
+ .option('--ops-off', 'disable dotenvx-ops features', sesh.opsOff())
148
150
  .option('--stdout', 'send to stdout')
149
151
  .action(function (...args) {
150
152
  this.envs = envs
151
153
  decryptAction.apply(this, args)
152
154
  })
153
155
 
156
+ // dotenvx rotate
157
+ const rotateAction = require('./actions/rotate')
158
+ program.command('rotate')
159
+ .description('rotate keypair(s) and re-encrypt .env file(s)')
160
+ .option('-f, --env-file <paths...>', 'path(s) to your env file(s)', collectEnvs('envFile'), [])
161
+ .option('-fk, --env-keys-file <path>', 'path to your .env.keys file (default: same path as your env file)')
162
+ .option('-k, --key <keys...>', 'keys(s) to encrypt (default: all keys in file)')
163
+ .option('-ek, --exclude-key <excludeKeys...>', 'keys(s) to exclude from encryption (default: none)')
164
+ .option('--ops-off', 'disable dotenvx-ops features', sesh.opsOff())
165
+ .option('--stdout', 'send to stdout')
166
+ .action(function (...args) {
167
+ this.envs = envs
168
+ rotateAction.apply(this, args)
169
+ })
170
+
154
171
  // dotenvx keypair
155
172
  const keypairAction = require('./actions/keypair')
156
173
  program.command('keypair')
@@ -159,8 +176,9 @@ program.command('keypair')
159
176
  .argument('[KEY]', 'environment variable key name')
160
177
  .option('-f, --env-file <paths...>', 'path(s) to your env file(s)')
161
178
  .option('-fk, --env-keys-file <path>', 'path to your .env.keys file (default: same path as your env file)')
162
- .option('--ops-off', 'disable dotenvx-ops features', false)
179
+ .option('--ops-off', 'disable dotenvx-ops features', sesh.opsOff())
163
180
  .option('-pp, --pretty-print', 'pretty print output')
181
+ .option('--pp', 'pretty print output (alias)')
164
182
  .option('--format <type>', 'format of the output (json, shell)', 'json')
165
183
  .action(keypairAction)
166
184
 
@@ -173,21 +191,6 @@ program.command('ls')
173
191
  .option('-ef, --exclude-env-file <excludeFilenames...>', 'path(s) to exclude from your env file(s) (default: none)')
174
192
  .action(lsAction)
175
193
 
176
- // dotenvx rotate
177
- const rotateAction = require('./actions/rotate')
178
- program.command('rotate')
179
- .description('rotate keypair(s) and re-encrypt .env file(s)')
180
- .option('-f, --env-file <paths...>', 'path(s) to your env file(s)', collectEnvs('envFile'), [])
181
- .option('-fk, --env-keys-file <path>', 'path to your .env.keys file (default: same path as your env file)')
182
- .option('-k, --key <keys...>', 'keys(s) to encrypt (default: all keys in file)')
183
- .option('-ek, --exclude-key <excludeKeys...>', 'keys(s) to exclude from encryption (default: none)')
184
- .option('--ops-off', 'disable dotenvx-ops features', false)
185
- .option('--stdout', 'send to stdout')
186
- .action(function (...args) {
187
- this.envs = envs
188
- rotateAction.apply(this, args)
189
- })
190
-
191
194
  // dotenvx help
192
195
  program.command('help [command]')
193
196
  .description('display help for command')
@@ -249,7 +252,8 @@ program.helpInformation = function () {
249
252
  const filteredLines = lines.filter(line =>
250
253
  !line.includes('DEPRECATED') &&
251
254
  !line.includes('help [command]') &&
252
- !line.includes('🔌 extensions')
255
+ !line.includes('🔌 extensions') &&
256
+ !/^\s*ls\b/.test(line)
253
257
  )
254
258
 
255
259
  return filteredLines.join('\n')
@@ -66,11 +66,11 @@ Examples:
66
66
  $ dotenvx ext gitignore --pattern .env.keys
67
67
  \`\`\`
68
68
 
69
- Try it:
69
+ Try it:
70
70
 
71
71
  \`\`\`
72
72
  $ dotenvx ext gitignore
73
- ignored .env* (.gitignore)
73
+ ignored .env* (.gitignore)
74
74
  \`\`\`
75
75
  `
76
76
  }
@@ -0,0 +1,21 @@
1
+ const Ops = require('./../lib/extensions/ops')
2
+
3
+ class Session {
4
+ constructor () {
5
+ this.ops = new Ops()
6
+ this.opsStatus = this.ops.status()
7
+ }
8
+
9
+ //
10
+ // opsOff/On
11
+ //
12
+ opsOn () {
13
+ return this.opsStatus === 'on'
14
+ }
15
+
16
+ opsOff () {
17
+ return !this.opsOn()
18
+ }
19
+ }
20
+
21
+ module.exports = Session
@@ -0,0 +1,98 @@
1
+ const path = require('path')
2
+ const childProcess = require('child_process')
3
+
4
+ // const { logger } = require('./../../shared/logger')
5
+
6
+ class Ops {
7
+ constructor () {
8
+ this.opsLib = null
9
+
10
+ if (this._isForcedOff()) {
11
+ return
12
+ }
13
+
14
+ // check npm lib
15
+ try { this.opsLib = this._opsNpm() } catch (_e) {}
16
+
17
+ // check binary cli
18
+ if (!this.opsLib) {
19
+ try { this.opsLib = this._opsCli() } catch (_e) {}
20
+ }
21
+
22
+ if (this.opsLib) {
23
+ // logger.successv(`🛡️ ops: ${this.opsLib.status()}`)
24
+ }
25
+ }
26
+
27
+ status () {
28
+ if (this._isForcedOff() || !this.opsLib) {
29
+ return 'off'
30
+ }
31
+
32
+ return this.opsLib.status()
33
+ }
34
+
35
+ keypair (publicKey) {
36
+ if (this._isForcedOff() || !this.opsLib) {
37
+ return {}
38
+ }
39
+
40
+ return this.opsLib.keypair(publicKey)
41
+ }
42
+
43
+ observe (payload) {
44
+ if (!this._isForcedOff() && this.opsLib && this.opsLib.status() !== 'off') {
45
+ const encoded = Buffer.from(JSON.stringify(payload)).toString('base64')
46
+ this.opsLib.observe(encoded)
47
+ }
48
+ }
49
+
50
+ //
51
+ // private
52
+ //
53
+ _opsNpm () {
54
+ const npmBin = path.resolve(process.cwd(), 'node_modules/.bin/dotenvx-ops')
55
+ return this._opsLib(npmBin)
56
+ }
57
+
58
+ _opsCli () {
59
+ return this._opsLib('dotenvx-ops')
60
+ }
61
+
62
+ _opsLib (binary) {
63
+ childProcess.execFileSync(binary, ['--version'], { stdio: ['pipe', 'pipe', 'ignore'] })
64
+
65
+ return {
66
+ status: () => {
67
+ return childProcess.execFileSync(binary, ['status'], { stdio: ['pipe', 'pipe', 'ignore'] }).toString().trim()
68
+ },
69
+ keypair: (publicKey) => {
70
+ const args = ['keypair']
71
+ if (publicKey) {
72
+ args.push(publicKey)
73
+ }
74
+ const output = childProcess.execFileSync(binary, args, { stdio: ['pipe', 'pipe', 'ignore'] }).toString().trim()
75
+ const parsed = JSON.parse(output.toString())
76
+ return parsed
77
+ },
78
+ observe: (encoded) => {
79
+ try {
80
+ const subprocess = childProcess.spawn(binary, ['observe', encoded], {
81
+ stdio: 'ignore',
82
+ detached: true
83
+ })
84
+
85
+ subprocess.unref() // let it run independently
86
+ } catch (e) {
87
+ // noop
88
+ }
89
+ }
90
+ }
91
+ }
92
+
93
+ _isForcedOff () {
94
+ return process.env.DOTENVX_OPS_OFF === 'true'
95
+ }
96
+ }
97
+
98
+ module.exports = Ops
@@ -1,10 +1,7 @@
1
- const path = require('path')
2
-
3
1
  const conventions = require('./conventions')
4
2
  const dotenvOptionPaths = require('./dotenvOptionPaths')
5
- const DeprecationNotice = require('./deprecationNotice')
6
3
 
7
- function buildEnvs (options, DOTENV_KEY = undefined) {
4
+ function buildEnvs (options) {
8
5
  // build envs using user set option.path
9
6
  const optionPaths = dotenvOptionPaths(options) // [ '.env' ]
10
7
 
@@ -13,18 +10,8 @@ function buildEnvs (options, DOTENV_KEY = undefined) {
13
10
  envs = conventions(options.convention).concat(envs)
14
11
  }
15
12
 
16
- new DeprecationNotice({ DOTENV_KEY }).dotenvKey() // DEPRECATION NOTICE
17
-
18
13
  for (const optionPath of optionPaths) {
19
- // if DOTENV_KEY is set then assume we are checking envVaultFile
20
- if (DOTENV_KEY) {
21
- envs.push({
22
- type: 'envVaultFile',
23
- value: path.join(path.dirname(optionPath), '.env.vault')
24
- })
25
- } else {
26
- envs.push({ type: 'envFile', value: optionPath })
27
- }
14
+ envs.push({ type: 'envFile', value: optionPath })
28
15
  }
29
16
 
30
17
  return envs
@@ -1,6 +1,6 @@
1
1
  const { decrypt } = require('eciesjs')
2
2
 
3
- const Errors = require('./errors')
3
+ const Errors = require('./../errors')
4
4
 
5
5
  const PREFIX = 'encrypted:'
6
6
 
@@ -0,0 +1,14 @@
1
+ module.exports = {
2
+ opsKeypair: require('./opsKeypair'),
3
+ localKeypair: require('./localKeypair'),
4
+ encryptValue: require('./encryptValue'),
5
+ decryptKeyValue: require('./decryptKeyValue'),
6
+ isEncrypted: require('./isEncrypted'),
7
+ isPublicKey: require('./isPublicKey'),
8
+ provision: require('./provision'),
9
+ provisionWithPrivateKey: require('./provisionWithPrivateKey'),
10
+ mutateSrc: require('./mutateSrc'),
11
+
12
+ // other
13
+ isFullyEncrypted: require('./../isFullyEncrypted')
14
+ }
@@ -1,6 +1,6 @@
1
1
  const PUBLIC_KEY_PATTERN = /^DOTENV_PUBLIC_KEY/
2
2
 
3
- function isPublicKey (key, value) {
3
+ function isPublicKey (key) {
4
4
  return PUBLIC_KEY_PATTERN.test(key)
5
5
  }
6
6
 
@@ -1,6 +1,6 @@
1
1
  const { PrivateKey } = require('eciesjs')
2
2
 
3
- function keypair (existingPrivateKey) {
3
+ function localKeypair (existingPrivateKey) {
4
4
  let kp
5
5
 
6
6
  if (existingPrivateKey) {
@@ -18,4 +18,4 @@ function keypair (existingPrivateKey) {
18
18
  }
19
19
  }
20
20
 
21
- module.exports = keypair
21
+ module.exports = localKeypair
@@ -0,0 +1,38 @@
1
+ const FIRST_TIME_KEYS_SRC = [
2
+ '#/------------------!DOTENV_PRIVATE_KEYS!-------------------/',
3
+ '#/ private decryption keys. DO NOT commit to source control /',
4
+ '#/ [how it works](https://dotenvx.com/encryption) /',
5
+ // '#/ backup with: `dotenvx ops backup` /',
6
+ '#/----------------------------------------------------------/'
7
+ ].join('\n')
8
+
9
+ const path = require('path')
10
+ const fsx = require('./../fsx')
11
+
12
+ function mutateKeysSrc ({ envFilepath, keysFilepath, privateKeyName, privateKeyValue }) {
13
+ const filename = path.basename(envFilepath)
14
+ const filepath = path.resolve(envFilepath)
15
+ let resolvedKeysFilepath = path.join(path.dirname(filepath), '.env.keys')
16
+ if (keysFilepath) {
17
+ resolvedKeysFilepath = path.resolve(keysFilepath)
18
+ }
19
+ const appendPrivateKey = [`# ${filename}`, `${privateKeyName}=${privateKeyValue}`, ''].join('\n')
20
+
21
+ let keysSrc = ''
22
+ if (fsx.existsSync(resolvedKeysFilepath)) {
23
+ keysSrc = fsx.readFileX(resolvedKeysFilepath)
24
+ }
25
+ keysSrc = keysSrc.length > 1 ? keysSrc : `${FIRST_TIME_KEYS_SRC}\n`
26
+ keysSrc = `${keysSrc}\n${appendPrivateKey}`
27
+
28
+ fsx.writeFileX(resolvedKeysFilepath, keysSrc) // TODO: don't write if ops
29
+
30
+ const envKeysFilepath = keysFilepath || path.join(path.dirname(envFilepath), path.basename(resolvedKeysFilepath))
31
+
32
+ return {
33
+ keysSrc,
34
+ envKeysFilepath
35
+ }
36
+ }
37
+
38
+ module.exports = mutateKeysSrc
@@ -0,0 +1,24 @@
1
+ const path = require('path')
2
+ const preserveShebang = require('./../preserveShebang')
3
+ const prependPublicKey = require('./../prependPublicKey')
4
+
5
+ function mutateSrc ({ envSrc, envFilepath, keysFilepath, publicKeyName, publicKeyValue }) {
6
+ const filename = path.basename(envFilepath)
7
+ const filepath = path.resolve(envFilepath)
8
+ let resolvedKeysFilepath = path.join(path.dirname(filepath), '.env.keys')
9
+ if (keysFilepath) {
10
+ resolvedKeysFilepath = path.resolve(keysFilepath)
11
+ }
12
+ const relativeFilepath = path.relative(path.dirname(filepath), resolvedKeysFilepath)
13
+
14
+ const ps = preserveShebang(envSrc)
15
+ const prependedPublicKey = prependPublicKey(publicKeyName, publicKeyValue, filename, relativeFilepath)
16
+
17
+ envSrc = `${ps.firstLinePreserved}${prependedPublicKey}\n${ps.envSrc}`
18
+
19
+ return {
20
+ envSrc
21
+ }
22
+ }
23
+
24
+ module.exports = mutateSrc
@@ -0,0 +1,14 @@
1
+ const Ops = require('../../extensions/ops')
2
+
3
+ function opsKeypair (existingPublicKey) {
4
+ const kp = new Ops().keypair(existingPublicKey)
5
+ const publicKey = kp.public_key
6
+ const privateKey = kp.private_key
7
+
8
+ return {
9
+ publicKey,
10
+ privateKey
11
+ }
12
+ }
13
+
14
+ module.exports = opsKeypair
@@ -0,0 +1,47 @@
1
+ const mutateSrc = require('./mutateSrc')
2
+ const mutateKeysSrc = require('./mutateKeysSrc')
3
+ const opsKeypair = require('./opsKeypair')
4
+ const localKeypair = require('./localKeypair')
5
+ const { keyNames } = require('../keyResolution')
6
+
7
+ function provision ({ envSrc, envFilepath, keysFilepath, opsOn }) {
8
+ opsOn = opsOn === true
9
+ const { publicKeyName, privateKeyName } = keyNames(envFilepath)
10
+
11
+ let publicKey
12
+ let privateKey
13
+ let keysSrc
14
+ let envKeysFilepath
15
+ let privateKeyAdded = false
16
+
17
+ if (opsOn) {
18
+ const kp = opsKeypair()
19
+ publicKey = kp.publicKey
20
+ privateKey = kp.privateKey
21
+ } else {
22
+ const kp = localKeypair()
23
+ publicKey = kp.publicKey
24
+ privateKey = kp.privateKey
25
+ }
26
+
27
+ const mutated = mutateSrc({ envSrc, envFilepath, keysFilepath, publicKeyName, publicKeyValue: publicKey })
28
+ envSrc = mutated.envSrc
29
+
30
+ if (!opsOn) {
31
+ const mutated = mutateKeysSrc({ envFilepath, keysFilepath, privateKeyName, privateKeyValue: privateKey })
32
+ keysSrc = mutated.keysSrc
33
+ envKeysFilepath = mutated.envKeysFilepath
34
+ privateKeyAdded = true
35
+ }
36
+
37
+ return {
38
+ envSrc,
39
+ keysSrc,
40
+ publicKey,
41
+ privateKey,
42
+ privateKeyAdded,
43
+ envKeysFilepath
44
+ }
45
+ }
46
+
47
+ module.exports = provision
@@ -0,0 +1,26 @@
1
+ const Errors = require('./../errors')
2
+ const mutateSrc = require('./mutateSrc')
3
+ const localKeypair = require('./localKeypair')
4
+
5
+ function provisionWithPrivateKey ({ envSrc, envFilepath, keysFilepath, privateKeyValue, publicKeyValue, publicKeyName }) {
6
+ const { publicKey, privateKey } = localKeypair(privateKeyValue) // opsOn doesn't matter here since privateKeyValue was already discovered prior (via ops and local) and passed as privateKeyValue
7
+
8
+ // if derivation doesn't match what's in the file (or preset in env)
9
+ if (publicKeyValue && publicKeyValue !== publicKey) {
10
+ throw new Errors({ publicKey, publicKeyExisting: publicKeyValue }).mispairedPrivateKey()
11
+ }
12
+
13
+ // scenario when encrypting a monorepo second .env file from a prior generated -fk .env.keys file
14
+ if (!publicKeyValue) {
15
+ const mutated = mutateSrc({ envSrc, envFilepath, keysFilepath, publicKeyName, publicKeyValue: publicKey })
16
+ envSrc = mutated.envSrc
17
+ }
18
+
19
+ return {
20
+ envSrc,
21
+ publicKey,
22
+ privateKey
23
+ }
24
+ }
25
+
26
+ module.exports = provisionWithPrivateKey
@@ -0,0 +1,46 @@
1
+ const dotenvPrivateKeyNames = require('./../dotenvPrivateKeyNames')
2
+ const guessPrivateKeyFilename = require('./../guessPrivateKeyFilename')
3
+
4
+ const TYPE_ENV_FILE = 'envFile'
5
+ const DEFAULT_ENVS = [{ type: TYPE_ENV_FILE, value: '.env' }]
6
+
7
+ function envsFromDotenvPrivateKey (privateKeyNames) {
8
+ const envs = []
9
+
10
+ for (const privateKeyName of privateKeyNames) {
11
+ const filename = guessPrivateKeyFilename(privateKeyName)
12
+ envs.push({ type: TYPE_ENV_FILE, value: filename })
13
+ }
14
+
15
+ return envs
16
+ }
17
+
18
+ function determine (envs = [], processEnv) {
19
+ const privateKeyNames = dotenvPrivateKeyNames(processEnv)
20
+ if (!envs || envs.length <= 0) {
21
+ // if process.env.DOTENV_PRIVATE_KEY or process.env.DOTENV_PRIVATE_KEY_${environment} is set, assume inline encryption methodology
22
+ if (privateKeyNames.length > 0) {
23
+ return envsFromDotenvPrivateKey(privateKeyNames)
24
+ }
25
+
26
+ return DEFAULT_ENVS // default to .env file expectation
27
+ } else {
28
+ let fileAlreadySpecified = false
29
+
30
+ for (const env of envs) {
31
+ if (env.type === TYPE_ENV_FILE) {
32
+ fileAlreadySpecified = true
33
+ }
34
+ }
35
+
36
+ // return early since envs array objects already contain 1 .env file
37
+ if (fileAlreadySpecified) {
38
+ return envs
39
+ }
40
+
41
+ // no .env file specified as a flag so default to .env
42
+ return [...DEFAULT_ENVS, ...envs]
43
+ }
44
+ }
45
+
46
+ module.exports = determine
@@ -1,7 +1,7 @@
1
1
  const path = require('path')
2
2
 
3
- function guessEnvironment (filepath) {
4
- const filename = path.basename(filepath)
3
+ function environment (filepath) {
4
+ const filename = path.basename(filepath).toLowerCase()
5
5
 
6
6
  const parts = filename.split('.')
7
7
  const possibleEnvironmentList = [...parts.slice(2)]
@@ -17,13 +17,11 @@ function guessEnvironment (filepath) {
17
17
  return possibleEnvironmentList[0]
18
18
  }
19
19
 
20
- if (
21
- possibleEnvironmentList.length === 2
22
- ) {
20
+ if (possibleEnvironmentList.length === 2) {
23
21
  return possibleEnvironmentList.join('_')
24
22
  }
25
23
 
26
24
  return possibleEnvironmentList.slice(0, 2).join('_')
27
25
  }
28
26
 
29
- module.exports = guessEnvironment
27
+ module.exports = environment
@@ -0,0 +1,8 @@
1
+ module.exports = {
2
+ buildEnvs: require('./../buildEnvs'),
3
+ determine: require('./determine'),
4
+ findEnvFiles: require('./../findEnvFiles'),
5
+ dotenvOptionPaths: require('./../dotenvOptionPaths'),
6
+ environment: require('./environment'),
7
+ conventions: require('./../conventions')
8
+ }
@@ -8,6 +8,8 @@ class Errors {
8
8
  this.key = options.key
9
9
  this.privateKey = options.privateKey
10
10
  this.privateKeyName = options.privateKeyName
11
+ this.publicKey = options.publicKey
12
+ this.publicKeyExisting = options.publicKeyExisting
11
13
  this.command = options.command
12
14
 
13
15
  this.message = options.message
@@ -55,6 +57,17 @@ class Errors {
55
57
  return e
56
58
  }
57
59
 
60
+ mispairedPrivateKey () {
61
+ const code = 'MISPAIRED_PRIVATE_KEY'
62
+ const message = `[${code}] private key's derived public key (${truncate(this.publicKey)}) does not match the existing public key (${truncate(this.publicKeyExisting)})`
63
+ const help = `[${code}] https://github.com/dotenvx/dotenvx/issues/752`
64
+
65
+ const e = new Error(message)
66
+ e.code = code
67
+ e.help = help
68
+ return e
69
+ }
70
+
58
71
  looksWrongPrivateKey () {
59
72
  const code = 'WRONG_PRIVATE_KEY'
60
73
  const message = `[${code}] could not decrypt ${this.key} using private key '${this.privateKeyName}=${truncate(this.privateKey)}'`
@@ -23,20 +23,17 @@ function executeDynamic (program, command, rawArgs) {
23
23
  const result = childProcess.spawnSync(`dotenvx-${command}`, forwardedArgs, { stdio: 'inherit', env })
24
24
  if (result.error) {
25
25
  if (command === 'ops') {
26
- const ops = ` _______________________________________________________________________
27
- | |
28
- | dotenvx-ops: production grade dotenvx–with operational primitives |
29
- | |
30
- | ░▒▓██████▓▒░░▒▓███████▓▒░ ░▒▓███████▓▒░ |
31
- | ░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░ |
32
- | ░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░ |
33
- | ░▒▓█▓▒░░▒▓█▓▒░▒▓███████▓▒░ ░▒▓██████▓▒░ |
34
- | ░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░ ░▒▓█▓▒░ |
35
- | ░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░ ░▒▓█▓▒░ |
36
- | ░▒▓██████▓▒░░▒▓█▓▒░ ░▒▓███████▓▒░ |
37
- | |
38
- | Learn more at https://dotenvx.com/ops |
39
- |_______________________________________________________________________|`
26
+ const ops = ` ___________________________________________________________________
27
+ | |
28
+ | ██████╗ ██████╗ ███████╗ |
29
+ | ██╔═══██╗██╔══██╗██╔════╝ |
30
+ | ██║ ██║██████╔╝███████╗ |
31
+ | ██║ ██║██╔═══╝ ╚════██║ |
32
+ | ╚██████╔╝██║ ███████║ |
33
+ | ╚═════╝ ╚═╝ ╚══════╝ |
34
+ | |
35
+ | Learn more at [https://dotenvx.com/ops] |
36
+ |___________________________________________________________________|`
40
37
 
41
38
  console.log(ops)
42
39
  console.log('')
@@ -1,6 +1,6 @@
1
1
  const fsx = require('./fsx')
2
2
 
3
- const RESERVED_ENV_FILES = ['.env.vault', '.env.project', '.env.keys', '.env.me', '.env.x', '.env.example']
3
+ const RESERVED_ENV_FILES = ['.env.project', '.env.keys', '.env.me', '.env.x', '.env.example']
4
4
 
5
5
  function findEnvFiles (directory) {
6
6
  try {