@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 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.1.0...main)
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
- * Add TypeScript type definitions ([#272](https://github.com/dotenvx/dotenvx/pull/272))
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
- * ๐Ÿž Fix expansion when preset on `process.env` and/or with `--overload` ([#271](https://github.com/dotenvx/dotenvx/pull/271))
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.1.0",
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
- "glob": "^10.3.10",
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})`)
@@ -48,15 +48,31 @@ const executeCommand = async function (commandArgs, env) {
48
48
  }
49
49
 
50
50
  try {
51
- let systemCommandPath = commandArgs[0]
51
+ // ensure the first command is expanded
52
52
  try {
53
- systemCommandPath = which.sync(`${commandArgs[0]}`)
54
- logger.debug(`expanding process command to [${systemCommandPath} ${commandArgs.slice(1).join(' ')}]`)
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 [${systemCommandPath} ${commandArgs.slice(1).join(' ')}]`)
56
+ logger.debug(`could not expand process command. using [${commandArgs.join(' ')}]`)
57
57
  }
58
58
 
59
- commandProcess = execa(systemCommandPath, commandArgs.slice(1), {
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
  }
@@ -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
- const pro = fs.readFileSync(path.join(__dirname, './pro.txt'), 'utf8')
103
-
104
- console.log(pro)
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
- const encrypted = isEncrypted(key, value)
56
- if (!encrypted) {
57
- row.keys.push(key) // track key(s)
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
- const encryptedValue = encryptValue(value, publicKey)
60
- // once newSrc is built write it out
61
- src = replace(src, key, encryptedValue)
62
+ const encryptedValue = encryptValue(value, publicKey)
63
+ // once newSrc is built write it out
64
+ src = replace(src, key, encryptedValue)
62
65
 
63
- row.changed = true // track change
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
@@ -1,5 +1,6 @@
1
+ const { fdir: Fdir } = require('fdir')
1
2
  const path = require('path')
2
- const globSync = require('glob').globSync
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 options = {
18
- ignore: this.ignore,
19
- cwd: this.cwd // context dirctory for globSync
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
- const patterns = this._patterns()
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
- const out = []
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