@dotenvx/dotenvx 1.7.0 → 1.8.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.
- package/CHANGELOG.md +18 -1
- package/package.json +4 -5
- package/src/cli/actions/ext/vault/status.js +1 -1
- package/src/cli/actions/run.js +9 -0
- package/src/cli/commands/ext.js +0 -2
- package/src/lib/helpers/colorDepth.js +4 -0
- package/src/lib/helpers/decryptValue.js +16 -5
- package/src/lib/helpers/dotenvExpand.js +9 -12
- package/src/lib/helpers/execute.js +2 -8
- package/src/lib/helpers/executeCommand.js +15 -7
- package/src/lib/helpers/executeExtension.js +4 -3
- package/src/lib/helpers/inject.js +4 -4
- package/src/lib/helpers/packageJson.js +2 -7
- package/src/lib/helpers/parseDecryptEvalExpand.js +36 -5
- package/src/lib/helpers/truncate.js +6 -0
- package/src/lib/services/decrypt.js +2 -2
- package/src/lib/services/ls.js +9 -7
- package/src/lib/services/run.js +11 -9
- package/src/lib/services/status.js +3 -3
- package/src/lib/services/vaultDecrypt.js +1 -1
- package/src/shared/colors.js +50 -0
- package/src/shared/logger.js +12 -11
package/CHANGELOG.md
CHANGED
|
@@ -2,7 +2,24 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
|
4
4
|
|
|
5
|
-
## [Unreleased](https://github.com/dotenvx/dotenvx/compare/v1.
|
|
5
|
+
## [Unreleased](https://github.com/dotenvx/dotenvx/compare/v1.8.0...main)
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
* warn when decryption fails on `run` or `get` ([#339](https://github.com/dotenvx/dotenvx/pull/339))
|
|
10
|
+
* decrypt expanded values as necessary ([#336](https://github.com/dotenvx/dotenvx/pull/336))
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
* use `ansi` colors over `rgb` - for wider terminal coverage ([#340](https://github.com/dotenvx/dotenvx/pull/340))
|
|
15
|
+
* replace `chalk` with `picocolors` and `color-name` - cutting down on 5 dependencies ([#335](https://github.com/dotenvx/dotenvx/pull/335))
|
|
16
|
+
* replace `execa` with `tinyexec` - cutting down on 15 dependencies ([#328](https://github.com/dotenvx/dotenvx/pull/328))
|
|
17
|
+
* optimize `Ls._filepaths` ([#317](https://github.com/dotenvx/dotenvx/pull/317/))
|
|
18
|
+
|
|
19
|
+
### Removed
|
|
20
|
+
|
|
21
|
+
* remove `picocolors` and `color-name` - cutting down on 2 dependencies ([#340](https://github.com/dotenvx/dotenvx/pull/340))
|
|
22
|
+
* remove `ext hub` from extension list (you can still install it as an extension [here](https://github.com/dotenvx/dotenvx-ext-hub)) ([#337](https://github.com/dotenvx/dotenvx/pull/337))
|
|
6
23
|
|
|
7
24
|
## 1.7.0
|
|
8
25
|
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "1.
|
|
2
|
+
"version": "1.8.0",
|
|
3
3
|
"name": "@dotenvx/dotenvx",
|
|
4
4
|
"description": "a better dotenv–from the creator of `dotenv`",
|
|
5
5
|
"author": "@motdotla",
|
|
@@ -36,16 +36,15 @@
|
|
|
36
36
|
},
|
|
37
37
|
"funding": "https://dotenvx.com",
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"chalk": "^4.1.2",
|
|
40
39
|
"commander": "^11.1.0",
|
|
41
40
|
"diff": "^5.2.0",
|
|
42
41
|
"dotenv": "^16.4.5",
|
|
43
42
|
"eciesjs": "^0.4.6",
|
|
44
|
-
"
|
|
45
|
-
"fdir": "^6.1.1",
|
|
43
|
+
"fdir": "^6.2.0",
|
|
46
44
|
"ignore": "^5.3.0",
|
|
47
45
|
"object-treeify": "1.1.33",
|
|
48
|
-
"picomatch": "^
|
|
46
|
+
"picomatch": "^4.0.2",
|
|
47
|
+
"tinyexec": "^0.2.0",
|
|
49
48
|
"which": "^4.0.0",
|
|
50
49
|
"winston": "^3.11.0",
|
|
51
50
|
"xxhashjs": "^0.2.2"
|
|
@@ -58,7 +58,7 @@ function status (directory) {
|
|
|
58
58
|
|
|
59
59
|
if (untrackedFilenames.length > 0) {
|
|
60
60
|
logger.warn(`untracked (${untrackedFilenames.join(', ')})`)
|
|
61
|
-
logger.help(`? track them with [dotenvx encrypt ${directory}]`)
|
|
61
|
+
logger.help(`? track them with [dotenvx ext vault encrypt ${directory}]`)
|
|
62
62
|
}
|
|
63
63
|
} catch (error) {
|
|
64
64
|
logger.error(error.message)
|
package/src/cli/actions/run.js
CHANGED
|
@@ -60,6 +60,15 @@ async function run () {
|
|
|
60
60
|
logger.warnv(processedEnv.error.message)
|
|
61
61
|
}
|
|
62
62
|
} else {
|
|
63
|
+
if (processedEnv.warnings) {
|
|
64
|
+
for (const warning of processedEnv.warnings) {
|
|
65
|
+
logger.warn(warning.message)
|
|
66
|
+
if (warning.help) {
|
|
67
|
+
logger.help(warning.help)
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
63
72
|
// debug parsed
|
|
64
73
|
const parsed = processedEnv.parsed
|
|
65
74
|
logger.debug(parsed)
|
package/src/cli/commands/ext.js
CHANGED
|
@@ -10,6 +10,7 @@ function decryptValue (value, privateKey) {
|
|
|
10
10
|
const privateKeys = privateKey.split(',')
|
|
11
11
|
|
|
12
12
|
let decryptedValue
|
|
13
|
+
let decryptionError
|
|
13
14
|
for (const key of privateKeys) {
|
|
14
15
|
const secret = Buffer.from(key, 'hex')
|
|
15
16
|
const encoded = value.substring(PREFIX.length)
|
|
@@ -17,15 +18,25 @@ function decryptValue (value, privateKey) {
|
|
|
17
18
|
|
|
18
19
|
try {
|
|
19
20
|
decryptedValue = decrypt(secret, ciphertext).toString()
|
|
21
|
+
decryptionError = null // reset to null error (scenario for multiple private keys)
|
|
20
22
|
break
|
|
21
|
-
} catch (
|
|
22
|
-
|
|
23
|
+
} catch (e) {
|
|
24
|
+
if (e.message === 'Invalid private key') {
|
|
25
|
+
decryptionError = new Error('private key looks invalid')
|
|
26
|
+
} else if (e.message === 'Unsupported state or unable to authenticate data') {
|
|
27
|
+
decryptionError = new Error('private key looks wrong')
|
|
28
|
+
} else if (e.message === 'Point of length 65 was invalid. Expected 33 compressed bytes or 65 uncompressed bytes') {
|
|
29
|
+
decryptionError = new Error('encrypted data looks malformed')
|
|
30
|
+
} else {
|
|
31
|
+
decryptionError = new Error(`${e.message}`)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
decryptionError.code = 'DECRYPTION_FAILED'
|
|
23
35
|
}
|
|
24
36
|
}
|
|
25
37
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
return value
|
|
38
|
+
if (decryptionError) {
|
|
39
|
+
throw decryptionError
|
|
29
40
|
}
|
|
30
41
|
|
|
31
42
|
return decryptedValue
|
|
@@ -42,30 +42,27 @@ function interpolate (value, lookups) {
|
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
function expand (options) {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
processEnv = options.processEnv
|
|
48
|
-
}
|
|
45
|
+
const processEnv = options.processEnv || {}
|
|
46
|
+
const parsed = options.parsed || {}
|
|
49
47
|
|
|
50
|
-
const combined = { ...processEnv, ...
|
|
51
|
-
const combinedReversed = { ...
|
|
48
|
+
const combined = { ...processEnv, ...parsed }
|
|
49
|
+
const combinedReversed = { ...parsed, ...processEnv }
|
|
52
50
|
|
|
53
|
-
for (const key in
|
|
54
|
-
const value =
|
|
51
|
+
for (const key in parsed) {
|
|
52
|
+
const value = parsed[key]
|
|
55
53
|
|
|
56
54
|
// interpolate using both file and processEnv (file interpolation wins. used for --overload later)
|
|
57
55
|
const fileValue = _resolveEscapeSequences(interpolate(value, combined))
|
|
58
|
-
|
|
56
|
+
parsed[key] = fileValue
|
|
59
57
|
|
|
60
58
|
if (fileValue === _resolveEscapeSequences(value)) {
|
|
61
59
|
continue // no change means no expansion, move on
|
|
62
60
|
}
|
|
63
61
|
|
|
64
62
|
if (processEnv[key]) {
|
|
65
|
-
continue // already has a value in
|
|
63
|
+
continue // already has a value in processEnv, move on
|
|
66
64
|
}
|
|
67
65
|
|
|
68
|
-
// interpolate with processEnv only (used for default no overload)
|
|
69
66
|
const processEnvValue = interpolate(value, combinedReversed) // could be empty string ''
|
|
70
67
|
if (processEnvValue) {
|
|
71
68
|
processEnv[key] = _resolveEscapeSequences(processEnvValue) // set it
|
|
@@ -73,7 +70,7 @@ function expand (options) {
|
|
|
73
70
|
}
|
|
74
71
|
|
|
75
72
|
return {
|
|
76
|
-
parsed
|
|
73
|
+
parsed,
|
|
77
74
|
processEnv
|
|
78
75
|
}
|
|
79
76
|
}
|
|
@@ -13,6 +13,8 @@ async function executeCommand (commandArgs, env) {
|
|
|
13
13
|
|
|
14
14
|
// handler for SIGINT
|
|
15
15
|
let commandProcess
|
|
16
|
+
// workaround until error.signal gets added https://github.com/tinylibs/tinyexec/issues/28
|
|
17
|
+
let signal
|
|
16
18
|
const sigintHandler = () => {
|
|
17
19
|
logger.debug('received SIGINT')
|
|
18
20
|
logger.debug('checking command process')
|
|
@@ -20,6 +22,7 @@ async function executeCommand (commandArgs, env) {
|
|
|
20
22
|
|
|
21
23
|
if (commandProcess) {
|
|
22
24
|
logger.debug('sending SIGINT to command process')
|
|
25
|
+
signal = 'SIGINT'
|
|
23
26
|
commandProcess.kill('SIGINT') // Send SIGINT to the command process
|
|
24
27
|
/* c8 ignore start */
|
|
25
28
|
} else {
|
|
@@ -37,6 +40,7 @@ async function executeCommand (commandArgs, env) {
|
|
|
37
40
|
|
|
38
41
|
if (commandProcess) {
|
|
39
42
|
logger.debug('sending SIGTERM to command process')
|
|
43
|
+
signal = 'SIGTERM'
|
|
40
44
|
commandProcess.kill('SIGTERM') // Send SIGTEM to the command process
|
|
41
45
|
} else {
|
|
42
46
|
logger.debug('no command process to send SIGTERM to')
|
|
@@ -73,9 +77,11 @@ async function executeCommand (commandArgs, env) {
|
|
|
73
77
|
}
|
|
74
78
|
}
|
|
75
79
|
|
|
76
|
-
commandProcess = execute.
|
|
77
|
-
|
|
78
|
-
|
|
80
|
+
commandProcess = execute.exec(commandArgs[0], commandArgs.slice(1), {
|
|
81
|
+
nodeOptions: {
|
|
82
|
+
stdio: 'inherit',
|
|
83
|
+
env: { ...process.env, ...env }
|
|
84
|
+
}
|
|
79
85
|
})
|
|
80
86
|
|
|
81
87
|
process.on('SIGINT', sigintHandler)
|
|
@@ -86,7 +92,9 @@ async function executeCommand (commandArgs, env) {
|
|
|
86
92
|
})
|
|
87
93
|
|
|
88
94
|
// Wait for the command process to finish
|
|
89
|
-
|
|
95
|
+
// exitCode is not in the awaited result, see https://github.com/tinylibs/tinyexec/issues/27
|
|
96
|
+
await commandProcess
|
|
97
|
+
const { exitCode } = commandProcess
|
|
90
98
|
|
|
91
99
|
if (exitCode !== 0) {
|
|
92
100
|
logger.debug(`received exitCode ${exitCode}`)
|
|
@@ -94,11 +102,11 @@ async function executeCommand (commandArgs, env) {
|
|
|
94
102
|
}
|
|
95
103
|
} catch (error) {
|
|
96
104
|
// no color on these errors as they can be standard errors for things like jest exiting with exitCode 1 for a single failed test.
|
|
97
|
-
if (
|
|
105
|
+
if (signal !== 'SIGINT' && signal !== 'SIGTERM') {
|
|
98
106
|
if (error.code === 'ENOENT') {
|
|
99
|
-
logger.errornocolor(`Unknown command: ${error.
|
|
107
|
+
logger.errornocolor(`Unknown command: ${error.path}${error.spawnargs ? ' ' + error.spawnargs.join(' ') : ''}`)
|
|
100
108
|
} else if (error.message.includes('Command failed with exit code 1')) {
|
|
101
|
-
logger.errornocolor(`Command exited with exit code 1: ${error.
|
|
109
|
+
logger.errornocolor(`Command exited with exit code 1: ${error.path}${error.spawnargs ? ' ' + error.spawnargs.join(' ') : ''}`)
|
|
102
110
|
} else {
|
|
103
111
|
logger.errornocolor(error.message)
|
|
104
112
|
}
|
|
@@ -22,9 +22,10 @@ function executeExtension (ext, command, rawArgs) {
|
|
|
22
22
|
|
|
23
23
|
const result = childProcess.spawnSync(`dotenvx-ext-${command}`, forwardedArgs, { stdio: 'inherit', env })
|
|
24
24
|
if (result.error) {
|
|
25
|
-
if (command === '
|
|
26
|
-
|
|
27
|
-
logger.
|
|
25
|
+
if (command === 'vault') {
|
|
26
|
+
// when ready, uncomment to deprecate ext vault
|
|
27
|
+
// logger.warn(`[INSTALLATION_NEEDED] install dotenvx-ext-${command} to use [dotenvx ext ${command}] commands`)
|
|
28
|
+
// logger.help('? see installation instructions [https://github.com/dotenvx/dotenvx-ext-vault]')
|
|
28
29
|
} else {
|
|
29
30
|
logger.info(`error: unknown command '${command}'`)
|
|
30
31
|
}
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
function inject (
|
|
1
|
+
function inject (clonedProcessEnv = {}, parsed = {}, overload = false, processEnv = process.env) {
|
|
2
2
|
const injected = {}
|
|
3
3
|
const preExisted = {}
|
|
4
4
|
|
|
5
5
|
// set processEnv
|
|
6
6
|
for (const key of Object.keys(parsed)) {
|
|
7
|
-
if (Object.prototype.hasOwnProperty.call(
|
|
7
|
+
if (Object.prototype.hasOwnProperty.call(clonedProcessEnv, key)) {
|
|
8
8
|
if (overload === true) {
|
|
9
9
|
processEnv[key] = parsed[key]
|
|
10
|
-
|
|
11
10
|
injected[key] = parsed[key] // track injected key/value
|
|
12
11
|
} else {
|
|
13
|
-
|
|
12
|
+
processEnv[key] = clonedProcessEnv[key]
|
|
13
|
+
preExisted[key] = clonedProcessEnv[key] // track preExisted key/value
|
|
14
14
|
}
|
|
15
15
|
} else {
|
|
16
16
|
processEnv[key] = parsed[key]
|
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
const
|
|
2
|
-
const path = require('path')
|
|
1
|
+
const { name, version, description } = require('../../../package.json')
|
|
3
2
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'))
|
|
7
|
-
|
|
8
|
-
module.exports = packageJson
|
|
3
|
+
module.exports = { name, version, description }
|
|
@@ -2,16 +2,29 @@ const dotenv = require('dotenv')
|
|
|
2
2
|
const dotenvEval = require('./dotenvEval')
|
|
3
3
|
const dotenvExpand = require('./dotenvExpand')
|
|
4
4
|
const decryptValue = require('./decryptValue')
|
|
5
|
+
const truncate = require('./truncate')
|
|
6
|
+
|
|
7
|
+
function warning (e, key, privateKey) {
|
|
8
|
+
const warning = new Error(`[${e.code}] could not decrypt ${key} using private key ${truncate(privateKey)}`)
|
|
9
|
+
warning.code = e.code
|
|
10
|
+
warning.help = `[${e.code}] ? ${e.message}`
|
|
11
|
+
|
|
12
|
+
return warning
|
|
13
|
+
}
|
|
5
14
|
|
|
6
15
|
function parseDecryptEvalExpand (src, privateKey = null, processEnv = process.env) {
|
|
16
|
+
const warnings = []
|
|
17
|
+
|
|
7
18
|
// parse
|
|
8
19
|
const parsed = dotenv.parse(src)
|
|
9
|
-
|
|
10
|
-
// handle inline encrypted values
|
|
11
20
|
if (privateKey && privateKey.length > 0) {
|
|
12
21
|
for (const key in parsed) {
|
|
13
|
-
|
|
14
|
-
|
|
22
|
+
try {
|
|
23
|
+
const decryptedValue = decryptValue(parsed[key], privateKey)
|
|
24
|
+
parsed[key] = decryptedValue
|
|
25
|
+
} catch (_e) {
|
|
26
|
+
// do nothing. warnings tracked further below.
|
|
27
|
+
}
|
|
15
28
|
}
|
|
16
29
|
}
|
|
17
30
|
|
|
@@ -28,6 +41,24 @@ function parseDecryptEvalExpand (src, privateKey = null, processEnv = process.en
|
|
|
28
41
|
parsed: evaled
|
|
29
42
|
}
|
|
30
43
|
const expanded = dotenvExpand.expand(inputEvaled)
|
|
44
|
+
if (privateKey && privateKey.length > 0) {
|
|
45
|
+
for (const key in expanded.parsed) {
|
|
46
|
+
try {
|
|
47
|
+
const decryptedValue = decryptValue(expanded.parsed[key], privateKey)
|
|
48
|
+
expanded.parsed[key] = decryptedValue
|
|
49
|
+
} catch (e) {
|
|
50
|
+
warnings.push(warning(e, key, privateKey))
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
for (const key in processEnv) {
|
|
54
|
+
try {
|
|
55
|
+
const decryptedValue = decryptValue(processEnv[key], privateKey)
|
|
56
|
+
processEnv[key] = decryptedValue
|
|
57
|
+
} catch (e) {
|
|
58
|
+
warnings.push(warning(e, key, privateKey))
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
31
62
|
|
|
32
63
|
// for logging only log the original keys existing in parsed. this feels unnecessarily complex - like dotenv-expand should support the ability to inject additional `process.env` or objects as it sees fit to the object it wants to expand
|
|
33
64
|
const result = {}
|
|
@@ -35,7 +66,7 @@ function parseDecryptEvalExpand (src, privateKey = null, processEnv = process.en
|
|
|
35
66
|
result[key] = expanded.parsed[key]
|
|
36
67
|
}
|
|
37
68
|
|
|
38
|
-
return { parsed: result, processEnv }
|
|
69
|
+
return { parsed: result, processEnv, warnings }
|
|
39
70
|
}
|
|
40
71
|
|
|
41
72
|
module.exports = parseDecryptEvalExpand
|
|
@@ -54,9 +54,9 @@ class Decrypt {
|
|
|
54
54
|
if (encrypted) {
|
|
55
55
|
row.keys.push(key) // track key(s)
|
|
56
56
|
|
|
57
|
-
const
|
|
57
|
+
const decryptedValue = decryptValue(value, privateKey)
|
|
58
58
|
// once newSrc is built write it out
|
|
59
|
-
src = replace(src, key,
|
|
59
|
+
src = replace(src, key, decryptedValue)
|
|
60
60
|
|
|
61
61
|
row.changed = true // track change
|
|
62
62
|
}
|
package/src/lib/services/ls.js
CHANGED
|
@@ -15,15 +15,17 @@ class Ls {
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
_filepaths () {
|
|
18
|
-
const
|
|
19
|
-
const
|
|
18
|
+
const exclude = picomatch(this.ignore)
|
|
19
|
+
const include = picomatch(this._patterns(), {
|
|
20
|
+
ignore: this.ignore
|
|
21
|
+
})
|
|
20
22
|
|
|
21
|
-
|
|
23
|
+
return new Fdir()
|
|
22
24
|
.withRelativePaths()
|
|
23
|
-
.exclude((dir, path) =>
|
|
24
|
-
.filter((path) =>
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
.exclude((dir, path) => exclude(path))
|
|
26
|
+
.filter((path) => include(path))
|
|
27
|
+
.crawl(this.cwd)
|
|
28
|
+
.sync()
|
|
27
29
|
}
|
|
28
30
|
|
|
29
31
|
_patterns () {
|
package/src/lib/services/run.js
CHANGED
|
@@ -63,12 +63,12 @@ class Run {
|
|
|
63
63
|
row.string = env
|
|
64
64
|
|
|
65
65
|
try {
|
|
66
|
-
const { parsed } = parseDecryptEvalExpand(env, null, this.processEnv)
|
|
67
|
-
|
|
66
|
+
const { parsed, processEnv, warnings } = parseDecryptEvalExpand(env, null, this.processEnv)
|
|
68
67
|
row.parsed = parsed
|
|
68
|
+
row.warnings = warnings
|
|
69
69
|
this.readableStrings.add(env)
|
|
70
70
|
|
|
71
|
-
const { injected, preExisted } = this._inject(
|
|
71
|
+
const { injected, preExisted } = this._inject(processEnv, parsed, this.overload, this.processEnv)
|
|
72
72
|
row.injected = injected
|
|
73
73
|
row.preExisted = preExisted
|
|
74
74
|
|
|
@@ -94,10 +94,11 @@ class Run {
|
|
|
94
94
|
|
|
95
95
|
// if DOTENV_PRIVATE_KEY_* already set in process.env then use it
|
|
96
96
|
const privateKey = smartDotenvPrivateKey(envFilepath)
|
|
97
|
-
const { parsed } = parseDecryptEvalExpand(src, privateKey, this.processEnv)
|
|
97
|
+
const { parsed, processEnv, warnings } = parseDecryptEvalExpand(src, privateKey, this.processEnv)
|
|
98
98
|
row.parsed = parsed
|
|
99
|
+
row.warnings = warnings
|
|
99
100
|
|
|
100
|
-
const { injected, preExisted } = this._inject(
|
|
101
|
+
const { injected, preExisted } = this._inject(processEnv, parsed, this.overload, this.processEnv)
|
|
101
102
|
row.injected = injected
|
|
102
103
|
row.preExisted = preExisted
|
|
103
104
|
|
|
@@ -163,10 +164,11 @@ class Run {
|
|
|
163
164
|
|
|
164
165
|
try {
|
|
165
166
|
// parse this. it's the equivalent of the .env file
|
|
166
|
-
const { parsed } = parseDecryptEvalExpand(decrypted, null, this.processEnv)
|
|
167
|
+
const { parsed, processEnv, warnings } = parseDecryptEvalExpand(decrypted, null, this.processEnv)
|
|
167
168
|
row.parsed = parsed
|
|
169
|
+
row.warnings = warnings
|
|
168
170
|
|
|
169
|
-
const { injected, preExisted } = this._inject(
|
|
171
|
+
const { injected, preExisted } = this._inject(processEnv, parsed, this.overload, this.processEnv)
|
|
170
172
|
row.injected = injected
|
|
171
173
|
row.preExisted = preExisted
|
|
172
174
|
|
|
@@ -180,8 +182,8 @@ class Run {
|
|
|
180
182
|
this.processedEnvs.push(row)
|
|
181
183
|
}
|
|
182
184
|
|
|
183
|
-
_inject (
|
|
184
|
-
return inject(
|
|
185
|
+
_inject (clonedProcessEnv, parsed, overload, processEnv) {
|
|
186
|
+
return inject(clonedProcessEnv, parsed, overload, processEnv)
|
|
185
187
|
}
|
|
186
188
|
|
|
187
189
|
_determineEnvsFromDotenvPrivateKey () {
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
const fs = require('fs')
|
|
2
2
|
const path = require('path')
|
|
3
3
|
const diff = require('diff')
|
|
4
|
-
const chalk = require('chalk')
|
|
5
4
|
|
|
6
5
|
const Ls = require('./ls')
|
|
7
6
|
const VaultDecrypt = require('./vaultDecrypt')
|
|
8
7
|
|
|
9
8
|
const containsDirectory = require('./../helpers/containsDirectory')
|
|
10
9
|
const guessEnvironment = require('./../helpers/guessEnvironment')
|
|
10
|
+
const { getColor } = require('./../../shared/colors')
|
|
11
11
|
|
|
12
12
|
const ENCODING = 'utf8'
|
|
13
13
|
|
|
@@ -94,12 +94,12 @@ class Status {
|
|
|
94
94
|
_colorizeDiff (part) {
|
|
95
95
|
// If the part was added, color it green
|
|
96
96
|
if (part.added) {
|
|
97
|
-
return
|
|
97
|
+
return getColor('green')(part.value)
|
|
98
98
|
}
|
|
99
99
|
|
|
100
100
|
// If the part was removed, color it red
|
|
101
101
|
if (part.removed) {
|
|
102
|
-
return
|
|
102
|
+
return getColor('red')(part.value)
|
|
103
103
|
}
|
|
104
104
|
|
|
105
105
|
// No color for unchanged parts
|
|
@@ -23,7 +23,7 @@ class VaultDecrypt {
|
|
|
23
23
|
if (!fs.existsSync(this.envVaultFilepath)) {
|
|
24
24
|
const code = 'MISSING_ENV_VAULT_FILE'
|
|
25
25
|
const message = `missing .env.vault (${this.envVaultFilepath})`
|
|
26
|
-
const help = `? generate one with [dotenvx encrypt ${this.directory}]`
|
|
26
|
+
const help = `? generate one with [dotenvx ext vault encrypt ${this.directory}]`
|
|
27
27
|
|
|
28
28
|
const error = new Error(message)
|
|
29
29
|
error.code = code
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
const depth = require('../lib/helpers/colorDepth')
|
|
2
|
+
|
|
3
|
+
const colors16 = new Map([
|
|
4
|
+
['blue', 34],
|
|
5
|
+
['gray', 37],
|
|
6
|
+
['green', 32],
|
|
7
|
+
['olive', 33],
|
|
8
|
+
['orangered', 31], // mapped to red
|
|
9
|
+
['plum', 35], // mapped to magenta
|
|
10
|
+
['red', 31]
|
|
11
|
+
])
|
|
12
|
+
|
|
13
|
+
const colors256 = new Map([
|
|
14
|
+
['blue', 21],
|
|
15
|
+
['gray', 244],
|
|
16
|
+
['green', 34],
|
|
17
|
+
['olive', 142],
|
|
18
|
+
['orangered', 202],
|
|
19
|
+
['plum', 182],
|
|
20
|
+
['red', 196]
|
|
21
|
+
])
|
|
22
|
+
|
|
23
|
+
function getColor (color) {
|
|
24
|
+
const colorDepth = depth.getColorDepth()
|
|
25
|
+
if (!colors256.has(color)) {
|
|
26
|
+
throw new Error(`Invalid color ${color}`)
|
|
27
|
+
}
|
|
28
|
+
if (colorDepth >= 8) {
|
|
29
|
+
const code = colors256.get(color)
|
|
30
|
+
return (message) => `\x1b[38;5;${code}m${message}\x1b[39m`
|
|
31
|
+
}
|
|
32
|
+
if (colorDepth >= 4) {
|
|
33
|
+
const code = colors16.get(color)
|
|
34
|
+
return (message) => `\x1b[${code}m${message}\x1b[39m`
|
|
35
|
+
}
|
|
36
|
+
return (message) => message
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function bold (message) {
|
|
40
|
+
if (depth.getColorDepth() >= 4) {
|
|
41
|
+
return `\x1b[1m${message}\x1b[22m`
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return message
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
module.exports = {
|
|
48
|
+
getColor,
|
|
49
|
+
bold
|
|
50
|
+
}
|
package/src/shared/logger.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
const winston = require('winston')
|
|
2
|
-
const chalk = require('chalk')
|
|
3
2
|
|
|
4
3
|
const printf = winston.format.printf
|
|
5
4
|
const combine = winston.format.combine
|
|
6
5
|
const createLogger = winston.createLogger
|
|
7
6
|
const transports = winston.transports
|
|
8
7
|
|
|
9
|
-
const packageJson = require('
|
|
8
|
+
const packageJson = require('../lib/helpers/packageJson')
|
|
9
|
+
const { getColor, bold } = require('./colors')
|
|
10
10
|
|
|
11
11
|
const levels = {
|
|
12
12
|
error: 0,
|
|
@@ -32,15 +32,15 @@ const levels = {
|
|
|
32
32
|
silly: 6
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
const error =
|
|
36
|
-
const warn =
|
|
37
|
-
const success =
|
|
38
|
-
const successv =
|
|
39
|
-
const help =
|
|
40
|
-
const help2 =
|
|
41
|
-
const http =
|
|
42
|
-
const verbose =
|
|
43
|
-
const debug =
|
|
35
|
+
const error = (m) => bold(getColor('red')(m))
|
|
36
|
+
const warn = getColor('orangered')
|
|
37
|
+
const success = getColor('green')
|
|
38
|
+
const successv = getColor('olive') // yellow-ish tint that 'looks' like dotenv
|
|
39
|
+
const help = getColor('blue')
|
|
40
|
+
const help2 = getColor('gray')
|
|
41
|
+
const http = getColor('green')
|
|
42
|
+
const verbose = getColor('plum')
|
|
43
|
+
const debug = getColor('plum')
|
|
44
44
|
|
|
45
45
|
const dotenvxFormat = printf(({ level, message, label, timestamp }) => {
|
|
46
46
|
const formattedMessage = typeof message === 'object' ? JSON.stringify(message) : message
|
|
@@ -119,5 +119,6 @@ const setLogLevel = options => {
|
|
|
119
119
|
|
|
120
120
|
module.exports = {
|
|
121
121
|
logger,
|
|
122
|
+
getColor,
|
|
122
123
|
setLogLevel
|
|
123
124
|
}
|