@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,87 +0,0 @@
1
- const fsx = require('./../../lib/helpers/fsx')
2
- const { logger } = require('./../../shared/logger')
3
-
4
- const Rotate = require('./../../lib/services/rotate')
5
-
6
- const catchAndLog = require('../../lib/helpers/catchAndLog')
7
- const createSpinner = require('../../lib/helpers/createSpinner')
8
- const Session = require('../../db/session')
9
- const normalizeArmorOptions = require('./normalizeArmorOptions')
10
-
11
- async function rotate () {
12
- const options = normalizeArmorOptions(this.opts())
13
- const spinner = await createSpinner({ ...options, text: 'rotating', frames: ['⟳', '⤾', '⥁'] })
14
-
15
- logger.debug(`options: ${JSON.stringify(options)}`)
16
-
17
- const envs = this.envs
18
- const sesh = new Session()
19
- const noArmor = options.armor === false || (await sesh.noArmor())
20
-
21
- // stdout - should not have a try so that exit codes can surface to stdout
22
- if (options.stdout) {
23
- if (spinner) spinner.stop()
24
- const {
25
- processedEnvs
26
- } = await new Rotate(envs, options.key, options.excludeKey, options.envKeysFile, noArmor, {
27
- command: process.argv.slice(2)
28
- }).run()
29
- if (spinner) spinner.stop()
30
- for (const processedEnv of processedEnvs) {
31
- console.log(processedEnv.envSrc)
32
- if (processedEnv.localPrivateKeyAdded) {
33
- console.log('')
34
- console.log(processedEnv.envKeysSrc)
35
- }
36
- }
37
- process.exit(0) // exit early
38
- } else {
39
- try {
40
- if (spinner) spinner.stop()
41
- const {
42
- processedEnvs,
43
- changedFilepaths,
44
- unchangedFilepaths
45
- } = await new Rotate(envs, options.key, options.excludeKey, options.envKeysFile, noArmor, {
46
- command: process.argv.slice(2)
47
- }).run()
48
-
49
- for (const processedEnv of processedEnvs) {
50
- logger.verbose(`rotating ${processedEnv.envFilepath} (${processedEnv.filepath})`)
51
- if (processedEnv.error) {
52
- logger.warn(processedEnv.error.messageWithHelp)
53
- } else if (processedEnv.changed) {
54
- await fsx.writeFileX(processedEnv.filepath, processedEnv.envSrc)
55
- if (processedEnv.localPrivateKeyAdded) {
56
- await fsx.writeFileX(processedEnv.envKeysFilepath, processedEnv.envKeysSrc)
57
- }
58
-
59
- logger.verbose(`rotated ${processedEnv.envFilepath} (${processedEnv.filepath})`)
60
- } else {
61
- logger.verbose(`no change ${processedEnv.envFilepath} (${processedEnv.filepath})`)
62
- }
63
- }
64
-
65
- if (spinner) spinner.stop()
66
- if (changedFilepaths.length > 0) {
67
- const remoteKeyAddedEnv = processedEnvs.find((processedEnv) => processedEnv.remotePrivateKeyAdded)
68
-
69
- let msg = `⟳ rotated (${changedFilepaths.join(',')})`
70
- if (remoteKeyAddedEnv) {
71
- msg += ' · armored ⛨'
72
- }
73
- logger.success(msg)
74
- } else if (unchangedFilepaths.length > 0) {
75
- logger.info(`○ no change (${unchangedFilepaths})`)
76
- } else {
77
- // do nothing - scenario when no .env files found
78
- }
79
- } catch (error) {
80
- if (spinner) spinner.stop()
81
- catchAndLog(error)
82
- process.exit(1)
83
- }
84
- }
85
- }
86
-
87
- module.exports = rotate
@@ -1,62 +0,0 @@
1
- const quotes = require('./quotes')
2
- const { scan } = require('@dotenvx/primitives')
3
- const escapeForRegex = require('./escapeForRegex')
4
- const escapeDollarSigns = require('./escapeDollarSigns')
5
-
6
- function append (src, key, appendValue) {
7
- let output
8
- let newPart = ''
9
-
10
- const { parsed } = scan(src, { expandDoubleQuotedNewlines: false, convertWindowsNewlines: false })
11
- const _quotes = quotes(src)
12
- if (Object.prototype.hasOwnProperty.call(parsed, key)) {
13
- const quote = _quotes[key]
14
- const values = parsed[key]
15
- const originalValue = values[values.length - 1]
16
-
17
- newPart += `${key}=${quote}${originalValue},${appendValue}${quote}`
18
-
19
- const escapedOriginalValue = escapeForRegex(originalValue)
20
-
21
- // conditionally enforce end of line
22
- let enforceEndOfLine = ''
23
- if (escapedOriginalValue === '') {
24
- enforceEndOfLine = '$' // EMPTY scenario
25
- }
26
-
27
- const currentPart = new RegExp(
28
- '^' + // start of line
29
- '(\\s*)?' + // spaces
30
- '(export\\s+)?' + // export
31
- key + // KEY
32
- '\\s*=\\s*' + // spaces (KEY = value)
33
- '["\'`]?' + // open quote
34
- escapedOriginalValue + // escaped value
35
- '["\'`]?' + // close quote
36
- enforceEndOfLine
37
- ,
38
- 'gm' // (g)lobal (m)ultiline
39
- )
40
-
41
- const saferInput = escapeDollarSigns(newPart) // cleanse user inputted capture groups ($1, $2 etc)
42
-
43
- // $1 preserves spaces
44
- // $2 preserves export
45
- output = src.replace(currentPart, `$1$2${saferInput}`)
46
- } else {
47
- newPart += `${key}="${appendValue}"`
48
-
49
- // append
50
- if (src.endsWith('\n')) {
51
- newPart = newPart + '\n'
52
- } else {
53
- newPart = '\n' + newPart
54
- }
55
-
56
- output = src + newPart
57
- }
58
-
59
- return output
60
- }
61
-
62
- module.exports = append
@@ -1,42 +0,0 @@
1
- const Session = require('../../../db/session')
2
- const ArmorKeypair = require('../../services/armorKeypair')
3
- const sanitizeCommandForMetadata = require('../sanitizeCommandForMetadata')
4
-
5
- function metadataFromOptions (options) {
6
- if (options.metadata) return options.metadata
7
- if (!options.command) return undefined
8
-
9
- return JSON.stringify({
10
- command: sanitizeCommandForMetadata(options.command)
11
- })
12
- }
13
-
14
- async function armorKeypair (existingPublicKey, options = {}) {
15
- const sesh = new Session()
16
- const token = options.token || sesh.token()
17
- if (!token) {
18
- return {
19
- publicKey: undefined,
20
- privateKey: undefined
21
- }
22
- }
23
-
24
- const json = await new ArmorKeypair(
25
- options.hostname || sesh.hostname(),
26
- token,
27
- sesh.devicePublicKey(),
28
- existingPublicKey,
29
- {
30
- envFile: options.envFilepath,
31
- team: options.team,
32
- metadata: metadataFromOptions(options)
33
- }
34
- ).run()
35
-
36
- return {
37
- publicKey: json.public_key,
38
- privateKey: json.private_key
39
- }
40
- }
41
-
42
- module.exports = armorKeypair
@@ -1,55 +0,0 @@
1
- const path = require('path')
2
- const childProcess = require('child_process')
3
-
4
- const EXEC_TIMEOUT = 5 * 60 * 1000
5
-
6
- function cliPath () {
7
- return path.resolve(__dirname, '../../../cli/dotenvx.js')
8
- }
9
-
10
- function execEnv () {
11
- const env = { ...process.env }
12
- env._TAPJS_PROCESSINFO_COVERAGE_ = '0'
13
-
14
- if (env.NODE_OPTIONS && env.NODE_OPTIONS.includes('@tapjs/processinfo')) {
15
- const nodeOptions = env.NODE_OPTIONS
16
- .split(/\s+/)
17
- .filter((option) => !option.includes('@tapjs/processinfo'))
18
- .join(' ')
19
- .trim()
20
-
21
- if (nodeOptions) {
22
- env.NODE_OPTIONS = nodeOptions
23
- } else {
24
- delete env.NODE_OPTIONS
25
- }
26
- }
27
-
28
- return env
29
- }
30
-
31
- function armorKeypairSync (_existingPublicKey, options = {}) {
32
- const args = [cliPath(), 'keypair', '--format', 'json']
33
- if (options.envFilepath) args.push('-f', options.envFilepath)
34
-
35
- let keypairs = {}
36
- try {
37
- keypairs = JSON.parse(childProcess.execFileSync(process.execPath, args, {
38
- env: execEnv(),
39
- stdio: ['inherit', 'pipe', 'inherit'],
40
- timeout: EXEC_TIMEOUT
41
- }).toString().trim())
42
- } catch (_error) {
43
- keypairs = {}
44
- }
45
-
46
- const publicKeyName = Object.keys(keypairs).find((key) => key === 'DOTENV_PUBLIC_KEY' || key.startsWith('DOTENV_PUBLIC_KEY_'))
47
- const privateKeyName = Object.keys(keypairs).find((key) => key === 'DOTENV_PRIVATE_KEY' || key.startsWith('DOTENV_PRIVATE_KEY_'))
48
-
49
- return {
50
- publicKey: keypairs[publicKeyName],
51
- privateKey: keypairs[privateKeyName]
52
- }
53
- }
54
-
55
- module.exports = armorKeypairSync
@@ -1,7 +0,0 @@
1
- const { encrypt } = require('@dotenvx/primitives')
2
-
3
- function encryptValue (value, publicKey) {
4
- return encrypt(publicKey, value)
5
- }
6
-
7
- module.exports = encryptValue
@@ -1,14 +0,0 @@
1
- const { derive, keypair } = require('@dotenvx/primitives')
2
-
3
- function localKeypair (existingPrivateKey) {
4
- if (existingPrivateKey) {
5
- return {
6
- publicKey: derive(existingPrivateKey),
7
- privateKey: existingPrivateKey
8
- }
9
- }
10
-
11
- return keypair()
12
- }
13
-
14
- module.exports = localKeypair
@@ -1,38 +0,0 @@
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
- '#/ ⛨ ARMORED KEYS: `dotenvx armor up` /',
6
- '#/----------------------------------------------------------/'
7
- ].join('\n')
8
-
9
- const path = require('path')
10
- const fsx = require('./../fsx')
11
-
12
- function mutateKeysSrcSync ({ 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.readFileXSync(resolvedKeysFilepath)
24
- }
25
- keysSrc = keysSrc.length > 1 ? keysSrc : `${FIRST_TIME_KEYS_SRC}\n`
26
- keysSrc = `${keysSrc}\n${appendPrivateKey}`
27
-
28
- fsx.writeFileXSync(resolvedKeysFilepath, keysSrc) // TODO: don't write if armor
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 = mutateKeysSrcSync
@@ -1,56 +0,0 @@
1
- const mutateSrc = require('./mutateSrc')
2
- const mutateKeysSrc = require('./mutateKeysSrc')
3
- const armorKeypair = require('./armorKeypair')
4
- const localKeypair = require('./localKeypair')
5
- const { keyNamesForEnvFile } = require('../keyResolution')
6
-
7
- async function provision ({ envSrc, envFilepath, keysFilepath, noArmor, token, selectKeyStorage, command }) {
8
- noArmor = noArmor !== false
9
- if (!noArmor && selectKeyStorage) {
10
- noArmor = await selectKeyStorage() !== 'armored'
11
- }
12
-
13
- const { publicKeyName, privateKeyName } = keyNamesForEnvFile(envFilepath)
14
-
15
- let publicKey
16
- let privateKey
17
- let keysSrc
18
- let envKeysFilepath
19
- let localPrivateKeyAdded = false
20
- let remotePrivateKeyAdded = false
21
-
22
- if (noArmor) {
23
- const kp = localKeypair()
24
- publicKey = kp.publicKey
25
- privateKey = kp.privateKey
26
- } else {
27
- const armorOptions = { token, envFilepath, command }
28
- const kp = await armorKeypair(undefined, armorOptions)
29
- publicKey = kp.publicKey
30
- privateKey = kp.privateKey
31
- }
32
-
33
- const mutated = mutateSrc({ envSrc, envFilepath, keysFilepath, publicKeyName, publicKeyValue: publicKey })
34
- envSrc = mutated.envSrc
35
-
36
- if (noArmor) {
37
- const mutated = await mutateKeysSrc({ envFilepath, keysFilepath, privateKeyName, privateKeyValue: privateKey })
38
- keysSrc = mutated.keysSrc
39
- envKeysFilepath = mutated.envKeysFilepath
40
- localPrivateKeyAdded = true
41
- } else {
42
- remotePrivateKeyAdded = true
43
- }
44
-
45
- return {
46
- envSrc,
47
- keysSrc,
48
- publicKey,
49
- privateKey,
50
- envKeysFilepath,
51
- localPrivateKeyAdded,
52
- remotePrivateKeyAdded
53
- }
54
- }
55
-
56
- module.exports = provision
@@ -1,51 +0,0 @@
1
- const mutateSrc = require('./mutateSrc')
2
- const mutateKeysSrcSync = require('./mutateKeysSrcSync')
3
- const armorKeypairSync = require('./armorKeypairSync')
4
- const localKeypair = require('./localKeypair')
5
- const { keyNamesForEnvFile } = require('../keyResolution')
6
-
7
- function provisionSync ({ envSrc, envFilepath, keysFilepath, noArmor, command }) {
8
- noArmor = noArmor !== false
9
- const { publicKeyName, privateKeyName } = keyNamesForEnvFile(envFilepath)
10
-
11
- let publicKey
12
- let privateKey
13
- let keysSrc
14
- let envKeysFilepath
15
- let localPrivateKeyAdded = false
16
- let remotePrivateKeyAdded = false
17
-
18
- if (noArmor) {
19
- const kp = localKeypair()
20
- publicKey = kp.publicKey
21
- privateKey = kp.privateKey
22
- } else {
23
- const kp = armorKeypairSync(undefined, { envFilepath, command })
24
- publicKey = kp.publicKey
25
- privateKey = kp.privateKey
26
- }
27
-
28
- const mutated = mutateSrc({ envSrc, envFilepath, keysFilepath, publicKeyName, publicKeyValue: publicKey })
29
- envSrc = mutated.envSrc
30
-
31
- if (noArmor) {
32
- const mutated = mutateKeysSrcSync({ envFilepath, keysFilepath, privateKeyName, privateKeyValue: privateKey })
33
- keysSrc = mutated.keysSrc
34
- envKeysFilepath = mutated.envKeysFilepath
35
- localPrivateKeyAdded = true
36
- } else {
37
- remotePrivateKeyAdded = true
38
- }
39
-
40
- return {
41
- envSrc,
42
- keysSrc,
43
- publicKey,
44
- privateKey,
45
- envKeysFilepath,
46
- localPrivateKeyAdded,
47
- remotePrivateKeyAdded
48
- }
49
- }
50
-
51
- module.exports = provisionSync
@@ -1,26 +0,0 @@
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) // noArmor doesn't matter here since privateKeyValue was already discovered prior (via armor 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
@@ -1,5 +0,0 @@
1
- function escapeDollarSigns (str) {
2
- return str.replace(/\$/g, '$$$$')
3
- }
4
-
5
- module.exports = escapeDollarSigns
@@ -1,5 +0,0 @@
1
- function escapeForRegex (str) {
2
- return str.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&').replace(/-/g, '\\x2d')
3
- }
4
-
5
- module.exports = escapeForRegex
@@ -1,23 +0,0 @@
1
- const { execSync } = require('child_process')
2
- const chomp = require('./chomp')
3
- const Errors = require('./errors')
4
-
5
- function evalKeyValue (key, value, processEnv, runningParsed) {
6
- // Match everything between the outermost $() using a regex with non-capturing groups
7
- const matches = value.match(/\$\(([^)]+(?:\)[^(]*)*)\)/g) || []
8
- return matches.reduce((newValue, match) => {
9
- const command = match.slice(2, -1) // Extract command by removing $() wrapper
10
- let result
11
-
12
- try {
13
- result = execSync(command, { env: { ...processEnv, ...runningParsed } }).toString() // execute command (including runningParsed)
14
- } catch (e) {
15
- throw new Errors({ key, command, message: e.message.trim() }).commandSubstitutionFailed()
16
- }
17
-
18
- result = chomp(result) // chomp it
19
- return newValue.replace(match, result) // Replace match with result
20
- }, value)
21
- }
22
-
23
- module.exports = evalKeyValue
@@ -1,19 +0,0 @@
1
- const fsx = require('./fsx')
2
- const ignore = require('ignore')
3
-
4
- function isIgnoringDotenvKeys () {
5
- if (!fsx.existsSync('.gitignore')) {
6
- return false
7
- }
8
-
9
- const gitignore = fsx.readFileXSync('.gitignore')
10
- const ig = ignore(gitignore).add(gitignore)
11
-
12
- if (!ig.ignores('.env.keys')) {
13
- return false
14
- }
15
-
16
- return true
17
- }
18
-
19
- module.exports = isIgnoringDotenvKeys
@@ -1,16 +0,0 @@
1
- module.exports = {
2
- keyNamesForEnvFile: require('./keyNamesForEnvFile'),
3
- keyValues: require('./keyValues'),
4
- keyValuesSync: require('./keyValuesSync'),
5
- keyValuesFromEnvSrc: require('./keyValuesFromEnvSrc'),
6
-
7
- // private
8
- // private keys are resolved via keyValuesSync()
9
-
10
- // other
11
- readProcessKey: require('./readProcessKey'),
12
- readFileKey: require('./readFileKey'),
13
- readFileKeySync: require('./readFileKeySync'),
14
- guessPrivateKeyFilename: require('./../guessPrivateKeyFilename'),
15
- dotenvPrivateKeyNames: require('./../dotenvPrivateKeyNames')
16
- }
@@ -1,24 +0,0 @@
1
- const canonicalEnvFilename = require('./../canonicalEnvFilename')
2
- const environment = require('./../envResolution/environment')
3
-
4
- function keyNamesForEnvFile (filepath) {
5
- const filename = canonicalEnvFilename(filepath)
6
-
7
- // .env
8
- if (filename === '.env') {
9
- return {
10
- publicKeyName: 'DOTENV_PUBLIC_KEY',
11
- privateKeyName: 'DOTENV_PRIVATE_KEY'
12
- }
13
- }
14
-
15
- // .env.ENVIRONMENT
16
- const resolvedEnvironment = environment(filename).toUpperCase()
17
-
18
- return {
19
- publicKeyName: `DOTENV_PUBLIC_KEY_${resolvedEnvironment}`,
20
- privateKeyName: `DOTENV_PRIVATE_KEY_${resolvedEnvironment}`
21
- }
22
- }
23
-
24
- module.exports = keyNamesForEnvFile
@@ -1,99 +0,0 @@
1
- const path = require('path')
2
- const { scan } = require('@dotenvx/primitives')
3
-
4
- const fsx = require('./../fsx')
5
- const keyNamesForEnvFile = require('./keyNamesForEnvFile')
6
- const readProcessKey = require('./readProcessKey')
7
- const readFileKey = require('./readFileKey')
8
- const armorKeypair = require('../cryptography/armorKeypair')
9
-
10
- async function invertForPrivateKeyName (filepath) {
11
- const PUBLIC_KEY_SCHEMA = 'DOTENV_PUBLIC_KEY'
12
- const PRIVATE_KEY_SCHEMA = 'DOTENV_PRIVATE_KEY'
13
-
14
- if (!(await fsx.exists(filepath))) {
15
- return null
16
- }
17
-
18
- const envSrc = await fsx.readFileX(filepath)
19
- const { parsed: envParsed } = scan(envSrc)
20
-
21
- let publicKeyName
22
- for (const keyName of Object.keys(envParsed)) {
23
- if (keyName === PUBLIC_KEY_SCHEMA || keyName.startsWith(PUBLIC_KEY_SCHEMA)) {
24
- publicKeyName = keyName // find DOTENV_PUBLIC_KEY* in filename
25
- }
26
- }
27
-
28
- if (publicKeyName) {
29
- return publicKeyName.replace(PUBLIC_KEY_SCHEMA, PRIVATE_KEY_SCHEMA) // return inverted (DOTENV_PUBLIC_KEY* -> DOTENV_PRIVATE_KEY*) if found
30
- }
31
-
32
- return null
33
- }
34
-
35
- async function keyValues (filepath, opts = {}) {
36
- let keysFilepath = opts.keysFilepath || null
37
- const noArmor = opts.noArmor === true
38
- const names = keyNamesForEnvFile(filepath)
39
- const publicKeyName = names.publicKeyName // DOTENV_PUBLIC_KEY_${ENVIRONMENT}
40
- let privateKeyName = names.privateKeyName // DOTENV_PRIVATE_KEY_${ENVIRONMENT}
41
-
42
- let publicKey = null
43
- let privateKey = null
44
- let privateKeySource = null
45
-
46
- // public key: process.env first, then .env*
47
- publicKey = readProcessKey(publicKeyName)
48
- if (!publicKey) {
49
- publicKey = await readFileKey(publicKeyName, filepath) || null
50
- }
51
-
52
- // private key: process.env first, then .env.keys, then invert public key
53
- privateKey = readProcessKey(privateKeyName)
54
- if (!privateKey) {
55
- if (keysFilepath) { // user specified -fk flag
56
- keysFilepath = path.resolve(keysFilepath)
57
- } else {
58
- keysFilepath = path.resolve(path.dirname(filepath), '.env.keys') // typical scenario
59
- }
60
-
61
- privateKey = await readFileKey(privateKeyName, keysFilepath)
62
- }
63
- // invert
64
- if (!privateKey) {
65
- privateKeyName = await invertForPrivateKeyName(filepath)
66
- if (privateKeyName) {
67
- privateKey = readProcessKey(privateKeyName)
68
- if (!privateKey) {
69
- privateKey = await readFileKey(privateKeyName, keysFilepath)
70
- }
71
- }
72
- }
73
-
74
- // armor
75
- if (!noArmor && !privateKey && publicKey && publicKey.length > 0) {
76
- const armorOptions = { envFilepath: filepath }
77
- if (opts.token) {
78
- armorOptions.token = opts.token
79
- }
80
- if (opts.command) {
81
- armorOptions.command = opts.command
82
- }
83
- const kp = await armorKeypair(publicKey, armorOptions)
84
- privateKey = kp.privateKey
85
- privateKeySource = 'armor'
86
- }
87
-
88
- const result = {
89
- publicKeyValue: publicKey || null, // important to make sure name is rendered
90
- privateKeyValue: privateKey || null // important to make sure name is rendered
91
- }
92
- if (privateKeySource) {
93
- result.privateKeySource = privateKeySource
94
- }
95
-
96
- return result
97
- }
98
-
99
- module.exports = keyValues