@dotenvx/dotenvx 1.25.0 → 1.25.2

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,23 @@
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.25.0...main)
5
+ [Unreleased](https://github.com/dotenvx/dotenvx/compare/v1.25.2...main)
6
+
7
+ ## [1.25.2](https://github.com/dotenvx/dotenvx/compare/v1.25.1...v1.25.2)
8
+
9
+ ### Added
10
+
11
+ * for binaries add pre-build step using esbuild ([#471](https://github.com/dotenvx/dotenvx/pull/471))
12
+
13
+ ### Removed
14
+
15
+ * remove types for functions that were removed a while back ([2aa660](https://github.com/dotenvx/dotenvx/commit/2aa660695757143f65751a201115f074b81942a8))
16
+
17
+ ## [1.25.1](https://github.com/dotenvx/dotenvx/compare/v1.25.0...v1.25.1)
18
+
19
+ ### Changed
20
+
21
+ * improve helpful error messaging around decryption failures by specifying specific key and private key name ([#463](https://github.com/dotenvx/dotenvx/pull/463))
6
22
 
7
23
  ## [1.25.0](https://github.com/dotenvx/dotenvx/compare/v1.24.5...v1.25.0)
8
24
 
package/README.md CHANGED
@@ -1632,110 +1632,6 @@ More examples
1632
1632
 
1633
1633
  </details>
1634
1634
 
1635
- ### config() 📦
1636
-
1637
- * <details><summary>`config()`</summary><br>
1638
-
1639
- Use directly in node.js code.
1640
-
1641
- ```ini
1642
- # .env
1643
- HELLO="World"
1644
- ```
1645
-
1646
- ```js
1647
- // index.js
1648
- require('@dotenvx/dotenvx').config()
1649
-
1650
- console.log(`Hello ${process.env.HELLO}`)
1651
- ```
1652
-
1653
- ```sh
1654
- $ node index.js
1655
- [dotenvx@1.24.5] injecting env (1) from .env
1656
- Hello World
1657
- ```
1658
-
1659
- </details>
1660
- * <details><summary>`config(path: ['.env.local', '.env'])` - multiple files</summary><br>
1661
-
1662
- Specify path(s) to multiple .env files.
1663
-
1664
- ```ini
1665
- # .env.local
1666
- HELLO="Me"
1667
- ```
1668
-
1669
- ```ini
1670
- # .env
1671
- HELLO="World"
1672
- ```
1673
-
1674
- ```js
1675
- // index.js
1676
- require('@dotenvx/dotenvx').config({path: ['.env.local', '.env']})
1677
-
1678
- console.log(`Hello ${process.env.HELLO}`)
1679
- ```
1680
-
1681
- ```sh
1682
- $ node index.js
1683
- [dotenvx@1.24.5] injecting env (1) from .env.local, .env
1684
- Hello Me
1685
- ```
1686
-
1687
- </details>
1688
- * <details><summary>`config(overload: true)` - overload</summary><br>
1689
-
1690
- User `overload` to overwrite the prior set value.
1691
-
1692
- ```ini
1693
- # .env.local
1694
- HELLO="Me"
1695
- ```
1696
-
1697
- ```ini
1698
- # .env
1699
- HELLO="World"
1700
- ```
1701
-
1702
- ```js
1703
- // index.js
1704
- require('@dotenvx/dotenvx').config({path: ['.env.local', '.env'], overload: true})
1705
-
1706
- console.log(`Hello ${process.env.HELLO}`)
1707
- ```
1708
-
1709
- ```sh
1710
- $ node index.js
1711
- [dotenvx@1.24.5] injecting env (1) from .env.local, .env
1712
- Hello World
1713
- ```
1714
-
1715
- </details>
1716
- * <details><summary>`config(strict: true)` - strict</summary><br>
1717
-
1718
- Use `strict` to throw if an error is encountered - like a missing .env file.
1719
-
1720
- ```ini
1721
- # .env
1722
- HELLO="World"
1723
- ```
1724
-
1725
- ```js
1726
- // index.js
1727
- require('@dotenvx/dotenvx').config({path: ['.env.missing', '.env'], strict: true})
1728
-
1729
- console.log(`Hello ${process.env.HELLO}`)
1730
- ```
1731
-
1732
- ```sh
1733
- $ node index.js
1734
- Error: [MISSING_ENV_FILE] missing .env.missing file (/path/to/.env.missing)
1735
- ```
1736
-
1737
- </details>
1738
-
1739
1635
  ### Extensions 🔌
1740
1636
 
1741
1637
  * <details><summary>`ext genexample`</summary><br>
@@ -1860,6 +1756,112 @@ More examples
1860
1756
 
1861
1757
  </details>
1862
1758
 
1759
+ ### config() 📦
1760
+
1761
+ * <details><summary>`config()`</summary><br>
1762
+
1763
+ Use directly in node.js code.
1764
+
1765
+ ```ini
1766
+ # .env
1767
+ HELLO="World"
1768
+ ```
1769
+
1770
+ ```js
1771
+ // index.js
1772
+ require('@dotenvx/dotenvx').config()
1773
+
1774
+ console.log(`Hello ${process.env.HELLO}`)
1775
+ ```
1776
+
1777
+ ```sh
1778
+ $ node index.js
1779
+ [dotenvx@1.24.5] injecting env (1) from .env
1780
+ Hello World
1781
+ ```
1782
+
1783
+ </details>
1784
+ * <details><summary>`config(path: ['.env.local', '.env'])` - multiple files</summary><br>
1785
+
1786
+ Specify path(s) to multiple .env files.
1787
+
1788
+ ```ini
1789
+ # .env.local
1790
+ HELLO="Me"
1791
+ ```
1792
+
1793
+ ```ini
1794
+ # .env
1795
+ HELLO="World"
1796
+ ```
1797
+
1798
+ ```js
1799
+ // index.js
1800
+ require('@dotenvx/dotenvx').config({path: ['.env.local', '.env']})
1801
+
1802
+ console.log(`Hello ${process.env.HELLO}`)
1803
+ ```
1804
+
1805
+ ```sh
1806
+ $ node index.js
1807
+ [dotenvx@1.24.5] injecting env (1) from .env.local, .env
1808
+ Hello Me
1809
+ ```
1810
+
1811
+ </details>
1812
+ * <details><summary>`config(overload: true)` - overload</summary><br>
1813
+
1814
+ User `overload` to overwrite the prior set value.
1815
+
1816
+ ```ini
1817
+ # .env.local
1818
+ HELLO="Me"
1819
+ ```
1820
+
1821
+ ```ini
1822
+ # .env
1823
+ HELLO="World"
1824
+ ```
1825
+
1826
+ ```js
1827
+ // index.js
1828
+ require('@dotenvx/dotenvx').config({path: ['.env.local', '.env'], overload: true})
1829
+
1830
+ console.log(`Hello ${process.env.HELLO}`)
1831
+ ```
1832
+
1833
+ ```sh
1834
+ $ node index.js
1835
+ [dotenvx@1.24.5] injecting env (1) from .env.local, .env
1836
+ Hello World
1837
+ ```
1838
+
1839
+ </details>
1840
+ * <details><summary>`config(strict: true)` - strict</summary><br>
1841
+
1842
+ Use `strict` to throw if an error is encountered - like a missing .env file.
1843
+
1844
+ ```ini
1845
+ # .env
1846
+ HELLO="World"
1847
+ ```
1848
+
1849
+ ```js
1850
+ // index.js
1851
+ require('@dotenvx/dotenvx').config({path: ['.env.missing', '.env'], strict: true})
1852
+
1853
+ console.log(`Hello ${process.env.HELLO}`)
1854
+ ```
1855
+
1856
+ ```sh
1857
+ $ node index.js
1858
+ Error: [MISSING_ENV_FILE] missing .env.missing file (/path/to/.env.missing)
1859
+ ```
1860
+
1861
+ </details>
1862
+
1863
+
1864
+
1863
1865
  &nbsp;
1864
1866
 
1865
1867
  ## Guides
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.25.0",
2
+ "version": "1.25.2",
3
3
  "name": "@dotenvx/dotenvx",
4
4
  "description": "a better dotenv–from the creator of `dotenv`",
5
5
  "author": "@motdotla",
@@ -48,6 +48,7 @@
48
48
  "devDependencies": {
49
49
  "@yao-pkg/pkg": "^5.14.2",
50
50
  "capture-console": "^1.0.2",
51
+ "esbuild": "^0.24.0",
51
52
  "proxyquire": "^2.1.3",
52
53
  "sinon": "^14.0.1",
53
54
  "standard": "^17.1.0",
@@ -1,10 +1,10 @@
1
1
  const { decrypt } = require('eciesjs')
2
2
 
3
- const truncate = require('./truncate')
3
+ const Errors = require('./errors')
4
4
 
5
5
  const PREFIX = 'encrypted:'
6
6
 
7
- function decryptValue (value, privateKey) {
7
+ function decryptKeyValue (key, value, privateKeyName, privateKey) {
8
8
  let decryptedValue
9
9
  let decryptionError
10
10
 
@@ -14,12 +14,11 @@ function decryptValue (value, privateKey) {
14
14
 
15
15
  privateKey = privateKey || ''
16
16
  if (privateKey.length <= 0) {
17
- decryptionError = new Error('private key missing or blank')
18
- decryptionError.code = 'DECRYPTION_FAILED'
17
+ decryptionError = new Errors({ key, privateKeyName, privateKey }).missingPrivateKey()
19
18
  } else {
20
19
  const privateKeys = privateKey.split(',')
21
- for (const key of privateKeys) {
22
- const secret = Buffer.from(key, 'hex')
20
+ for (const privKey of privateKeys) {
21
+ const secret = Buffer.from(privKey, 'hex')
23
22
  const encoded = value.substring(PREFIX.length)
24
23
  const ciphertext = Buffer.from(encoded, 'base64')
25
24
 
@@ -29,16 +28,14 @@ function decryptValue (value, privateKey) {
29
28
  break
30
29
  } catch (e) {
31
30
  if (e.message === 'Invalid private key') {
32
- decryptionError = new Error(`private key [${truncate(privateKey)}] looks invalid`)
31
+ decryptionError = new Errors({ key, privateKeyName, privateKey }).invalidPrivateKey()
33
32
  } else if (e.message === 'Unsupported state or unable to authenticate data') {
34
- decryptionError = new Error(`private key [${truncate(privateKey)}] looks wrong`)
33
+ decryptionError = new Errors({ key, privateKeyName, privateKey }).looksWrongPrivateKey()
35
34
  } else if (e.message === 'Point of length 65 was invalid. Expected 33 compressed bytes or 65 uncompressed bytes') {
36
- decryptionError = new Error('encrypted data looks malformed')
35
+ decryptionError = new Errors({ key, privateKeyName, privateKey }).malformedEncryptedData()
37
36
  } else {
38
- decryptionError = new Error(`${e.message}`)
37
+ decryptionError = new Errors({ key, privateKeyName, privateKey, message: e.message }).decryptionFailed()
39
38
  }
40
-
41
- decryptionError.code = 'DECRYPTION_FAILED'
42
39
  }
43
40
  }
44
41
  }
@@ -50,4 +47,4 @@ function decryptValue (value, privateKey) {
50
47
  return decryptedValue
51
48
  }
52
49
 
53
- module.exports = decryptValue
50
+ module.exports = decryptKeyValue
@@ -1,9 +1,15 @@
1
+ const truncate = require('./truncate')
2
+
1
3
  class Errors {
2
4
  constructor (options = {}) {
3
5
  this.filepath = options.filepath
4
6
  this.envFilepath = options.envFilepath
5
7
 
6
8
  this.key = options.key
9
+ this.privateKey = options.privateKey
10
+ this.privateKeyName = options.privateKeyName
11
+
12
+ this.message = options.message
7
13
  }
8
14
 
9
15
  missingEnvFile () {
@@ -25,6 +31,59 @@ class Errors {
25
31
  e.code = code
26
32
  return e
27
33
  }
34
+
35
+ missingPrivateKey () {
36
+ const code = 'MISSING_PRIVATE_KEY'
37
+ const message = `[${code}] could not decrypt ${this.key} using private key '${this.privateKeyName}=${truncate(this.privateKey)}'`
38
+ const help = `[${code}] https://github.com/dotenvx/dotenvx/issues/464`
39
+
40
+ const e = new Error(message)
41
+ e.code = code
42
+ e.help = help
43
+ return e
44
+ }
45
+
46
+ invalidPrivateKey () {
47
+ const code = 'INVALID_PRIVATE_KEY'
48
+ const message = `[${code}] could not decrypt ${this.key} using private key '${this.privateKeyName}=${truncate(this.privateKey)}'`
49
+ const help = `[${code}] https://github.com/dotenvx/dotenvx/issues/465`
50
+
51
+ const e = new Error(message)
52
+ e.code = code
53
+ e.help = help
54
+ return e
55
+ }
56
+
57
+ looksWrongPrivateKey () {
58
+ const code = 'WRONG_PRIVATE_KEY'
59
+ const message = `[${code}] could not decrypt ${this.key} using private key '${this.privateKeyName}=${truncate(this.privateKey)}'`
60
+ const help = `[${code}] https://github.com/dotenvx/dotenvx/issues/466`
61
+
62
+ const e = new Error(message)
63
+ e.code = code
64
+ e.help = help
65
+ return e
66
+ }
67
+
68
+ malformedEncryptedData () {
69
+ const code = 'MALFORMED_ENCRYPTED_DATA'
70
+ const message = `[${code}] could not decrypt ${this.key} because encrypted data appears malformed`
71
+ const help = `[${code}] https://github.com/dotenvx/dotenvx/issues/467`
72
+
73
+ const e = new Error(message)
74
+ e.code = code
75
+ e.help = help
76
+ return e
77
+ }
78
+
79
+ decryptionFailed () {
80
+ const code = 'DECRYPTION_FAILED'
81
+ const message = this.message
82
+
83
+ const e = new Error(message)
84
+ e.code = code
85
+ return e
86
+ }
28
87
  }
29
88
 
30
89
  module.exports = Errors
@@ -1,15 +1,15 @@
1
1
  const chomp = require('./chomp')
2
- const truncate = require('./truncate')
3
- const decryptValue = require('./decryptValue')
2
+ const decryptKeyValue = require('./decryptKeyValue')
4
3
  const resolveEscapeSequences = require('./resolveEscapeSequences')
5
4
  const { execSync } = require('child_process')
6
5
 
7
6
  class Parse {
8
7
  static LINE = /(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|\s*`(?:\\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/mg
9
8
 
10
- constructor (src, privateKey = null, processEnv = process.env, overload = false) {
9
+ constructor (src, privateKey = null, processEnv = process.env, overload = false, privateKeyName = null) {
11
10
  this.src = src
12
11
  this.privateKey = privateKey
12
+ this.privateKeyName = privateKeyName
13
13
  this.processEnv = processEnv
14
14
  this.overload = overload
15
15
 
@@ -40,9 +40,9 @@ class Parse {
40
40
 
41
41
  // decrypt
42
42
  try {
43
- this.parsed[key] = this.decrypt(this.parsed[key])
43
+ this.parsed[key] = this.decrypt(key, this.parsed[key])
44
44
  } catch (e) {
45
- this.errors.push(this.error(e, key))
45
+ this.errors.push(e)
46
46
  }
47
47
 
48
48
  // eval empty, double, or backticks
@@ -128,8 +128,8 @@ class Parse {
128
128
  return v
129
129
  }
130
130
 
131
- decrypt (value) {
132
- return decryptValue(value, this.privateKey)
131
+ decrypt (key, value) {
132
+ return decryptKeyValue(key, value, this.privateKeyName, this.privateKey)
133
133
  }
134
134
 
135
135
  eval (value) {
@@ -207,14 +207,6 @@ class Parse {
207
207
  getLines () {
208
208
  return (this.src || '').toString().replace(/\r\n?/mg, '\n') // Convert buffer to string and Convert line breaks to same format
209
209
  }
210
-
211
- error (e, key) {
212
- const error = new Error(`[${e.code}] could not decrypt ${key} using private key '${truncate(this.privateKey)}'`)
213
- error.code = e.code
214
- error.help = `[${e.code}] ? ${e.message}`
215
-
216
- return error
217
- }
218
210
  }
219
211
 
220
212
  module.exports = Parse
package/src/lib/main.d.ts CHANGED
@@ -124,50 +124,6 @@ export interface DotenvPopulateInput {
124
124
  */
125
125
  export function config(options?: DotenvConfigOptions): DotenvConfigOutput;
126
126
 
127
- /**
128
- * Decrypt ciphertext
129
- *
130
- * @see https://dotenvx.com/docs
131
- *
132
- * @param envFile - the encrypted ciphertext string
133
- * @param key - the decryption key(s)
134
- */
135
- export function decrypt(
136
- envFile?: string | string[],
137
- key?: string | string[]
138
- ): string;
139
-
140
- export type EncryptRowOutput = {
141
- keys: string[];
142
- filepath: string;
143
- envFilepath: string;
144
- publicKey: string;
145
- privateKey: string;
146
- privateKeyName: string;
147
- privateKeyAdded: boolean;
148
- envSrc: string;
149
- changed: boolean;
150
- error?: Error;
151
- };
152
-
153
- export type EncryptOutput = {
154
- processedEnvFiles: EncryptRowOutput[];
155
- changedFilepaths: string[];
156
- unchangedFilepaths: string[];
157
- };
158
-
159
- /**
160
- * Encrypt plaintext
161
- *
162
- * @see https://dotenvx.com/docs
163
- * @param envFile - path to the .env file(s)
164
- * @param key - keys(s) to encrypt env file(s) (default: all keys in .env file)
165
- */
166
- export function encrypt(
167
- envFile?: string | string[],
168
- key?: string | string[]
169
- ): EncryptOutput;
170
-
171
127
  /**
172
128
  * List all env files in the current working directory
173
129
  *
@@ -181,53 +137,6 @@ export function ls(
181
137
  excludeEnvFile: string | string[]
182
138
  ): string[];
183
139
 
184
- /**
185
- * Get the value of a key from the .env file
186
- *
187
- * @param [key] - the key to get the value of
188
- * @param [envs] - the environment(s) to get the value from
189
- * @param [overload] - whether to overload the value from the .env file
190
- * @param [DOTENV_KEY] - the decryption key string
191
- * @param [all] - whether to return all values
192
- */
193
- export function get(
194
- key?: string,
195
- envs?: string[],
196
- overload?: boolean,
197
- DOTENV_KEY?: string,
198
- all?: boolean
199
- ): Record<string, string | undefined> | string | undefined;
200
-
201
- export type SetOutput = {
202
- key: string;
203
- value: string;
204
- filepath: string;
205
- envFilepath: string;
206
- envSrc: string;
207
- changed: boolean;
208
- encryptedValue?: string;
209
- publicKey?: string;
210
- privateKey?: string;
211
- privateKeyAdded?: boolean;
212
- privateKeyName?: string;
213
- error?: Error;
214
- };
215
-
216
- /**
217
- * Set the value of a key in the .env file
218
- *
219
- * @param key - the key to set the value of
220
- * @param value - the value to set
221
- * @param envFile - the path to the .env file
222
- * @param [encrypt] - whether to encrypt the value
223
- */
224
- export function set(
225
- key: string,
226
- value: string,
227
- envFile: string | string,
228
- encrypt?: boolean
229
- ): EncryptOutput;
230
-
231
140
  export type GenExampleOutput = {
232
141
  envExampleFile: string;
233
142
  envFile: string | string[];
@@ -8,7 +8,7 @@ const TYPE_ENV_FILE = 'envFile'
8
8
  const Errors = require('./../helpers/errors')
9
9
  const guessPrivateKeyName = require('./../helpers/guessPrivateKeyName')
10
10
  const findPrivateKey = require('./../helpers/findPrivateKey')
11
- const decryptValue = require('./../helpers/decryptValue')
11
+ const decryptKeyValue = require('./../helpers/decryptKeyValue')
12
12
  const isEncrypted = require('./../helpers/isEncrypted')
13
13
  const replace = require('./../helpers/replace')
14
14
  const detectEncoding = require('./../helpers/detectEncoding')
@@ -86,7 +86,7 @@ class Decrypt {
86
86
  if (encrypted) {
87
87
  row.keys.push(key) // track key(s)
88
88
 
89
- const decryptedValue = decryptValue(value, privateKey)
89
+ const decryptedValue = decryptKeyValue(key, value, privateKeyName, privateKey)
90
90
  // once newSrc is built write it out
91
91
  envSrc = replace(envSrc, key, decryptedValue)
92
92
 
@@ -12,6 +12,7 @@ const Errors = require('./../helpers/errors')
12
12
  const parseEnvironmentFromDotenvKey = require('./../helpers/parseEnvironmentFromDotenvKey')
13
13
  const detectEncoding = require('./../helpers/detectEncoding')
14
14
  const findPrivateKey = require('./../helpers/findPrivateKey')
15
+ const guessPrivateKeyName = require('./../helpers/guessPrivateKeyName')
15
16
  const determineEnvs = require('./../helpers/determineEnvs')
16
17
 
17
18
  class Run {
@@ -92,7 +93,8 @@ class Run {
92
93
  this.readableFilepaths.add(envFilepath)
93
94
 
94
95
  const privateKey = findPrivateKey(envFilepath)
95
- const { parsed, errors, injected, preExisted } = new Parse(src, privateKey, this.processEnv, this.overload).run()
96
+ const privateKeyName = guessPrivateKeyName(envFilepath)
97
+ const { parsed, errors, injected, preExisted } = new Parse(src, privateKey, this.processEnv, this.overload, privateKeyName).run()
96
98
 
97
99
  row.parsed = parsed
98
100
  row.errors = errors
@@ -8,7 +8,7 @@ const Errors = require('./../helpers/errors')
8
8
  const guessPrivateKeyName = require('./../helpers/guessPrivateKeyName')
9
9
  const guessPublicKeyName = require('./../helpers/guessPublicKeyName')
10
10
  const encryptValue = require('./../helpers/encryptValue')
11
- const decryptValue = require('./../helpers/decryptValue')
11
+ const decryptKeyValue = require('./../helpers/decryptKeyValue')
12
12
  const replace = require('./../helpers/replace')
13
13
  const detectEncoding = require('./../helpers/detectEncoding')
14
14
  const determineEnvs = require('./../helpers/determineEnvs')
@@ -85,7 +85,7 @@ class Sets {
85
85
  privateKey = kp.privateKey
86
86
 
87
87
  if (row.originalValue) {
88
- row.originalValue = decryptValue(row.originalValue, privateKey)
88
+ row.originalValue = decryptKeyValue(row.key, row.originalValue, privateKeyName, privateKey)
89
89
  }
90
90
 
91
91
  // if derivation doesn't match what's in the file (or preset in env)