@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
|
@@ -1,7 +1,50 @@
|
|
|
1
1
|
const path = require('path')
|
|
2
|
+
const fs = require('fs')
|
|
2
3
|
const childProcess = require('child_process')
|
|
3
4
|
const { logger } = require('../../shared/logger')
|
|
4
5
|
|
|
6
|
+
function installCommandForOps () {
|
|
7
|
+
const userAgent = process.env.npm_config_user_agent || ''
|
|
8
|
+
if (userAgent.startsWith('pnpm/')) return 'pnpm add -g @dotenvx/dotenvx-ops'
|
|
9
|
+
if (userAgent.startsWith('yarn/')) return 'yarn global add @dotenvx/dotenvx-ops'
|
|
10
|
+
if (userAgent.startsWith('npm/')) return 'npm i -g @dotenvx/dotenvx-ops'
|
|
11
|
+
|
|
12
|
+
const cwd = process.cwd()
|
|
13
|
+
if (fs.existsSync(path.join(cwd, 'pnpm-lock.yaml'))) return 'pnpm add -g @dotenvx/dotenvx-ops'
|
|
14
|
+
if (fs.existsSync(path.join(cwd, 'yarn.lock'))) return 'yarn global add @dotenvx/dotenvx-ops'
|
|
15
|
+
if (
|
|
16
|
+
fs.existsSync(path.join(cwd, 'package-lock.json')) ||
|
|
17
|
+
fs.existsSync(path.join(cwd, 'npm-shrinkwrap.json'))
|
|
18
|
+
) return 'npm i -g @dotenvx/dotenvx-ops'
|
|
19
|
+
|
|
20
|
+
if (fs.existsSync(path.join(cwd, 'package.json'))) return 'npm i -g @dotenvx/dotenvx-ops'
|
|
21
|
+
|
|
22
|
+
return 'curl -sfS https://dotenvx.sh/ops | sh'
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function opsBanner (installCommand) {
|
|
26
|
+
const lines = [
|
|
27
|
+
'',
|
|
28
|
+
' ██████╗ ██████╗ ███████╗',
|
|
29
|
+
' ██╔═══██╗██╔══██╗██╔════╝',
|
|
30
|
+
' ██║ ██║██████╔╝███████╗',
|
|
31
|
+
' ██║ ██║██╔═══╝ ╚════██║',
|
|
32
|
+
' ╚██████╔╝██║ ███████║',
|
|
33
|
+
' ╚═════╝ ╚═╝ ╚══════╝',
|
|
34
|
+
'',
|
|
35
|
+
' KEYS OFF COMPUTER: Add hardened key protection with dotenvx-ops.',
|
|
36
|
+
` Install now: [${installCommand}]`,
|
|
37
|
+
' Learn more: [https://dotenvx.com/ops]'
|
|
38
|
+
]
|
|
39
|
+
|
|
40
|
+
const innerWidth = Math.max(67, ...lines.map((line) => line.length))
|
|
41
|
+
const top = ` ${'_'.repeat(innerWidth)}`
|
|
42
|
+
const middle = lines.map((line) => `|${line.padEnd(innerWidth)}|`).join('\n')
|
|
43
|
+
const bottom = `|${'_'.repeat(innerWidth)}|`
|
|
44
|
+
|
|
45
|
+
return `${top}\n${middle}\n${bottom}`
|
|
46
|
+
}
|
|
47
|
+
|
|
5
48
|
function executeDynamic (program, command, rawArgs) {
|
|
6
49
|
if (!command) {
|
|
7
50
|
program.outputHelp()
|
|
@@ -23,26 +66,8 @@ function executeDynamic (program, command, rawArgs) {
|
|
|
23
66
|
const result = childProcess.spawnSync(`dotenvx-${command}`, forwardedArgs, { stdio: 'inherit', env })
|
|
24
67
|
if (result.error) {
|
|
25
68
|
if (command === 'ops') {
|
|
26
|
-
const
|
|
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
|
-
|_______________________________________________________________________|`
|
|
40
|
-
|
|
41
|
-
console.log(ops)
|
|
42
|
-
console.log('')
|
|
43
|
-
logger.warn(`[INSTALLATION_NEEDED] install dotenvx-${command} to use [dotenvx ${command}] 🛡️`)
|
|
44
|
-
logger.help('⮕ next run: [curl -sfS https://dotenvx.sh/ops | sh]')
|
|
45
|
-
logger.help('⮕ see more: [https://dotenvx.com/ops]')
|
|
69
|
+
const installCommand = installCommandForOps()
|
|
70
|
+
console.log(opsBanner(installCommand))
|
|
46
71
|
} else {
|
|
47
72
|
logger.info(`error: unknown command '${command}'`)
|
|
48
73
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const fsx = require('./fsx')
|
|
2
|
+
const Errors = require('./errors')
|
|
2
3
|
|
|
3
4
|
const RESERVED_ENV_FILES = ['.env.project', '.env.keys', '.env.me', '.env.x', '.env.example']
|
|
4
5
|
|
|
@@ -14,10 +15,7 @@ function findEnvFiles (directory) {
|
|
|
14
15
|
return envFiles
|
|
15
16
|
} catch (e) {
|
|
16
17
|
if (e.code === 'ENOENT') {
|
|
17
|
-
|
|
18
|
-
error.code = 'MISSING_DIRECTORY'
|
|
19
|
-
|
|
20
|
-
throw error
|
|
18
|
+
throw new Errors({ directory }).missingDirectory()
|
|
21
19
|
} else {
|
|
22
20
|
throw e
|
|
23
21
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
const fsx = require('./fsx')
|
|
2
2
|
const path = require('path')
|
|
3
|
+
const Errors = require('./errors')
|
|
3
4
|
|
|
4
5
|
const HOOK_SCRIPT = `#!/bin/sh
|
|
5
6
|
|
|
@@ -45,8 +46,7 @@ class InstallPrecommitHook {
|
|
|
45
46
|
successMessage
|
|
46
47
|
}
|
|
47
48
|
} catch (err) {
|
|
48
|
-
|
|
49
|
-
throw error
|
|
49
|
+
throw new Errors({ error: err }).precommitHookModifyFailed()
|
|
50
50
|
}
|
|
51
51
|
}
|
|
52
52
|
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
const path = require('path')
|
|
2
|
+
|
|
3
|
+
function localDisplayPath (filepath) {
|
|
4
|
+
if (!filepath) return '.env.keys'
|
|
5
|
+
if (!path.isAbsolute(filepath)) return filepath
|
|
6
|
+
|
|
7
|
+
const relative = path.relative(process.cwd(), filepath)
|
|
8
|
+
return relative || path.basename(filepath)
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
module.exports = localDisplayPath
|
package/src/lib/main.js
CHANGED
|
@@ -17,7 +17,7 @@ const Genexample = require('./services/genexample')
|
|
|
17
17
|
const buildEnvs = require('./helpers/buildEnvs')
|
|
18
18
|
const Parse = require('./helpers/parse')
|
|
19
19
|
const fsx = require('./helpers/fsx')
|
|
20
|
-
const
|
|
20
|
+
const localDisplayPath = require('./helpers/localDisplayPath')
|
|
21
21
|
|
|
22
22
|
/** @type {import('./main').config} */
|
|
23
23
|
const config = function (options = {}) {
|
|
@@ -81,16 +81,10 @@ const config = function (options = {}) {
|
|
|
81
81
|
|
|
82
82
|
if (error.code === 'MISSING_ENV_FILE') {
|
|
83
83
|
if (!options.convention) { // do not output error for conventions (too noisy)
|
|
84
|
-
logger.error(error.
|
|
85
|
-
if (error.help) {
|
|
86
|
-
logger.error(error.help)
|
|
87
|
-
}
|
|
84
|
+
logger.error(error.messageWithHelp)
|
|
88
85
|
}
|
|
89
86
|
} else {
|
|
90
|
-
logger.error(error.
|
|
91
|
-
if (error.help) {
|
|
92
|
-
logger.error(error.help)
|
|
93
|
-
}
|
|
87
|
+
logger.error(error.messageWithHelp)
|
|
94
88
|
}
|
|
95
89
|
}
|
|
96
90
|
|
|
@@ -127,10 +121,7 @@ const config = function (options = {}) {
|
|
|
127
121
|
} catch (error) {
|
|
128
122
|
if (strict) throw error // throw immediately if strict
|
|
129
123
|
|
|
130
|
-
logger.error(error.
|
|
131
|
-
if (error.help) {
|
|
132
|
-
logger.help(error.help)
|
|
133
|
-
}
|
|
124
|
+
logger.error(error.messageWithHelp)
|
|
134
125
|
|
|
135
126
|
return { parsed: {}, error }
|
|
136
127
|
}
|
|
@@ -154,10 +145,7 @@ const parse = function (src, options = {}) {
|
|
|
154
145
|
|
|
155
146
|
// display any errors
|
|
156
147
|
for (const error of errors) {
|
|
157
|
-
logger.error(error.
|
|
158
|
-
if (error.help) {
|
|
159
|
-
logger.error(error.help)
|
|
160
|
-
}
|
|
148
|
+
logger.error(error.messageWithHelp)
|
|
161
149
|
}
|
|
162
150
|
|
|
163
151
|
return parsed
|
|
@@ -199,15 +187,9 @@ const set = function (key, value, options = {}) {
|
|
|
199
187
|
logger.verbose(`setting for ${processedEnv.envFilepath}`)
|
|
200
188
|
|
|
201
189
|
if (processedEnv.error) {
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
} else {
|
|
206
|
-
logger.warn(processedEnv.error.message)
|
|
207
|
-
if (processedEnv.error.help) {
|
|
208
|
-
logger.help(processedEnv.error.help)
|
|
209
|
-
}
|
|
210
|
-
}
|
|
190
|
+
const error = processedEnv.error
|
|
191
|
+
const message = error.messageWithHelp || (error.help ? `${error.message}. ${error.help}` : error.message)
|
|
192
|
+
logger.warn(message)
|
|
211
193
|
} else {
|
|
212
194
|
fsx.writeFileX(processedEnv.filepath, processedEnv.envSrc)
|
|
213
195
|
|
|
@@ -216,26 +198,25 @@ const set = function (key, value, options = {}) {
|
|
|
216
198
|
}
|
|
217
199
|
}
|
|
218
200
|
|
|
201
|
+
const keyAddedEnv = processedEnvs.find((processedEnv) => processedEnv.privateKeyAdded)
|
|
202
|
+
const keyAddedSuffix = keyAddedEnv ? ` + key (${localDisplayPath(keyAddedEnv.envKeysFilepath)})` : ''
|
|
203
|
+
|
|
219
204
|
if (changedFilepaths.length > 0) {
|
|
220
|
-
|
|
205
|
+
if (encrypt) {
|
|
206
|
+
logger.success(`◈ encrypted ${key} (${changedFilepaths.join(',')})${keyAddedSuffix}`)
|
|
207
|
+
} else {
|
|
208
|
+
logger.success(`◇ set ${key} (${changedFilepaths.join(',')})`)
|
|
209
|
+
}
|
|
210
|
+
} else if (encrypt && keyAddedEnv) {
|
|
211
|
+
const keyAddedEnvFilepath = keyAddedEnv.envFilepath || changedFilepaths[0] || '.env'
|
|
212
|
+
logger.success(`◈ encrypted ${key} (${keyAddedEnvFilepath})${keyAddedSuffix}`)
|
|
221
213
|
} else if (unchangedFilepaths.length > 0) {
|
|
222
|
-
logger.info(
|
|
214
|
+
logger.info(`○ no changes (${unchangedFilepaths})`)
|
|
223
215
|
} else {
|
|
224
216
|
// do nothing
|
|
225
217
|
}
|
|
226
218
|
|
|
227
|
-
|
|
228
|
-
if (processedEnv.privateKeyAdded) {
|
|
229
|
-
logger.success(`✔ key added to ${processedEnv.envKeysFilepath} (${processedEnv.privateKeyName})`)
|
|
230
|
-
// logger.help('⮕ optional: [dotenvx ops backup] to securely backup private key')
|
|
231
|
-
|
|
232
|
-
if (!isIgnoringDotenvKeys()) {
|
|
233
|
-
logger.help('⮕ next run: [dotenvx ext gitignore --pattern .env.keys] to gitignore .env.keys')
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
logger.help(`⮕ next run: [${processedEnv.privateKeyName}='${processedEnv.privateKey}' dotenvx get ${key}] to test decryption locally`)
|
|
237
|
-
}
|
|
238
|
-
}
|
|
219
|
+
// intentionally quiet: success line communicates key creation
|
|
239
220
|
|
|
240
221
|
return {
|
|
241
222
|
processedEnvs,
|
|
@@ -261,10 +242,7 @@ const get = function (key, options = {}) {
|
|
|
261
242
|
|
|
262
243
|
if (options.strict) throw error // throw immediately if strict
|
|
263
244
|
|
|
264
|
-
logger.error(error.
|
|
265
|
-
if (error.help) {
|
|
266
|
-
logger.error(error.help)
|
|
267
|
-
}
|
|
245
|
+
logger.error(error.messageWithHelp)
|
|
268
246
|
}
|
|
269
247
|
|
|
270
248
|
if (key) {
|
|
@@ -122,7 +122,12 @@ class Encrypt {
|
|
|
122
122
|
if (!encrypted) {
|
|
123
123
|
row.keys.push(key) // track key(s)
|
|
124
124
|
|
|
125
|
-
|
|
125
|
+
let encryptedValue
|
|
126
|
+
try {
|
|
127
|
+
encryptedValue = encryptValue(value, publicKey)
|
|
128
|
+
} catch {
|
|
129
|
+
throw new Errors({ publicKeyName, publicKey }).invalidPublicKey()
|
|
130
|
+
}
|
|
126
131
|
|
|
127
132
|
// once newSrc is built write it out
|
|
128
133
|
envSrc = replace(envSrc, key, encryptedValue)
|
|
@@ -17,14 +17,7 @@ class Genexample {
|
|
|
17
17
|
|
|
18
18
|
run () {
|
|
19
19
|
if (this.envFile.length < 1) {
|
|
20
|
-
|
|
21
|
-
const message = 'no .env* files found'
|
|
22
|
-
const help = '? add one with [echo "HELLO=World" > .env] and then run [dotenvx genexample]'
|
|
23
|
-
|
|
24
|
-
const error = new Error(message)
|
|
25
|
-
error.code = code
|
|
26
|
-
error.help = help
|
|
27
|
-
throw error
|
|
20
|
+
throw new Errors().missingEnvFiles()
|
|
28
21
|
}
|
|
29
22
|
|
|
30
23
|
const keys = new Set()
|
|
@@ -4,6 +4,7 @@ const path = require('path')
|
|
|
4
4
|
const ignore = require('ignore')
|
|
5
5
|
|
|
6
6
|
const Ls = require('../services/ls')
|
|
7
|
+
const Errors = require('../helpers/errors')
|
|
7
8
|
|
|
8
9
|
const isFullyEncrypted = require('./../helpers/isFullyEncrypted')
|
|
9
10
|
const packageJson = require('./../helpers/packageJson')
|
|
@@ -24,7 +25,10 @@ class Prebuild {
|
|
|
24
25
|
|
|
25
26
|
// 1. check for .dockerignore file
|
|
26
27
|
if (!fsx.existsSync('.dockerignore')) {
|
|
27
|
-
const warning = new
|
|
28
|
+
const warning = new Errors({
|
|
29
|
+
message: `[dotenvx@${packageJson.version}][prebuild] .dockerignore missing`,
|
|
30
|
+
help: 'fix: [touch .dockerignore]'
|
|
31
|
+
}).custom()
|
|
28
32
|
warnings.push(warning)
|
|
29
33
|
} else {
|
|
30
34
|
dockerignore = fsx.readFileX('.dockerignore')
|
|
@@ -42,8 +46,10 @@ class Prebuild {
|
|
|
42
46
|
// check if that file is being ignored
|
|
43
47
|
if (ig.ignores(file)) {
|
|
44
48
|
if (file === '.env.example' || file === '.env.x') {
|
|
45
|
-
const warning = new
|
|
46
|
-
|
|
49
|
+
const warning = new Errors({
|
|
50
|
+
message: `[dotenvx@${packageJson.version}][prebuild] ${file} (currently ignored but should not be)`,
|
|
51
|
+
help: `fix: [dotenvx ext gitignore --pattern !${file}]`
|
|
52
|
+
}).custom()
|
|
47
53
|
warnings.push(warning)
|
|
48
54
|
}
|
|
49
55
|
} else {
|
|
@@ -54,15 +60,13 @@ class Prebuild {
|
|
|
54
60
|
// if contents are encrypted don't raise an error
|
|
55
61
|
if (!encrypted) {
|
|
56
62
|
let errorMsg = `[dotenvx@${packageJson.version}][prebuild] ${file} not protected (encrypted or dockerignored)`
|
|
57
|
-
let errorHelp = `
|
|
63
|
+
let errorHelp = `fix: [dotenvx encrypt -f ${file}] or [dotenvx ext gitignore --pattern ${file}]`
|
|
58
64
|
if (file.includes('.env.keys')) {
|
|
59
65
|
errorMsg = `[dotenvx@${packageJson.version}][prebuild] ${file} not protected (dockerignored)`
|
|
60
|
-
errorHelp = `
|
|
66
|
+
errorHelp = `fix: [dotenvx ext gitignore --pattern ${file}]`
|
|
61
67
|
}
|
|
62
68
|
|
|
63
|
-
|
|
64
|
-
error.help = errorHelp
|
|
65
|
-
throw error
|
|
69
|
+
throw new Errors({ message: errorMsg, help: errorHelp }).custom()
|
|
66
70
|
}
|
|
67
71
|
}
|
|
68
72
|
}
|
|
@@ -8,6 +8,7 @@ const Ls = require('../services/ls')
|
|
|
8
8
|
const isFullyEncrypted = require('./../helpers/isFullyEncrypted')
|
|
9
9
|
const packageJson = require('./../helpers/packageJson')
|
|
10
10
|
const InstallPrecommitHook = require('./../helpers/installPrecommitHook')
|
|
11
|
+
const Errors = require('./../helpers/errors')
|
|
11
12
|
const childProcess = require('child_process')
|
|
12
13
|
const MISSING_GITIGNORE = '.env.keys' // by default only ignore .env.keys. all other .env* files COULD be included - as long as they are encrypted
|
|
13
14
|
|
|
@@ -37,7 +38,10 @@ class Precommit {
|
|
|
37
38
|
|
|
38
39
|
// 1. check for .gitignore file
|
|
39
40
|
if (!fsx.existsSync('.gitignore')) {
|
|
40
|
-
const warning = new
|
|
41
|
+
const warning = new Errors({
|
|
42
|
+
message: `[dotenvx@${packageJson.version}][precommit] .gitignore missing`,
|
|
43
|
+
help: 'fix: [touch .gitignore]'
|
|
44
|
+
}).custom()
|
|
41
45
|
warnings.push(warning)
|
|
42
46
|
} else {
|
|
43
47
|
gitignore = fsx.readFileX('.gitignore')
|
|
@@ -58,8 +62,10 @@ class Precommit {
|
|
|
58
62
|
// check if that file is being ignored
|
|
59
63
|
if (ig.ignores(file)) {
|
|
60
64
|
if (file === '.env.example' || file === '.env.x') {
|
|
61
|
-
const warning = new
|
|
62
|
-
|
|
65
|
+
const warning = new Errors({
|
|
66
|
+
message: `[dotenvx@${packageJson.version}][precommit] ${file} (currently ignored but should not be)`,
|
|
67
|
+
help: `fix: [dotenvx ext gitignore --pattern !${file}]`
|
|
68
|
+
}).custom()
|
|
63
69
|
warnings.push(warning)
|
|
64
70
|
}
|
|
65
71
|
} else {
|
|
@@ -70,15 +76,13 @@ class Precommit {
|
|
|
70
76
|
// if contents are encrypted don't raise an error
|
|
71
77
|
if (!encrypted) {
|
|
72
78
|
let errorMsg = `[dotenvx@${packageJson.version}][precommit] ${file} not protected (encrypted or gitignored)`
|
|
73
|
-
let errorHelp = `
|
|
79
|
+
let errorHelp = `fix: [dotenvx encrypt -f ${file}] or [dotenvx ext gitignore --pattern ${file}]`
|
|
74
80
|
if (file.includes('.env.keys')) {
|
|
75
81
|
errorMsg = `[dotenvx@${packageJson.version}][precommit] ${file} not protected (gitignored)`
|
|
76
|
-
errorHelp = `
|
|
82
|
+
errorHelp = `fix: [dotenvx ext gitignore --pattern ${file}]`
|
|
77
83
|
}
|
|
78
84
|
|
|
79
|
-
|
|
80
|
-
error.help = errorHelp
|
|
81
|
-
throw error
|
|
85
|
+
throw new Errors({ message: errorMsg, help: errorHelp }).custom()
|
|
82
86
|
}
|
|
83
87
|
}
|
|
84
88
|
}
|
|
@@ -131,7 +131,12 @@ class Rotate {
|
|
|
131
131
|
row.keys.push(key) // track key(s)
|
|
132
132
|
|
|
133
133
|
const decryptedValue = decryptKeyValue(key, value, privateKeyName, privateKeyValue) // get decrypted value
|
|
134
|
-
|
|
134
|
+
let encryptedValue
|
|
135
|
+
try {
|
|
136
|
+
encryptedValue = encryptValue(decryptedValue, newPublicKey) // encrypt with the new publicKey
|
|
137
|
+
} catch {
|
|
138
|
+
throw new Errors({ publicKeyName, publicKey: newPublicKey }).invalidPublicKey()
|
|
139
|
+
}
|
|
135
140
|
|
|
136
141
|
envSrc = replace(envSrc, key, encryptedValue)
|
|
137
142
|
}
|
package/src/lib/services/sets.js
CHANGED
|
@@ -109,7 +109,11 @@ class Sets {
|
|
|
109
109
|
|
|
110
110
|
row.publicKey = publicKey
|
|
111
111
|
row.privateKey = privateKey
|
|
112
|
-
|
|
112
|
+
try {
|
|
113
|
+
row.encryptedValue = encryptValue(this.value, publicKey)
|
|
114
|
+
} catch {
|
|
115
|
+
throw new Errors({ publicKeyName, publicKey }).invalidPublicKey()
|
|
116
|
+
}
|
|
113
117
|
row.privateKeyName = privateKeyName
|
|
114
118
|
}
|
|
115
119
|
|
package/src/shared/colors.js
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
const depth = require('../lib/helpers/colorDepth')
|
|
2
|
+
const Errors = require('../lib/helpers/errors')
|
|
2
3
|
|
|
3
4
|
const colors16 = new Map([
|
|
5
|
+
['amber', 33],
|
|
4
6
|
['blue', 34],
|
|
5
7
|
['gray', 37],
|
|
6
8
|
['green', 32],
|
|
7
9
|
['olive', 33],
|
|
8
|
-
['orangered',
|
|
10
|
+
['orangered', 33], // mapped to yellow/brown
|
|
9
11
|
['plum', 35], // mapped to magenta
|
|
10
12
|
['red', 31],
|
|
11
13
|
['electricblue', 36],
|
|
@@ -13,21 +15,32 @@ const colors16 = new Map([
|
|
|
13
15
|
])
|
|
14
16
|
|
|
15
17
|
const colors256 = new Map([
|
|
18
|
+
['amber', 136],
|
|
16
19
|
['blue', 21],
|
|
17
20
|
['gray', 244],
|
|
18
21
|
['green', 34],
|
|
19
22
|
['olive', 142],
|
|
20
|
-
['orangered',
|
|
23
|
+
['orangered', 130], // burnished copper
|
|
21
24
|
['plum', 182],
|
|
22
|
-
['red',
|
|
25
|
+
['red', 124], // brighter garnet
|
|
23
26
|
['electricblue', 45],
|
|
24
27
|
['dodgerblue', 33]
|
|
25
28
|
])
|
|
26
29
|
|
|
30
|
+
const colorsTrueColor = new Map([
|
|
31
|
+
['amber', [236, 213, 63]],
|
|
32
|
+
['orangered', [138, 90, 43]], // #8A5A2B burnished copper
|
|
33
|
+
['red', [140, 35, 50]] // #8C2332 brighter garnet
|
|
34
|
+
])
|
|
35
|
+
|
|
27
36
|
function getColor (color) {
|
|
28
37
|
const colorDepth = depth.getColorDepth()
|
|
29
38
|
if (!colors256.has(color)) {
|
|
30
|
-
throw new
|
|
39
|
+
throw new Errors({ color }).invalidColor()
|
|
40
|
+
}
|
|
41
|
+
if (colorDepth >= 24 && colorsTrueColor.has(color)) {
|
|
42
|
+
const [r, g, b] = colorsTrueColor.get(color)
|
|
43
|
+
return (message) => `\x1b[38;2;${r};${g};${b}m${message}\x1b[39m`
|
|
31
44
|
}
|
|
32
45
|
if (colorDepth >= 8) {
|
|
33
46
|
const code = colors256.get(color)
|
package/src/shared/logger.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const packageJson = require('../lib/helpers/packageJson')
|
|
2
|
+
const Errors = require('../lib/helpers/errors')
|
|
2
3
|
const { getColor, bold } = require('./colors')
|
|
3
4
|
|
|
4
5
|
const levels = {
|
|
@@ -13,10 +14,11 @@ const levels = {
|
|
|
13
14
|
silly: 6
|
|
14
15
|
}
|
|
15
16
|
|
|
16
|
-
const error = (m) => bold(getColor('red')(m))
|
|
17
|
-
const warn = getColor('orangered')
|
|
18
|
-
const success = getColor('
|
|
19
|
-
const successv = getColor('
|
|
17
|
+
const error = (m) => bold(getColor('red')(`☠ ${m}`))
|
|
18
|
+
const warn = (m) => getColor('orangered')(`⚠ ${m}`)
|
|
19
|
+
const success = getColor('amber')
|
|
20
|
+
const successv = getColor('amber')
|
|
21
|
+
const info = getColor('gray')
|
|
20
22
|
const help = getColor('dodgerblue')
|
|
21
23
|
const verbose = getColor('plum')
|
|
22
24
|
const debug = getColor('plum')
|
|
@@ -32,7 +34,7 @@ function stderr (level, message) {
|
|
|
32
34
|
|
|
33
35
|
function stdout (level, message) {
|
|
34
36
|
if (levels[level] === undefined) {
|
|
35
|
-
throw new
|
|
37
|
+
throw new Errors({ level }).missingLogLevel()
|
|
36
38
|
}
|
|
37
39
|
|
|
38
40
|
if (levels[level] <= currentLevel) {
|
|
@@ -58,7 +60,7 @@ function formatMessage (level, message) {
|
|
|
58
60
|
return successv(`[${currentName}@${currentVersion}] ${formattedMessage}`)
|
|
59
61
|
// info
|
|
60
62
|
case 'info':
|
|
61
|
-
return formattedMessage
|
|
63
|
+
return info(formattedMessage)
|
|
62
64
|
// help
|
|
63
65
|
case 'help':
|
|
64
66
|
return help(formattedMessage)
|