@dotenvx/dotenvx 0.42.0 → 0.43.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/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.42.0",
2
+ "version": "0.43.0",
3
3
  "name": "@dotenvx/dotenvx",
4
4
  "description": "a better dotenv–from the creator of `dotenv`",
5
5
  "author": "@motdotla",
@@ -0,0 +1,21 @@
1
+ const resolveHome = require('./resolveHome')
2
+
3
+ function dotenvOptionPaths (options) {
4
+ let optionPaths = ['.env']
5
+
6
+ if (options && options.path) {
7
+ if (!Array.isArray(options.path)) {
8
+ optionPaths = [resolveHome(options.path)]
9
+ } else {
10
+ optionPaths = [] // reset default
11
+
12
+ for (const filepath of options.path) {
13
+ optionPaths.push(resolveHome(filepath))
14
+ }
15
+ }
16
+ }
17
+
18
+ return optionPaths
19
+ }
20
+
21
+ module.exports = dotenvOptionPaths
@@ -7,13 +7,10 @@ function parseDecryptEvalExpand (src, privateKey = null) {
7
7
  // parse
8
8
  const parsed = dotenv.parse(src)
9
9
 
10
- // inline decrypt
11
- for (const key in parsed) {
12
- const value = parsed[key]
13
-
14
- // handle inline encrypted values
15
- if (privateKey && privateKey.length > 0) {
16
- // privateKey
10
+ // handle inline encrypted values
11
+ if (privateKey && privateKey.length > 0) {
12
+ for (const key in parsed) {
13
+ const value = parsed[key]
17
14
  parsed[key] = decryptValue(value, privateKey)
18
15
  }
19
16
  }
@@ -0,0 +1,12 @@
1
+ const os = require('os')
2
+ const path = require('path')
3
+
4
+ function resolveHome (filepath) {
5
+ if (filepath[0] === '~') {
6
+ return path.join(os.homedir(), filepath.slice(1))
7
+ }
8
+
9
+ return filepath
10
+ }
11
+
12
+ module.exports = resolveHome
package/src/lib/main.js CHANGED
@@ -1,10 +1,11 @@
1
+ const path = require('path')
1
2
  const logger = require('./../shared/logger')
2
3
  const dotenv = require('dotenv')
3
- const dotenvExpand = require('dotenv-expand')
4
4
 
5
5
  // services
6
6
  const Ls = require('./services/ls')
7
7
  const Get = require('./services/get')
8
+ const Run = require('./services/run')
8
9
  const Sets = require('./services/sets')
9
10
  const Status = require('./services/status')
10
11
  const Encrypt = require('./services/encrypt')
@@ -13,25 +14,119 @@ const Settings = require('./services/settings')
13
14
  const VaultEncrypt = require('./services/vaultEncrypt')
14
15
 
15
16
  // helpers
16
- const dotenvEval = require('./helpers/dotenvEval')
17
+ const dotenvOptionPaths = require('./helpers/dotenvOptionPaths')
17
18
 
18
19
  // proxies to dotenv
19
- const config = function (options) {
20
- const env = dotenv.config(options)
20
+ const config = function (options = {}) {
21
+ // allow user to set processEnv to write to
22
+ let processEnv = process.env
23
+ if (options && options.processEnv != null) {
24
+ processEnv = options.processEnv
25
+ }
26
+
27
+ // overload
28
+ const overload = options.overload || options.override
21
29
 
22
- // if processEnv passed also pass to expand
23
- if (options && options.processEnv) {
24
- env.processEnv = options.processEnv
30
+ // DOTENV_KEY
31
+ let DOTENV_KEY = process.env.DOTENV_KEY
32
+ if (options && options.DOTENV_KEY) {
33
+ DOTENV_KEY = options.DOTENV_KEY
25
34
  }
26
- const expanded = dotenvExpand.expand(env)
27
35
 
28
- // if processEnv passed also pass to eval
29
- if (options && options.processEnv) {
30
- expanded.processEnv = options.processEnv
36
+ // debug -> log level
37
+ if (options && options.debug) {
38
+ logger.level = 'debug'
39
+ logger.debug('setting log level to debug')
31
40
  }
32
- const evaluated = dotenvEval.eval(expanded)
33
41
 
34
- return evaluated
42
+ // build envs using user set option.path
43
+ const optionPaths = dotenvOptionPaths(options) // [ '.env' ]
44
+
45
+ try {
46
+ const envs = []
47
+ for (const optionPath of optionPaths) {
48
+ // if DOTENV_KEY is set then assume we are checking envVaultFile
49
+ if (DOTENV_KEY) {
50
+ envs.push({ type: 'envVaultFile', value: path.join(path.dirname(optionPath), '.env.vault') })
51
+ } else {
52
+ envs.push({ type: 'envFile', value: optionPath })
53
+ }
54
+ }
55
+
56
+ const {
57
+ processedEnvs,
58
+ readableFilepaths,
59
+ uniqueInjectedKeys
60
+ } = new Run(envs, overload, DOTENV_KEY, processEnv).run()
61
+
62
+ let lastError
63
+ const parsedAll = {}
64
+
65
+ for (const processedEnv of processedEnvs) {
66
+ if (processedEnv.type === 'envVaultFile') {
67
+ logger.verbose(`loading env from encrypted ${processedEnv.filepath} (${path.resolve(processedEnv.filepath)})`)
68
+ logger.debug(`decrypting encrypted env from ${processedEnv.filepath} (${path.resolve(processedEnv.filepath)})`)
69
+ }
70
+
71
+ if (processedEnv.type === 'envFile') {
72
+ logger.verbose(`loading env from ${processedEnv.filepath} (${path.resolve(processedEnv.filepath)})`)
73
+ }
74
+
75
+ if (processedEnv.error) {
76
+ lastError = processedEnv.error
77
+
78
+ if (processedEnv.error.code === 'MISSING_ENV_FILE') {
79
+ // do not warn for conventions (too noisy)
80
+ if (!options.convention) {
81
+ logger.warnv(processedEnv.error)
82
+ logger.help(`? add one with [echo "HELLO=World" > ${processedEnv.filepath}] and re-run [dotenvx run -- yourcommand]`)
83
+ }
84
+ } else {
85
+ logger.warnv(processedEnv.error)
86
+ }
87
+ } else {
88
+ Object.assign(parsedAll, processedEnv.injected)
89
+ Object.assign(parsedAll, processedEnv.preExisted) // preExisted 'wins'
90
+
91
+ // debug parsed
92
+ const parsed = processedEnv.parsed
93
+ logger.debug(parsed)
94
+
95
+ // verbose/debug injected key/value
96
+ const injected = processedEnv.injected
97
+ for (const [key, value] of Object.entries(injected)) {
98
+ logger.verbose(`${key} set`)
99
+ logger.debug(`${key} set to ${value}`)
100
+ }
101
+
102
+ // verbose/debug preExisted key/value
103
+ const preExisted = processedEnv.preExisted
104
+ for (const [key, value] of Object.entries(preExisted)) {
105
+ logger.verbose(`${key} pre-exists (protip: use --overload to override)`)
106
+ logger.debug(`${key} pre-exists as ${value} (protip: use --overload to override)`)
107
+ }
108
+ }
109
+ }
110
+
111
+ let msg = `injecting env (${uniqueInjectedKeys.length})`
112
+ if (readableFilepaths.length > 0) {
113
+ msg += ` from ${readableFilepaths.join(', ')}`
114
+ }
115
+ logger.successv(msg)
116
+
117
+ if (lastError) {
118
+ return { parsed: parsedAll, error: lastError }
119
+ } else {
120
+ return { parsed: parsedAll }
121
+ }
122
+ } catch (error) {
123
+ logger.error(error.message)
124
+ if (error.help) {
125
+ logger.help(error.help)
126
+ }
127
+
128
+ return { parsed: {}, error }
129
+ }
35
130
  }
36
131
 
37
132
  const configDotenv = function (options) {