@dotenvx/dotenvx 1.56.0 → 1.57.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +24 -4
- package/README.md +61 -52
- package/package.json +1 -1
- package/src/cli/actions/decrypt.js +4 -17
- package/src/cli/actions/encrypt.js +11 -20
- package/src/cli/actions/ext/genexample.js +5 -9
- package/src/cli/actions/ext/gitignore.js +2 -2
- package/src/cli/actions/ext/prebuild.js +3 -9
- package/src/cli/actions/ext/precommit.js +3 -9
- package/src/cli/actions/ext/scan.js +2 -2
- package/src/cli/actions/get.js +3 -8
- package/src/cli/actions/rotate.js +10 -25
- package/src/cli/actions/run.js +5 -15
- package/src/cli/actions/set.js +15 -24
- package/src/cli/dotenvx.js +19 -19
- package/src/cli/examples.js +2 -2
- package/src/lib/helpers/catchAndLog.js +1 -4
- package/src/lib/helpers/conventions.js +3 -1
- package/src/lib/helpers/cryptography/decryptKeyValue.js +1 -1
- package/src/lib/helpers/errors.js +187 -32
- package/src/lib/helpers/executeCommand.js +2 -1
- package/src/lib/helpers/executeDynamic.js +45 -20
- package/src/lib/helpers/findEnvFiles.js +2 -4
- package/src/lib/helpers/installPrecommitHook.js +2 -2
- package/src/lib/helpers/localDisplayPath.js +11 -0
- package/src/lib/main.js +22 -44
- package/src/lib/services/encrypt.js +6 -1
- package/src/lib/services/genexample.js +1 -8
- package/src/lib/services/prebuild.js +12 -8
- package/src/lib/services/precommit.js +12 -8
- package/src/lib/services/rotate.js +6 -1
- package/src/lib/services/sets.js +5 -1
- package/src/shared/colors.js +17 -4
- package/src/shared/logger.js +8 -6
|
@@ -4,7 +4,7 @@ const { logger } = require('./../../shared/logger')
|
|
|
4
4
|
const Rotate = require('./../../lib/services/rotate')
|
|
5
5
|
|
|
6
6
|
const catchAndLog = require('../../lib/helpers/catchAndLog')
|
|
7
|
-
const
|
|
7
|
+
const localDisplayPath = require('../../lib/helpers/localDisplayPath')
|
|
8
8
|
|
|
9
9
|
function rotate () {
|
|
10
10
|
const options = this.opts()
|
|
@@ -38,15 +38,7 @@ function rotate () {
|
|
|
38
38
|
for (const processedEnv of processedEnvs) {
|
|
39
39
|
logger.verbose(`rotating ${processedEnv.envFilepath} (${processedEnv.filepath})`)
|
|
40
40
|
if (processedEnv.error) {
|
|
41
|
-
|
|
42
|
-
logger.warn(processedEnv.error.message)
|
|
43
|
-
logger.help(`? add one with [echo "HELLO=World" > ${processedEnv.envFilepath}] and re-run [dotenvx rotate]`)
|
|
44
|
-
} else {
|
|
45
|
-
logger.warn(processedEnv.error.message)
|
|
46
|
-
if (processedEnv.error.help) {
|
|
47
|
-
logger.help(processedEnv.error.help)
|
|
48
|
-
}
|
|
49
|
-
}
|
|
41
|
+
logger.warn(processedEnv.error.messageWithHelp)
|
|
50
42
|
} else if (processedEnv.changed) {
|
|
51
43
|
fsx.writeFileX(processedEnv.filepath, processedEnv.envSrc)
|
|
52
44
|
if (processedEnv.privateKeyAdded) {
|
|
@@ -60,25 +52,18 @@ function rotate () {
|
|
|
60
52
|
}
|
|
61
53
|
|
|
62
54
|
if (changedFilepaths.length > 0) {
|
|
63
|
-
|
|
55
|
+
const keyAddedEnv = processedEnvs.find((processedEnv) => processedEnv.privateKeyAdded)
|
|
56
|
+
let msg = `⟳ rotated (${changedFilepaths.join(',')})`
|
|
57
|
+
if (keyAddedEnv) {
|
|
58
|
+
const envKeysFilepath = localDisplayPath(keyAddedEnv.envKeysFilepath)
|
|
59
|
+
msg += ` + key (${envKeysFilepath})`
|
|
60
|
+
}
|
|
61
|
+
logger.success(msg)
|
|
64
62
|
} else if (unchangedFilepaths.length > 0) {
|
|
65
|
-
logger.info(
|
|
63
|
+
logger.info(`○ no changes (${unchangedFilepaths})`)
|
|
66
64
|
} else {
|
|
67
65
|
// do nothing - scenario when no .env files found
|
|
68
66
|
}
|
|
69
|
-
|
|
70
|
-
for (const processedEnv of processedEnvs) {
|
|
71
|
-
if (processedEnv.privateKeyAdded) {
|
|
72
|
-
logger.success(`✔ key added to .env.keys (${processedEnv.privateKeyName})`)
|
|
73
|
-
// logger.help('⮕ optional: [dotenvx ops backup] to securely backup private key')
|
|
74
|
-
|
|
75
|
-
if (!isIgnoringDotenvKeys()) {
|
|
76
|
-
logger.help('⮕ next run: [dotenvx ext gitignore --pattern .env.keys] to gitignore .env.keys')
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
logger.help(`⮕ next run: [${processedEnv.privateKeyName}='${processedEnv.privateKey}' dotenvx get] to test decryption locally`)
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
67
|
} catch (error) {
|
|
83
68
|
catchAndLog(error)
|
|
84
69
|
process.exit(1)
|
package/src/cli/actions/run.js
CHANGED
|
@@ -3,6 +3,7 @@ const { logger } = require('./../../shared/logger')
|
|
|
3
3
|
|
|
4
4
|
const executeCommand = require('./../../lib/helpers/executeCommand')
|
|
5
5
|
const Run = require('./../../lib/services/run')
|
|
6
|
+
const catchAndLog = require('./../../lib/helpers/catchAndLog')
|
|
6
7
|
|
|
7
8
|
const conventions = require('./../../lib/helpers/conventions')
|
|
8
9
|
|
|
@@ -64,18 +65,10 @@ async function run () {
|
|
|
64
65
|
|
|
65
66
|
if (options.strict) throw error // throw if strict and not ignored
|
|
66
67
|
|
|
67
|
-
if (error.code === 'MISSING_ENV_FILE') {
|
|
68
|
-
|
|
69
|
-
logger.error(error.message)
|
|
70
|
-
if (error.help) {
|
|
71
|
-
logger.error(`${error.help} and re-run [dotenvx run -- ${commandArgs.join(' ')}]`)
|
|
72
|
-
}
|
|
73
|
-
}
|
|
68
|
+
if (error.code === 'MISSING_ENV_FILE' && options.convention) { // do not output error for conventions (too noisy)
|
|
69
|
+
// intentionally quiet
|
|
74
70
|
} else {
|
|
75
|
-
logger.error(error.
|
|
76
|
-
if (error.help) {
|
|
77
|
-
logger.error(error.help)
|
|
78
|
-
}
|
|
71
|
+
logger.error(error.messageWithHelp)
|
|
79
72
|
}
|
|
80
73
|
}
|
|
81
74
|
|
|
@@ -106,10 +99,7 @@ async function run () {
|
|
|
106
99
|
|
|
107
100
|
logger.successv(msg)
|
|
108
101
|
} catch (error) {
|
|
109
|
-
|
|
110
|
-
if (error.help) {
|
|
111
|
-
logger.error(error.help)
|
|
112
|
-
}
|
|
102
|
+
catchAndLog(error)
|
|
113
103
|
process.exit(1)
|
|
114
104
|
}
|
|
115
105
|
|
package/src/cli/actions/set.js
CHANGED
|
@@ -4,7 +4,7 @@ const { logger } = require('./../../shared/logger')
|
|
|
4
4
|
const Sets = require('./../../lib/services/sets')
|
|
5
5
|
|
|
6
6
|
const catchAndLog = require('../../lib/helpers/catchAndLog')
|
|
7
|
-
const
|
|
7
|
+
const localDisplayPath = require('../../lib/helpers/localDisplayPath')
|
|
8
8
|
|
|
9
9
|
function set (key, value) {
|
|
10
10
|
logger.debug(`key: ${key}`)
|
|
@@ -40,15 +40,7 @@ function set (key, value) {
|
|
|
40
40
|
logger.verbose(`setting for ${processedEnv.envFilepath}`)
|
|
41
41
|
|
|
42
42
|
if (processedEnv.error) {
|
|
43
|
-
|
|
44
|
-
logger.warn(processedEnv.error.message)
|
|
45
|
-
logger.help(`? add one with [echo "HELLO=World" > ${processedEnv.envFilepath}] and re-run [dotenvx set]`)
|
|
46
|
-
} else {
|
|
47
|
-
logger.warn(processedEnv.error.message)
|
|
48
|
-
if (processedEnv.error.help) {
|
|
49
|
-
logger.help(processedEnv.error.help)
|
|
50
|
-
}
|
|
51
|
-
}
|
|
43
|
+
logger.warn(processedEnv.error.messageWithHelp)
|
|
52
44
|
} else {
|
|
53
45
|
fsx.writeFileX(processedEnv.filepath, processedEnv.envSrc)
|
|
54
46
|
|
|
@@ -57,26 +49,25 @@ function set (key, value) {
|
|
|
57
49
|
}
|
|
58
50
|
}
|
|
59
51
|
|
|
52
|
+
const keyAddedEnv = processedEnvs.find((processedEnv) => processedEnv.privateKeyAdded)
|
|
53
|
+
const keyAddedSuffix = keyAddedEnv ? ` + key (${localDisplayPath(keyAddedEnv.envKeysFilepath)})` : ''
|
|
54
|
+
|
|
60
55
|
if (changedFilepaths.length > 0) {
|
|
61
|
-
|
|
56
|
+
if (encrypt) {
|
|
57
|
+
logger.success(`◈ encrypted ${key} (${changedFilepaths.join(',')})${keyAddedSuffix}`)
|
|
58
|
+
} else {
|
|
59
|
+
logger.success(`◇ set ${key} (${changedFilepaths.join(',')})`)
|
|
60
|
+
}
|
|
61
|
+
} else if (encrypt && keyAddedEnv) {
|
|
62
|
+
const keyAddedEnvFilepath = keyAddedEnv.envFilepath || changedFilepaths[0] || '.env'
|
|
63
|
+
logger.success(`◈ encrypted ${key} (${keyAddedEnvFilepath})${keyAddedSuffix}`)
|
|
62
64
|
} else if (unchangedFilepaths.length > 0) {
|
|
63
|
-
logger.info(
|
|
65
|
+
logger.info(`○ no changes (${unchangedFilepaths})`)
|
|
64
66
|
} else {
|
|
65
67
|
// do nothing
|
|
66
68
|
}
|
|
67
69
|
|
|
68
|
-
|
|
69
|
-
if (processedEnv.privateKeyAdded) { // TODO: change to localPrivateKeyAdded
|
|
70
|
-
logger.success(`✔ key added to ${processedEnv.envKeysFilepath} (${processedEnv.privateKeyName})`)
|
|
71
|
-
// logger.help('⮕ optional: [dotenvx ops backup] to securely backup private key')
|
|
72
|
-
|
|
73
|
-
if (!isIgnoringDotenvKeys()) {
|
|
74
|
-
logger.help('⮕ next run: [dotenvx ext gitignore --pattern .env.keys] to gitignore .env.keys')
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
logger.help(`⮕ next run: [${processedEnv.privateKeyName}='${processedEnv.privateKey}' dotenvx get ${key}] to test decryption locally`)
|
|
78
|
-
}
|
|
79
|
-
}
|
|
70
|
+
// intentionally quiet: success line communicates key creation
|
|
80
71
|
} catch (error) {
|
|
81
72
|
catchAndLog(error)
|
|
82
73
|
process.exit(1)
|
package/src/cli/dotenvx.js
CHANGED
|
@@ -30,8 +30,7 @@ const commanderVersion = getCommanderVersion()
|
|
|
30
30
|
if (commanderVersion && parseInt(commanderVersion.split('.')[0], 10) >= 12) {
|
|
31
31
|
const message = `dotenvx depends on commander@11.x.x but you are attempting to hoist commander@${commanderVersion}`
|
|
32
32
|
const error = new Errors({ message }).dangerousDependencyHoist()
|
|
33
|
-
logger.error(error.
|
|
34
|
-
if (error.help) logger.error(error.help)
|
|
33
|
+
logger.error(error.messageWithHelp)
|
|
35
34
|
}
|
|
36
35
|
|
|
37
36
|
// global log levels
|
|
@@ -108,7 +107,7 @@ program.command('get')
|
|
|
108
107
|
const setAction = require('./actions/set')
|
|
109
108
|
program.command('set')
|
|
110
109
|
.usage('<KEY> <value> [options]')
|
|
111
|
-
.description('
|
|
110
|
+
.description('encrypt a single environment variable')
|
|
112
111
|
.addHelpText('after', examples.set)
|
|
113
112
|
.allowUnknownOption()
|
|
114
113
|
.argument('KEY', 'KEY')
|
|
@@ -153,6 +152,21 @@ program.command('decrypt')
|
|
|
153
152
|
decryptAction.apply(this, args)
|
|
154
153
|
})
|
|
155
154
|
|
|
155
|
+
// dotenvx rotate
|
|
156
|
+
const rotateAction = require('./actions/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('--ops-off', 'disable dotenvx-ops features', sesh.opsOff())
|
|
164
|
+
.option('--stdout', 'send to stdout')
|
|
165
|
+
.action(function (...args) {
|
|
166
|
+
this.envs = envs
|
|
167
|
+
rotateAction.apply(this, args)
|
|
168
|
+
})
|
|
169
|
+
|
|
156
170
|
// dotenvx keypair
|
|
157
171
|
const keypairAction = require('./actions/keypair')
|
|
158
172
|
program.command('keypair')
|
|
@@ -176,21 +190,6 @@ program.command('ls')
|
|
|
176
190
|
.option('-ef, --exclude-env-file <excludeFilenames...>', 'path(s) to exclude from your env file(s) (default: none)')
|
|
177
191
|
.action(lsAction)
|
|
178
192
|
|
|
179
|
-
// dotenvx rotate
|
|
180
|
-
const rotateAction = require('./actions/rotate')
|
|
181
|
-
program.command('rotate')
|
|
182
|
-
.description('rotate keypair(s) and re-encrypt .env file(s)')
|
|
183
|
-
.option('-f, --env-file <paths...>', 'path(s) to your env file(s)', collectEnvs('envFile'), [])
|
|
184
|
-
.option('-fk, --env-keys-file <path>', 'path to your .env.keys file (default: same path as your env file)')
|
|
185
|
-
.option('-k, --key <keys...>', 'keys(s) to encrypt (default: all keys in file)')
|
|
186
|
-
.option('-ek, --exclude-key <excludeKeys...>', 'keys(s) to exclude from encryption (default: none)')
|
|
187
|
-
.option('--ops-off', 'disable dotenvx-ops features', sesh.opsOff())
|
|
188
|
-
.option('--stdout', 'send to stdout')
|
|
189
|
-
.action(function (...args) {
|
|
190
|
-
this.envs = envs
|
|
191
|
-
rotateAction.apply(this, args)
|
|
192
|
-
})
|
|
193
|
-
|
|
194
193
|
// dotenvx help
|
|
195
194
|
program.command('help [command]')
|
|
196
195
|
.description('display help for command')
|
|
@@ -252,7 +251,8 @@ program.helpInformation = function () {
|
|
|
252
251
|
const filteredLines = lines.filter(line =>
|
|
253
252
|
!line.includes('DEPRECATED') &&
|
|
254
253
|
!line.includes('help [command]') &&
|
|
255
|
-
!line.includes('🔌 extensions')
|
|
254
|
+
!line.includes('🔌 extensions') &&
|
|
255
|
+
!/^\s*ls\b/.test(line)
|
|
256
256
|
)
|
|
257
257
|
|
|
258
258
|
return filteredLines.join('\n')
|
package/src/cli/examples.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
const Errors = require('./errors')
|
|
2
|
+
|
|
1
3
|
function conventions (convention) {
|
|
2
4
|
const env = process.env.DOTENV_ENV || process.env.NODE_ENV || 'development'
|
|
3
5
|
|
|
@@ -19,7 +21,7 @@ function conventions (convention) {
|
|
|
19
21
|
{ type: 'envFile', value: '.env.defaults' }
|
|
20
22
|
]
|
|
21
23
|
} else {
|
|
22
|
-
throw new
|
|
24
|
+
throw new Errors({ convention }).invalidConvention()
|
|
23
25
|
}
|
|
24
26
|
}
|
|
25
27
|
|
|
@@ -30,7 +30,7 @@ function decryptKeyValue (key, value, privateKeyName, privateKey) {
|
|
|
30
30
|
if (e.message === 'Invalid private key') {
|
|
31
31
|
decryptionError = new Errors({ key, privateKeyName, privateKey }).invalidPrivateKey()
|
|
32
32
|
} else if (e.message === 'Unsupported state or unable to authenticate data') {
|
|
33
|
-
decryptionError = new Errors({ key, privateKeyName, privateKey }).
|
|
33
|
+
decryptionError = new Errors({ key, privateKeyName, privateKey }).wrongPrivateKey()
|
|
34
34
|
} else if (e.message === 'Point of length 65 was invalid. Expected 33 compressed bytes or 65 uncompressed bytes') {
|
|
35
35
|
decryptionError = new Errors({ key, privateKeyName, privateKey }).malformedEncryptedData()
|
|
36
36
|
} else {
|
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
const truncate = require('./truncate')
|
|
2
2
|
|
|
3
|
+
const ISSUE_BY_CODE = {
|
|
4
|
+
COMMAND_EXITED_WITH_CODE: 'https://github.com/dotenvx/dotenvx/issues/new',
|
|
5
|
+
COMMAND_SUBSTITUTION_FAILED: 'https://github.com/dotenvx/dotenvx/issues/532',
|
|
6
|
+
DECRYPTION_FAILED: 'https://github.com/dotenvx/dotenvx/issues/757',
|
|
7
|
+
DANGEROUS_DEPENDENCY_HOIST: 'https://github.com/dotenvx/dotenvx/issues/622',
|
|
8
|
+
INVALID_COLOR: 'must be 256 colors',
|
|
9
|
+
INVALID_CONVENTION: 'https://github.com/dotenvx/dotenvx/issues/761',
|
|
10
|
+
INVALID_PRIVATE_KEY: 'https://github.com/dotenvx/dotenvx/issues/465',
|
|
11
|
+
INVALID_PUBLIC_KEY: 'https://github.com/dotenvx/dotenvx/issues/756',
|
|
12
|
+
MALFORMED_ENCRYPTED_DATA: 'https://github.com/dotenvx/dotenvx/issues/467',
|
|
13
|
+
MISPAIRED_PRIVATE_KEY: 'https://github.com/dotenvx/dotenvx/issues/752',
|
|
14
|
+
MISSING_DIRECTORY: 'https://github.com/dotenvx/dotenvx/issues/758',
|
|
15
|
+
MISSING_ENV_FILE: 'https://github.com/dotenvx/dotenvx/issues/484',
|
|
16
|
+
MISSING_ENV_FILES: 'https://github.com/dotenvx/dotenvx/issues/760',
|
|
17
|
+
MISSING_KEY: 'https://github.com/dotenvx/dotenvx/issues/759',
|
|
18
|
+
MISSING_LOG_LEVEL: 'must be valid log level',
|
|
19
|
+
MISSING_PRIVATE_KEY: 'https://github.com/dotenvx/dotenvx/issues/464',
|
|
20
|
+
PRECOMMIT_HOOK_MODIFY_FAILED: 'try again or report error',
|
|
21
|
+
WRONG_PRIVATE_KEY: 'https://github.com/dotenvx/dotenvx/issues/466'
|
|
22
|
+
}
|
|
23
|
+
|
|
3
24
|
class Errors {
|
|
4
25
|
constructor (options = {}) {
|
|
5
26
|
this.filepath = options.filepath
|
|
@@ -8,118 +29,252 @@ class Errors {
|
|
|
8
29
|
this.key = options.key
|
|
9
30
|
this.privateKey = options.privateKey
|
|
10
31
|
this.privateKeyName = options.privateKeyName
|
|
32
|
+
this.publicKeyName = options.publicKeyName
|
|
11
33
|
this.publicKey = options.publicKey
|
|
12
34
|
this.publicKeyExisting = options.publicKeyExisting
|
|
13
35
|
this.command = options.command
|
|
14
36
|
|
|
15
37
|
this.message = options.message
|
|
38
|
+
this.code = options.code
|
|
39
|
+
this.help = options.help
|
|
40
|
+
this.debug = options.debug
|
|
41
|
+
|
|
42
|
+
this.convention = options.convention
|
|
43
|
+
this.directory = options.directory
|
|
44
|
+
this.exitCode = options.exitCode
|
|
45
|
+
this.level = options.level
|
|
46
|
+
this.color = options.color
|
|
47
|
+
this.error = options.error
|
|
16
48
|
}
|
|
17
49
|
|
|
18
|
-
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
50
|
+
custom () {
|
|
51
|
+
const e = new Error(this.message)
|
|
52
|
+
if (this.code) e.code = this.code
|
|
53
|
+
if (this.help) e.help = this.help
|
|
54
|
+
if (this.code && !e.help) e.help = `fix: [${ISSUE_BY_CODE[this.code]}]`
|
|
55
|
+
e.messageWithHelp = `${e.message}. ${e.help}`
|
|
56
|
+
if (this.debug) e.debug = this.debug
|
|
57
|
+
return e
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
commandExitedWithCode () {
|
|
61
|
+
const code = 'COMMAND_EXITED_WITH_CODE'
|
|
62
|
+
const message = `[${code}] Command exited with exit code ${this.exitCode}`
|
|
63
|
+
const help = `fix: [${ISSUE_BY_CODE[code]}]`
|
|
22
64
|
|
|
23
65
|
const e = new Error(message)
|
|
24
66
|
e.code = code
|
|
25
67
|
e.help = help
|
|
68
|
+
e.messageWithHelp = `${message}. ${help}`
|
|
26
69
|
return e
|
|
27
70
|
}
|
|
28
71
|
|
|
29
|
-
|
|
30
|
-
const code = '
|
|
31
|
-
const message = `[${code}]
|
|
72
|
+
commandSubstitutionFailed () {
|
|
73
|
+
const code = 'COMMAND_SUBSTITUTION_FAILED'
|
|
74
|
+
const message = `[${code}] could not eval ${this.key} containing command '${this.command}': ${this.message}`
|
|
75
|
+
const help = `fix: [${ISSUE_BY_CODE[code]}]`
|
|
32
76
|
|
|
33
77
|
const e = new Error(message)
|
|
34
78
|
e.code = code
|
|
79
|
+
e.help = help
|
|
80
|
+
e.messageWithHelp = `${message}. ${help}`
|
|
35
81
|
return e
|
|
36
82
|
}
|
|
37
83
|
|
|
38
|
-
|
|
39
|
-
const code = '
|
|
40
|
-
const message = `[${code}]
|
|
41
|
-
const help = `[${code}]
|
|
84
|
+
decryptionFailed () {
|
|
85
|
+
const code = 'DECRYPTION_FAILED'
|
|
86
|
+
const message = `[${code}] ${this.message}`
|
|
87
|
+
const help = `fix: [${ISSUE_BY_CODE[code]}]`
|
|
42
88
|
|
|
43
89
|
const e = new Error(message)
|
|
44
90
|
e.code = code
|
|
45
91
|
e.help = help
|
|
92
|
+
e.messageWithHelp = `${message}. ${help}`
|
|
93
|
+
return e
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
dangerousDependencyHoist () {
|
|
97
|
+
const code = 'DANGEROUS_DEPENDENCY_HOIST'
|
|
98
|
+
const message = `[${code}] your environment has hoisted an incompatible version of a dotenvx dependency: ${this.message}`
|
|
99
|
+
const help = `fix: [${ISSUE_BY_CODE[code]}]`
|
|
100
|
+
|
|
101
|
+
const e = new Error(message)
|
|
102
|
+
e.code = code
|
|
103
|
+
e.help = help
|
|
104
|
+
e.messageWithHelp = `${message}. ${help}`
|
|
105
|
+
return e
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
invalidColor () {
|
|
109
|
+
const code = 'INVALID_COLOR'
|
|
110
|
+
const message = `[${code}] Invalid color ${this.color}`
|
|
111
|
+
const help = `fix: [${ISSUE_BY_CODE[code]}]`
|
|
112
|
+
|
|
113
|
+
const e = new Error(message)
|
|
114
|
+
e.code = code
|
|
115
|
+
e.help = help
|
|
116
|
+
e.messageWithHelp = `${message}. ${help}`
|
|
117
|
+
return e
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
invalidConvention () {
|
|
121
|
+
const code = 'INVALID_CONVENTION'
|
|
122
|
+
const message = `[${code}] invalid convention (${this.convention})`
|
|
123
|
+
const help = `fix: [${ISSUE_BY_CODE[code]}]`
|
|
124
|
+
|
|
125
|
+
const e = new Error(message)
|
|
126
|
+
e.code = code
|
|
127
|
+
e.help = help
|
|
128
|
+
e.messageWithHelp = `${message}. ${help}`
|
|
46
129
|
return e
|
|
47
130
|
}
|
|
48
131
|
|
|
49
132
|
invalidPrivateKey () {
|
|
50
133
|
const code = 'INVALID_PRIVATE_KEY'
|
|
51
134
|
const message = `[${code}] could not decrypt ${this.key} using private key '${this.privateKeyName}=${truncate(this.privateKey)}'`
|
|
52
|
-
const help = `[${code}]
|
|
135
|
+
const help = `fix: [${ISSUE_BY_CODE[code]}]`
|
|
53
136
|
|
|
54
137
|
const e = new Error(message)
|
|
55
138
|
e.code = code
|
|
56
139
|
e.help = help
|
|
140
|
+
e.messageWithHelp = `${message}. ${help}`
|
|
141
|
+
return e
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
invalidPublicKey () {
|
|
145
|
+
const code = 'INVALID_PUBLIC_KEY'
|
|
146
|
+
const message = `[${code}] could not encrypt using public key '${this.publicKeyName}=${truncate(this.publicKey)}'`
|
|
147
|
+
const help = `fix: [${ISSUE_BY_CODE[code]}]`
|
|
148
|
+
|
|
149
|
+
const e = new Error(message)
|
|
150
|
+
e.code = code
|
|
151
|
+
e.help = help
|
|
152
|
+
e.messageWithHelp = `${message}. ${help}`
|
|
153
|
+
return e
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
malformedEncryptedData () {
|
|
157
|
+
const code = 'MALFORMED_ENCRYPTED_DATA'
|
|
158
|
+
const message = `[${code}] could not decrypt ${this.key} because encrypted data appears malformed`
|
|
159
|
+
const help = `fix: [${ISSUE_BY_CODE[code]}]`
|
|
160
|
+
|
|
161
|
+
const e = new Error(message)
|
|
162
|
+
e.code = code
|
|
163
|
+
e.help = help
|
|
164
|
+
e.messageWithHelp = `${message}. ${help}`
|
|
57
165
|
return e
|
|
58
166
|
}
|
|
59
167
|
|
|
60
168
|
mispairedPrivateKey () {
|
|
61
169
|
const code = 'MISPAIRED_PRIVATE_KEY'
|
|
62
170
|
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}]
|
|
171
|
+
const help = `fix: [${ISSUE_BY_CODE[code]}]`
|
|
64
172
|
|
|
65
173
|
const e = new Error(message)
|
|
66
174
|
e.code = code
|
|
67
175
|
e.help = help
|
|
176
|
+
e.messageWithHelp = `${message}. ${help}`
|
|
68
177
|
return e
|
|
69
178
|
}
|
|
70
179
|
|
|
71
|
-
|
|
72
|
-
const code = '
|
|
73
|
-
const message = `[${code}]
|
|
74
|
-
const help = `[${code}]
|
|
180
|
+
missingDirectory () {
|
|
181
|
+
const code = 'MISSING_DIRECTORY'
|
|
182
|
+
const message = `[${code}] missing directory (${this.directory})`
|
|
183
|
+
const help = `fix: [${ISSUE_BY_CODE[code]}]`
|
|
75
184
|
|
|
76
185
|
const e = new Error(message)
|
|
77
186
|
e.code = code
|
|
78
187
|
e.help = help
|
|
188
|
+
e.messageWithHelp = `${message}. ${help}`
|
|
79
189
|
return e
|
|
80
190
|
}
|
|
81
191
|
|
|
82
|
-
|
|
83
|
-
const code = '
|
|
84
|
-
const
|
|
85
|
-
const
|
|
192
|
+
missingEnvFile () {
|
|
193
|
+
const code = 'MISSING_ENV_FILE'
|
|
194
|
+
const envFilepath = this.envFilepath || '.env'
|
|
195
|
+
const message = `[${code}] missing file (${envFilepath})`
|
|
196
|
+
const help = `fix: [${ISSUE_BY_CODE[code]}]`
|
|
86
197
|
|
|
87
198
|
const e = new Error(message)
|
|
88
199
|
e.code = code
|
|
89
200
|
e.help = help
|
|
201
|
+
e.messageWithHelp = `${message}. ${help}`
|
|
90
202
|
return e
|
|
91
203
|
}
|
|
92
204
|
|
|
93
|
-
|
|
94
|
-
const code = '
|
|
95
|
-
const message =
|
|
205
|
+
missingEnvFiles () {
|
|
206
|
+
const code = 'MISSING_ENV_FILES'
|
|
207
|
+
const message = `[${code}] no .env* files found`
|
|
208
|
+
const help = `fix: [${ISSUE_BY_CODE[code]}]`
|
|
96
209
|
|
|
97
210
|
const e = new Error(message)
|
|
98
211
|
e.code = code
|
|
212
|
+
e.help = help
|
|
213
|
+
e.messageWithHelp = `${message}. ${help}`
|
|
99
214
|
return e
|
|
100
215
|
}
|
|
101
216
|
|
|
102
|
-
|
|
103
|
-
const code = '
|
|
104
|
-
const message = `[${code}]
|
|
105
|
-
const help = `[${code}]
|
|
217
|
+
missingKey () {
|
|
218
|
+
const code = 'MISSING_KEY'
|
|
219
|
+
const message = `[${code}] missing key (${this.key})`
|
|
220
|
+
const help = `fix: [${ISSUE_BY_CODE[code]}]`
|
|
106
221
|
|
|
107
222
|
const e = new Error(message)
|
|
108
223
|
e.code = code
|
|
109
224
|
e.help = help
|
|
225
|
+
e.messageWithHelp = `${message}. ${help}`
|
|
110
226
|
return e
|
|
111
227
|
}
|
|
112
228
|
|
|
113
|
-
|
|
114
|
-
const code = '
|
|
115
|
-
const message = `[${code}]
|
|
116
|
-
const help = `[${code}]
|
|
229
|
+
missingLogLevel () {
|
|
230
|
+
const code = 'MISSING_LOG_LEVEL'
|
|
231
|
+
const message = `[${code}] missing log level '${this.level}'. implement in logger`
|
|
232
|
+
const help = `fix: [${ISSUE_BY_CODE[code]}]`
|
|
233
|
+
|
|
234
|
+
const e = new Error(message)
|
|
235
|
+
e.code = code
|
|
236
|
+
e.help = help
|
|
237
|
+
e.messageWithHelp = `${message}. ${help}`
|
|
238
|
+
return e
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
missingPrivateKey () {
|
|
242
|
+
const code = 'MISSING_PRIVATE_KEY'
|
|
243
|
+
const message = `[${code}] could not decrypt ${this.key} using private key '${this.privateKeyName}=${truncate(this.privateKey)}'`
|
|
244
|
+
const help = `fix: [${ISSUE_BY_CODE[code]}]`
|
|
245
|
+
|
|
246
|
+
const e = new Error(message)
|
|
247
|
+
e.code = code
|
|
248
|
+
e.help = help
|
|
249
|
+
e.messageWithHelp = `${message}. ${help}`
|
|
250
|
+
return e
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
precommitHookModifyFailed () {
|
|
254
|
+
const code = 'PRECOMMIT_HOOK_MODIFY_FAILED'
|
|
255
|
+
const message = `[${code}] failed to modify pre-commit hook: ${this.error.message}`
|
|
256
|
+
const help = `fix: [${ISSUE_BY_CODE[code]}]`
|
|
117
257
|
|
|
118
258
|
const e = new Error(message)
|
|
119
259
|
e.code = code
|
|
120
260
|
e.help = help
|
|
261
|
+
e.messageWithHelp = `${message}. ${help}`
|
|
262
|
+
return e
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
wrongPrivateKey () {
|
|
266
|
+
const code = 'WRONG_PRIVATE_KEY'
|
|
267
|
+
const message = `[${code}] could not decrypt ${this.key} using private key '${this.privateKeyName}=${truncate(this.privateKey)}'`
|
|
268
|
+
const help = `fix: [${ISSUE_BY_CODE[code]}]`
|
|
269
|
+
|
|
270
|
+
const e = new Error(message)
|
|
271
|
+
e.code = code
|
|
272
|
+
e.help = help
|
|
273
|
+
e.messageWithHelp = `${message}. ${help}`
|
|
121
274
|
return e
|
|
122
275
|
}
|
|
123
276
|
}
|
|
124
277
|
|
|
278
|
+
Errors.ISSUE_BY_CODE = ISSUE_BY_CODE
|
|
279
|
+
|
|
125
280
|
module.exports = Errors
|
|
@@ -2,6 +2,7 @@ const path = require('path')
|
|
|
2
2
|
const which = require('which')
|
|
3
3
|
const execute = require('./../../lib/helpers/execute')
|
|
4
4
|
const { logger } = require('./../../shared/logger')
|
|
5
|
+
const Errors = require('./errors')
|
|
5
6
|
|
|
6
7
|
async function executeCommand (commandArgs, env) {
|
|
7
8
|
const signals = [
|
|
@@ -91,7 +92,7 @@ async function executeCommand (commandArgs, env) {
|
|
|
91
92
|
|
|
92
93
|
if (exitCode !== 0) {
|
|
93
94
|
logger.debug(`received exitCode ${exitCode}`)
|
|
94
|
-
throw new
|
|
95
|
+
throw new Errors({ exitCode }).commandExitedWithCode()
|
|
95
96
|
}
|
|
96
97
|
} catch (error) {
|
|
97
98
|
// no color on these errors as they can be standard errors for things like jest exiting with exitCode 1 for a single failed test.
|