@dotenvx/dotenvx 1.39.0 → 1.40.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 +15 -1
- package/README.md +148 -0
- package/package.json +1 -1
- package/src/lib/helpers/dotenvParse.js +13 -3
- package/src/lib/helpers/executeDynamic.js +6 -6
- package/src/lib/helpers/isFullyEncrypted.js +14 -5
- package/src/lib/services/precommit.js +14 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,7 +2,21 @@
|
|
|
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.40.0...main)
|
|
6
|
+
|
|
7
|
+
## [1.40.0](https://github.com/dotenvx/dotenvx/compare/v1.39.1...v1.40.0)
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
* Smarter `ext precommit` and `ext prebuild` – catch duplicate KEYs in the same .env file where one is mistakenly left unencrypted ([#567](https://github.com/dotenvx/dotenvx/pull/567))
|
|
12
|
+
|
|
13
|
+
## [1.39.1](https://github.com/dotenvx/dotenvx/compare/v1.39.0...v1.39.1)
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
|
|
17
|
+
* Add `version` to homebrew formula ([#564](https://github.com/dotenvx/dotenvx/pull/564))
|
|
18
|
+
|
|
19
|
+
## [1.39.0](https://github.com/dotenvx/dotenvx/compare/v1.38.5...v1.39.0)
|
|
6
20
|
|
|
7
21
|
### Added
|
|
8
22
|
|
package/README.md
CHANGED
|
@@ -614,6 +614,9 @@ More examples
|
|
|
614
614
|
|
|
615
615
|
$ dotenvx run --convention=nextjs -- node index.js
|
|
616
616
|
Hello development local
|
|
617
|
+
|
|
618
|
+
$ dotenvx run --convention=flow -- node index.js
|
|
619
|
+
Hello development local
|
|
617
620
|
```
|
|
618
621
|
|
|
619
622
|
(more conventions available upon request)
|
|
@@ -1156,6 +1159,29 @@ Advanced CLI commands.
|
|
|
1156
1159
|
development local
|
|
1157
1160
|
```
|
|
1158
1161
|
|
|
1162
|
+
</details>
|
|
1163
|
+
* <details><summary>`get KEY --convention=flow`</summary><br>
|
|
1164
|
+
|
|
1165
|
+
Return a single environment variable's value using [dotenv-flow's convention](https://www.npmjs.com/package/dotenv-flow). Set `--convention` to `flow`:
|
|
1166
|
+
|
|
1167
|
+
```sh
|
|
1168
|
+
$ echo "HELLO=development local" > .env.development.local
|
|
1169
|
+
$ echo "HELLO=development" > .env.development
|
|
1170
|
+
$ echo "HELLO=local" > .env.local
|
|
1171
|
+
$ echo "HELLO=env" > .env
|
|
1172
|
+
$ echo "console.log('Hello ' + process.env.HELLO)" > index.js
|
|
1173
|
+
|
|
1174
|
+
$ NODE_ENV=development dotenvx get HELLO --convention=flow
|
|
1175
|
+
development local
|
|
1176
|
+
```
|
|
1177
|
+
|
|
1178
|
+
Further, we recommend using `DOTENV_ENV` over `NODE_ENV`– as `dotenvx` works everywhere, not just node.
|
|
1179
|
+
|
|
1180
|
+
```sh
|
|
1181
|
+
$ DOTENV_ENV=development dotenvx get HELLO --convention=flow
|
|
1182
|
+
development local
|
|
1183
|
+
```
|
|
1184
|
+
|
|
1159
1185
|
</details>
|
|
1160
1186
|
* <details><summary>`get` (json)</summary><br>
|
|
1161
1187
|
|
|
@@ -2261,6 +2287,128 @@ Use dotenvx directly in code.
|
|
|
2261
2287
|
|
|
2262
2288
|
</details>
|
|
2263
2289
|
|
|
2290
|
+
### Pro 🏆
|
|
2291
|
+
|
|
2292
|
+
*Secrets Management – Done Right. Encrypted, Cloaked, Secrets as Code.*
|
|
2293
|
+
|
|
2294
|
+
* <details><summary>`pro keypair`</summary><br>
|
|
2295
|
+
|
|
2296
|
+
Print fully managed public/private keys for `.env` file.
|
|
2297
|
+
|
|
2298
|
+
```sh
|
|
2299
|
+
$ echo "HELLO=World" > .env
|
|
2300
|
+
$ dotenvx encrypt
|
|
2301
|
+
|
|
2302
|
+
$ dotenvx pro push
|
|
2303
|
+
|
|
2304
|
+
$ dotenvx pro keypair
|
|
2305
|
+
{"DOTENV_PUBLIC_KEY":"<publicKey>","DOTENV_PRIVATE_KEY":"<privateKey>"}
|
|
2306
|
+
```
|
|
2307
|
+
|
|
2308
|
+
</details>
|
|
2309
|
+
* <details><summary>`pro keypair -f`</summary><br>
|
|
2310
|
+
|
|
2311
|
+
Print fully managed public/private keys for `.env.production` file.
|
|
2312
|
+
|
|
2313
|
+
```sh
|
|
2314
|
+
$ echo "HELLO=Production" > .env.production
|
|
2315
|
+
$ dotenvx encrypt -f .env.production
|
|
2316
|
+
|
|
2317
|
+
$ dotenvx pro push
|
|
2318
|
+
|
|
2319
|
+
$ dotenvx pro keypair -f .env.production
|
|
2320
|
+
{"DOTENV_PUBLIC_KEY_PRODUCTION":"<publicKey>","DOTENV_PRIVATE_KEY_PRODUCTION":"<privateKey>"}
|
|
2321
|
+
```
|
|
2322
|
+
|
|
2323
|
+
</details>
|
|
2324
|
+
* <details><summary>`pro keypair DOTENV_PRIVATE_KEY`</summary><br>
|
|
2325
|
+
|
|
2326
|
+
Print specific fully managed keypair for `.env` file.
|
|
2327
|
+
|
|
2328
|
+
```sh
|
|
2329
|
+
$ echo "HELLO=World" > .env
|
|
2330
|
+
$ dotenvx encrypt
|
|
2331
|
+
|
|
2332
|
+
$ dotenvx pro push
|
|
2333
|
+
|
|
2334
|
+
$ dotenvx pro keypair DOTENV_PRIVATE_KEY
|
|
2335
|
+
<privateKey>
|
|
2336
|
+
```
|
|
2337
|
+
|
|
2338
|
+
</details>
|
|
2339
|
+
* <details><summary>`pro settings org`</summary><br>
|
|
2340
|
+
|
|
2341
|
+
Print organization.
|
|
2342
|
+
|
|
2343
|
+
```sh
|
|
2344
|
+
$ dotenvx pro settings org
|
|
2345
|
+
motdotla
|
|
2346
|
+
```
|
|
2347
|
+
|
|
2348
|
+
</details>
|
|
2349
|
+
* <details><summary>`pro settings orgpublickey`</summary><br>
|
|
2350
|
+
|
|
2351
|
+
Print organization public key–used for encrypting project private keys.
|
|
2352
|
+
|
|
2353
|
+
```sh
|
|
2354
|
+
$ dotenvx pro settings orgpublickey
|
|
2355
|
+
02761eccd2a442ebbfa14ac2e72762d885a1e96b8949428deea62db305947d6408
|
|
2356
|
+
```
|
|
2357
|
+
|
|
2358
|
+
</details>
|
|
2359
|
+
* <details><summary>`pro settings orgprivatekey`</summary><br>
|
|
2360
|
+
|
|
2361
|
+
Print masked organization private key–used for decrypting project private keys.
|
|
2362
|
+
|
|
2363
|
+
```sh
|
|
2364
|
+
$ dotenvx pro settings orgprivatekey
|
|
2365
|
+
322c004*********************************************************
|
|
2366
|
+
```
|
|
2367
|
+
|
|
2368
|
+
</details>
|
|
2369
|
+
* <details><summary>`pro settings orgprivatekey --unmask`</summary><br>
|
|
2370
|
+
|
|
2371
|
+
Print unmasked organization private key–used for decrypting project private keys.
|
|
2372
|
+
|
|
2373
|
+
```sh
|
|
2374
|
+
$ dotenvx pro settings orgprivatekey --unmask
|
|
2375
|
+
322c004271ac6ad1b548df3f316ff4e8f08e17e0b15f459db64f3f3b48b0efb7
|
|
2376
|
+
```
|
|
2377
|
+
|
|
2378
|
+
</details>
|
|
2379
|
+
* <details><summary>`pro settings orgteam`</summary><br>
|
|
2380
|
+
|
|
2381
|
+
Print team status in tabular format.
|
|
2382
|
+
|
|
2383
|
+
```sh
|
|
2384
|
+
$ dotenvx pro settings orgteam
|
|
2385
|
+
╔═══════════╤════════╗
|
|
2386
|
+
║ username │ synced ║
|
|
2387
|
+
╟───────────┼────────╢
|
|
2388
|
+
║ motdotla │ ✔ ║
|
|
2389
|
+
╟───────────┼────────╢
|
|
2390
|
+
║ motdotenv │ ✔ ║
|
|
2391
|
+
╚═══════════╧════════╝
|
|
2392
|
+
```
|
|
2393
|
+
|
|
2394
|
+
</details>
|
|
2395
|
+
* <details><summary>`pro settings storetree`</summary><br>
|
|
2396
|
+
|
|
2397
|
+
Print encrypted store tree–backing your dotenvx pro installation.
|
|
2398
|
+
|
|
2399
|
+
```sh
|
|
2400
|
+
$ dotenvx pro settings storetree
|
|
2401
|
+
├─ .env
|
|
2402
|
+
└─ pro.dotenvx.com
|
|
2403
|
+
├─ user-1-organization-1.json
|
|
2404
|
+
├─ user-1-private-key.json
|
|
2405
|
+
└─ user-1.json
|
|
2406
|
+
```
|
|
2407
|
+
|
|
2408
|
+
</details>
|
|
2409
|
+
|
|
2410
|
+
|
|
2411
|
+
|
|
2264
2412
|
## Whitepaper
|
|
2265
2413
|
|
|
2266
2414
|
> **Dotenvx: Reducing Secrets Risk with Cryptographic Separation**
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// historical dotenv.parse - https://github.com/motdotla/dotenv)
|
|
2
2
|
const LINE = /(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|\s*`(?:\\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/mg
|
|
3
3
|
|
|
4
|
-
function dotenvParse (src, skipExpandForDoubleQuotes = false, skipConvertingWindowsNewlines = false) {
|
|
4
|
+
function dotenvParse (src, skipExpandForDoubleQuotes = false, skipConvertingWindowsNewlines = false, collectAllValues = false) {
|
|
5
5
|
const obj = {}
|
|
6
6
|
|
|
7
7
|
// Convert buffer to string
|
|
@@ -35,8 +35,18 @@ function dotenvParse (src, skipExpandForDoubleQuotes = false, skipConvertingWind
|
|
|
35
35
|
value = value.replace(/\\t/g, '\t') // tabs
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
if (collectAllValues) {
|
|
39
|
+
// handle scenario where user mistakenly includes plaintext duplicate in .env:
|
|
40
|
+
//
|
|
41
|
+
// # .env
|
|
42
|
+
// HELLO="World"
|
|
43
|
+
// HELLO="enrypted:1234"
|
|
44
|
+
obj[key] = obj[key] || []
|
|
45
|
+
obj[key].push(value)
|
|
46
|
+
} else {
|
|
47
|
+
// Add to object
|
|
48
|
+
obj[key] = value
|
|
49
|
+
}
|
|
40
50
|
}
|
|
41
51
|
|
|
42
52
|
return obj
|
|
@@ -23,12 +23,9 @@ function executeDynamic (program, command, rawArgs) {
|
|
|
23
23
|
const result = childProcess.spawnSync(`dotenvx-${command}`, forwardedArgs, { stdio: 'inherit', env })
|
|
24
24
|
if (result.error) {
|
|
25
25
|
if (command === 'pro') {
|
|
26
|
-
// logger.warn(`[INSTALLATION_NEEDED] install dotenvx-${command} to use [dotenvx ${command}] commands 🏆`)
|
|
27
|
-
// logger.help('? see installation instructions [https://github.com/dotenvx/dotenvx-pro]')
|
|
28
|
-
|
|
29
26
|
const pro = `_______________________________________________________________
|
|
30
27
|
| |
|
|
31
|
-
|
|
|
28
|
+
| For small and medium businesses |
|
|
32
29
|
| |
|
|
33
30
|
| | | | | |
|
|
34
31
|
| __| | ___ | |_ ___ _ ____ ____ __ _ __ _ __ ___ |
|
|
@@ -37,9 +34,9 @@ function executeDynamic (program, command, rawArgs) {
|
|
|
37
34
|
| \\__,_|\\___/ \\__\\___|_| |_|\\_/ /_/\\_\\ | .__/|_| \\___/ |
|
|
38
35
|
| | | |
|
|
39
36
|
| |_| |
|
|
40
|
-
| ## learn more on
|
|
37
|
+
| ## learn more on dotenvx 🟨 |
|
|
41
38
|
| |
|
|
42
|
-
| >> https://
|
|
39
|
+
| >> https://dotenvx.com/pricing |
|
|
43
40
|
| |
|
|
44
41
|
| ## subscribe on github to be notified 📣 |
|
|
45
42
|
| |
|
|
@@ -50,6 +47,9 @@ function executeDynamic (program, command, rawArgs) {
|
|
|
50
47
|
|_____________________________________________________________|`
|
|
51
48
|
|
|
52
49
|
console.log(pro)
|
|
50
|
+
console.log('')
|
|
51
|
+
logger.warn(`[INSTALLATION_NEEDED] install dotenvx-${command} to use [dotenvx ${command}] commands 🏆`)
|
|
52
|
+
logger.help('? see installation instructions [https://github.com/dotenvx/dotenvx-pro]')
|
|
53
53
|
} else {
|
|
54
54
|
logger.info(`error: unknown command '${command}'`)
|
|
55
55
|
}
|
|
@@ -3,12 +3,21 @@ const isEncrypted = require('./isEncrypted')
|
|
|
3
3
|
const isPublicKey = require('./isPublicKey')
|
|
4
4
|
|
|
5
5
|
function isFullyEncrypted (src) {
|
|
6
|
-
const parsed = dotenvParse(src)
|
|
6
|
+
const parsed = dotenvParse(src, false, false, true) // collect all values
|
|
7
7
|
|
|
8
|
-
for (const [key,
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
for (const [key, values] of Object.entries(parsed)) {
|
|
9
|
+
// handle scenario where user mistakenly includes plaintext duplicate in .env:
|
|
10
|
+
//
|
|
11
|
+
// # .env
|
|
12
|
+
// HELLO="World"
|
|
13
|
+
// HELLO="enrypted:1234"
|
|
14
|
+
//
|
|
15
|
+
// key => [value1, ...]
|
|
16
|
+
for (const value of values) {
|
|
17
|
+
const result = isEncrypted(value) || isPublicKey(key, value)
|
|
18
|
+
if (!result) {
|
|
19
|
+
return false
|
|
20
|
+
}
|
|
12
21
|
}
|
|
13
22
|
}
|
|
14
23
|
|
|
@@ -93,11 +93,24 @@ class Precommit {
|
|
|
93
93
|
}
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
+
_isInGitRepo () {
|
|
97
|
+
try {
|
|
98
|
+
childProcess.execSync('git rev-parse --is-inside-work-tree', { stdio: 'ignore' })
|
|
99
|
+
return true
|
|
100
|
+
} catch {
|
|
101
|
+
return false
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
96
105
|
_isFileToBeCommitted (filePath) {
|
|
97
106
|
try {
|
|
107
|
+
if (!this._isInGitRepo()) {
|
|
108
|
+
// consider file to be committed if there is an error (not a git repo)
|
|
109
|
+
return true
|
|
110
|
+
}
|
|
111
|
+
|
|
98
112
|
const output = childProcess.execSync('git diff HEAD --name-only').toString()
|
|
99
113
|
const files = output.split('\n')
|
|
100
|
-
|
|
101
114
|
return files.includes(filePath)
|
|
102
115
|
} catch (error) {
|
|
103
116
|
// consider file to be committed if there is an error (not using git)
|