@dotenvx/dotenvx 1.33.0 → 1.35.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 +16 -1
- package/README.md +1 -1
- package/package.json +1 -1
- package/src/lib/helpers/installPrecommitHook.js +7 -3
- package/src/lib/main.d.ts +7 -0
- package/src/lib/main.js +114 -5
package/CHANGELOG.md
CHANGED
|
@@ -2,7 +2,22 @@
|
|
|
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.35.0...main)
|
|
6
|
+
|
|
7
|
+
## [1.35.0](https://github.com/dotenvx/dotenvx/compare/v1.34.0...v1.35.0)
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
* `npx dotenvx precommit` support as a convenience ([#523](https://github.com/dotenvx/dotenvx/pull/523))
|
|
12
|
+
* `main.get` method ([#524](https://github.com/dotenvx/dotenvx/pull/524))
|
|
13
|
+
|
|
14
|
+
The addition of `main.get` facilitates what we term Decryption at Access, a concept explored in greater detail in our [whitepaper](https://dotenvx.com/dotenvx.pdf).
|
|
15
|
+
|
|
16
|
+
## [1.34.0](https://github.com/dotenvx/dotenvx/compare/v1.33.0...v1.34.0)
|
|
17
|
+
|
|
18
|
+
### Added
|
|
19
|
+
|
|
20
|
+
* `main.set` method now writes to files ([#517](https://github.com/dotenvx/dotenvx/pull/517))
|
|
6
21
|
|
|
7
22
|
## [1.33.0](https://github.com/dotenvx/dotenvx/compare/v1.32.1...v1.33.0)
|
|
8
23
|
|
package/README.md
CHANGED
|
@@ -19,7 +19,7 @@ npm install @dotenvx/dotenvx --save
|
|
|
19
19
|
```js
|
|
20
20
|
// index.js
|
|
21
21
|
require('@dotenvx/dotenvx').config()
|
|
22
|
-
// or import
|
|
22
|
+
// or import '@dotenvx/dotenvx/config' // for esm
|
|
23
23
|
|
|
24
24
|
console.log(`Hello ${process.env.HELLO}`)
|
|
25
25
|
```
|
package/package.json
CHANGED
|
@@ -3,15 +3,19 @@ const path = require('path')
|
|
|
3
3
|
|
|
4
4
|
const HOOK_SCRIPT = `#!/bin/sh
|
|
5
5
|
|
|
6
|
-
if
|
|
6
|
+
if command -v dotenvx 2>&1 >/dev/null
|
|
7
7
|
then
|
|
8
|
+
dotenvx ext precommit
|
|
9
|
+
elif npx dotenvx -V >/dev/null 2>&1
|
|
10
|
+
then
|
|
11
|
+
npx dotenvx ext precommit
|
|
12
|
+
else
|
|
8
13
|
echo "[dotenvx][precommit] 'dotenvx' command not found"
|
|
9
14
|
echo "[dotenvx][precommit] ? install it with [curl -fsS https://dotenvx.sh | sh]"
|
|
10
15
|
echo "[dotenvx][precommit] ? other install options [https://dotenvx.com/docs/install]"
|
|
11
16
|
exit 1
|
|
12
17
|
fi
|
|
13
|
-
|
|
14
|
-
dotenvx ext precommit`
|
|
18
|
+
`
|
|
15
19
|
|
|
16
20
|
class InstallPrecommitHook {
|
|
17
21
|
constructor () {
|
package/src/lib/main.d.ts
CHANGED
|
@@ -194,6 +194,13 @@ export interface SetOptions {
|
|
|
194
194
|
* Set a .env convention (available conventions: 'nextjs')
|
|
195
195
|
*/
|
|
196
196
|
convention?: string;
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Specify whether the variable has to be encrypted
|
|
200
|
+
* @default true
|
|
201
|
+
* @example require('@dotenvx/dotenvx').config(key, value, { encrypt: false } })
|
|
202
|
+
*/
|
|
203
|
+
encrypt?: boolean;
|
|
197
204
|
}
|
|
198
205
|
|
|
199
206
|
export type SetOutput = {
|
package/src/lib/main.js
CHANGED
|
@@ -9,12 +9,15 @@ const { getColor, bold } = require('./../shared/colors')
|
|
|
9
9
|
const Ls = require('./services/ls')
|
|
10
10
|
const Run = require('./services/run')
|
|
11
11
|
const Sets = require('./services/sets')
|
|
12
|
+
const Get = require('./services/get')
|
|
12
13
|
const Keypair = require('./services/keypair')
|
|
13
14
|
const Genexample = require('./services/genexample')
|
|
14
15
|
|
|
15
16
|
// helpers
|
|
16
17
|
const buildEnvs = require('./helpers/buildEnvs')
|
|
17
18
|
const Parse = require('./helpers/parse')
|
|
19
|
+
const fsx = require('./helpers/fsx')
|
|
20
|
+
const isIgnoringDotenvKeys = require('./helpers/isIgnoringDotenvKeys')
|
|
18
21
|
|
|
19
22
|
/** @type {import('./main').config} */
|
|
20
23
|
const config = function (options = {}) {
|
|
@@ -55,7 +58,6 @@ const config = function (options = {}) {
|
|
|
55
58
|
let lastError
|
|
56
59
|
/** @type {Record<string, string>} */
|
|
57
60
|
const parsedAll = {}
|
|
58
|
-
|
|
59
61
|
for (const processedEnv of processedEnvs) {
|
|
60
62
|
if (processedEnv.type === 'envVaultFile') {
|
|
61
63
|
logger.verbose(`loading env from encrypted ${processedEnv.filepath} (${path.resolve(processedEnv.filepath)})`)
|
|
@@ -169,13 +171,119 @@ const set = function (key, value, options = {}) {
|
|
|
169
171
|
encrypt = false
|
|
170
172
|
}
|
|
171
173
|
|
|
172
|
-
|
|
173
|
-
const
|
|
174
|
+
const envs = buildEnvs(options)
|
|
175
|
+
const envKeysFilepath = options.envKeysFile
|
|
176
|
+
|
|
177
|
+
const {
|
|
178
|
+
processedEnvs,
|
|
179
|
+
changedFilepaths,
|
|
180
|
+
unchangedFilepaths
|
|
181
|
+
} = new Sets(key, value, envs, encrypt, envKeysFilepath).run()
|
|
182
|
+
|
|
183
|
+
let withEncryption = ''
|
|
184
|
+
|
|
185
|
+
if (encrypt) {
|
|
186
|
+
withEncryption = ' with encryption'
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
for (const processedEnv of processedEnvs) {
|
|
190
|
+
logger.verbose(`setting for ${processedEnv.envFilepath}`)
|
|
191
|
+
|
|
192
|
+
if (processedEnv.error) {
|
|
193
|
+
if (processedEnv.error.code === 'MISSING_ENV_FILE') {
|
|
194
|
+
logger.warn(processedEnv.error.message)
|
|
195
|
+
logger.help(`? add one with [echo "HELLO=World" > ${processedEnv.envFilepath}] and re-run [dotenvx set]`)
|
|
196
|
+
} else {
|
|
197
|
+
logger.warn(processedEnv.error.message)
|
|
198
|
+
if (processedEnv.error.help) {
|
|
199
|
+
logger.help(processedEnv.error.help)
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
} else {
|
|
203
|
+
fsx.writeFileX(processedEnv.filepath, processedEnv.envSrc)
|
|
204
|
+
|
|
205
|
+
logger.verbose(`${processedEnv.key} set${withEncryption} (${processedEnv.envFilepath})`)
|
|
206
|
+
logger.debug(`${processedEnv.key} set${withEncryption} to ${processedEnv.value} (${processedEnv.envFilepath})`)
|
|
207
|
+
}
|
|
208
|
+
}
|
|
174
209
|
|
|
175
|
-
|
|
210
|
+
if (changedFilepaths.length > 0) {
|
|
211
|
+
logger.success(`✔ set ${key}${withEncryption} (${changedFilepaths.join(',')})`)
|
|
212
|
+
} else if (unchangedFilepaths.length > 0) {
|
|
213
|
+
logger.info(`no changes (${unchangedFilepaths})`)
|
|
214
|
+
} else {
|
|
215
|
+
// do nothing
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
for (const processedEnv of processedEnvs) {
|
|
219
|
+
if (processedEnv.privateKeyAdded) {
|
|
220
|
+
logger.success(`✔ key added to ${processedEnv.envKeysFilepath} (${processedEnv.privateKeyName})`)
|
|
221
|
+
|
|
222
|
+
if (!isIgnoringDotenvKeys()) {
|
|
223
|
+
logger.help('⮕ next run [dotenvx ext gitignore --pattern .env.keys] to gitignore .env.keys')
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
logger.help(`⮕ next run [${processedEnv.privateKeyName}='${processedEnv.privateKey}' dotenvx get ${key}] to test decryption locally`)
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
return {
|
|
231
|
+
processedEnvs,
|
|
232
|
+
changedFilepaths,
|
|
233
|
+
unchangedFilepaths
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/* @type {import('./main').get} */
|
|
238
|
+
const get = function (key, options = {}) {
|
|
176
239
|
const envs = buildEnvs(options)
|
|
177
240
|
|
|
178
|
-
|
|
241
|
+
// ignore
|
|
242
|
+
const ignore = options.ignore || []
|
|
243
|
+
|
|
244
|
+
const { parsed, errors } = new Get(key, envs, options.overload, process.env.DOTENV_KEY, options.all, options.envKeysFile).run()
|
|
245
|
+
|
|
246
|
+
for (const error of errors || []) {
|
|
247
|
+
if (options.strict) throw error // throw immediately if strict
|
|
248
|
+
|
|
249
|
+
if (ignore.includes(error.code)) {
|
|
250
|
+
continue // ignore error
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
console.error(error.message)
|
|
254
|
+
if (error.help) {
|
|
255
|
+
console.error(error.help)
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
if (key) {
|
|
260
|
+
const single = parsed[key]
|
|
261
|
+
if (single === undefined) {
|
|
262
|
+
return undefined
|
|
263
|
+
} else {
|
|
264
|
+
return single
|
|
265
|
+
}
|
|
266
|
+
} else {
|
|
267
|
+
if (options.format === 'eval') {
|
|
268
|
+
let inline = ''
|
|
269
|
+
for (const [key, value] of Object.entries(parsed)) {
|
|
270
|
+
inline += `${key}=${escape(value)}\n`
|
|
271
|
+
}
|
|
272
|
+
inline = inline.trim()
|
|
273
|
+
|
|
274
|
+
return inline
|
|
275
|
+
} else if (options.format === 'shell') {
|
|
276
|
+
let inline = ''
|
|
277
|
+
for (const [key, value] of Object.entries(parsed)) {
|
|
278
|
+
inline += `${key}=${value} `
|
|
279
|
+
}
|
|
280
|
+
inline = inline.trim()
|
|
281
|
+
|
|
282
|
+
return inline
|
|
283
|
+
} else {
|
|
284
|
+
return parsed
|
|
285
|
+
}
|
|
286
|
+
}
|
|
179
287
|
}
|
|
180
288
|
|
|
181
289
|
/** @type {import('./main').ls} */
|
|
@@ -204,6 +312,7 @@ module.exports = {
|
|
|
204
312
|
parse,
|
|
205
313
|
// actions related
|
|
206
314
|
set,
|
|
315
|
+
get,
|
|
207
316
|
ls,
|
|
208
317
|
keypair,
|
|
209
318
|
genexample,
|