@dotenvx/dotenvx 1.1.0 โ 1.3.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 +19 -3
- package/README.md +12 -0
- package/package.json +6 -3
- package/src/cli/actions/encrypt.js +1 -1
- package/src/cli/actions/run.js +21 -6
- package/src/cli/dotenvx.js +10 -3
- package/src/lib/main.d.ts +3 -1
- package/src/lib/main.js +2 -2
- package/src/lib/services/encrypt.js +20 -8
- package/src/lib/services/ls.js +12 -15
package/CHANGELOG.md
CHANGED
|
@@ -2,19 +2,35 @@
|
|
|
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.3.0...main)
|
|
6
|
+
|
|
7
|
+
## 1.3.0
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
* encrypt specified keys with `--key` option - `dotenvx encrypt -k HELLO` ([#281](https://github.com/dotenvx/dotenvx/pull/281))
|
|
12
|
+
|
|
13
|
+
## 1.2.0
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
|
|
17
|
+
* handle nested `dotenvx` invocations - `dotenvx run -- dotenvx run -- env` ([#279](https://github.com/dotenvx/dotenvx/pull/279))
|
|
18
|
+
|
|
19
|
+
### Changed
|
|
20
|
+
|
|
21
|
+
* replace `glob` with faster approach ([#278](https://github.com/dotenvx/dotenvx/pull/278))
|
|
6
22
|
|
|
7
23
|
## 1.1.0
|
|
8
24
|
|
|
9
25
|
### Added
|
|
10
26
|
|
|
11
|
-
*
|
|
27
|
+
* add TypeScript type definitions ([#272](https://github.com/dotenvx/dotenvx/pull/272))
|
|
12
28
|
|
|
13
29
|
## 1.0.1
|
|
14
30
|
|
|
15
31
|
### Changed
|
|
16
32
|
|
|
17
|
-
* ๐
|
|
33
|
+
* ๐ fix expansion when preset on `process.env` and/or with `--overload` ([#271](https://github.com/dotenvx/dotenvx/pull/271))
|
|
18
34
|
|
|
19
35
|
## 1.0.0
|
|
20
36
|
|
package/README.md
CHANGED
|
@@ -1114,6 +1114,18 @@ More examples
|
|
|
1114
1114
|
โน run [DOTENV_PRIVATE_KEY_PRODUCTION='bff..bc4' dotenvx run -- yourcommand] to test decryption locally
|
|
1115
1115
|
```
|
|
1116
1116
|
|
|
1117
|
+
</details>
|
|
1118
|
+
* <details><summary>`encrypt -k`</summary><br>
|
|
1119
|
+
|
|
1120
|
+
Specify the key(s) to encrypt by passing `--key`.
|
|
1121
|
+
|
|
1122
|
+
```sh
|
|
1123
|
+
$ echo "HELLO=World\nHELLO2=Universe" > .env
|
|
1124
|
+
|
|
1125
|
+
$ dotenvx encrypt -k HELLO2
|
|
1126
|
+
โ encrypted (.env)
|
|
1127
|
+
```
|
|
1128
|
+
|
|
1117
1129
|
</details>
|
|
1118
1130
|
* <details><summary>`help`</summary><br>
|
|
1119
1131
|
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "1.
|
|
2
|
+
"version": "1.3.0",
|
|
3
3
|
"name": "@dotenvx/dotenvx",
|
|
4
4
|
"description": "a better dotenvโfrom the creator of `dotenv`",
|
|
5
5
|
"author": "@motdotla",
|
|
@@ -26,7 +26,8 @@
|
|
|
26
26
|
"test": "tap run --show-full-coverage",
|
|
27
27
|
"testshell": "bash shellspec",
|
|
28
28
|
"prerelease": "npm test && npm run testshell",
|
|
29
|
-
"release": "standard-version"
|
|
29
|
+
"release": "standard-version",
|
|
30
|
+
"postinstall": "patch-package"
|
|
30
31
|
},
|
|
31
32
|
"funding": "https://dotenvx.com",
|
|
32
33
|
"dependencies": {
|
|
@@ -39,12 +40,13 @@
|
|
|
39
40
|
"dotenv": "^16.4.5",
|
|
40
41
|
"eciesjs": "^0.4.6",
|
|
41
42
|
"execa": "^5.1.1",
|
|
42
|
-
"
|
|
43
|
+
"fdir": "^6.1.1",
|
|
43
44
|
"ignore": "^5.3.0",
|
|
44
45
|
"is-wsl": "^2.1.1",
|
|
45
46
|
"object-treeify": "1.1.33",
|
|
46
47
|
"open": "^8.4.2",
|
|
47
48
|
"ora": "^5.4.1",
|
|
49
|
+
"picomatch": "^3.0.1",
|
|
48
50
|
"semver": "^7.3.4",
|
|
49
51
|
"undici": "^5.28.3",
|
|
50
52
|
"which": "^4.0.0",
|
|
@@ -53,6 +55,7 @@
|
|
|
53
55
|
},
|
|
54
56
|
"devDependencies": {
|
|
55
57
|
"capture-console": "^1.0.2",
|
|
58
|
+
"patch-package": "^8.0.0",
|
|
56
59
|
"pkg": "^5.8.1",
|
|
57
60
|
"proxyquire": "^2.1.3",
|
|
58
61
|
"sinon": "^14.0.1",
|
|
@@ -16,7 +16,7 @@ async function encrypt () {
|
|
|
16
16
|
processedEnvFiles,
|
|
17
17
|
changedFilepaths,
|
|
18
18
|
unchangedFilepaths
|
|
19
|
-
} = main.encrypt(options.envFile)
|
|
19
|
+
} = main.encrypt(options.envFile, options.key)
|
|
20
20
|
|
|
21
21
|
for (const processedEnvFile of processedEnvFiles) {
|
|
22
22
|
logger.verbose(`encrypting ${processedEnvFile.envFilepath} (${processedEnvFile.filepath})`)
|
package/src/cli/actions/run.js
CHANGED
|
@@ -48,15 +48,31 @@ const executeCommand = async function (commandArgs, env) {
|
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
try {
|
|
51
|
-
|
|
51
|
+
// ensure the first command is expanded
|
|
52
52
|
try {
|
|
53
|
-
|
|
54
|
-
logger.debug(`expanding process command to [${
|
|
53
|
+
commandArgs[0] = path.resolve(which.sync(`${commandArgs[0]}`))
|
|
54
|
+
logger.debug(`expanding process command to [${commandArgs.join(' ')}]`)
|
|
55
55
|
} catch (e) {
|
|
56
|
-
logger.debug(`could not expand process command. using [${
|
|
56
|
+
logger.debug(`could not expand process command. using [${commandArgs.join(' ')}]`)
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
|
|
59
|
+
// expand any other commands that follow a --
|
|
60
|
+
let expandNext = false
|
|
61
|
+
for (let i = 0; i < commandArgs.length; i++) {
|
|
62
|
+
if (commandArgs[i] === '--') {
|
|
63
|
+
expandNext = true
|
|
64
|
+
} else if (expandNext) {
|
|
65
|
+
try {
|
|
66
|
+
commandArgs[i] = path.resolve(which.sync(`${commandArgs[i]}`))
|
|
67
|
+
logger.debug(`expanding process command to [${commandArgs.join(' ')}]`)
|
|
68
|
+
} catch (e) {
|
|
69
|
+
logger.debug(`could not expand process command. using [${commandArgs.join(' ')}]`)
|
|
70
|
+
}
|
|
71
|
+
expandNext = false
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
commandProcess = execa(commandArgs[0], commandArgs.slice(1), {
|
|
60
76
|
stdio: 'inherit',
|
|
61
77
|
env: { ...process.env, ...env }
|
|
62
78
|
})
|
|
@@ -197,7 +213,6 @@ async function run () {
|
|
|
197
213
|
logger.error(' or try: [dotenvx run -- npm run dev]')
|
|
198
214
|
process.exit(1)
|
|
199
215
|
} else {
|
|
200
|
-
// const commandArgs = process.argv.slice(commandIndex + 1)
|
|
201
216
|
await executeCommand(commandArgs, process.env)
|
|
202
217
|
}
|
|
203
218
|
}
|
package/src/cli/dotenvx.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const fs = require('fs')
|
|
4
4
|
const path = require('path')
|
|
5
|
+
const { execSync } = require('child_process')
|
|
5
6
|
const UpdateNotice = require('./../lib/helpers/updateNotice')
|
|
6
7
|
const { Command } = require('commander')
|
|
7
8
|
const program = new Command()
|
|
@@ -93,15 +94,21 @@ const encryptAction = require('./actions/encrypt')
|
|
|
93
94
|
program.command('encrypt')
|
|
94
95
|
.description('convert .env file(s) to encrypted .env file(s)')
|
|
95
96
|
.option('-f, --env-file <paths...>', 'path(s) to your env file(s)')
|
|
97
|
+
.option('-k, --key <keys...>', 'keys(s) to encrypt (default: all keys in file)')
|
|
96
98
|
.action(encryptAction)
|
|
97
99
|
|
|
98
100
|
// dotenvx pro
|
|
99
101
|
program.command('pro')
|
|
100
102
|
.description('๐ pro')
|
|
101
103
|
.action(function (...args) {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
104
|
+
try {
|
|
105
|
+
// execute `dotenvx-pro` if available
|
|
106
|
+
execSync('dotenvx-pro', { stdio: ['inherit', 'inherit', 'ignore'] })
|
|
107
|
+
} catch (_error) {
|
|
108
|
+
const pro = fs.readFileSync(path.join(__dirname, './pro.txt'), 'utf8')
|
|
109
|
+
|
|
110
|
+
console.log(pro)
|
|
111
|
+
}
|
|
105
112
|
})
|
|
106
113
|
|
|
107
114
|
// // dotenvx ent
|
package/src/lib/main.d.ts
CHANGED
|
@@ -144,8 +144,9 @@ export type EncryptOutput = {
|
|
|
144
144
|
*
|
|
145
145
|
* @see https://dotenvx.com/docs
|
|
146
146
|
* @param envFile - path to the .env file
|
|
147
|
+
* @param key - keys(s) to encrypt (default: all keys in .env file)
|
|
147
148
|
*/
|
|
148
|
-
export function encrypt(envFile: string): EncryptOutput;
|
|
149
|
+
export function encrypt(envFile: string, key: string): EncryptOutput;
|
|
149
150
|
|
|
150
151
|
export type VaultEncryptOutput = {
|
|
151
152
|
dotenvKeys: Record<string, string>;
|
|
@@ -157,6 +158,7 @@ export type VaultEncryptOutput = {
|
|
|
157
158
|
existingVaults: string[];
|
|
158
159
|
addedDotenvFilenames: string[];
|
|
159
160
|
envFile: string | string[];
|
|
161
|
+
key: string | string[];
|
|
160
162
|
};
|
|
161
163
|
|
|
162
164
|
/**
|
package/src/lib/main.js
CHANGED
|
@@ -194,8 +194,8 @@ const set = function (key, value, envFile, encrypt) {
|
|
|
194
194
|
}
|
|
195
195
|
|
|
196
196
|
/** @type {import('./main').encrypt} */
|
|
197
|
-
const encrypt = function (envFile) {
|
|
198
|
-
return new Encrypt(envFile).run()
|
|
197
|
+
const encrypt = function (envFile, key) {
|
|
198
|
+
return new Encrypt(envFile, key).run()
|
|
199
199
|
}
|
|
200
200
|
|
|
201
201
|
/** @type {import('./main').status} */
|
|
@@ -11,8 +11,9 @@ const replace = require('./../helpers/replace')
|
|
|
11
11
|
const ENCODING = 'utf8'
|
|
12
12
|
|
|
13
13
|
class Encrypt {
|
|
14
|
-
constructor (envFile = '.env') {
|
|
14
|
+
constructor (envFile = '.env', key = []) {
|
|
15
15
|
this.envFile = envFile
|
|
16
|
+
this.key = key
|
|
16
17
|
this.processedEnvFiles = []
|
|
17
18
|
this.changedFilepaths = new Set()
|
|
18
19
|
this.unchangedFilepaths = new Set()
|
|
@@ -20,6 +21,7 @@ class Encrypt {
|
|
|
20
21
|
|
|
21
22
|
run () {
|
|
22
23
|
const envFilepaths = this._envFilepaths()
|
|
24
|
+
const keys = this._keys()
|
|
23
25
|
for (const envFilepath of envFilepaths) {
|
|
24
26
|
const filepath = path.resolve(envFilepath)
|
|
25
27
|
|
|
@@ -52,15 +54,17 @@ class Encrypt {
|
|
|
52
54
|
// iterate over all non-encrypted values and encrypt them
|
|
53
55
|
const parsed = dotenv.parse(src)
|
|
54
56
|
for (const [key, value] of Object.entries(parsed)) {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
57
|
+
if (keys.length < 1 || keys.includes(key)) { // optionally control which key to encrypt
|
|
58
|
+
const encrypted = isEncrypted(key, value)
|
|
59
|
+
if (!encrypted) {
|
|
60
|
+
row.keys.push(key) // track key(s)
|
|
58
61
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
+
const encryptedValue = encryptValue(value, publicKey)
|
|
63
|
+
// once newSrc is built write it out
|
|
64
|
+
src = replace(src, key, encryptedValue)
|
|
62
65
|
|
|
63
|
-
|
|
66
|
+
row.changed = true // track change
|
|
67
|
+
}
|
|
64
68
|
}
|
|
65
69
|
}
|
|
66
70
|
|
|
@@ -99,6 +103,14 @@ class Encrypt {
|
|
|
99
103
|
|
|
100
104
|
return this.envFile
|
|
101
105
|
}
|
|
106
|
+
|
|
107
|
+
_keys () {
|
|
108
|
+
if (!Array.isArray(this.key)) {
|
|
109
|
+
return [this.key]
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return this.key
|
|
113
|
+
}
|
|
102
114
|
}
|
|
103
115
|
|
|
104
116
|
module.exports = Encrypt
|
package/src/lib/services/ls.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
const { fdir: Fdir } = require('fdir')
|
|
1
2
|
const path = require('path')
|
|
2
|
-
const
|
|
3
|
+
const picomatch = require('picomatch')
|
|
3
4
|
|
|
4
5
|
class Ls {
|
|
5
6
|
constructor (directory = './', envFile = '.env*') {
|
|
@@ -14,27 +15,23 @@ class Ls {
|
|
|
14
15
|
}
|
|
15
16
|
|
|
16
17
|
_filepaths () {
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
const ignoreMatchers = this.ignore.map(pattern => picomatch(pattern))
|
|
19
|
+
const pathMatchers = this._patterns().map(pattern => picomatch(pattern))
|
|
20
|
+
|
|
21
|
+
const api = new Fdir()
|
|
22
|
+
.withRelativePaths()
|
|
23
|
+
.exclude((dir, path) => ignoreMatchers.some(matcher => matcher(path)))
|
|
24
|
+
.filter((path) => pathMatchers.some(matcher => matcher(path)))
|
|
21
25
|
|
|
22
|
-
|
|
23
|
-
return globSync(patterns, options)
|
|
26
|
+
return api.crawl(this.cwd).sync()
|
|
24
27
|
}
|
|
25
28
|
|
|
26
29
|
_patterns () {
|
|
27
30
|
if (!Array.isArray(this.envFile)) {
|
|
28
|
-
return `**/${this.envFile}`
|
|
31
|
+
return [`**/${this.envFile}`]
|
|
29
32
|
}
|
|
30
33
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
for (let i = 0; i < this.envFile.length; i++) {
|
|
34
|
-
const part = this.envFile[i]
|
|
35
|
-
out.push(`**/${part}`)
|
|
36
|
-
}
|
|
37
|
-
return out
|
|
34
|
+
return this.envFile.map(part => `**/${part}`)
|
|
38
35
|
}
|
|
39
36
|
}
|
|
40
37
|
|