@dotenvx/dotenvx 2.7.2 → 2.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 +14 -1
- package/README.md +34 -0
- package/package.json +1 -1
- package/src/cli/actions/armor/down.js +2 -1
- package/src/cli/actions/armor/move.js +2 -1
- package/src/cli/actions/armor/pull.js +2 -1
- package/src/cli/actions/armor/push.js +2 -1
- package/src/cli/actions/armor/up.js +2 -1
- package/src/cli/actions/decrypt.js +2 -1
- package/src/cli/actions/encrypt.js +2 -1
- package/src/cli/actions/ext/prebuild.js +1 -1
- package/src/cli/actions/ext/precommit.js +1 -1
- package/src/cli/actions/get.js +3 -2
- package/src/cli/actions/keychain/down.js +2 -1
- package/src/cli/actions/keychain/pull.js +2 -1
- package/src/cli/actions/keychain/push.js +2 -1
- package/src/cli/actions/keychain/up.js +2 -1
- package/src/cli/actions/keypair.js +2 -1
- package/src/cli/actions/login.js +2 -1
- package/src/cli/actions/logout.js +2 -1
- package/src/cli/actions/run.js +3 -2
- package/src/cli/actions/set.js +2 -1
- package/src/lib/api/postArmorDecrypt.js +49 -0
- package/src/lib/decryptors/armor/index.js +21 -0
- package/src/lib/decryptors/decryptor-worker.js +6 -0
- package/src/lib/decryptors/index.js +69 -0
- package/src/lib/helpers/catchAndLog.js +5 -0
- package/src/lib/helpers/errors.js +14 -0
- package/src/lib/helpers/isNetworkError.js +21 -0
- package/src/lib/helpers/parseWithDecryptor.js +66 -0
- package/src/lib/main.js +5 -5
- package/src/lib/providers/armor/index.js +10 -1
- package/src/lib/providers/index.js +2 -2
- package/src/lib/providers/provider-worker.js +6 -0
- package/src/lib/resolvers/envs.js +32 -16
- package/src/lib/transforms/decrypt.js +5 -2
- package/src/lib/providers/worker.js +0 -6
package/CHANGELOG.md
CHANGED
|
@@ -2,7 +2,20 @@
|
|
|
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/v2.
|
|
5
|
+
[Unreleased](https://github.com/dotenvx/dotenvx/compare/v2.8.0...main)
|
|
6
|
+
|
|
7
|
+
## [2.8.0](https://github.com/dotenvx/dotenvx/compare/v2.7.3...v2.8.0) (2026-07-14)
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
* Add `FILE_NOT_WRITABLE` error for user convenience ([#891](https://github.com/dotenvx/dotenvx/pull/891))
|
|
12
|
+
* Support Enclaved Armored Keys ([#892](https://github.com/dotenvx/dotenvx/pull/892))
|
|
13
|
+
|
|
14
|
+
## [2.7.3](https://github.com/dotenvx/dotenvx/compare/v2.7.2...v2.7.3) (2026-07-13)
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
|
|
18
|
+
* Fix: `--quiet` should not display the spinner and its stderr messages ([#889](https://github.com/dotenvx/dotenvx/pull/889))
|
|
6
19
|
|
|
7
20
|
## [2.7.2](https://github.com/dotenvx/dotenvx/compare/v2.7.1...v2.7.2) (2026-07-13)
|
|
8
21
|
|
package/README.md
CHANGED
|
@@ -2648,6 +2648,8 @@ Log in to Dotenvx Armor.
|
|
|
2648
2648
|
$ dotenvx armor login
|
|
2649
2649
|
```
|
|
2650
2650
|
|
|
2651
|
+
After authentication, dotenvx first attempts to store your access token in your operating system's native secret store: macOS Keychain, Windows Credential Manager, or Linux Secret Service. If native secure storage is unavailable, dotenvx falls back to its settings file. This follows a common CLI credential-storage pattern: prefer protected OS storage when available while remaining usable in headless or minimal environments.
|
|
2652
|
+
|
|
2651
2653
|
</details>
|
|
2652
2654
|
<details><summary>`armor logout`</summary><br>
|
|
2653
2655
|
|
|
@@ -2657,6 +2659,38 @@ Log out of Dotenvx Armor.
|
|
|
2657
2659
|
$ dotenvx armor logout
|
|
2658
2660
|
```
|
|
2659
2661
|
|
|
2662
|
+
</details>
|
|
2663
|
+
<details><summary>`armor status`</summary><br>
|
|
2664
|
+
|
|
2665
|
+
Print the current Armor status. It returns `on` when you are logged in and Armor is enabled; otherwise it returns `off`.
|
|
2666
|
+
|
|
2667
|
+
```sh
|
|
2668
|
+
$ dotenvx armor status
|
|
2669
|
+
on
|
|
2670
|
+
```
|
|
2671
|
+
|
|
2672
|
+
</details>
|
|
2673
|
+
<details><summary>`armor settings`</summary><br>
|
|
2674
|
+
|
|
2675
|
+
Inspect and manage your local Armor settings.
|
|
2676
|
+
|
|
2677
|
+
```sh
|
|
2678
|
+
$ dotenvx armor settings username
|
|
2679
|
+
$ dotenvx armor settings token
|
|
2680
|
+
$ dotenvx armor settings device
|
|
2681
|
+
$ dotenvx armor settings hostname
|
|
2682
|
+
$ dotenvx armor settings path
|
|
2683
|
+
$ dotenvx armor settings on
|
|
2684
|
+
$ dotenvx armor settings off
|
|
2685
|
+
```
|
|
2686
|
+
|
|
2687
|
+
Access tokens and device public keys are masked by default. Reveal the complete value only when you explicitly need it.
|
|
2688
|
+
|
|
2689
|
+
```sh
|
|
2690
|
+
$ dotenvx armor settings token --unmask
|
|
2691
|
+
$ dotenvx armor settings device --unmask
|
|
2692
|
+
```
|
|
2693
|
+
|
|
2660
2694
|
</details>
|
|
2661
2695
|
<details><summary>`help`</summary><br>
|
|
2662
2696
|
|
package/package.json
CHANGED
|
@@ -6,7 +6,8 @@ const armoredKeyDisplay = require('../../../lib/helpers/armoredKeyDisplay')
|
|
|
6
6
|
|
|
7
7
|
async function down () {
|
|
8
8
|
const options = this.opts()
|
|
9
|
-
const
|
|
9
|
+
const spinnerOptions = typeof this.optsWithGlobals === 'function' ? this.optsWithGlobals() : options
|
|
10
|
+
const spinner = await createSpinner({ ...spinnerOptions, ...options, text: 'dearmoring' })
|
|
10
11
|
|
|
11
12
|
logger.debug(`options: ${JSON.stringify(options)}`)
|
|
12
13
|
|
|
@@ -6,7 +6,8 @@ const armoredKeyDisplay = require('../../../lib/helpers/armoredKeyDisplay')
|
|
|
6
6
|
|
|
7
7
|
async function move () {
|
|
8
8
|
const options = this.opts()
|
|
9
|
-
const
|
|
9
|
+
const spinnerOptions = typeof this.optsWithGlobals === 'function' ? this.optsWithGlobals() : options
|
|
10
|
+
const spinner = await createSpinner({ ...spinnerOptions, ...options, text: 'moving' })
|
|
10
11
|
|
|
11
12
|
logger.debug(`options: ${JSON.stringify(options)}`)
|
|
12
13
|
|
|
@@ -6,7 +6,8 @@ const armoredKeyDisplay = require('../../../lib/helpers/armoredKeyDisplay')
|
|
|
6
6
|
|
|
7
7
|
async function pull () {
|
|
8
8
|
const options = this.opts()
|
|
9
|
-
const
|
|
9
|
+
const spinnerOptions = typeof this.optsWithGlobals === 'function' ? this.optsWithGlobals() : options
|
|
10
|
+
const spinner = await createSpinner({ ...spinnerOptions, ...options, text: 'pulling' })
|
|
10
11
|
|
|
11
12
|
logger.debug(`options: ${JSON.stringify(options)}`)
|
|
12
13
|
|
|
@@ -6,7 +6,8 @@ const armoredKeyDisplay = require('../../../lib/helpers/armoredKeyDisplay')
|
|
|
6
6
|
|
|
7
7
|
async function push () {
|
|
8
8
|
const options = this.opts()
|
|
9
|
-
const
|
|
9
|
+
const spinnerOptions = typeof this.optsWithGlobals === 'function' ? this.optsWithGlobals() : options
|
|
10
|
+
const spinner = await createSpinner({ ...spinnerOptions, ...options, text: 'pushing' })
|
|
10
11
|
|
|
11
12
|
logger.debug(`options: ${JSON.stringify(options)}`)
|
|
12
13
|
|
|
@@ -6,7 +6,8 @@ const armoredKeyDisplay = require('../../../lib/helpers/armoredKeyDisplay')
|
|
|
6
6
|
|
|
7
7
|
async function up () {
|
|
8
8
|
const options = this.opts()
|
|
9
|
-
const
|
|
9
|
+
const spinnerOptions = typeof this.optsWithGlobals === 'function' ? this.optsWithGlobals() : options
|
|
10
|
+
const spinner = await createSpinner({ ...spinnerOptions, ...options, text: 'armoring' })
|
|
10
11
|
|
|
11
12
|
logger.debug(`options: ${JSON.stringify(options)}`)
|
|
12
13
|
|
|
@@ -10,7 +10,8 @@ const maskEnvSrc = require('../../lib/helpers/maskEnvSrc')
|
|
|
10
10
|
|
|
11
11
|
async function decrypt () {
|
|
12
12
|
const options = this.opts()
|
|
13
|
-
const
|
|
13
|
+
const spinnerOptions = typeof this.optsWithGlobals === 'function' ? this.optsWithGlobals() : options
|
|
14
|
+
const spinner = await createSpinner({ ...spinnerOptions, ...options, text: 'decrypting' })
|
|
14
15
|
|
|
15
16
|
logger.debug(`options: ${JSON.stringify(options)}`)
|
|
16
17
|
|
|
@@ -9,7 +9,8 @@ const Session = require('../../db/session')
|
|
|
9
9
|
|
|
10
10
|
async function encryptAction () {
|
|
11
11
|
const options = this.opts()
|
|
12
|
-
const
|
|
12
|
+
const spinnerOptions = typeof this.optsWithGlobals === 'function' ? this.optsWithGlobals() : options
|
|
13
|
+
const spinner = await createSpinner({ ...spinnerOptions, ...options, text: 'encrypting' })
|
|
13
14
|
const sesh = new Session()
|
|
14
15
|
|
|
15
16
|
logger.debug(`options: ${JSON.stringify(options)}`)
|
|
@@ -17,7 +17,7 @@ function precommit (directory) {
|
|
|
17
17
|
} = new Precommit(directory, options).run()
|
|
18
18
|
|
|
19
19
|
for (const warning of warnings) {
|
|
20
|
-
logger.warn(warning.messageWithHelp)
|
|
20
|
+
logger.warn(warning.messageWithHelp || warning.message)
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
logger.success(successMessage)
|
package/src/cli/actions/get.js
CHANGED
|
@@ -12,7 +12,8 @@ const mask = require('../../lib/helpers/mask')
|
|
|
12
12
|
|
|
13
13
|
async function get (key) {
|
|
14
14
|
const options = normalizeDotenvConfigConvention(this.opts())
|
|
15
|
-
const
|
|
15
|
+
const spinnerOptions = typeof this.optsWithGlobals === 'function' ? this.optsWithGlobals() : options
|
|
16
|
+
const spinner = await createSpinner({ ...spinnerOptions, ...options, text: 'decrypting' })
|
|
16
17
|
|
|
17
18
|
logger.debug(`options: ${JSON.stringify(options)}`)
|
|
18
19
|
if (key) {
|
|
@@ -52,7 +53,7 @@ async function get (key) {
|
|
|
52
53
|
}
|
|
53
54
|
|
|
54
55
|
errorCount += 1
|
|
55
|
-
logger.error(error.messageWithHelp)
|
|
56
|
+
logger.error(error.messageWithHelp || error.message)
|
|
56
57
|
}
|
|
57
58
|
|
|
58
59
|
if (spinner) spinner.stop()
|
|
@@ -5,7 +5,8 @@ const armoredKeyDisplay = require('../../../lib/helpers/armoredKeyDisplay')
|
|
|
5
5
|
|
|
6
6
|
async function down () {
|
|
7
7
|
const options = this.opts()
|
|
8
|
-
const
|
|
8
|
+
const spinnerOptions = typeof this.optsWithGlobals === 'function' ? this.optsWithGlobals() : options
|
|
9
|
+
const spinner = await createSpinner({ ...spinnerOptions, ...options, text: 'unkeychaining' })
|
|
9
10
|
|
|
10
11
|
logger.debug(`options: ${JSON.stringify(options)}`)
|
|
11
12
|
|
|
@@ -5,7 +5,8 @@ const armoredKeyDisplay = require('../../../lib/helpers/armoredKeyDisplay')
|
|
|
5
5
|
|
|
6
6
|
async function pull () {
|
|
7
7
|
const options = this.opts()
|
|
8
|
-
const
|
|
8
|
+
const spinnerOptions = typeof this.optsWithGlobals === 'function' ? this.optsWithGlobals() : options
|
|
9
|
+
const spinner = await createSpinner({ ...spinnerOptions, ...options, text: 'pulling' })
|
|
9
10
|
|
|
10
11
|
logger.debug(`options: ${JSON.stringify(options)}`)
|
|
11
12
|
|
|
@@ -5,7 +5,8 @@ const armoredKeyDisplay = require('../../../lib/helpers/armoredKeyDisplay')
|
|
|
5
5
|
|
|
6
6
|
async function push () {
|
|
7
7
|
const options = this.opts()
|
|
8
|
-
const
|
|
8
|
+
const spinnerOptions = typeof this.optsWithGlobals === 'function' ? this.optsWithGlobals() : options
|
|
9
|
+
const spinner = await createSpinner({ ...spinnerOptions, ...options, text: 'pushing' })
|
|
9
10
|
|
|
10
11
|
logger.debug(`options: ${JSON.stringify(options)}`)
|
|
11
12
|
|
|
@@ -5,7 +5,8 @@ const armoredKeyDisplay = require('../../../lib/helpers/armoredKeyDisplay')
|
|
|
5
5
|
|
|
6
6
|
async function up () {
|
|
7
7
|
const options = this.opts()
|
|
8
|
-
const
|
|
8
|
+
const spinnerOptions = typeof this.optsWithGlobals === 'function' ? this.optsWithGlobals() : options
|
|
9
|
+
const spinner = await createSpinner({ ...spinnerOptions, ...options, text: 'storing' })
|
|
9
10
|
|
|
10
11
|
logger.debug(`options: ${JSON.stringify(options)}`)
|
|
11
12
|
|
|
@@ -6,7 +6,8 @@ const createSpinner = require('../../lib/helpers/createSpinner')
|
|
|
6
6
|
|
|
7
7
|
async function keypair (key) {
|
|
8
8
|
const options = this.opts()
|
|
9
|
-
const
|
|
9
|
+
const spinnerOptions = typeof this.optsWithGlobals === 'function' ? this.optsWithGlobals() : options
|
|
10
|
+
const spinner = await createSpinner({ ...spinnerOptions, ...options, text: 'retrieving' })
|
|
10
11
|
|
|
11
12
|
logger.debug(`options: ${JSON.stringify(options)}`)
|
|
12
13
|
if (key) {
|
package/src/cli/actions/login.js
CHANGED
|
@@ -12,7 +12,8 @@ const FRAMES = ['◐', '◓', '◑', '◒']
|
|
|
12
12
|
|
|
13
13
|
async function login () {
|
|
14
14
|
const options = this.opts()
|
|
15
|
-
const
|
|
15
|
+
const spinnerOptions = typeof this.optsWithGlobals === 'function' ? this.optsWithGlobals() : options
|
|
16
|
+
const spinner = await createSpinner({ ...spinnerOptions, ...options, text: 'logging in', frames: FRAMES })
|
|
16
17
|
|
|
17
18
|
logger.debug(`options: ${JSON.stringify(options)}`)
|
|
18
19
|
|
|
@@ -8,7 +8,8 @@ const FRAMES = ['◐', '◓', '◑', '◒']
|
|
|
8
8
|
|
|
9
9
|
async function logout () {
|
|
10
10
|
const options = this.opts()
|
|
11
|
-
const
|
|
11
|
+
const spinnerOptions = typeof this.optsWithGlobals === 'function' ? this.optsWithGlobals() : options
|
|
12
|
+
const spinner = await createSpinner({ ...spinnerOptions, ...options, text: 'logging out', frames: FRAMES })
|
|
12
13
|
|
|
13
14
|
logger.debug(`options: ${JSON.stringify(options)}`)
|
|
14
15
|
|
package/src/cli/actions/run.js
CHANGED
|
@@ -51,6 +51,7 @@ function uniqueInjectedKeys (processedEnvs) {
|
|
|
51
51
|
|
|
52
52
|
async function run () {
|
|
53
53
|
const options = normalizeDotenvConfigConvention(normalizeDotenvConfigQuiet(this.opts()))
|
|
54
|
+
const spinnerOptions = typeof this.optsWithGlobals === 'function' ? this.optsWithGlobals() : options
|
|
54
55
|
const maskEnabled = options.mask !== undefined
|
|
55
56
|
let showChar = options.mask
|
|
56
57
|
if (options.mask === true) {
|
|
@@ -63,7 +64,7 @@ async function run () {
|
|
|
63
64
|
commandArgs = inferCommandArgsFromProcessArgv(process.argv)
|
|
64
65
|
}
|
|
65
66
|
|
|
66
|
-
const spinner = await createSpinner({ ...options, text: 'injecting' })
|
|
67
|
+
const spinner = await createSpinner({ ...spinnerOptions, ...options, text: 'injecting' })
|
|
67
68
|
|
|
68
69
|
let debugOptions = options
|
|
69
70
|
if (maskEnabled) {
|
|
@@ -150,7 +151,7 @@ async function run () {
|
|
|
150
151
|
if (error.code === 'MISSING_ENV_FILE' && options.convention) { // do not output error for conventions (too noisy)
|
|
151
152
|
// intentionally quiet
|
|
152
153
|
} else {
|
|
153
|
-
logger.error(error.messageWithHelp)
|
|
154
|
+
logger.error(error.messageWithHelp || error.message)
|
|
154
155
|
}
|
|
155
156
|
}
|
|
156
157
|
|
package/src/cli/actions/set.js
CHANGED
|
@@ -11,6 +11,7 @@ const Session = require('../../db/session')
|
|
|
11
11
|
|
|
12
12
|
async function set (key, value) {
|
|
13
13
|
const options = this.opts()
|
|
14
|
+
const spinnerOptions = typeof this.optsWithGlobals === 'function' ? this.optsWithGlobals() : options
|
|
14
15
|
|
|
15
16
|
let encrypt = true
|
|
16
17
|
let settingMessage = 'encrypting'
|
|
@@ -47,7 +48,7 @@ async function set (key, value) {
|
|
|
47
48
|
}
|
|
48
49
|
}
|
|
49
50
|
|
|
50
|
-
const spinner = await createSpinner({ ...options, text: settingMessage })
|
|
51
|
+
const spinner = await createSpinner({ ...spinnerOptions, ...options, text: settingMessage })
|
|
51
52
|
const sesh = new Session()
|
|
52
53
|
|
|
53
54
|
logger.debug(`key: ${key}`)
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
const { http } = require('../helpers/http')
|
|
2
|
+
const buildApiError = require('../helpers/buildApiError')
|
|
3
|
+
const packageJson = require('../helpers/packageJson')
|
|
4
|
+
const normalizeToken = require('../helpers/normalizeToken')
|
|
5
|
+
|
|
6
|
+
class PostArmorDecrypt {
|
|
7
|
+
constructor (hostname, token, devicePublicKey, publicKey, src, grantToken) {
|
|
8
|
+
this.hostname = hostname || 'https://armor.dotenvx.com'
|
|
9
|
+
this.token = token
|
|
10
|
+
this.devicePublicKey = devicePublicKey
|
|
11
|
+
this.publicKey = publicKey
|
|
12
|
+
this.src = src
|
|
13
|
+
this.grantToken = grantToken
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
async run () {
|
|
17
|
+
const token = normalizeToken(this.token)
|
|
18
|
+
const url = `${this.hostname}/api/armor/decrypt`
|
|
19
|
+
const body = {
|
|
20
|
+
device_public_key: this.devicePublicKey,
|
|
21
|
+
cli_version: packageJson.version,
|
|
22
|
+
public_key: this.publicKey,
|
|
23
|
+
src: this.src
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (this.grantToken) {
|
|
27
|
+
body.grant_token = this.grantToken
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const resp = await http(url, {
|
|
31
|
+
method: 'POST',
|
|
32
|
+
headers: {
|
|
33
|
+
Authorization: `Bearer ${token}`,
|
|
34
|
+
'Content-Type': 'application/json'
|
|
35
|
+
},
|
|
36
|
+
body: JSON.stringify(body)
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
const json = await resp.body.json()
|
|
40
|
+
|
|
41
|
+
if (resp.statusCode >= 400) {
|
|
42
|
+
throw buildApiError(resp.statusCode, json)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return json
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
module.exports = PostArmorDecrypt
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
const Session = require('../../../db/session')
|
|
2
|
+
const PostArmorDecrypt = require('../../api/postArmorDecrypt')
|
|
3
|
+
|
|
4
|
+
async function index (src, options = {}) {
|
|
5
|
+
const sesh = new Session()
|
|
6
|
+
|
|
7
|
+
const hostname = sesh.hostname()
|
|
8
|
+
const token = sesh.token()
|
|
9
|
+
const devicePublicKey = sesh.devicePublicKey()
|
|
10
|
+
|
|
11
|
+
return await new PostArmorDecrypt(
|
|
12
|
+
hostname,
|
|
13
|
+
token,
|
|
14
|
+
devicePublicKey,
|
|
15
|
+
options.publicKey,
|
|
16
|
+
src,
|
|
17
|
+
options.grantToken
|
|
18
|
+
).run()
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
module.exports = index
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
const Session = require('./../../db/session')
|
|
2
|
+
|
|
3
|
+
const armorDecryptor = require('./armor/index')
|
|
4
|
+
|
|
5
|
+
function syncArmorDecryptor (src, options) {
|
|
6
|
+
const { createSyncFn } = require('@dotenvx/tooling')
|
|
7
|
+
const runDecryptorSync = createSyncFn(require.resolve('./decryptor-worker.js'))
|
|
8
|
+
return runDecryptorSync(src, options)
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function armorDecryptorForOptions (options) {
|
|
12
|
+
return (src, decryptOptions) => armorDecryptor(src, {
|
|
13
|
+
...decryptOptions,
|
|
14
|
+
onStatus: options.onStatus,
|
|
15
|
+
token: options.token,
|
|
16
|
+
command: options.command
|
|
17
|
+
})
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function syncArmorDecryptorForOptions (options) {
|
|
21
|
+
return (src, decryptOptions) => syncArmorDecryptor(src, {
|
|
22
|
+
...decryptOptions,
|
|
23
|
+
onStatus: options.onStatus,
|
|
24
|
+
token: options.token,
|
|
25
|
+
command: options.command
|
|
26
|
+
})
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function useArmor (options, noArmor) {
|
|
30
|
+
return options.noArmor !== true && options.armor !== false && !noArmor
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async function decryptors (options = {}) {
|
|
34
|
+
if (Object.prototype.hasOwnProperty.call(options, 'decryptor')) {
|
|
35
|
+
return options.decryptor
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (options.noArmor === true || options.armor === false) {
|
|
39
|
+
return null
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const sesh = new Session()
|
|
43
|
+
const noArmor = !options.token && await sesh.noArmor()
|
|
44
|
+
if (!useArmor(options, noArmor)) {
|
|
45
|
+
return null
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return armorDecryptorForOptions(options)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
decryptors.sync = function decryptorsSync (options = {}) {
|
|
52
|
+
if (Object.prototype.hasOwnProperty.call(options, 'decryptor')) {
|
|
53
|
+
return options.decryptor
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (options.noArmor === true || options.armor === false) {
|
|
57
|
+
return null
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const sesh = new Session()
|
|
61
|
+
const noArmor = !options.token && sesh.noArmorSync()
|
|
62
|
+
if (!useArmor(options, noArmor)) {
|
|
63
|
+
return null
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return syncArmorDecryptorForOptions(options)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
module.exports = decryptors
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
const { logger } = require('./../../shared/logger')
|
|
2
|
+
const Errors = require('./errors')
|
|
2
3
|
|
|
3
4
|
function catchAndLog (error) {
|
|
5
|
+
if (error.code === 'EACCES' || error.code === 'EPERM') {
|
|
6
|
+
error = new Errors({ filepath: error.path }).fileNotWritable()
|
|
7
|
+
}
|
|
8
|
+
|
|
4
9
|
const msg = error.messageWithHelp || error.message
|
|
5
10
|
if (msg) {
|
|
6
11
|
logger.error(msg)
|
|
@@ -20,6 +20,7 @@ const ISSUE_BY_CODE = {
|
|
|
20
20
|
MISSING_PRIVATE_KEY: 'https://github.com/dotenvx/dotenvx/issues/464',
|
|
21
21
|
MISSING_PUBLIC_KEY: 'https://github.com/dotenvx/dotenvx/issues/865',
|
|
22
22
|
MISSING_VALUE: 'https://github.com/dotenvx/dotenvx/issues/864',
|
|
23
|
+
FILE_NOT_WRITABLE: 'https://github.com/dotenvx/dotenvx/issues/890',
|
|
23
24
|
PRECOMMIT_HOOK_MODIFY_FAILED: 'try again or report error',
|
|
24
25
|
WRONG_PRIVATE_KEY: 'https://github.com/dotenvx/dotenvx/issues/466'
|
|
25
26
|
}
|
|
@@ -279,6 +280,19 @@ class Errors {
|
|
|
279
280
|
return e
|
|
280
281
|
}
|
|
281
282
|
|
|
283
|
+
fileNotWritable () {
|
|
284
|
+
const code = 'FILE_NOT_WRITABLE'
|
|
285
|
+
const filepath = this.filepath || 'unknown'
|
|
286
|
+
const message = `[${code}] cannot write to file (${filepath})`
|
|
287
|
+
const help = `fix: [${ISSUE_BY_CODE[code]}]`
|
|
288
|
+
|
|
289
|
+
const e = new Error(message)
|
|
290
|
+
e.code = code
|
|
291
|
+
e.help = help
|
|
292
|
+
e.messageWithHelp = `${message}. ${help}`
|
|
293
|
+
return e
|
|
294
|
+
}
|
|
295
|
+
|
|
282
296
|
missingValue () {
|
|
283
297
|
const code = 'MISSING_VALUE'
|
|
284
298
|
const message = `[${code}] missing value (${this.key})`
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
const NETWORK_ERROR_CODES = new Set([
|
|
2
|
+
'ECONNRESET',
|
|
3
|
+
'ECONNREFUSED',
|
|
4
|
+
'ENOTFOUND',
|
|
5
|
+
'ENETDOWN',
|
|
6
|
+
'ENETUNREACH',
|
|
7
|
+
'EHOSTDOWN',
|
|
8
|
+
'EHOSTUNREACH',
|
|
9
|
+
'EPIPE',
|
|
10
|
+
'ETIMEDOUT',
|
|
11
|
+
'UND_ERR_CONNECT_TIMEOUT',
|
|
12
|
+
'UND_ERR_HEADERS_TIMEOUT',
|
|
13
|
+
'UND_ERR_BODY_TIMEOUT',
|
|
14
|
+
'UND_ERR_SOCKET'
|
|
15
|
+
])
|
|
16
|
+
|
|
17
|
+
function isNetworkError (error) {
|
|
18
|
+
return NETWORK_ERROR_CODES.has(error && error.code) || NETWORK_ERROR_CODES.has(error && error.cause && error.cause.code)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
module.exports = isNetworkError
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
const { parse, parseSync } = require('@dotenvx/primitives')
|
|
2
|
+
const isNetworkError = require('./isNetworkError')
|
|
3
|
+
|
|
4
|
+
const SERVER_SIDE_DECRYPTION_REQUIRED = 'SERVER_SIDE_DECRYPTION_REQUIRED'
|
|
5
|
+
|
|
6
|
+
function decryptOptions (error) {
|
|
7
|
+
const meta = error.meta || {}
|
|
8
|
+
|
|
9
|
+
return {
|
|
10
|
+
publicKey: meta.public_key,
|
|
11
|
+
grantToken: meta.grant_token,
|
|
12
|
+
error
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function parseOptionsWithoutProvider (options) {
|
|
17
|
+
return {
|
|
18
|
+
...options,
|
|
19
|
+
provider: null,
|
|
20
|
+
decryptor: null
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
async function parseWithDecryptor (src, options = {}) {
|
|
25
|
+
try {
|
|
26
|
+
return await parse(src, options)
|
|
27
|
+
} catch (error) {
|
|
28
|
+
if (error.code !== SERVER_SIDE_DECRYPTION_REQUIRED || typeof options.decryptor !== 'function') {
|
|
29
|
+
throw error
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
try {
|
|
33
|
+
const result = await options.decryptor(src, decryptOptions(error))
|
|
34
|
+
return await parse(result.src, parseOptionsWithoutProvider(options))
|
|
35
|
+
} catch (decryptorError) {
|
|
36
|
+
if (isNetworkError(decryptorError)) {
|
|
37
|
+
return await parse(src, parseOptionsWithoutProvider(options))
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
throw decryptorError
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
parseWithDecryptor.sync = function parseWithDecryptorSync (src, options = {}) {
|
|
46
|
+
try {
|
|
47
|
+
return parseSync(src, options)
|
|
48
|
+
} catch (error) {
|
|
49
|
+
if (error.code !== SERVER_SIDE_DECRYPTION_REQUIRED || typeof options.decryptor !== 'function') {
|
|
50
|
+
throw error
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
try {
|
|
54
|
+
const result = options.decryptor(src, decryptOptions(error))
|
|
55
|
+
return parseSync(result.src, parseOptionsWithoutProvider(options))
|
|
56
|
+
} catch (decryptorError) {
|
|
57
|
+
if (isNetworkError(decryptorError)) {
|
|
58
|
+
return parseSync(src, parseOptionsWithoutProvider(options))
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
throw decryptorError
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
module.exports = parseWithDecryptor
|
package/src/lib/main.js
CHANGED
|
@@ -115,10 +115,10 @@ const config = function (options = {}) {
|
|
|
115
115
|
|
|
116
116
|
if (error.code === 'MISSING_ENV_FILE') {
|
|
117
117
|
if (!options.convention) { // do not output error for conventions (too noisy)
|
|
118
|
-
logger.error(error.messageWithHelp)
|
|
118
|
+
logger.error(error.messageWithHelp || error.message)
|
|
119
119
|
}
|
|
120
120
|
} else {
|
|
121
|
-
logger.error(error.messageWithHelp)
|
|
121
|
+
logger.error(error.messageWithHelp || error.message)
|
|
122
122
|
}
|
|
123
123
|
}
|
|
124
124
|
|
|
@@ -155,7 +155,7 @@ const config = function (options = {}) {
|
|
|
155
155
|
} catch (error) {
|
|
156
156
|
if (strict) throw error // throw immediately if strict
|
|
157
157
|
|
|
158
|
-
logger.error(error.messageWithHelp)
|
|
158
|
+
logger.error(error.messageWithHelp || error.message)
|
|
159
159
|
|
|
160
160
|
return { parsed: {}, error }
|
|
161
161
|
}
|
|
@@ -209,7 +209,7 @@ const parse = function (src, options = {}) {
|
|
|
209
209
|
continue // ignore error
|
|
210
210
|
}
|
|
211
211
|
|
|
212
|
-
logger.error(error.messageWithHelp)
|
|
212
|
+
logger.error(error.messageWithHelp || error.message)
|
|
213
213
|
}
|
|
214
214
|
|
|
215
215
|
return parsed
|
|
@@ -347,7 +347,7 @@ const get = async function (key, options = {}) {
|
|
|
347
347
|
|
|
348
348
|
if (options.strict) throw error // throw immediately if strict
|
|
349
349
|
|
|
350
|
-
logger.error(error.messageWithHelp)
|
|
350
|
+
logger.error(error.messageWithHelp || error.message)
|
|
351
351
|
}
|
|
352
352
|
|
|
353
353
|
if (key) {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const Session = require('../../../db/session')
|
|
2
2
|
const ArmorKeyring = require('../../services/armorKeyring')
|
|
3
3
|
const armoredKeyDisplay = require('../../helpers/armoredKeyDisplay')
|
|
4
|
+
const isNetworkError = require('../../helpers/isNetworkError')
|
|
4
5
|
|
|
5
6
|
async function index (publicKeyHex, options = {}) {
|
|
6
7
|
const sesh = new Session()
|
|
@@ -23,7 +24,15 @@ async function index (publicKeyHex, options = {}) {
|
|
|
23
24
|
}
|
|
24
25
|
}
|
|
25
26
|
|
|
26
|
-
|
|
27
|
+
try {
|
|
28
|
+
return await keyring.run() // { "publicKey": "privateKey" }
|
|
29
|
+
} catch (error) {
|
|
30
|
+
if (isNetworkError(error)) {
|
|
31
|
+
return {}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
throw error
|
|
35
|
+
}
|
|
27
36
|
}
|
|
28
37
|
|
|
29
38
|
module.exports = index
|
|
@@ -5,8 +5,8 @@ const nativeProvider = require('./native/index')
|
|
|
5
5
|
|
|
6
6
|
function syncArmorProvider (publicKeyHex) {
|
|
7
7
|
const { createSyncFn } = require('@dotenvx/tooling')
|
|
8
|
-
const runProviderSync = createSyncFn(require.resolve('./worker.js'))
|
|
9
|
-
return runProviderSync(
|
|
8
|
+
const runProviderSync = createSyncFn(require.resolve('./provider-worker.js'))
|
|
9
|
+
return runProviderSync(publicKeyHex)
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
function hasKey (keyring, publicKeyHex) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const fsx = require('./../helpers/fsx')
|
|
2
2
|
const path = require('path')
|
|
3
|
-
const { encrypted
|
|
3
|
+
const { encrypted } = require('@dotenvx/primitives')
|
|
4
4
|
|
|
5
5
|
const TYPE_ENV = 'env'
|
|
6
6
|
const TYPE_ENV_FILE = 'envFile'
|
|
@@ -10,6 +10,8 @@ const detectEncoding = require('./../helpers/detectEncoding')
|
|
|
10
10
|
const detectEncodingSync = require('./../helpers/detectEncodingSync')
|
|
11
11
|
const keynames = require('./../conventions/keynames')
|
|
12
12
|
const providers = require('./../providers')
|
|
13
|
+
const decryptors = require('./../decryptors')
|
|
14
|
+
const parseWithDecryptor = require('./../helpers/parseWithDecryptor')
|
|
13
15
|
|
|
14
16
|
function unresolvedEncryptedErrors (parsed) {
|
|
15
17
|
const keys = []
|
|
@@ -48,7 +50,7 @@ function inject (processEnv, parsed) {
|
|
|
48
50
|
}
|
|
49
51
|
}
|
|
50
52
|
|
|
51
|
-
function buildParseOptions ({ processEnv, overload, envKeysFilepath, provider }) {
|
|
53
|
+
function buildParseOptions ({ processEnv, overload, envKeysFilepath, provider, decryptor }) {
|
|
52
54
|
const options = {
|
|
53
55
|
processEnv,
|
|
54
56
|
overload,
|
|
@@ -61,10 +63,14 @@ function buildParseOptions ({ processEnv, overload, envKeysFilepath, provider })
|
|
|
61
63
|
options.provider = null
|
|
62
64
|
}
|
|
63
65
|
|
|
66
|
+
if (decryptor) {
|
|
67
|
+
options.decryptor = decryptor
|
|
68
|
+
}
|
|
69
|
+
|
|
64
70
|
return options
|
|
65
71
|
}
|
|
66
72
|
|
|
67
|
-
async function injectEnv ({ env, overload, processEnv, envKeysFilepath, provider }) {
|
|
73
|
+
async function injectEnv ({ env, overload, processEnv, envKeysFilepath, provider, decryptor }) {
|
|
68
74
|
const row = {}
|
|
69
75
|
row.type = TYPE_ENV
|
|
70
76
|
row.string = env.value
|
|
@@ -79,7 +85,8 @@ async function injectEnv ({ env, overload, processEnv, envKeysFilepath, provider
|
|
|
79
85
|
processEnv: parseProcessEnv,
|
|
80
86
|
overload,
|
|
81
87
|
envKeysFilepath,
|
|
82
|
-
provider
|
|
88
|
+
provider,
|
|
89
|
+
decryptor
|
|
83
90
|
})
|
|
84
91
|
|
|
85
92
|
const {
|
|
@@ -87,7 +94,7 @@ async function injectEnv ({ env, overload, processEnv, envKeysFilepath, provider
|
|
|
87
94
|
errors,
|
|
88
95
|
injected,
|
|
89
96
|
existed
|
|
90
|
-
} = await
|
|
97
|
+
} = await parseWithDecryptor(env.value, parseOptions)
|
|
91
98
|
|
|
92
99
|
row.parsed = parsed
|
|
93
100
|
row.errors = decryptErrors(parsed, errors)
|
|
@@ -102,7 +109,7 @@ async function injectEnv ({ env, overload, processEnv, envKeysFilepath, provider
|
|
|
102
109
|
return row
|
|
103
110
|
}
|
|
104
111
|
|
|
105
|
-
function injectEnvSync ({ env, overload, processEnv, envKeysFilepath, provider }) {
|
|
112
|
+
function injectEnvSync ({ env, overload, processEnv, envKeysFilepath, provider, decryptor }) {
|
|
106
113
|
const row = {}
|
|
107
114
|
row.type = TYPE_ENV
|
|
108
115
|
row.string = env.value
|
|
@@ -117,7 +124,8 @@ function injectEnvSync ({ env, overload, processEnv, envKeysFilepath, provider }
|
|
|
117
124
|
processEnv: parseProcessEnv,
|
|
118
125
|
overload,
|
|
119
126
|
envKeysFilepath,
|
|
120
|
-
provider
|
|
127
|
+
provider,
|
|
128
|
+
decryptor
|
|
121
129
|
})
|
|
122
130
|
|
|
123
131
|
const {
|
|
@@ -125,7 +133,7 @@ function injectEnvSync ({ env, overload, processEnv, envKeysFilepath, provider }
|
|
|
125
133
|
errors,
|
|
126
134
|
injected,
|
|
127
135
|
existed
|
|
128
|
-
} =
|
|
136
|
+
} = parseWithDecryptor.sync(env.value, parseOptions)
|
|
129
137
|
|
|
130
138
|
row.parsed = parsed
|
|
131
139
|
row.errors = decryptErrors(parsed, errors)
|
|
@@ -140,7 +148,7 @@ function injectEnvSync ({ env, overload, processEnv, envKeysFilepath, provider }
|
|
|
140
148
|
return row
|
|
141
149
|
}
|
|
142
150
|
|
|
143
|
-
async function injectEnvFile ({ env, overload, processEnv, envKeysFilepath, provider, readableFilepaths }) {
|
|
151
|
+
async function injectEnvFile ({ env, overload, processEnv, envKeysFilepath, provider, decryptor, readableFilepaths }) {
|
|
144
152
|
const row = {}
|
|
145
153
|
row.type = TYPE_ENV_FILE
|
|
146
154
|
row.filepath = env.value
|
|
@@ -157,7 +165,8 @@ async function injectEnvFile ({ env, overload, processEnv, envKeysFilepath, prov
|
|
|
157
165
|
processEnv,
|
|
158
166
|
overload,
|
|
159
167
|
envKeysFilepath: fk,
|
|
160
|
-
provider
|
|
168
|
+
provider,
|
|
169
|
+
decryptor
|
|
161
170
|
})
|
|
162
171
|
|
|
163
172
|
const {
|
|
@@ -165,7 +174,7 @@ async function injectEnvFile ({ env, overload, processEnv, envKeysFilepath, prov
|
|
|
165
174
|
errors,
|
|
166
175
|
injected,
|
|
167
176
|
existed
|
|
168
|
-
} = await
|
|
177
|
+
} = await parseWithDecryptor(src, parseOptions)
|
|
169
178
|
|
|
170
179
|
row.src = src
|
|
171
180
|
row.parsed = parsed
|
|
@@ -185,7 +194,7 @@ async function injectEnvFile ({ env, overload, processEnv, envKeysFilepath, prov
|
|
|
185
194
|
return row
|
|
186
195
|
}
|
|
187
196
|
|
|
188
|
-
function injectEnvFileSync ({ env, overload, processEnv, envKeysFilepath, provider, readableFilepaths }) {
|
|
197
|
+
function injectEnvFileSync ({ env, overload, processEnv, envKeysFilepath, provider, decryptor, readableFilepaths }) {
|
|
189
198
|
const row = {}
|
|
190
199
|
row.type = TYPE_ENV_FILE
|
|
191
200
|
row.filepath = env.value
|
|
@@ -202,7 +211,8 @@ function injectEnvFileSync ({ env, overload, processEnv, envKeysFilepath, provid
|
|
|
202
211
|
processEnv,
|
|
203
212
|
overload,
|
|
204
213
|
envKeysFilepath: fk,
|
|
205
|
-
provider
|
|
214
|
+
provider,
|
|
215
|
+
decryptor
|
|
206
216
|
})
|
|
207
217
|
|
|
208
218
|
const {
|
|
@@ -210,7 +220,7 @@ function injectEnvFileSync ({ env, overload, processEnv, envKeysFilepath, provid
|
|
|
210
220
|
errors,
|
|
211
221
|
injected,
|
|
212
222
|
existed
|
|
213
|
-
} =
|
|
223
|
+
} = parseWithDecryptor.sync(src, parseOptions)
|
|
214
224
|
|
|
215
225
|
row.src = src
|
|
216
226
|
row.parsed = parsed
|
|
@@ -236,6 +246,7 @@ async function envs (options = {}) {
|
|
|
236
246
|
const processEnv = options.processEnv || process.env
|
|
237
247
|
const envKeysFilepath = options.envKeysFilepath || options.envKeysFile || null
|
|
238
248
|
const provider = await providers(options)
|
|
249
|
+
const decryptor = await decryptors(options)
|
|
239
250
|
|
|
240
251
|
for (const env of options.envs || []) {
|
|
241
252
|
if (env.type === TYPE_ENV_FILE) {
|
|
@@ -245,6 +256,7 @@ async function envs (options = {}) {
|
|
|
245
256
|
processEnv,
|
|
246
257
|
envKeysFilepath,
|
|
247
258
|
provider,
|
|
259
|
+
decryptor,
|
|
248
260
|
readableFilepaths
|
|
249
261
|
}))
|
|
250
262
|
} else if (env.type === TYPE_ENV) {
|
|
@@ -253,7 +265,8 @@ async function envs (options = {}) {
|
|
|
253
265
|
overload: options.overload,
|
|
254
266
|
processEnv,
|
|
255
267
|
envKeysFilepath,
|
|
256
|
-
provider
|
|
268
|
+
provider,
|
|
269
|
+
decryptor
|
|
257
270
|
}))
|
|
258
271
|
}
|
|
259
272
|
}
|
|
@@ -270,6 +283,7 @@ function envsSync (options = {}) {
|
|
|
270
283
|
const processEnv = options.processEnv || process.env
|
|
271
284
|
const envKeysFilepath = options.envKeysFilepath || options.envKeysFile || null
|
|
272
285
|
const provider = providers.sync(options)
|
|
286
|
+
const decryptor = decryptors.sync(options)
|
|
273
287
|
|
|
274
288
|
for (const env of options.envs || []) {
|
|
275
289
|
if (env.type === TYPE_ENV_FILE) {
|
|
@@ -279,6 +293,7 @@ function envsSync (options = {}) {
|
|
|
279
293
|
processEnv,
|
|
280
294
|
envKeysFilepath,
|
|
281
295
|
provider,
|
|
296
|
+
decryptor,
|
|
282
297
|
readableFilepaths
|
|
283
298
|
}))
|
|
284
299
|
} else if (env.type === TYPE_ENV) {
|
|
@@ -287,7 +302,8 @@ function envsSync (options = {}) {
|
|
|
287
302
|
overload: options.overload,
|
|
288
303
|
processEnv,
|
|
289
304
|
envKeysFilepath,
|
|
290
|
-
provider
|
|
305
|
+
provider,
|
|
306
|
+
decryptor
|
|
291
307
|
}))
|
|
292
308
|
}
|
|
293
309
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const fsx = require('./../helpers/fsx')
|
|
2
2
|
const path = require('path')
|
|
3
|
-
const {
|
|
3
|
+
const { upsert } = require('@dotenvx/primitives')
|
|
4
4
|
|
|
5
5
|
const TYPE_ENV_FILE = 'envFile'
|
|
6
6
|
|
|
@@ -8,6 +8,8 @@ const Errors = require('./../helpers/errors')
|
|
|
8
8
|
const { determine } = require('./../helpers/envResolution')
|
|
9
9
|
const detectEncoding = require('./../helpers/detectEncoding')
|
|
10
10
|
const providers = require('./../providers')
|
|
11
|
+
const decryptors = require('./../decryptors')
|
|
12
|
+
const parseWithDecryptor = require('./../helpers/parseWithDecryptor')
|
|
11
13
|
|
|
12
14
|
function parseError (error) {
|
|
13
15
|
return new Errors({
|
|
@@ -23,6 +25,7 @@ async function decrypt (options = {}) {
|
|
|
23
25
|
const ek = options.ek
|
|
24
26
|
const fk = options.fk
|
|
25
27
|
const provider = await providers(options)
|
|
28
|
+
const decryptor = await decryptors(options)
|
|
26
29
|
|
|
27
30
|
const processedEnvs = []
|
|
28
31
|
const changedFilepaths = []
|
|
@@ -41,7 +44,7 @@ async function decrypt (options = {}) {
|
|
|
41
44
|
const encoding = await detectEncoding(filepath)
|
|
42
45
|
row.envSrc = await fsx.readFileX(filepath, { encoding })
|
|
43
46
|
|
|
44
|
-
const { parsed, errors } = await
|
|
47
|
+
const { parsed, errors } = await parseWithDecryptor(row.envSrc, { fk, ik, ek, array: true, provider, decryptor })
|
|
45
48
|
|
|
46
49
|
if (errors.length > 0) {
|
|
47
50
|
row.error = parseError(errors[0])
|