@dotenvx/dotenvx 1.75.1 → 2.0.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 +24 -1
- package/README.md +4 -114
- package/package.json +8 -7
- package/src/cli/actions/decrypt.js +35 -17
- package/src/cli/actions/doctor.js +2 -2
- package/src/cli/actions/encrypt.js +64 -85
- package/src/cli/actions/ext/genexample.js +2 -2
- package/src/cli/actions/get.js +16 -7
- package/src/cli/actions/keypair.js +55 -42
- package/src/cli/actions/login.js +4 -3
- package/src/cli/actions/normalizeArmorAliases.js +9 -0
- package/src/cli/actions/run.js +65 -22
- package/src/cli/actions/set.js +51 -37
- package/src/cli/dotenvx.js +6 -21
- package/src/lib/api/{postKeypair.js → postArmorKeyring.js} +4 -14
- package/src/lib/{helpers/envResolution → conventions}/environment.js +1 -1
- package/src/lib/conventions/filepaths.js +9 -0
- package/src/lib/conventions/keynames.js +38 -0
- package/src/lib/helpers/catchAndLog.js +4 -1
- package/src/lib/helpers/cryptography/index.js +0 -8
- package/src/lib/helpers/cryptography/mutateKeysSrc.js +5 -21
- package/src/lib/helpers/envResolution/index.js +1 -1
- package/src/lib/helpers/errors.js +13 -0
- package/src/lib/helpers/keypairMetadata.js +1 -1
- package/src/lib/main.d.ts +2 -39
- package/src/lib/main.js +82 -45
- package/src/lib/providers/armor/index.js +29 -0
- package/src/lib/providers/index.js +46 -0
- package/src/lib/providers/worker.js +6 -0
- package/src/lib/resolvers/envs.js +302 -0
- package/src/lib/resolvers/get.js +69 -0
- package/src/lib/resolvers/keypair.js +81 -0
- package/src/lib/resolvers/ls.js +41 -0
- package/src/lib/services/armorDown.js +2 -2
- package/src/lib/services/{armorKeypair.js → armorKeyring.js} +14 -51
- package/src/lib/services/armorMove.js +2 -2
- package/src/lib/services/armorPull.js +2 -2
- package/src/lib/services/armorPush.js +2 -2
- package/src/lib/services/armorUp.js +2 -2
- package/src/lib/services/genexample.js +5 -6
- package/src/lib/services/login.js +25 -0
- package/src/lib/services/prebuild.js +9 -3
- package/src/lib/services/precommit.js +9 -3
- package/src/lib/transforms/decrypt.js +83 -0
- package/src/lib/transforms/encrypt.js +179 -0
- package/src/lib/transforms/set.js +179 -0
- package/src/shared/logger.js +5 -0
- package/src/cli/actions/normalizeArmorOptions.js +0 -10
- package/src/cli/actions/rotate.js +0 -87
- package/src/lib/helpers/append.js +0 -62
- package/src/lib/helpers/cryptography/armorKeypair.js +0 -42
- package/src/lib/helpers/cryptography/armorKeypairSync.js +0 -55
- package/src/lib/helpers/cryptography/encryptValue.js +0 -7
- package/src/lib/helpers/cryptography/localKeypair.js +0 -14
- package/src/lib/helpers/cryptography/mutateKeysSrcSync.js +0 -38
- package/src/lib/helpers/cryptography/provision.js +0 -56
- package/src/lib/helpers/cryptography/provisionSync.js +0 -51
- package/src/lib/helpers/cryptography/provisionWithPrivateKey.js +0 -26
- package/src/lib/helpers/escapeDollarSigns.js +0 -5
- package/src/lib/helpers/escapeForRegex.js +0 -5
- package/src/lib/helpers/evalKeyValue.js +0 -23
- package/src/lib/helpers/isIgnoringDotenvKeys.js +0 -19
- package/src/lib/helpers/keyResolution/index.js +0 -16
- package/src/lib/helpers/keyResolution/keyNamesForEnvFile.js +0 -24
- package/src/lib/helpers/keyResolution/keyValues.js +0 -99
- package/src/lib/helpers/keyResolution/keyValuesFromEnvSrc.js +0 -85
- package/src/lib/helpers/keyResolution/keyValuesSync.js +0 -103
- package/src/lib/helpers/keyResolution/readFileKey.js +0 -19
- package/src/lib/helpers/keyResolution/readFileKeySync.js +0 -17
- package/src/lib/helpers/keyResolution/readProcessKey.js +0 -7
- package/src/lib/helpers/localDisplayPath.js +0 -11
- package/src/lib/helpers/parse.js +0 -214
- package/src/lib/helpers/pluralize.js +0 -10
- package/src/lib/helpers/quotes.js +0 -36
- package/src/lib/helpers/replace.js +0 -82
- package/src/lib/helpers/resolveEscapeSequences.js +0 -5
- package/src/lib/services/decrypt.js +0 -156
- package/src/lib/services/encrypt.js +0 -213
- package/src/lib/services/get.js +0 -76
- package/src/lib/services/keypair.js +0 -60
- package/src/lib/services/loginPoll.js +0 -36
- package/src/lib/services/ls.js +0 -57
- package/src/lib/services/rotate.js +0 -197
- package/src/lib/services/run.js +0 -255
- package/src/lib/services/sets.js +0 -328
package/CHANGELOG.md
CHANGED
|
@@ -2,7 +2,30 @@
|
|
|
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/
|
|
5
|
+
[Unreleased](https://github.com/dotenvx/dotenvx/compare/v2.0.0...main)
|
|
6
|
+
|
|
7
|
+
## [2.0.0](https://github.com/dotenvx/dotenvx/compare/v1.76.0...v2.0.0) (2026-06-30)
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
|
|
11
|
+
* BREAKING: lib/main#`set` async only ([#855](https://github.com/dotenvx/dotenvx/pull/855))
|
|
12
|
+
* BREAKING: lib/main#`get` async only ([#855](https://github.com/dotenvx/dotenvx/pull/855))
|
|
13
|
+
* New keyring support - for local and armor providers and to unlock future providers ([#855](https://github.com/dotenvx/dotenvx/pull/855))
|
|
14
|
+
* Route `run`, `config`, and `get` through shared env and keypair resolvers backed by `@dotenvx/primitives` ([#855](https://github.com/dotenvx/dotenvx/pull/855))
|
|
15
|
+
* Route `set`, `encrypt`, and `decrypt` through shared transforms that operate on primitive scan, parse, encrypt, and upsert results ([#855](https://github.com/dotenvx/dotenvx/pull/855))
|
|
16
|
+
* Update library `parse` to use primitive parsing while preserving dotenvx-style encrypted value errors ([#855](https://github.com/dotenvx/dotenvx/pull/855))
|
|
17
|
+
|
|
18
|
+
### Removed
|
|
19
|
+
|
|
20
|
+
* BREAKING: Remove the `rotate` command (it will return in 2.1 or 2.2 soon with a more complete implementation for local and armored keys) ([#855](https://github.com/dotenvx/dotenvx/pull/855))
|
|
21
|
+
* BREAKING: Remove the library `doctor`, `keypair`, and `genexample` exports from `lib/main` ([#855](https://github.com/dotenvx/dotenvx/pull/855))
|
|
22
|
+
|
|
23
|
+
## [1.76.0](https://github.com/dotenvx/dotenvx/compare/v1.75.1...v1.76.0) (2026-06-24)
|
|
24
|
+
|
|
25
|
+
### Changed
|
|
26
|
+
|
|
27
|
+
* Support dotenvx across powershell ([#856](https://github.com/dotenvx/dotenvx/pull/856))
|
|
28
|
+
* BREAKING: Remove variadic `-f`. You can still do `dotenvx run -f .env1 -f .env2` but ambiguos variadic like `dotenvx run -f .env1 .env2 ...` is removed ([#856](https://github.com/dotenvx/dotenvx/pull/856))
|
|
6
29
|
|
|
7
30
|
## [1.75.1](https://github.com/dotenvx/dotenvx/compare/v1.75.0...v1.75.1) (2026-06-20)
|
|
8
31
|
|
package/README.md
CHANGED
|
@@ -58,7 +58,9 @@ dotenvx encrypt
|
|
|
58
58
|
<details><summary>with brew 🍺</summary><br>
|
|
59
59
|
|
|
60
60
|
```sh
|
|
61
|
-
brew
|
|
61
|
+
brew tap dotenvx/brew
|
|
62
|
+
brew trust dotenvx/brew
|
|
63
|
+
brew install dotenvx
|
|
62
64
|
dotenvx encrypt
|
|
63
65
|
```
|
|
64
66
|
|
|
@@ -2026,117 +2028,6 @@ $ dotenvx ls -ef '**/.env.prod*'
|
|
|
2026
2028
|
└─ .env
|
|
2027
2029
|
```
|
|
2028
2030
|
|
|
2029
|
-
</details>
|
|
2030
|
-
<details><summary>`rotate`</summary><br>
|
|
2031
|
-
|
|
2032
|
-
Rotate public/private keys for `.env` file and re-encrypt all encrypted values.
|
|
2033
|
-
|
|
2034
|
-
```sh
|
|
2035
|
-
$ echo "HELLO=Dotenvx" > .env
|
|
2036
|
-
$ dotenvx encrypt
|
|
2037
|
-
◈ encrypted (.env)
|
|
2038
|
-
$ dotenvx rotate
|
|
2039
|
-
⟳ rotated (.env)
|
|
2040
|
-
```
|
|
2041
|
-
|
|
2042
|
-
</details>
|
|
2043
|
-
<details><summary>`rotate -f`</summary><br>
|
|
2044
|
-
|
|
2045
|
-
Rotate public/private keys for a specified encrypted `.env` file and re-encrypt all encrypted values.
|
|
2046
|
-
|
|
2047
|
-
```sh
|
|
2048
|
-
$ echo "HELLO=Dotenvx" > .env
|
|
2049
|
-
$ echo "HELLO=Production" > .env.production
|
|
2050
|
-
|
|
2051
|
-
$ dotenvx encrypt -f .env.production
|
|
2052
|
-
◈ encrypted (.env.production)
|
|
2053
|
-
$ dotenvx rotate -f .env.production
|
|
2054
|
-
⟳ rotated (.env.production)
|
|
2055
|
-
```
|
|
2056
|
-
|
|
2057
|
-
</details>
|
|
2058
|
-
<details><summary>`rotate -fk`</summary><br>
|
|
2059
|
-
|
|
2060
|
-
Specify path to `.env.keys`. This is useful with monorepos.
|
|
2061
|
-
|
|
2062
|
-
```sh
|
|
2063
|
-
$ mkdir -p apps/app1
|
|
2064
|
-
$ echo "HELLO=Dotenvx" > apps/app1/.env
|
|
2065
|
-
|
|
2066
|
-
$ dotenvx encrypt -fk .env.keys -f apps/app1/.env
|
|
2067
|
-
◈ encrypted (apps/app1/.env)
|
|
2068
|
-
$ dotenvx rotate -fk .env.keys -f apps/app1/.env
|
|
2069
|
-
⟳ rotated (apps/app1/.env)
|
|
2070
|
-
```
|
|
2071
|
-
|
|
2072
|
-
</details>
|
|
2073
|
-
<details><summary>`rotate -k`</summary><br>
|
|
2074
|
-
|
|
2075
|
-
Rotate the contents of a specified key inside an encrypted `.env` file.
|
|
2076
|
-
|
|
2077
|
-
```sh
|
|
2078
|
-
$ echo "HELLO=Dotenvx\nHOLA=Mundo" > .env
|
|
2079
|
-
$ dotenvx encrypt
|
|
2080
|
-
◈ encrypted (.env)
|
|
2081
|
-
$ dotenvx rotate -k HELLO
|
|
2082
|
-
⟳ rotated (.env)
|
|
2083
|
-
```
|
|
2084
|
-
|
|
2085
|
-
Even specify a glob pattern.
|
|
2086
|
-
|
|
2087
|
-
```sh
|
|
2088
|
-
$ echo "HELLO=Dotenvx\nHOLA=Mundo" > .env
|
|
2089
|
-
$ dotenvx encrypt
|
|
2090
|
-
◈ encrypted (.env)
|
|
2091
|
-
$ dotenvx rotate -k "HE*"
|
|
2092
|
-
⟳ rotated (.env)
|
|
2093
|
-
```
|
|
2094
|
-
|
|
2095
|
-
</details>
|
|
2096
|
-
<details><summary>`rotate -ek`</summary><br>
|
|
2097
|
-
|
|
2098
|
-
Rotate the encrypted contents inside an encrypted `.env` file except for an excluded key.
|
|
2099
|
-
|
|
2100
|
-
```sh
|
|
2101
|
-
$ echo "HELLO=Dotenvx\nHOLA=Mundo" > .env
|
|
2102
|
-
$ dotenvx encrypt
|
|
2103
|
-
◈ encrypted (.env)
|
|
2104
|
-
$ dotenvx rotate -ek HOLA
|
|
2105
|
-
⟳ rotated (.env)
|
|
2106
|
-
```
|
|
2107
|
-
|
|
2108
|
-
Even specify a glob pattern.
|
|
2109
|
-
|
|
2110
|
-
```sh
|
|
2111
|
-
$ echo "HELLO=Dotenvx\nHOLA=Mundo" > .env
|
|
2112
|
-
$ dotenvx encrypt
|
|
2113
|
-
◈ encrypted (.env)
|
|
2114
|
-
$ dotenvx rotate -ek "HO*"
|
|
2115
|
-
⟳ rotated (.env)
|
|
2116
|
-
```
|
|
2117
|
-
|
|
2118
|
-
</details>
|
|
2119
|
-
<details><summary>`rotate --stdout`</summary><br>
|
|
2120
|
-
|
|
2121
|
-
Rotate the contents of an encrypted `.env` file and send to stdout.
|
|
2122
|
-
|
|
2123
|
-
```sh
|
|
2124
|
-
$ dotenvx rotate --stdout
|
|
2125
|
-
#/-------------------[DOTENV_PUBLIC_KEY]--------------------/
|
|
2126
|
-
#/ public-key encryption for .env files /
|
|
2127
|
-
#/ [how it works](https://dotenvx.com/encryption) /
|
|
2128
|
-
#/----------------------------------------------------------/
|
|
2129
|
-
DOTENV_PUBLIC_KEY="034af93e93708b994c10f236c96ef88e47291066946cce2e8d98c9e02c741ced45"
|
|
2130
|
-
# .env
|
|
2131
|
-
HELLO="encrypted:12345"
|
|
2132
|
-
```
|
|
2133
|
-
|
|
2134
|
-
or send to a file:
|
|
2135
|
-
|
|
2136
|
-
```sh
|
|
2137
|
-
$ dotenvx rotate --stdout > somefile.txt
|
|
2138
|
-
```
|
|
2139
|
-
|
|
2140
2031
|
</details>
|
|
2141
2032
|
<details><summary>`help`</summary><br>
|
|
2142
2033
|
|
|
@@ -2162,7 +2053,6 @@ Commands:
|
|
|
2162
2053
|
set <KEY> <value> set a single environment variable
|
|
2163
2054
|
encrypt encrypt .env file(s)
|
|
2164
2055
|
decrypt decrypt .env file(s)
|
|
2165
|
-
rotate rotate keypair(s) and re-encrypt .env file(s)
|
|
2166
2056
|
keypair [KEY] print public/private keys for .env file(s)
|
|
2167
2057
|
ls [directory] print all .env files in a tree structure
|
|
2168
2058
|
gitignore append to .gitignore
|
|
@@ -2703,7 +2593,7 @@ Programmatically get an environment variable at access/runtime.
|
|
|
2703
2593
|
```js
|
|
2704
2594
|
// index.js
|
|
2705
2595
|
const dotenvx = require('@dotenvx/dotenvx')
|
|
2706
|
-
const decryptedValue = dotenvx.get('HELLO')
|
|
2596
|
+
const decryptedValue = await dotenvx.get('HELLO')
|
|
2707
2597
|
console.log(decryptedValue)
|
|
2708
2598
|
```
|
|
2709
2599
|
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "
|
|
2
|
+
"version": "2.0.0",
|
|
3
3
|
"name": "@dotenvx/dotenvx",
|
|
4
4
|
"description": "a secure dotenv–from the creator of `dotenv`",
|
|
5
5
|
"author": "@motdotla",
|
|
@@ -43,22 +43,23 @@
|
|
|
43
43
|
},
|
|
44
44
|
"funding": "https://dotenvx.com",
|
|
45
45
|
"dependencies": {
|
|
46
|
-
"@dotenvx/primitives": "^
|
|
46
|
+
"@dotenvx/primitives": "^1.7.0",
|
|
47
47
|
"commander": "^11.1.0",
|
|
48
48
|
"conf": "^10.2.0",
|
|
49
|
-
"dotenv": "^17.2
|
|
49
|
+
"dotenv": "^17.4.2",
|
|
50
50
|
"enquirer": "^2.4.1",
|
|
51
51
|
"env-paths": "^2.2.1",
|
|
52
52
|
"execa": "^5.1.1",
|
|
53
53
|
"fdir": "^6.2.0",
|
|
54
|
-
"ignore": "^
|
|
54
|
+
"ignore": "^7.0.5",
|
|
55
55
|
"object-treeify": "1.1.33",
|
|
56
56
|
"open": "^8.4.2",
|
|
57
57
|
"picomatch": "^4.0.4",
|
|
58
|
-
"
|
|
58
|
+
"synckit": "0.11.13",
|
|
59
|
+
"systeminformation": "^5.31.11",
|
|
59
60
|
"undici": "^7.11.0",
|
|
60
|
-
"which": "^
|
|
61
|
-
"yocto-spinner": "^1.
|
|
61
|
+
"which": "^6.0.1",
|
|
62
|
+
"yocto-spinner": "^1.2.0"
|
|
62
63
|
},
|
|
63
64
|
"devDependencies": {
|
|
64
65
|
"@yao-pkg/pkg": "^6.12.0",
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
const fsx = require('./../../lib/helpers/fsx')
|
|
2
2
|
const { logger } = require('./../../shared/logger')
|
|
3
3
|
|
|
4
|
-
const Decrypt = require('./../../lib/services/decrypt')
|
|
5
4
|
const catchAndLog = require('../../lib/helpers/catchAndLog')
|
|
6
5
|
const createSpinner = require('../../lib/helpers/createSpinner')
|
|
7
6
|
const Session = require('../../db/session')
|
|
8
|
-
const
|
|
7
|
+
const normalizeArmorAliases = require('./normalizeArmorAliases')
|
|
8
|
+
|
|
9
|
+
const decryptTransform = require('./../../lib/transforms/decrypt')
|
|
9
10
|
|
|
10
11
|
async function decrypt () {
|
|
11
|
-
const options =
|
|
12
|
+
const options = normalizeArmorAliases(this.opts())
|
|
12
13
|
const spinner = await createSpinner({ ...options, text: 'decrypting' })
|
|
13
14
|
|
|
14
15
|
logger.debug(`options: ${JSON.stringify(options)}`)
|
|
@@ -21,17 +22,26 @@ async function decrypt () {
|
|
|
21
22
|
|
|
22
23
|
// stdout - should not have a try so that exit codes can surface to stdout
|
|
23
24
|
if (options.stdout) {
|
|
24
|
-
if (spinner) spinner.stop()
|
|
25
25
|
const {
|
|
26
26
|
processedEnvs
|
|
27
|
-
} = await
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
} = await decryptTransform({
|
|
28
|
+
envs,
|
|
29
|
+
ik: options.key,
|
|
30
|
+
ek: options.excludeKey,
|
|
31
|
+
fk: options.envKeysFile,
|
|
32
|
+
noArmor,
|
|
33
|
+
onStatus: (text) => {
|
|
34
|
+
if (spinner && text) {
|
|
35
|
+
spinner.text = text
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
})
|
|
39
|
+
|
|
30
40
|
if (spinner) spinner.stop()
|
|
31
41
|
for (const processedEnv of processedEnvs) {
|
|
32
42
|
if (processedEnv.error) {
|
|
33
43
|
errorCount += 1
|
|
34
|
-
logger.error(processedEnv.error.messageWithHelp)
|
|
44
|
+
logger.error(processedEnv.error.messageWithHelp || processedEnv.error.message)
|
|
35
45
|
} else {
|
|
36
46
|
console.log(processedEnv.envSrc)
|
|
37
47
|
}
|
|
@@ -44,22 +54,32 @@ async function decrypt () {
|
|
|
44
54
|
}
|
|
45
55
|
} else {
|
|
46
56
|
try {
|
|
47
|
-
if (spinner) spinner.stop()
|
|
48
57
|
const {
|
|
49
58
|
processedEnvs,
|
|
50
59
|
changedFilepaths,
|
|
51
60
|
unchangedFilepaths
|
|
52
|
-
} = await
|
|
53
|
-
|
|
54
|
-
|
|
61
|
+
} = await decryptTransform({
|
|
62
|
+
envs,
|
|
63
|
+
ik: options.key,
|
|
64
|
+
ek: options.excludeKey,
|
|
65
|
+
fk: options.envKeysFile,
|
|
66
|
+
noArmor,
|
|
67
|
+
onStatus: (text) => {
|
|
68
|
+
if (spinner && text) {
|
|
69
|
+
spinner.text = text
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
})
|
|
55
73
|
|
|
56
74
|
for (const processedEnv of processedEnvs) {
|
|
57
75
|
logger.verbose(`decrypting ${processedEnv.envFilepath} (${processedEnv.filepath})`)
|
|
58
76
|
|
|
59
77
|
if (processedEnv.error) {
|
|
60
78
|
errorCount += 1
|
|
61
|
-
logger.error(processedEnv.error.messageWithHelp)
|
|
62
|
-
}
|
|
79
|
+
logger.error(processedEnv.error.messageWithHelp || processedEnv.error.message)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (processedEnv.changed) {
|
|
63
83
|
await fsx.writeFileX(processedEnv.filepath, processedEnv.envSrc)
|
|
64
84
|
|
|
65
85
|
logger.verbose(`decrypted ${processedEnv.envFilepath} (${processedEnv.filepath})`)
|
|
@@ -69,10 +89,8 @@ async function decrypt () {
|
|
|
69
89
|
}
|
|
70
90
|
|
|
71
91
|
if (spinner) spinner.stop()
|
|
72
|
-
const armoredPrivateKeyUsed = processedEnvs.some((processedEnv) => processedEnv.armoredPrivateKeyUsed)
|
|
73
|
-
const keyUsedSuffix = armoredPrivateKeyUsed ? ' · armored ⛨' : ''
|
|
74
92
|
if (changedFilepaths.length > 0) {
|
|
75
|
-
logger.success(`◇ decrypted (${changedFilepaths.join(',')})
|
|
93
|
+
logger.success(`◇ decrypted (${changedFilepaths.join(',')})`)
|
|
76
94
|
} else if (unchangedFilepaths.length > 0) {
|
|
77
95
|
logger.info(`○ no change (${unchangedFilepaths})`)
|
|
78
96
|
} else {
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
const { logger } = require('./../../shared/logger')
|
|
2
|
-
const
|
|
2
|
+
const Doctor = require('./../../lib/services/doctor')
|
|
3
3
|
|
|
4
4
|
function doctor (directory = '.') {
|
|
5
5
|
logger.debug(`directory: ${directory}`)
|
|
6
6
|
|
|
7
|
-
const findings =
|
|
7
|
+
const findings = new Doctor(directory).run()
|
|
8
8
|
logger.debug(`findings: ${JSON.stringify(findings)}`)
|
|
9
9
|
|
|
10
10
|
if (findings.length === 0) {
|
|
@@ -1,114 +1,93 @@
|
|
|
1
1
|
const fsx = require('./../../lib/helpers/fsx')
|
|
2
2
|
const { logger } = require('./../../shared/logger')
|
|
3
3
|
|
|
4
|
-
const
|
|
4
|
+
const encryptTransform = require('./../../lib/transforms/encrypt')
|
|
5
5
|
|
|
6
6
|
const catchAndLog = require('../../lib/helpers/catchAndLog')
|
|
7
7
|
const createSpinner = require('../../lib/helpers/createSpinner')
|
|
8
|
-
const prompts = require('../../lib/helpers/prompts')
|
|
9
8
|
const Session = require('../../db/session')
|
|
10
|
-
const
|
|
9
|
+
const normalizeArmorAliases = require('./normalizeArmorAliases')
|
|
11
10
|
|
|
12
|
-
function
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
return async function selectKeyStorage () {
|
|
16
|
-
if (selected) return selected
|
|
17
|
-
|
|
18
|
-
selected = await prompts.select({
|
|
19
|
-
message: 'Choose private key storage',
|
|
20
|
-
choices: [
|
|
21
|
-
{ name: '◫ File (.env.keys)', value: 'file' },
|
|
22
|
-
{ name: '⛨ Armor (armor.dotenvx.com)', value: 'armored' }
|
|
23
|
-
]
|
|
24
|
-
}, {
|
|
25
|
-
input: process.stdin,
|
|
26
|
-
output: process.stderr
|
|
27
|
-
})
|
|
28
|
-
|
|
29
|
-
return selected
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
function encryptOptions (noArmor) {
|
|
34
|
-
const options = {}
|
|
35
|
-
|
|
36
|
-
if (!noArmor) {
|
|
37
|
-
options.selectKeyStorage = keyStorageSelector()
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
return options
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
async function encrypt () {
|
|
44
|
-
const options = normalizeArmorOptions(this.opts())
|
|
11
|
+
async function encryptAction () {
|
|
12
|
+
const options = normalizeArmorAliases(this.opts())
|
|
45
13
|
const spinner = await createSpinner({ ...options, text: 'encrypting' })
|
|
14
|
+
const sesh = new Session()
|
|
46
15
|
|
|
47
16
|
logger.debug(`options: ${JSON.stringify(options)}`)
|
|
48
17
|
|
|
49
|
-
const envs = this.envs
|
|
50
|
-
const
|
|
51
|
-
const
|
|
18
|
+
const envs = this.envs || []
|
|
19
|
+
const ik = options.key
|
|
20
|
+
const ek = options.excludeKey
|
|
21
|
+
const fk = options.envKeysFile || '.env.keys'
|
|
52
22
|
const noCreate = options.create === false
|
|
23
|
+
const noArmor = options.armor === false || (!options.token && (await sesh.noArmor()))
|
|
24
|
+
|
|
25
|
+
let errorCount = 0
|
|
53
26
|
|
|
54
27
|
// stdout - should not have a try so that exit codes can surface to stdout
|
|
55
28
|
if (options.stdout) {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
processedEnvs
|
|
59
|
-
} = await new Encrypt(envs, options.key, options.excludeKey, options.envKeysFile, noArmor, noCreate, options.token, {
|
|
60
|
-
...encryptOptions(noArmor),
|
|
61
|
-
command: process.argv.slice(2)
|
|
62
|
-
}).run()
|
|
29
|
+
const { processedEnvs } = await encryptTransform({ envs, ik, ek, fk, noArmor, noCreate })
|
|
30
|
+
|
|
63
31
|
if (spinner) spinner.stop()
|
|
64
32
|
for (const processedEnv of processedEnvs) {
|
|
65
|
-
|
|
33
|
+
if (processedEnv.error) {
|
|
34
|
+
errorCount += 1
|
|
35
|
+
logger.error(processedEnv.error.messageWithHelp || processedEnv.error.message)
|
|
36
|
+
}
|
|
37
|
+
if (processedEnv.envSrc) {
|
|
38
|
+
console.log(processedEnv.envSrc)
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (errorCount > 0) {
|
|
43
|
+
process.exit(1)
|
|
44
|
+
} else {
|
|
45
|
+
process.exit(0) // exit early
|
|
66
46
|
}
|
|
67
|
-
|
|
68
|
-
} else {
|
|
69
|
-
try {
|
|
70
|
-
if (spinner) spinner.stop()
|
|
71
|
-
const {
|
|
72
|
-
processedEnvs,
|
|
73
|
-
changedFilepaths,
|
|
74
|
-
unchangedFilepaths
|
|
75
|
-
} = await new Encrypt(envs, options.key, options.excludeKey, options.envKeysFile, noArmor, noCreate, options.token, {
|
|
76
|
-
...encryptOptions(noArmor),
|
|
77
|
-
command: process.argv.slice(2)
|
|
78
|
-
}).run()
|
|
47
|
+
}
|
|
79
48
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
if (processedEnv.error) {
|
|
83
|
-
logger.warn(processedEnv.error.messageWithHelp)
|
|
84
|
-
} else if (processedEnv.changed) {
|
|
85
|
-
await fsx.writeFileX(processedEnv.filepath, processedEnv.envSrc)
|
|
49
|
+
try {
|
|
50
|
+
const { keysSrc, processedEnvs, changedFilepaths, unchangedFilepaths } = await encryptTransform({ envs, ik, ek, fk, noArmor, noCreate })
|
|
86
51
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
}
|
|
91
|
-
}
|
|
52
|
+
if (keysSrc) {
|
|
53
|
+
await fsx.writeFileX(fk, keysSrc)
|
|
54
|
+
}
|
|
92
55
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
logger.info(`○ no change (${unchangedFilepaths})`)
|
|
56
|
+
if (spinner) spinner.stop()
|
|
57
|
+
for (const processedEnv of processedEnvs) {
|
|
58
|
+
logger.verbose(`encrypting ${processedEnv.envFilepath} (${processedEnv.filepath})`)
|
|
59
|
+
if (processedEnv.error) {
|
|
60
|
+
errorCount += 1
|
|
61
|
+
logger.error(processedEnv.error.messageWithHelp || processedEnv.error.message)
|
|
62
|
+
} else if (processedEnv.changed) {
|
|
63
|
+
await fsx.writeFileX(processedEnv.filepath, processedEnv.envSrc)
|
|
64
|
+
logger.verbose(`encrypted ${processedEnv.envFilepath} (${processedEnv.filepath})`)
|
|
103
65
|
} else {
|
|
104
|
-
|
|
66
|
+
logger.verbose(`no change ${processedEnv.envFilepath} (${processedEnv.filepath})`)
|
|
105
67
|
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (changedFilepaths.length > 0) {
|
|
71
|
+
// const remoteKeyAddedEnv = processedEnvs.find((processedEnv) => processedEnv.remotePrivateKeyAdded)
|
|
72
|
+
const msg = `◈ encrypted (${changedFilepaths.join(',')})`
|
|
73
|
+
// if (remoteKeyAddedEnv) {
|
|
74
|
+
// msg += ' · armored ⛨'
|
|
75
|
+
// }
|
|
76
|
+
logger.success(msg)
|
|
77
|
+
} else if (unchangedFilepaths.length > 0) {
|
|
78
|
+
logger.info(`○ no change (${unchangedFilepaths})`)
|
|
79
|
+
} else {
|
|
80
|
+
// do nothing - scenario when no .env files found
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (errorCount > 0) {
|
|
109
84
|
process.exit(1)
|
|
110
85
|
}
|
|
86
|
+
} catch (error) {
|
|
87
|
+
if (spinner) spinner.stop()
|
|
88
|
+
catchAndLog(error)
|
|
89
|
+
process.exit(1)
|
|
111
90
|
}
|
|
112
91
|
}
|
|
113
92
|
|
|
114
|
-
module.exports =
|
|
93
|
+
module.exports = encryptAction
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const fsx = require('./../../../lib/helpers/fsx')
|
|
2
2
|
const path = require('path')
|
|
3
|
-
const
|
|
3
|
+
const Genexample = require('./../../../lib/services/genexample')
|
|
4
4
|
const { logger } = require('./../../../shared/logger')
|
|
5
5
|
const catchAndLog = require('./../../../lib/helpers/catchAndLog')
|
|
6
6
|
|
|
@@ -16,7 +16,7 @@ function genexample (directory) {
|
|
|
16
16
|
envFile,
|
|
17
17
|
exampleFilepath,
|
|
18
18
|
addedKeys
|
|
19
|
-
} =
|
|
19
|
+
} = new Genexample(directory, options.envFile).run()
|
|
20
20
|
|
|
21
21
|
logger.verbose(`loading env from ${envFile}`)
|
|
22
22
|
|
package/src/cli/actions/get.js
CHANGED
|
@@ -5,11 +5,11 @@ const escape = require('./../../lib/helpers/escape')
|
|
|
5
5
|
const catchAndLog = require('./../../lib/helpers/catchAndLog')
|
|
6
6
|
const createSpinner = require('../../lib/helpers/createSpinner')
|
|
7
7
|
const Session = require('../../db/session')
|
|
8
|
-
const
|
|
9
|
-
const
|
|
8
|
+
const getResolver = require('./../../lib/resolvers/get')
|
|
9
|
+
const normalizeArmorAliases = require('./normalizeArmorAliases')
|
|
10
10
|
|
|
11
11
|
async function get (key) {
|
|
12
|
-
const options =
|
|
12
|
+
const options = normalizeArmorAliases(this.opts())
|
|
13
13
|
const spinner = await createSpinner({ ...options, text: 'decrypting' })
|
|
14
14
|
|
|
15
15
|
logger.debug(`options: ${JSON.stringify(options)}`)
|
|
@@ -31,10 +31,19 @@ async function get (key) {
|
|
|
31
31
|
try {
|
|
32
32
|
const sesh = new Session()
|
|
33
33
|
const noArmor = options.armor === false || (await sesh.noArmor())
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
34
|
+
const { parsed, errors } = await getResolver({
|
|
35
|
+
key,
|
|
36
|
+
envs,
|
|
37
|
+
overload: options.overload,
|
|
38
|
+
all: options.all,
|
|
39
|
+
envKeysFile: options.envKeysFile,
|
|
40
|
+
noArmor,
|
|
41
|
+
onStatus: (text) => {
|
|
42
|
+
if (spinner && text) {
|
|
43
|
+
spinner.text = text
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
})
|
|
38
47
|
|
|
39
48
|
for (const error of errors || []) {
|
|
40
49
|
if (options.strict) throw error // throw immediately if strict
|