@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 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.7.0...main)
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.7.0",
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
- "execa": "^5.1.1",
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": "^3.0.1",
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)
@@ -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)
@@ -9,8 +9,6 @@ ext
9
9
  .description('🔌 extensions')
10
10
  .allowUnknownOption()
11
11
 
12
- ext.addHelpText('after', ' hub 🚫 DEPRECATED: to be replaced by [dotenvx pro]')
13
-
14
12
  ext
15
13
  .argument('[command]', 'dynamic ext command')
16
14
  .argument('[args...]', 'dynamic ext command arguments')
@@ -0,0 +1,4 @@
1
+ const { WriteStream } = require('tty')
2
+ const getColorDepth = () => WriteStream.prototype.getColorDepth()
3
+
4
+ module.exports = { getColorDepth }
@@ -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 (_error) {
22
- // TODO: somehow surface these errors to the user's logs
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
- // return 'encrypted:string' value if undefined or null
27
- if (decryptedValue === undefined || decryptedValue === null) {
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
- let processEnv = process.env
46
- if (options && options.processEnv != null) {
47
- processEnv = options.processEnv
48
- }
45
+ const processEnv = options.processEnv || {}
46
+ const parsed = options.parsed || {}
49
47
 
50
- const combined = { ...processEnv, ...options.parsed }
51
- const combinedReversed = { ...options.parsed, ...processEnv }
48
+ const combined = { ...processEnv, ...parsed }
49
+ const combinedReversed = { ...parsed, ...processEnv }
52
50
 
53
- for (const key in options.parsed) {
54
- const value = options.parsed[key]
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
- options.parsed[key] = fileValue
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 process.env, move on
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: options.parsed,
73
+ parsed,
77
74
  processEnv
78
75
  }
79
76
  }
@@ -1,9 +1,3 @@
1
- const execa = require('execa')
1
+ const { exec } = require('tinyexec')
2
2
 
3
- const execute = {
4
- execa (command, args, options) {
5
- return execa(command, args, options)
6
- }
7
- }
8
-
9
- module.exports = execute
3
+ module.exports = { exec }
@@ -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.execa(commandArgs[0], commandArgs.slice(1), {
77
- stdio: 'inherit',
78
- env: { ...process.env, ...env }
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
- const { exitCode } = await commandProcess
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 (error.signal !== 'SIGINT' && error.signal !== 'SIGTERM') {
105
+ if (signal !== 'SIGINT' && signal !== 'SIGTERM') {
98
106
  if (error.code === 'ENOENT') {
99
- logger.errornocolor(`Unknown command: ${error.command}`)
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.command}`)
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 === 'hub') {
26
- logger.warn(`[INSTALLATION_NEEDED] install dotenvx-ext-${command} to use [dotenvx ext ${command}] commands`)
27
- logger.help('? see installation instructions [https://github.com/dotenvx/dotenvx-ext-hub]')
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 (processEnv = {}, parsed = {}, overload = false) {
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(processEnv, key)) {
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
- preExisted[key] = processEnv[key] // track preExisted key/value
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 fs = require('fs')
2
- const path = require('path')
1
+ const { name, version, description } = require('../../../package.json')
3
2
 
4
- const packageJsonPath = path.join(__dirname, '../../../package.json')
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
- const value = parsed[key]
14
- parsed[key] = decryptValue(value, privateKey)
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
@@ -0,0 +1,6 @@
1
+ function truncate (str, showChar = 7) {
2
+ const visiblePart = str.slice(0, showChar)
3
+ return visiblePart + '…'
4
+ }
5
+
6
+ module.exports = truncate
@@ -54,9 +54,9 @@ class Decrypt {
54
54
  if (encrypted) {
55
55
  row.keys.push(key) // track key(s)
56
56
 
57
- const plainValue = decryptValue(value, privateKey)
57
+ const decryptedValue = decryptValue(value, privateKey)
58
58
  // once newSrc is built write it out
59
- src = replace(src, key, plainValue)
59
+ src = replace(src, key, decryptedValue)
60
60
 
61
61
  row.changed = true // track change
62
62
  }
@@ -15,15 +15,17 @@ class Ls {
15
15
  }
16
16
 
17
17
  _filepaths () {
18
- const ignoreMatchers = this.ignore.map(pattern => picomatch(pattern))
19
- const pathMatchers = this._patterns().map(pattern => picomatch(pattern))
18
+ const exclude = picomatch(this.ignore)
19
+ const include = picomatch(this._patterns(), {
20
+ ignore: this.ignore
21
+ })
20
22
 
21
- const api = new Fdir()
23
+ return new Fdir()
22
24
  .withRelativePaths()
23
- .exclude((dir, path) => ignoreMatchers.some(matcher => matcher(path)))
24
- .filter((path) => pathMatchers.some(matcher => matcher(path)))
25
-
26
- return api.crawl(this.cwd).sync()
25
+ .exclude((dir, path) => exclude(path))
26
+ .filter((path) => include(path))
27
+ .crawl(this.cwd)
28
+ .sync()
27
29
  }
28
30
 
29
31
  _patterns () {
@@ -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(this.processEnv, parsed, this.overload)
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(this.processEnv, parsed, this.overload)
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(this.processEnv, parsed, this.overload)
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 (processEnv, parsed, overload) {
184
- return inject(processEnv, parsed, overload)
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 chalk.green(part.value)
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 chalk.red(part.value)
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
+ }
@@ -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('./../lib/helpers/packageJson')
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 = chalk.bold.red
36
- const warn = chalk.keyword('orangered')
37
- const success = chalk.keyword('green')
38
- const successv = chalk.keyword('olive') // yellow-ish tint that 'looks' like dotenv
39
- const help = chalk.keyword('blue')
40
- const help2 = chalk.keyword('gray')
41
- const http = chalk.keyword('green')
42
- const verbose = chalk.keyword('plum')
43
- const debug = chalk.keyword('plum')
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
  }