@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 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.33.0...main)
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('@dotenvx/dotenvx/config') if you're using esm
22
+ // or import '@dotenvx/dotenvx/config' // for esm
23
23
 
24
24
  console.log(`Hello ${process.env.HELLO}`)
25
25
  ```
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.33.0",
2
+ "version": "1.35.0",
3
3
  "name": "@dotenvx/dotenvx",
4
4
  "description": "a better dotenv–from the creator of `dotenv`",
5
5
  "author": "@motdotla",
@@ -3,15 +3,19 @@ const path = require('path')
3
3
 
4
4
  const HOOK_SCRIPT = `#!/bin/sh
5
5
 
6
- if ! command -v dotenvx 2>&1 >/dev/null
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
- // envKeysFile
173
- const envKeysFile = options.envKeysFile
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
- // envs
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
- return new Sets(key, value, envs, encrypt, envKeysFile).run()
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,