@dotenvx/dotenvx 1.24.5 → 1.25.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 +17 -1
- package/README.md +129 -0
- package/package.json +1 -1
- package/src/cli/actions/decrypt.js +2 -2
- package/src/cli/actions/ext/genexample.js +1 -1
- package/src/cli/actions/ext/scan.js +2 -2
- package/src/cli/actions/get.js +44 -27
- package/src/cli/actions/run.js +29 -37
- package/src/cli/dotenvx.js +2 -0
- package/src/lib/helpers/catchAndLog.js +1 -1
- package/src/lib/helpers/deprecationNotice.js +17 -0
- package/src/lib/helpers/errors.js +30 -0
- package/src/lib/helpers/parse.js +9 -9
- package/src/lib/main.js +47 -74
- package/src/lib/services/decrypt.js +2 -4
- package/src/lib/services/encrypt.js +2 -4
- package/src/lib/services/genexample.js +3 -7
- package/src/lib/services/get.js +25 -8
- package/src/lib/services/run.js +12 -14
- package/src/lib/services/sets.js +2 -4
package/CHANGELOG.md
CHANGED
|
@@ -2,7 +2,23 @@
|
|
|
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.25.0...main)
|
|
6
|
+
|
|
7
|
+
## [1.25.0](https://github.com/dotenvx/dotenvx/compare/v1.24.5...v1.25.0)
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
* add `run --strict` flag to exit with code `1` if any errors are encountered - like a missing `.env` file or decryption failure ([#460](https://github.com/dotenvx/dotenvx/pull/460))
|
|
12
|
+
* add `get --strict` flag to exit with code `1` if any errors are encountered - like a missing `.env` file or decryption failure ([#461](https://github.com/dotenvx/dotenvx/pull/461))
|
|
13
|
+
* add `strict` option to `config()` to throw for any errors ([#459](https://github.com/dotenvx/dotenvx/pull/459))
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
|
|
17
|
+
* log `MISSING_ENV_FILE` and `DECRYPTION_FAILED` errors to stderr (prior was stdout as a warning) ([#459](https://github.com/dotenvx/dotenvx/pull/459))
|
|
18
|
+
|
|
19
|
+
### Removed
|
|
20
|
+
|
|
21
|
+
* remove `dotenvx.get()` function from `lib/main.js`. (`parse` already historically exists for this purpose) ([#461](https://github.com/dotenvx/dotenvx/pull/461))
|
|
6
22
|
|
|
7
23
|
## [1.24.5](https://github.com/dotenvx/dotenvx/compare/v1.24.4...v1.24.5)
|
|
8
24
|
|
package/README.md
CHANGED
|
@@ -968,6 +968,21 @@ More examples
|
|
|
968
968
|
|
|
969
969
|
Available log levels are `error, warn, info, verbose, debug, silly` ([source](https://docs.npmjs.com/cli/v8/using-npm/logging#setting-log-levels))
|
|
970
970
|
|
|
971
|
+
</details>
|
|
972
|
+
* <details><summary>`run --strict`</summary><br>
|
|
973
|
+
|
|
974
|
+
Exit with code `1` if any errors are encountered - like a missing .env file or decryption failure.
|
|
975
|
+
|
|
976
|
+
```sh
|
|
977
|
+
$ echo "console.log('Hello ' + process.env.HELLO)" > index.js
|
|
978
|
+
|
|
979
|
+
$ dotenvx run -f .env.missing --strict -- node index.js
|
|
980
|
+
[MISSING_ENV_FILE] missing .env.missing file (/path/to/.env.missing)
|
|
981
|
+
[MISSING_ENV_FILE] ? add one with [echo "HELLO=World" > .env.missing]
|
|
982
|
+
```
|
|
983
|
+
|
|
984
|
+
This can be useful in `ci` scripts where you want to fail the ci if your `.env` file could not be decrypted at runtime.
|
|
985
|
+
|
|
971
986
|
</details>
|
|
972
987
|
* <details><summary>`run --convention=nextjs`</summary><br>
|
|
973
988
|
|
|
@@ -1036,6 +1051,16 @@ More examples
|
|
|
1036
1051
|
World
|
|
1037
1052
|
```
|
|
1038
1053
|
|
|
1054
|
+
</details>
|
|
1055
|
+
* <details><summary>`get KEY --strict`</summary><br>
|
|
1056
|
+
|
|
1057
|
+
Exit with code `1` if any errors are encountered - like a missing key, missing .env file, or decryption failure.
|
|
1058
|
+
|
|
1059
|
+
```sh
|
|
1060
|
+
$ dotenvx get DOES_NOT_EXIST --strict
|
|
1061
|
+
[MISSING_KEY] missing DOES_NOT_EXIST key
|
|
1062
|
+
```
|
|
1063
|
+
|
|
1039
1064
|
</details>
|
|
1040
1065
|
* <details><summary>`get KEY --convention=nextjs`</summary><br>
|
|
1041
1066
|
|
|
@@ -1607,6 +1632,110 @@ More examples
|
|
|
1607
1632
|
|
|
1608
1633
|
</details>
|
|
1609
1634
|
|
|
1635
|
+
### config() 📦
|
|
1636
|
+
|
|
1637
|
+
* <details><summary>`config()`</summary><br>
|
|
1638
|
+
|
|
1639
|
+
Use directly in node.js code.
|
|
1640
|
+
|
|
1641
|
+
```ini
|
|
1642
|
+
# .env
|
|
1643
|
+
HELLO="World"
|
|
1644
|
+
```
|
|
1645
|
+
|
|
1646
|
+
```js
|
|
1647
|
+
// index.js
|
|
1648
|
+
require('@dotenvx/dotenvx').config()
|
|
1649
|
+
|
|
1650
|
+
console.log(`Hello ${process.env.HELLO}`)
|
|
1651
|
+
```
|
|
1652
|
+
|
|
1653
|
+
```sh
|
|
1654
|
+
$ node index.js
|
|
1655
|
+
[dotenvx@1.24.5] injecting env (1) from .env
|
|
1656
|
+
Hello World
|
|
1657
|
+
```
|
|
1658
|
+
|
|
1659
|
+
</details>
|
|
1660
|
+
* <details><summary>`config(path: ['.env.local', '.env'])` - multiple files</summary><br>
|
|
1661
|
+
|
|
1662
|
+
Specify path(s) to multiple .env files.
|
|
1663
|
+
|
|
1664
|
+
```ini
|
|
1665
|
+
# .env.local
|
|
1666
|
+
HELLO="Me"
|
|
1667
|
+
```
|
|
1668
|
+
|
|
1669
|
+
```ini
|
|
1670
|
+
# .env
|
|
1671
|
+
HELLO="World"
|
|
1672
|
+
```
|
|
1673
|
+
|
|
1674
|
+
```js
|
|
1675
|
+
// index.js
|
|
1676
|
+
require('@dotenvx/dotenvx').config({path: ['.env.local', '.env']})
|
|
1677
|
+
|
|
1678
|
+
console.log(`Hello ${process.env.HELLO}`)
|
|
1679
|
+
```
|
|
1680
|
+
|
|
1681
|
+
```sh
|
|
1682
|
+
$ node index.js
|
|
1683
|
+
[dotenvx@1.24.5] injecting env (1) from .env.local, .env
|
|
1684
|
+
Hello Me
|
|
1685
|
+
```
|
|
1686
|
+
|
|
1687
|
+
</details>
|
|
1688
|
+
* <details><summary>`config(overload: true)` - overload</summary><br>
|
|
1689
|
+
|
|
1690
|
+
User `overload` to overwrite the prior set value.
|
|
1691
|
+
|
|
1692
|
+
```ini
|
|
1693
|
+
# .env.local
|
|
1694
|
+
HELLO="Me"
|
|
1695
|
+
```
|
|
1696
|
+
|
|
1697
|
+
```ini
|
|
1698
|
+
# .env
|
|
1699
|
+
HELLO="World"
|
|
1700
|
+
```
|
|
1701
|
+
|
|
1702
|
+
```js
|
|
1703
|
+
// index.js
|
|
1704
|
+
require('@dotenvx/dotenvx').config({path: ['.env.local', '.env'], overload: true})
|
|
1705
|
+
|
|
1706
|
+
console.log(`Hello ${process.env.HELLO}`)
|
|
1707
|
+
```
|
|
1708
|
+
|
|
1709
|
+
```sh
|
|
1710
|
+
$ node index.js
|
|
1711
|
+
[dotenvx@1.24.5] injecting env (1) from .env.local, .env
|
|
1712
|
+
Hello World
|
|
1713
|
+
```
|
|
1714
|
+
|
|
1715
|
+
</details>
|
|
1716
|
+
* <details><summary>`config(strict: true)` - strict</summary><br>
|
|
1717
|
+
|
|
1718
|
+
Use `strict` to throw if an error is encountered - like a missing .env file.
|
|
1719
|
+
|
|
1720
|
+
```ini
|
|
1721
|
+
# .env
|
|
1722
|
+
HELLO="World"
|
|
1723
|
+
```
|
|
1724
|
+
|
|
1725
|
+
```js
|
|
1726
|
+
// index.js
|
|
1727
|
+
require('@dotenvx/dotenvx').config({path: ['.env.missing', '.env'], strict: true})
|
|
1728
|
+
|
|
1729
|
+
console.log(`Hello ${process.env.HELLO}`)
|
|
1730
|
+
```
|
|
1731
|
+
|
|
1732
|
+
```sh
|
|
1733
|
+
$ node index.js
|
|
1734
|
+
Error: [MISSING_ENV_FILE] missing .env.missing file (/path/to/.env.missing)
|
|
1735
|
+
```
|
|
1736
|
+
|
|
1737
|
+
</details>
|
|
1738
|
+
|
|
1610
1739
|
### Extensions 🔌
|
|
1611
1740
|
|
|
1612
1741
|
* <details><summary>`ext genexample`</summary><br>
|
package/package.json
CHANGED
|
@@ -48,10 +48,10 @@ function decrypt () {
|
|
|
48
48
|
errorCount += 1
|
|
49
49
|
|
|
50
50
|
if (processedEnv.error.code === 'MISSING_ENV_FILE') {
|
|
51
|
-
|
|
51
|
+
console.error(processedEnv.error.message)
|
|
52
52
|
logger.help(`? add one with [echo "HELLO=World" > ${processedEnv.envFilepath}] and re-run [dotenvx decrypt]`)
|
|
53
53
|
} else {
|
|
54
|
-
|
|
54
|
+
console.error(processedEnv.error.message)
|
|
55
55
|
}
|
|
56
56
|
} else if (processedEnv.changed) {
|
|
57
57
|
fsx.writeFileX(processedEnv.filepath, processedEnv.envSrc)
|
|
@@ -10,7 +10,7 @@ function scan () {
|
|
|
10
10
|
// redirect stderr to stdout to capture and ignore it
|
|
11
11
|
childProcess.execSync('gitleaks version', { stdio: ['ignore', 'pipe', 'ignore'] })
|
|
12
12
|
} catch (error) {
|
|
13
|
-
|
|
13
|
+
console.error('gitleaks: command not found')
|
|
14
14
|
logger.help('? install gitleaks: [brew install gitleaks]')
|
|
15
15
|
logger.help2('? other install options: [https://github.com/gitleaks/gitleaks]')
|
|
16
16
|
process.exit(1)
|
|
@@ -21,7 +21,7 @@ function scan () {
|
|
|
21
21
|
const output = childProcess.execSync('gitleaks detect -v 2>&1', { stdio: 'pipe' }).toString() // gitleaks sends output as stderr for strange reason
|
|
22
22
|
logger.blank(output)
|
|
23
23
|
} catch (error) {
|
|
24
|
-
|
|
24
|
+
console.error(error.message)
|
|
25
25
|
|
|
26
26
|
process.exit(1)
|
|
27
27
|
}
|
package/src/cli/actions/get.js
CHANGED
|
@@ -3,7 +3,7 @@ const { logger } = require('./../../shared/logger')
|
|
|
3
3
|
const conventions = require('./../../lib/helpers/conventions')
|
|
4
4
|
const escape = require('./../../lib/helpers/escape')
|
|
5
5
|
|
|
6
|
-
const
|
|
6
|
+
const Get = require('./../../lib/services/get')
|
|
7
7
|
|
|
8
8
|
function get (key) {
|
|
9
9
|
if (key) {
|
|
@@ -21,40 +21,57 @@ function get (key) {
|
|
|
21
21
|
envs = this.envs
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
try {
|
|
25
|
+
const { parsed, errors } = new Get(key, envs, options.overload, process.env.DOTENV_KEY, options.all).run()
|
|
25
26
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
let inline = ''
|
|
29
|
-
for (const [key, value] of Object.entries(results)) {
|
|
30
|
-
inline += `${key}=${escape(value)}\n`
|
|
31
|
-
}
|
|
32
|
-
inline = inline.trim()
|
|
27
|
+
for (const error of errors || []) {
|
|
28
|
+
if (options.strict) throw error // throw immediately if strict
|
|
33
29
|
|
|
34
|
-
console.
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
for (const [key, value] of Object.entries(results)) {
|
|
38
|
-
inline += `${key}=${value} `
|
|
30
|
+
console.error(error.message)
|
|
31
|
+
if (error.help) {
|
|
32
|
+
console.error(error.help)
|
|
39
33
|
}
|
|
40
|
-
|
|
34
|
+
}
|
|
41
35
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
36
|
+
if (key) {
|
|
37
|
+
const single = parsed[key]
|
|
38
|
+
if (single === undefined) {
|
|
39
|
+
console.log('')
|
|
40
|
+
} else {
|
|
41
|
+
console.log(single)
|
|
47
42
|
}
|
|
43
|
+
} else {
|
|
44
|
+
if (options.format === 'eval') {
|
|
45
|
+
let inline = ''
|
|
46
|
+
for (const [key, value] of Object.entries(parsed)) {
|
|
47
|
+
inline += `${key}=${escape(value)}\n`
|
|
48
|
+
}
|
|
49
|
+
inline = inline.trim()
|
|
50
|
+
|
|
51
|
+
console.log(inline)
|
|
52
|
+
} else if (options.format === 'shell') {
|
|
53
|
+
let inline = ''
|
|
54
|
+
for (const [key, value] of Object.entries(parsed)) {
|
|
55
|
+
inline += `${key}=${value} `
|
|
56
|
+
}
|
|
57
|
+
inline = inline.trim()
|
|
48
58
|
|
|
49
|
-
|
|
59
|
+
console.log(inline)
|
|
60
|
+
} else {
|
|
61
|
+
let space = 0
|
|
62
|
+
if (options.prettyPrint) {
|
|
63
|
+
space = 2
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
console.log(JSON.stringify(parsed, null, space))
|
|
67
|
+
}
|
|
50
68
|
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
} else {
|
|
56
|
-
console.log(results)
|
|
69
|
+
} catch (error) {
|
|
70
|
+
console.error(error.message)
|
|
71
|
+
if (error.help) {
|
|
72
|
+
console.error(error.help)
|
|
57
73
|
}
|
|
74
|
+
process.exit(1)
|
|
58
75
|
}
|
|
59
76
|
}
|
|
60
77
|
|
package/src/cli/actions/run.js
CHANGED
|
@@ -5,6 +5,7 @@ const executeCommand = require('./../../lib/helpers/executeCommand')
|
|
|
5
5
|
const Run = require('./../../lib/services/run')
|
|
6
6
|
|
|
7
7
|
const conventions = require('./../../lib/helpers/conventions')
|
|
8
|
+
const DeprecationNotice = require('./../../lib/helpers/deprecationNotice')
|
|
8
9
|
|
|
9
10
|
async function run () {
|
|
10
11
|
const commandArgs = this.args
|
|
@@ -35,11 +36,7 @@ async function run () {
|
|
|
35
36
|
envs = this.envs
|
|
36
37
|
}
|
|
37
38
|
|
|
38
|
-
|
|
39
|
-
logger.warn('DEPRECATION NOTICE: Setting DOTENV_KEY with .env.vault is deprecated.')
|
|
40
|
-
logger.warn('DEPRECATION NOTICE: Run [dotenvx ext vault migrate] for instructions on converting your .env.vault file to encrypted .env files (using public key encryption algorithm secp256k1)')
|
|
41
|
-
logger.warn('DEPRECATION NOTICE: Read more at [https://github.com/dotenvx/dotenvx/blob/main/CHANGELOG.md#0380]')
|
|
42
|
-
}
|
|
39
|
+
new DeprecationNotice().dotenvKey() // DEPRECATION NOTICE
|
|
43
40
|
|
|
44
41
|
const {
|
|
45
42
|
processedEnvs,
|
|
@@ -62,43 +59,37 @@ async function run () {
|
|
|
62
59
|
logger.verbose(`loading env from string (${processedEnv.string})`)
|
|
63
60
|
}
|
|
64
61
|
|
|
65
|
-
|
|
66
|
-
if (
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
62
|
+
for (const error of processedEnv.errors || []) {
|
|
63
|
+
if (options.strict) throw error // throw immediately if strict
|
|
64
|
+
|
|
65
|
+
if (error.code === 'MISSING_ENV_FILE') {
|
|
66
|
+
if (!options.convention) { // do not output error for conventions (too noisy)
|
|
67
|
+
console.error(error.message)
|
|
68
|
+
if (error.help) {
|
|
69
|
+
console.error(`${error.help} and re-run [dotenvx run -- ${commandArgs.join(' ')}]`)
|
|
70
|
+
}
|
|
71
71
|
}
|
|
72
72
|
} else {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
if (processedEnv.warnings) {
|
|
77
|
-
for (const warning of processedEnv.warnings) {
|
|
78
|
-
logger.warn(warning.message)
|
|
79
|
-
if (warning.help) {
|
|
80
|
-
logger.help(warning.help)
|
|
81
|
-
}
|
|
73
|
+
console.error(error.message)
|
|
74
|
+
if (error.help) {
|
|
75
|
+
console.error(error.help)
|
|
82
76
|
}
|
|
83
77
|
}
|
|
78
|
+
}
|
|
84
79
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
logger.debug(parsed)
|
|
80
|
+
// debug parsed
|
|
81
|
+
logger.debug(processedEnv.parsed)
|
|
88
82
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
}
|
|
83
|
+
// verbose/debug injected key/value
|
|
84
|
+
for (const [key, value] of Object.entries(processedEnv.injected || {})) {
|
|
85
|
+
logger.verbose(`${key} set`)
|
|
86
|
+
logger.debug(`${key} set to ${value}`)
|
|
87
|
+
}
|
|
95
88
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
logger.debug(`${key} pre-exists as ${value} (protip: use --overload to override)`)
|
|
101
|
-
}
|
|
89
|
+
// verbose/debug preExisted key/value
|
|
90
|
+
for (const [key, value] of Object.entries(processedEnv.preExisted || {})) {
|
|
91
|
+
logger.verbose(`${key} pre-exists (protip: use --overload to override)`)
|
|
92
|
+
logger.debug(`${key} pre-exists as ${value} (protip: use --overload to override)`)
|
|
102
93
|
}
|
|
103
94
|
}
|
|
104
95
|
|
|
@@ -113,10 +104,11 @@ async function run () {
|
|
|
113
104
|
|
|
114
105
|
logger.successv(msg)
|
|
115
106
|
} catch (error) {
|
|
116
|
-
|
|
107
|
+
console.error(error.message)
|
|
117
108
|
if (error.help) {
|
|
118
|
-
|
|
109
|
+
console.error(error.help)
|
|
119
110
|
}
|
|
111
|
+
process.exit(1)
|
|
120
112
|
}
|
|
121
113
|
|
|
122
114
|
await executeCommand(commandArgs, process.env)
|
package/src/cli/dotenvx.js
CHANGED
|
@@ -58,6 +58,7 @@ program.command('run')
|
|
|
58
58
|
.option('-f, --env-file <paths...>', 'path(s) to your env file(s)', collectEnvs('envFile'), [])
|
|
59
59
|
.option('-fv, --env-vault-file <paths...>', 'path(s) to your .env.vault file(s)', collectEnvs('envVaultFile'), [])
|
|
60
60
|
.option('-o, --overload', 'override existing env variables')
|
|
61
|
+
.option('--strict', 'process.exit(1) on any errors (default: false)', false)
|
|
61
62
|
.option('--convention <name>', 'load a .env convention (available conventions: [\'nextjs\'])')
|
|
62
63
|
.action(function (...args) {
|
|
63
64
|
this.envs = envs
|
|
@@ -74,6 +75,7 @@ program.command('get')
|
|
|
74
75
|
.option('-f, --env-file <paths...>', 'path(s) to your env file(s)', collectEnvs('envFile'), [])
|
|
75
76
|
.option('-fv, --env-vault-file <paths...>', 'path(s) to your .env.vault file(s)', collectEnvs('envVaultFile'), [])
|
|
76
77
|
.option('-o, --overload', 'override existing env variables')
|
|
78
|
+
.option('--strict', 'process.exit(1) on any errors (default: false)', false)
|
|
77
79
|
.option('--convention <name>', 'load a .env convention (available conventions: [\'nextjs\'])')
|
|
78
80
|
.option('-a, --all', 'include all machine envs as well')
|
|
79
81
|
.option('-pp, --pretty-print', 'pretty print output')
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
const { logger } = require('./../../shared/logger')
|
|
2
|
+
|
|
3
|
+
class DeprecationNotice {
|
|
4
|
+
constructor (options = {}) {
|
|
5
|
+
this.DOTENV_KEY = options.DOTENV_KEY || process.env.DOTENV_KEY
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
dotenvKey () {
|
|
9
|
+
if (this.DOTENV_KEY) {
|
|
10
|
+
logger.warn('[DEPRECATION NOTICE] Setting DOTENV_KEY with .env.vault is deprecated.')
|
|
11
|
+
logger.warn('[DEPRECATION NOTICE] Run [dotenvx ext vault migrate] for instructions on converting your .env.vault file to encrypted .env files (using public key encryption algorithm secp256k1)')
|
|
12
|
+
logger.warn('[DEPRECATION NOTICE] Read more at [https://github.com/dotenvx/dotenvx/blob/main/CHANGELOG.md#0380]')
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
module.exports = DeprecationNotice
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
class Errors {
|
|
2
|
+
constructor (options = {}) {
|
|
3
|
+
this.filepath = options.filepath
|
|
4
|
+
this.envFilepath = options.envFilepath
|
|
5
|
+
|
|
6
|
+
this.key = options.key
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
missingEnvFile () {
|
|
10
|
+
const code = 'MISSING_ENV_FILE'
|
|
11
|
+
const message = `[${code}] missing ${this.envFilepath} file (${this.filepath})`
|
|
12
|
+
const help = `[${code}] ? add one with [echo "HELLO=World" > ${this.envFilepath}]`
|
|
13
|
+
|
|
14
|
+
const e = new Error(message)
|
|
15
|
+
e.code = code
|
|
16
|
+
e.help = help
|
|
17
|
+
return e
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
missingKey () {
|
|
21
|
+
const code = 'MISSING_KEY'
|
|
22
|
+
const message = `[${code}] missing ${this.key} key`
|
|
23
|
+
|
|
24
|
+
const e = new Error(message)
|
|
25
|
+
e.code = code
|
|
26
|
+
return e
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
module.exports = Errors
|
package/src/lib/helpers/parse.js
CHANGED
|
@@ -16,7 +16,7 @@ class Parse {
|
|
|
16
16
|
this.parsed = {}
|
|
17
17
|
this.preExisted = {}
|
|
18
18
|
this.injected = {}
|
|
19
|
-
this.
|
|
19
|
+
this.errors = []
|
|
20
20
|
|
|
21
21
|
// for use with progressive expansion
|
|
22
22
|
this.runningParsed = {}
|
|
@@ -42,7 +42,7 @@ class Parse {
|
|
|
42
42
|
try {
|
|
43
43
|
this.parsed[key] = this.decrypt(this.parsed[key])
|
|
44
44
|
} catch (e) {
|
|
45
|
-
this.
|
|
45
|
+
this.errors.push(this.error(e, key))
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
// eval empty, double, or backticks
|
|
@@ -78,8 +78,8 @@ class Parse {
|
|
|
78
78
|
parsed: this.parsed,
|
|
79
79
|
processEnv: this.processEnv,
|
|
80
80
|
injected: this.injected,
|
|
81
|
-
|
|
82
|
-
|
|
81
|
+
preExisted: this.preExisted,
|
|
82
|
+
errors: this.errors
|
|
83
83
|
}
|
|
84
84
|
}
|
|
85
85
|
|
|
@@ -208,12 +208,12 @@ class Parse {
|
|
|
208
208
|
return (this.src || '').toString().replace(/\r\n?/mg, '\n') // Convert buffer to string and Convert line breaks to same format
|
|
209
209
|
}
|
|
210
210
|
|
|
211
|
-
|
|
212
|
-
const
|
|
213
|
-
|
|
214
|
-
|
|
211
|
+
error (e, key) {
|
|
212
|
+
const error = new Error(`[${e.code}] could not decrypt ${key} using private key '${truncate(this.privateKey)}'`)
|
|
213
|
+
error.code = e.code
|
|
214
|
+
error.help = `[${e.code}] ? ${e.message}`
|
|
215
215
|
|
|
216
|
-
return
|
|
216
|
+
return error
|
|
217
217
|
}
|
|
218
218
|
}
|
|
219
219
|
|
package/src/lib/main.js
CHANGED
|
@@ -7,7 +7,6 @@ const { getColor, bold } = require('./../shared/colors')
|
|
|
7
7
|
|
|
8
8
|
// services
|
|
9
9
|
const Ls = require('./services/ls')
|
|
10
|
-
const Get = require('./services/get')
|
|
11
10
|
const Run = require('./services/run')
|
|
12
11
|
const Keypair = require('./services/keypair')
|
|
13
12
|
const Genexample = require('./services/genexample')
|
|
@@ -16,6 +15,7 @@ const Genexample = require('./services/genexample')
|
|
|
16
15
|
const conventions = require('./helpers/conventions')
|
|
17
16
|
const dotenvOptionPaths = require('./helpers/dotenvOptionPaths')
|
|
18
17
|
const Parse = require('./helpers/parse')
|
|
18
|
+
const DeprecationNotice = require('./helpers/deprecationNotice')
|
|
19
19
|
|
|
20
20
|
/** @type {import('./main').config} */
|
|
21
21
|
const config = function (options = {}) {
|
|
@@ -28,7 +28,10 @@ const config = function (options = {}) {
|
|
|
28
28
|
// overload
|
|
29
29
|
const overload = options.overload || options.override
|
|
30
30
|
|
|
31
|
-
//
|
|
31
|
+
// strict
|
|
32
|
+
const strict = options.strict
|
|
33
|
+
|
|
34
|
+
// DOTENV_KEY (DEPRECATED)
|
|
32
35
|
let DOTENV_KEY = process.env.DOTENV_KEY
|
|
33
36
|
if (options && options.DOTENV_KEY) {
|
|
34
37
|
DOTENV_KEY = options.DOTENV_KEY
|
|
@@ -46,11 +49,7 @@ const config = function (options = {}) {
|
|
|
46
49
|
envs = conventions(options.convention).concat(envs)
|
|
47
50
|
}
|
|
48
51
|
|
|
49
|
-
|
|
50
|
-
logger.warn('DEPRECATION NOTICE: Setting DOTENV_KEY with .env.vault is deprecated.')
|
|
51
|
-
logger.warn('DEPRECATION NOTICE: Run [dotenvx ext vault migrate] for instructions on converting your .env.vault file to encrypted .env files (using public key encryption algorithm secp256k1)')
|
|
52
|
-
logger.warn('DEPRECATION NOTICE: Read more at [https://github.com/dotenvx/dotenvx/blob/main/CHANGELOG.md#0380]')
|
|
53
|
-
}
|
|
52
|
+
new DeprecationNotice({ DOTENV_KEY }).dotenvKey() // DEPRECATION NOTICE
|
|
54
53
|
|
|
55
54
|
for (const optionPath of optionPaths) {
|
|
56
55
|
// if DOTENV_KEY is set then assume we are checking envVaultFile
|
|
@@ -64,12 +63,11 @@ const config = function (options = {}) {
|
|
|
64
63
|
}
|
|
65
64
|
}
|
|
66
65
|
|
|
67
|
-
const {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
).run()
|
|
66
|
+
const {
|
|
67
|
+
processedEnvs,
|
|
68
|
+
readableFilepaths,
|
|
69
|
+
uniqueInjectedKeys
|
|
70
|
+
} = new Run(envs, overload, DOTENV_KEY, processEnv).run()
|
|
73
71
|
|
|
74
72
|
let lastError
|
|
75
73
|
/** @type {Record<string, string>} */
|
|
@@ -77,65 +75,50 @@ const config = function (options = {}) {
|
|
|
77
75
|
|
|
78
76
|
for (const processedEnv of processedEnvs) {
|
|
79
77
|
if (processedEnv.type === 'envVaultFile') {
|
|
80
|
-
logger.verbose(
|
|
81
|
-
|
|
82
|
-
processedEnv.filepath
|
|
83
|
-
)})`
|
|
84
|
-
)
|
|
85
|
-
logger.debug(
|
|
86
|
-
`decrypting encrypted env from ${
|
|
87
|
-
processedEnv.filepath
|
|
88
|
-
} (${path.resolve(processedEnv.filepath)})`
|
|
89
|
-
)
|
|
78
|
+
logger.verbose(`loading env from encrypted ${processedEnv.filepath} (${path.resolve(processedEnv.filepath)})`)
|
|
79
|
+
logger.debug(`decrypting encrypted env from ${processedEnv.filepath} (${path.resolve(processedEnv.filepath)})`)
|
|
90
80
|
}
|
|
91
81
|
|
|
92
82
|
if (processedEnv.type === 'envFile') {
|
|
93
|
-
logger.verbose(
|
|
94
|
-
`loading env from ${processedEnv.filepath} (${path.resolve(
|
|
95
|
-
processedEnv.filepath
|
|
96
|
-
)})`
|
|
97
|
-
)
|
|
83
|
+
logger.verbose(`loading env from ${processedEnv.filepath} (${path.resolve(processedEnv.filepath)})`)
|
|
98
84
|
}
|
|
99
85
|
|
|
100
|
-
|
|
101
|
-
|
|
86
|
+
for (const error of processedEnv.errors || []) {
|
|
87
|
+
if (strict) throw error // throw immediately if strict
|
|
102
88
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
89
|
+
lastError = error // surface later in { error }
|
|
90
|
+
|
|
91
|
+
if (error.code === 'MISSING_ENV_FILE') {
|
|
92
|
+
if (!options.convention) { // do not output error for conventions (too noisy)
|
|
93
|
+
console.error(error.message)
|
|
94
|
+
if (error.help) {
|
|
95
|
+
logger.help(error.help)
|
|
96
|
+
}
|
|
110
97
|
}
|
|
111
98
|
} else {
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
Object.assign(parsedAll, processedEnv.preExisted) // preExisted 'wins'
|
|
117
|
-
|
|
118
|
-
// debug parsed
|
|
119
|
-
const parsed = processedEnv.parsed
|
|
120
|
-
logger.debug(parsed)
|
|
121
|
-
|
|
122
|
-
// verbose/debug injected key/value
|
|
123
|
-
const injected = processedEnv.injected
|
|
124
|
-
for (const [key, value] of Object.entries(injected)) {
|
|
125
|
-
logger.verbose(`${key} set`)
|
|
126
|
-
logger.debug(`${key} set to ${value}`)
|
|
99
|
+
console.error(error.message)
|
|
100
|
+
if (error.help) {
|
|
101
|
+
logger.help(error.help)
|
|
102
|
+
}
|
|
127
103
|
}
|
|
104
|
+
}
|
|
128
105
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
}
|
|
106
|
+
Object.assign(parsedAll, processedEnv.injected || {})
|
|
107
|
+
Object.assign(parsedAll, processedEnv.preExisted || {}) // preExisted 'wins'
|
|
108
|
+
|
|
109
|
+
// debug parsed
|
|
110
|
+
logger.debug(processedEnv.parsed)
|
|
111
|
+
|
|
112
|
+
// verbose/debug injected key/value
|
|
113
|
+
for (const [key, value] of Object.entries(processedEnv.injected || {})) {
|
|
114
|
+
logger.verbose(`${key} set`)
|
|
115
|
+
logger.debug(`${key} set to ${value}`)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// verbose/debug preExisted key/value
|
|
119
|
+
for (const [key, value] of Object.entries(processedEnv.preExisted || {})) {
|
|
120
|
+
logger.verbose(`${key} pre-exists (protip: use --overload to override)`)
|
|
121
|
+
logger.debug(`${key} pre-exists as ${value} (protip: use --overload to override)`)
|
|
139
122
|
}
|
|
140
123
|
}
|
|
141
124
|
|
|
@@ -151,6 +134,8 @@ const config = function (options = {}) {
|
|
|
151
134
|
return { parsed: parsedAll }
|
|
152
135
|
}
|
|
153
136
|
} catch (error) {
|
|
137
|
+
if (strict) throw error // throw immediately if strict
|
|
138
|
+
|
|
154
139
|
logger.error(error.message)
|
|
155
140
|
if (error.help) {
|
|
156
141
|
logger.help(error.help)
|
|
@@ -189,17 +174,6 @@ const genexample = function (directory, envFile) {
|
|
|
189
174
|
return new Genexample(directory, envFile).run()
|
|
190
175
|
}
|
|
191
176
|
|
|
192
|
-
/** @type {import('./main').get} */
|
|
193
|
-
const get = function (
|
|
194
|
-
key,
|
|
195
|
-
envs = [],
|
|
196
|
-
overload = false,
|
|
197
|
-
DOTENV_KEY = '',
|
|
198
|
-
all = false
|
|
199
|
-
) {
|
|
200
|
-
return new Get(key, envs, overload, DOTENV_KEY, all).run()
|
|
201
|
-
}
|
|
202
|
-
|
|
203
177
|
/** @type {import('./main').keypair} */
|
|
204
178
|
const keypair = function (envFile, key) {
|
|
205
179
|
return new Keypair(envFile, key).run()
|
|
@@ -211,7 +185,6 @@ module.exports = {
|
|
|
211
185
|
parse,
|
|
212
186
|
// actions related
|
|
213
187
|
ls,
|
|
214
|
-
get,
|
|
215
188
|
keypair,
|
|
216
189
|
genexample,
|
|
217
190
|
// expose for libs depending on @dotenvx/dotenvx - like dotenvx-pro
|
|
@@ -5,6 +5,7 @@ const picomatch = require('picomatch')
|
|
|
5
5
|
|
|
6
6
|
const TYPE_ENV_FILE = 'envFile'
|
|
7
7
|
|
|
8
|
+
const Errors = require('./../helpers/errors')
|
|
8
9
|
const guessPrivateKeyName = require('./../helpers/guessPrivateKeyName')
|
|
9
10
|
const findPrivateKey = require('./../helpers/findPrivateKey')
|
|
10
11
|
const decryptValue = require('./../helpers/decryptValue')
|
|
@@ -101,10 +102,7 @@ class Decrypt {
|
|
|
101
102
|
}
|
|
102
103
|
} catch (e) {
|
|
103
104
|
if (e.code === 'ENOENT') {
|
|
104
|
-
|
|
105
|
-
error.code = 'MISSING_ENV_FILE'
|
|
106
|
-
|
|
107
|
-
row.error = error
|
|
105
|
+
row.error = new Errors({ envFilepath, filepath }).missingEnvFile()
|
|
108
106
|
} else {
|
|
109
107
|
row.error = e
|
|
110
108
|
}
|
|
@@ -5,6 +5,7 @@ const picomatch = require('picomatch')
|
|
|
5
5
|
|
|
6
6
|
const TYPE_ENV_FILE = 'envFile'
|
|
7
7
|
|
|
8
|
+
const Errors = require('./../helpers/errors')
|
|
8
9
|
const guessPrivateKeyName = require('./../helpers/guessPrivateKeyName')
|
|
9
10
|
const guessPublicKeyName = require('./../helpers/guessPublicKeyName')
|
|
10
11
|
const encryptValue = require('./../helpers/encryptValue')
|
|
@@ -181,10 +182,7 @@ class Encrypt {
|
|
|
181
182
|
}
|
|
182
183
|
} catch (e) {
|
|
183
184
|
if (e.code === 'ENOENT') {
|
|
184
|
-
|
|
185
|
-
error.code = 'MISSING_ENV_FILE'
|
|
186
|
-
|
|
187
|
-
row.error = error
|
|
185
|
+
row.error = new Errors({ envFilepath, filepath }).missingEnvFile()
|
|
188
186
|
} else {
|
|
189
187
|
row.error = e
|
|
190
188
|
}
|
|
@@ -2,6 +2,7 @@ const fsx = require('./../helpers/fsx')
|
|
|
2
2
|
const path = require('path')
|
|
3
3
|
const dotenv = require('dotenv')
|
|
4
4
|
|
|
5
|
+
const Errors = require('../helpers/errors')
|
|
5
6
|
const findEnvFiles = require('../helpers/findEnvFiles')
|
|
6
7
|
const replace = require('../helpers/replace')
|
|
7
8
|
|
|
@@ -39,13 +40,8 @@ class Genexample {
|
|
|
39
40
|
for (const envFilepath of envFilepaths) {
|
|
40
41
|
const filepath = path.resolve(this.directory, envFilepath)
|
|
41
42
|
if (!fsx.existsSync(filepath)) {
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
const help = `? add it with [echo "HELLO=World" > ${envFilepath}] and then run [dotenvx genexample]`
|
|
45
|
-
|
|
46
|
-
const error = new Error(message)
|
|
47
|
-
error.code = code
|
|
48
|
-
error.help = help
|
|
43
|
+
const error = new Errors({ envFilepath, filepath }).missingEnvFile()
|
|
44
|
+
error.help = `? add it with [echo "HELLO=World" > ${envFilepath}] and then run [dotenvx genexample]`
|
|
49
45
|
throw error
|
|
50
46
|
}
|
|
51
47
|
|
package/src/lib/services/get.js
CHANGED
|
@@ -1,41 +1,58 @@
|
|
|
1
1
|
const Run = require('./run')
|
|
2
|
+
const Errors = require('./../helpers/errors')
|
|
2
3
|
|
|
3
4
|
class Get {
|
|
4
|
-
constructor (key, envs = [], overload = false, DOTENV_KEY = '', all = false) {
|
|
5
|
+
constructor (key, envs = [], overload = false, DOTENV_KEY = '', all = false, strict = false) {
|
|
5
6
|
this.key = key
|
|
6
7
|
this.envs = envs
|
|
7
8
|
this.overload = overload
|
|
8
9
|
this.DOTENV_KEY = DOTENV_KEY
|
|
9
10
|
this.all = all
|
|
11
|
+
this.strict = strict
|
|
10
12
|
}
|
|
11
13
|
|
|
12
14
|
run () {
|
|
13
15
|
const processEnv = { ...process.env }
|
|
14
16
|
const { processedEnvs } = new Run(this.envs, this.overload, this.DOTENV_KEY, processEnv).run()
|
|
15
17
|
|
|
16
|
-
|
|
18
|
+
const errors = []
|
|
19
|
+
for (const processedEnv of processedEnvs) {
|
|
20
|
+
for (const error of processedEnv.errors) {
|
|
21
|
+
errors.push(error)
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (this.key) {
|
|
26
|
+
const parsed = {}
|
|
27
|
+
const value = processEnv[this.key]
|
|
28
|
+
parsed[this.key] = value
|
|
29
|
+
|
|
30
|
+
if (value === undefined) {
|
|
31
|
+
errors.push(new Errors({ key: this.key }).missingKey())
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return { parsed, errors }
|
|
35
|
+
} else {
|
|
17
36
|
// if user wants to return ALL envs (even prior set on machine)
|
|
18
37
|
if (this.all) {
|
|
19
|
-
return processEnv
|
|
38
|
+
return { parsed: processEnv, errors }
|
|
20
39
|
}
|
|
21
40
|
|
|
22
41
|
// typical scenario - return only envs that were identified in the .env file
|
|
23
42
|
// iterate over all processedEnvs.parsed and grab from processEnv
|
|
24
43
|
/** @type {Record<string, string>} */
|
|
25
|
-
const
|
|
44
|
+
const parsed = {}
|
|
26
45
|
for (const processedEnv of processedEnvs) {
|
|
27
46
|
// parsed means we saw the key in a file or --env flag. this effectively filters out any preset machine envs - while still respecting complex evaluating, expansion, and overload. in other words, the value might be the machine value because the key was displayed in a .env file
|
|
28
47
|
if (processedEnv.parsed) {
|
|
29
48
|
for (const key of Object.keys(processedEnv.parsed)) {
|
|
30
|
-
|
|
49
|
+
parsed[key] = processEnv[key]
|
|
31
50
|
}
|
|
32
51
|
}
|
|
33
52
|
}
|
|
34
53
|
|
|
35
|
-
return
|
|
54
|
+
return { parsed, errors }
|
|
36
55
|
}
|
|
37
|
-
|
|
38
|
-
return processEnv[this.key]
|
|
39
56
|
}
|
|
40
57
|
}
|
|
41
58
|
|
package/src/lib/services/run.js
CHANGED
|
@@ -8,6 +8,7 @@ const TYPE_ENV_VAULT_FILE = 'envVaultFile'
|
|
|
8
8
|
|
|
9
9
|
const decrypt = require('./../helpers/decrypt')
|
|
10
10
|
const Parse = require('./../helpers/parse')
|
|
11
|
+
const Errors = require('./../helpers/errors')
|
|
11
12
|
const parseEnvironmentFromDotenvKey = require('./../helpers/parseEnvironmentFromDotenvKey')
|
|
12
13
|
const detectEncoding = require('./../helpers/detectEncoding')
|
|
13
14
|
const findPrivateKey = require('./../helpers/findPrivateKey')
|
|
@@ -59,9 +60,9 @@ class Run {
|
|
|
59
60
|
row.string = env
|
|
60
61
|
|
|
61
62
|
try {
|
|
62
|
-
const { parsed,
|
|
63
|
+
const { parsed, errors, injected, preExisted } = new Parse(env, null, this.processEnv, this.overload).run()
|
|
63
64
|
row.parsed = parsed
|
|
64
|
-
row.
|
|
65
|
+
row.errors = errors
|
|
65
66
|
row.injected = injected
|
|
66
67
|
row.preExisted = preExisted
|
|
67
68
|
|
|
@@ -73,7 +74,7 @@ class Run {
|
|
|
73
74
|
this.uniqueInjectedKeys.add(key) // track uniqueInjectedKeys across multiple files
|
|
74
75
|
}
|
|
75
76
|
} catch (e) {
|
|
76
|
-
row.
|
|
77
|
+
row.errors = [e]
|
|
77
78
|
}
|
|
78
79
|
|
|
79
80
|
this.processedEnvs.push(row)
|
|
@@ -91,10 +92,10 @@ class Run {
|
|
|
91
92
|
this.readableFilepaths.add(envFilepath)
|
|
92
93
|
|
|
93
94
|
const privateKey = findPrivateKey(envFilepath)
|
|
94
|
-
const { parsed,
|
|
95
|
+
const { parsed, errors, injected, preExisted } = new Parse(src, privateKey, this.processEnv, this.overload).run()
|
|
95
96
|
|
|
96
97
|
row.parsed = parsed
|
|
97
|
-
row.
|
|
98
|
+
row.errors = errors
|
|
98
99
|
row.injected = injected
|
|
99
100
|
row.preExisted = preExisted
|
|
100
101
|
|
|
@@ -104,13 +105,10 @@ class Run {
|
|
|
104
105
|
this.uniqueInjectedKeys.add(key) // track uniqueInjectedKeys across multiple files
|
|
105
106
|
}
|
|
106
107
|
} catch (e) {
|
|
107
|
-
if (e.code === 'ENOENT') {
|
|
108
|
-
|
|
109
|
-
error.code = 'MISSING_ENV_FILE'
|
|
110
|
-
|
|
111
|
-
row.error = error
|
|
108
|
+
if (e.code === 'ENOENT' || e.code === 'EISDIR') {
|
|
109
|
+
row.errors = [new Errors({ envFilepath, filepath }).missingEnvFile()]
|
|
112
110
|
} else {
|
|
113
|
-
row.
|
|
111
|
+
row.errors = [e]
|
|
114
112
|
}
|
|
115
113
|
}
|
|
116
114
|
|
|
@@ -162,9 +160,9 @@ class Run {
|
|
|
162
160
|
|
|
163
161
|
try {
|
|
164
162
|
// parse this. it's the equivalent of the .env file
|
|
165
|
-
const { parsed,
|
|
163
|
+
const { parsed, errors, injected, preExisted } = new Parse(decrypted, null, this.processEnv, this.overload).run()
|
|
166
164
|
row.parsed = parsed
|
|
167
|
-
row.
|
|
165
|
+
row.errors = errors
|
|
168
166
|
row.injected = injected
|
|
169
167
|
row.preExisted = preExisted
|
|
170
168
|
|
|
@@ -174,7 +172,7 @@ class Run {
|
|
|
174
172
|
this.uniqueInjectedKeys.add(key) // track uniqueInjectedKeys across multiple files
|
|
175
173
|
}
|
|
176
174
|
} catch (e) {
|
|
177
|
-
row.
|
|
175
|
+
row.errors = [e]
|
|
178
176
|
}
|
|
179
177
|
|
|
180
178
|
this.processedEnvs.push(row)
|
package/src/lib/services/sets.js
CHANGED
|
@@ -4,6 +4,7 @@ const dotenv = require('dotenv')
|
|
|
4
4
|
|
|
5
5
|
const TYPE_ENV_FILE = 'envFile'
|
|
6
6
|
|
|
7
|
+
const Errors = require('./../helpers/errors')
|
|
7
8
|
const guessPrivateKeyName = require('./../helpers/guessPrivateKeyName')
|
|
8
9
|
const guessPublicKeyName = require('./../helpers/guessPublicKeyName')
|
|
9
10
|
const encryptValue = require('./../helpers/encryptValue')
|
|
@@ -169,10 +170,7 @@ class Sets {
|
|
|
169
170
|
}
|
|
170
171
|
} catch (e) {
|
|
171
172
|
if (e.code === 'ENOENT') {
|
|
172
|
-
|
|
173
|
-
error.code = 'MISSING_ENV_FILE'
|
|
174
|
-
|
|
175
|
-
row.error = error
|
|
173
|
+
row.error = new Errors({ envFilepath, filepath }).missingEnvFile()
|
|
176
174
|
} else {
|
|
177
175
|
row.error = e
|
|
178
176
|
}
|