@dotenvx/dotenvx 1.75.0 → 2.0.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.
Files changed (89) hide show
  1. package/CHANGELOG.md +34 -1
  2. package/README.md +4 -114
  3. package/package.json +8 -7
  4. package/src/cli/actions/decrypt.js +35 -17
  5. package/src/cli/actions/doctor.js +2 -2
  6. package/src/cli/actions/encrypt.js +64 -85
  7. package/src/cli/actions/ext/genexample.js +2 -2
  8. package/src/cli/actions/get.js +16 -7
  9. package/src/cli/actions/keypair.js +55 -42
  10. package/src/cli/actions/login.js +4 -3
  11. package/src/cli/actions/normalizeArmorAliases.js +9 -0
  12. package/src/cli/actions/run.js +65 -22
  13. package/src/cli/actions/set.js +51 -37
  14. package/src/cli/dotenvx.js +6 -21
  15. package/src/lib/api/{postKeypair.js → postArmorKeyring.js} +4 -14
  16. package/src/lib/{helpers/envResolution → conventions}/environment.js +1 -1
  17. package/src/lib/conventions/filepaths.js +9 -0
  18. package/src/lib/conventions/keynames.js +38 -0
  19. package/src/lib/helpers/catchAndLog.js +4 -1
  20. package/src/lib/helpers/cryptography/index.js +1 -12
  21. package/src/lib/helpers/cryptography/mutateKeysSrc.js +5 -21
  22. package/src/lib/helpers/envResolution/index.js +1 -1
  23. package/src/lib/helpers/errors.js +13 -0
  24. package/src/lib/helpers/executeDynamic.js +1 -3
  25. package/src/lib/helpers/keypairMetadata.js +3 -3
  26. package/src/lib/helpers/readEnvKey.js +4 -3
  27. package/src/lib/main.d.ts +2 -39
  28. package/src/lib/main.js +82 -45
  29. package/src/lib/providers/armor/index.js +29 -0
  30. package/src/lib/providers/index.js +46 -0
  31. package/src/lib/providers/worker.js +6 -0
  32. package/src/lib/resolvers/envs.js +302 -0
  33. package/src/lib/resolvers/get.js +69 -0
  34. package/src/lib/resolvers/keypair.js +81 -0
  35. package/src/lib/resolvers/ls.js +41 -0
  36. package/src/lib/services/armorDown.js +2 -2
  37. package/src/lib/services/{armorKeypair.js → armorKeyring.js} +14 -51
  38. package/src/lib/services/armorMove.js +2 -2
  39. package/src/lib/services/armorPull.js +2 -2
  40. package/src/lib/services/armorPush.js +2 -2
  41. package/src/lib/services/armorUp.js +2 -2
  42. package/src/lib/services/genexample.js +19 -8
  43. package/src/lib/services/login.js +25 -0
  44. package/src/lib/services/prebuild.js +11 -5
  45. package/src/lib/services/precommit.js +11 -5
  46. package/src/lib/transforms/decrypt.js +83 -0
  47. package/src/lib/transforms/encrypt.js +179 -0
  48. package/src/lib/transforms/set.js +179 -0
  49. package/src/shared/logger.js +5 -0
  50. package/src/cli/actions/normalizeArmorOptions.js +0 -10
  51. package/src/cli/actions/rotate.js +0 -87
  52. package/src/lib/helpers/append.js +0 -61
  53. package/src/lib/helpers/cryptography/armorKeypair.js +0 -42
  54. package/src/lib/helpers/cryptography/armorKeypairSync.js +0 -55
  55. package/src/lib/helpers/cryptography/encryptValue.js +0 -7
  56. package/src/lib/helpers/cryptography/localKeypair.js +0 -14
  57. package/src/lib/helpers/cryptography/mutateKeysSrcSync.js +0 -38
  58. package/src/lib/helpers/cryptography/provision.js +0 -56
  59. package/src/lib/helpers/cryptography/provisionSync.js +0 -51
  60. package/src/lib/helpers/cryptography/provisionWithPrivateKey.js +0 -26
  61. package/src/lib/helpers/dotenvParse.js +0 -55
  62. package/src/lib/helpers/escapeDollarSigns.js +0 -5
  63. package/src/lib/helpers/escapeForRegex.js +0 -5
  64. package/src/lib/helpers/evalKeyValue.js +0 -23
  65. package/src/lib/helpers/isFullyEncrypted.js +0 -27
  66. package/src/lib/helpers/isIgnoringDotenvKeys.js +0 -19
  67. package/src/lib/helpers/keyResolution/index.js +0 -16
  68. package/src/lib/helpers/keyResolution/keyNamesForEnvFile.js +0 -24
  69. package/src/lib/helpers/keyResolution/keyValues.js +0 -99
  70. package/src/lib/helpers/keyResolution/keyValuesFromEnvSrc.js +0 -80
  71. package/src/lib/helpers/keyResolution/keyValuesSync.js +0 -103
  72. package/src/lib/helpers/keyResolution/readFileKey.js +0 -17
  73. package/src/lib/helpers/keyResolution/readFileKeySync.js +0 -15
  74. package/src/lib/helpers/keyResolution/readProcessKey.js +0 -7
  75. package/src/lib/helpers/localDisplayPath.js +0 -11
  76. package/src/lib/helpers/parse.js +0 -214
  77. package/src/lib/helpers/pluralize.js +0 -10
  78. package/src/lib/helpers/quotes.js +0 -36
  79. package/src/lib/helpers/replace.js +0 -82
  80. package/src/lib/helpers/resolveEscapeSequences.js +0 -5
  81. package/src/lib/services/decrypt.js +0 -157
  82. package/src/lib/services/encrypt.js +0 -214
  83. package/src/lib/services/get.js +0 -76
  84. package/src/lib/services/keypair.js +0 -60
  85. package/src/lib/services/loginPoll.js +0 -36
  86. package/src/lib/services/ls.js +0 -57
  87. package/src/lib/services/rotate.js +0 -198
  88. package/src/lib/services/run.js +0 -255
  89. package/src/lib/services/sets.js +0 -326
@@ -1,326 +0,0 @@
1
- const fsx = require('./../helpers/fsx')
2
- const path = require('path')
3
- const { encrypted } = require('@dotenvx/primitives')
4
-
5
- const TYPE_ENV_FILE = 'envFile'
6
-
7
- const Errors = require('./../helpers/errors')
8
-
9
- const {
10
- determine
11
- } = require('./../helpers/envResolution')
12
-
13
- const {
14
- keyNamesForEnvFile,
15
- keyValues,
16
- keyValuesSync
17
- } = require('./../helpers/keyResolution')
18
-
19
- const {
20
- encryptValue,
21
- decryptKeyValue,
22
- provision,
23
- provisionSync,
24
- provisionWithPrivateKey
25
- } = require('./../helpers/cryptography')
26
-
27
- const replace = require('./../helpers/replace')
28
- const dotenvParse = require('./../helpers/dotenvParse')
29
- const detectEncoding = require('./../helpers/detectEncoding')
30
- const detectEncodingSync = require('./../helpers/detectEncodingSync')
31
-
32
- function allValuesForKey (envSrc, key) {
33
- return dotenvParse(envSrc, false, false, true)[key] || []
34
- }
35
-
36
- class Sets {
37
- constructor (key, value, envs = [], encrypt = true, envKeysFilepath = null, noArmor = false, noCreate = false, options = {}) {
38
- this.envs = determine(envs, process.env)
39
- this.key = key
40
- this.value = value
41
- this.encrypt = encrypt
42
- this.envKeysFilepath = envKeysFilepath
43
- this.noArmor = noArmor
44
- this.noCreate = noCreate
45
- this.command = options.command
46
-
47
- this.processedEnvs = []
48
- this.changedFilepaths = new Set()
49
- this.unchangedFilepaths = new Set()
50
- this.readableFilepaths = new Set()
51
- }
52
-
53
- runSync () {
54
- // example
55
- // envs [
56
- // { type: 'envFile', value: '.env' }
57
- // ]
58
-
59
- for (const env of this.envs) {
60
- if (env.type === TYPE_ENV_FILE) {
61
- this._setEnvFileSync(env.value)
62
- }
63
- }
64
-
65
- return {
66
- processedEnvs: this.processedEnvs,
67
- changedFilepaths: [...this.changedFilepaths],
68
- unchangedFilepaths: [...this.unchangedFilepaths]
69
- }
70
- }
71
-
72
- async run () {
73
- // example
74
- // envs [
75
- // { type: 'envFile', value: '.env' }
76
- // ]
77
-
78
- for (const env of this.envs) {
79
- if (env.type === TYPE_ENV_FILE) {
80
- await this._setEnvFile(env.value)
81
- }
82
- }
83
-
84
- return {
85
- processedEnvs: this.processedEnvs,
86
- changedFilepaths: [...this.changedFilepaths],
87
- unchangedFilepaths: [...this.unchangedFilepaths]
88
- }
89
- }
90
-
91
- _setEnvFileSync (envFilepath) {
92
- const row = {}
93
- row.key = this.key || null
94
- row.value = this.value || null
95
- row.type = TYPE_ENV_FILE
96
-
97
- const filepath = path.resolve(envFilepath)
98
- row.filepath = filepath
99
- row.envFilepath = envFilepath
100
- row.changed = false
101
-
102
- try {
103
- let seededWithInitialKey = false
104
-
105
- if (!fsx.existsSync(filepath)) {
106
- if (this.noCreate) {
107
- detectEncodingSync(filepath) // throws ENOENT
108
- } else {
109
- fsx.writeFileXSync(filepath, '')
110
- }
111
- }
112
-
113
- const encoding = detectEncodingSync(filepath)
114
- let envSrc = fsx.readFileXSync(filepath, { encoding })
115
-
116
- // blank files seeded by `set` should contain only the key being set
117
- if (row.key && envSrc.trim().length === 0) {
118
- envSrc = `${row.key}="${this.value}"\n`
119
- seededWithInitialKey = true
120
- }
121
-
122
- const envParsed = dotenvParse(envSrc)
123
- row.originalValue = envParsed[row.key] || null
124
- if (seededWithInitialKey) {
125
- row.originalValue = null
126
- }
127
- const wasPlainText = !encrypted(row.originalValue)
128
- this.readableFilepaths.add(envFilepath)
129
-
130
- if (this.encrypt) {
131
- let publicKey
132
- let privateKey
133
-
134
- const { publicKeyName, privateKeyName } = keyNamesForEnvFile(filepath)
135
- const { publicKeyValue, privateKeyValue } = keyValuesSync(filepath, {
136
- keysFilepath: this.envKeysFilepath,
137
- noArmor: this.noArmor,
138
- command: this.command
139
- })
140
-
141
- // first pass - provisionSync
142
- if (!privateKeyValue && !publicKeyValue) {
143
- const prov = provisionSync({
144
- envSrc,
145
- envFilepath,
146
- keysFilepath: this.envKeysFilepath,
147
- noArmor: this.noArmor,
148
- command: this.command
149
- })
150
- envSrc = prov.envSrc
151
- publicKey = prov.publicKey
152
- privateKey = prov.privateKey
153
- row.envKeysFilepath = prov.envKeysFilepath
154
- row.localPrivateKeyAdded = prov.localPrivateKeyAdded
155
- row.remotePrivateKeyAdded = prov.remotePrivateKeyAdded
156
- } else if (privateKeyValue) {
157
- const prov = provisionWithPrivateKey({ envSrc, envFilepath, keysFilepath: this.envKeysFilepath, privateKeyValue, publicKeyValue, publicKeyName })
158
- publicKey = prov.publicKey
159
- privateKey = prov.privateKey
160
- envSrc = prov.envSrc
161
-
162
- if (row.originalValue) {
163
- row.originalValue = decryptKeyValue(row.key, row.originalValue, privateKeyName, privateKey)
164
- }
165
- } else if (publicKeyValue) {
166
- publicKey = publicKeyValue
167
- }
168
-
169
- row.publicKey = publicKey
170
- row.privateKey = privateKey
171
- try {
172
- row.encryptedValue = encryptValue(this.value, publicKey)
173
- } catch {
174
- throw new Errors({ publicKeyName, publicKey }).invalidPublicKey()
175
- }
176
- row.privateKeyName = privateKeyName
177
- }
178
-
179
- const goingFromPlainTextToEncrypted = wasPlainText && this.encrypt
180
- const valueChanged = this.value !== row.originalValue
181
- const duplicateKey = allValuesForKey(envSrc, row.key).length > 1
182
- const shouldPersistSeededPlainValue = seededWithInitialKey && !this.encrypt
183
-
184
- if (shouldPersistSeededPlainValue) {
185
- row.envSrc = envSrc
186
- this.changedFilepaths.add(envFilepath)
187
- row.changed = true
188
- } else if (goingFromPlainTextToEncrypted || valueChanged || duplicateKey) {
189
- row.envSrc = replace(envSrc, this.key, row.encryptedValue || this.value)
190
- this.changedFilepaths.add(envFilepath)
191
- row.changed = true
192
- } else {
193
- row.envSrc = envSrc
194
- this.unchangedFilepaths.add(envFilepath)
195
- row.changed = false
196
- }
197
- } catch (e) {
198
- if (e.code === 'ENOENT') {
199
- row.error = new Errors({ envFilepath, filepath }).missingEnvFile()
200
- } else {
201
- row.error = e
202
- }
203
- }
204
-
205
- this.processedEnvs.push(row)
206
- }
207
-
208
- async _setEnvFile (envFilepath) {
209
- const row = {}
210
- row.key = this.key || null
211
- row.value = this.value || null
212
- row.type = TYPE_ENV_FILE
213
-
214
- const filepath = path.resolve(envFilepath)
215
- row.filepath = filepath
216
- row.envFilepath = envFilepath
217
- row.changed = false
218
-
219
- try {
220
- let seededWithInitialKey = false
221
-
222
- if (!(await fsx.exists(filepath))) {
223
- if (this.noCreate) {
224
- await detectEncoding(filepath) // throws ENOENT
225
- } else {
226
- await fsx.writeFileX(filepath, '')
227
- }
228
- }
229
-
230
- const encoding = await detectEncoding(filepath)
231
- let envSrc = await fsx.readFileX(filepath, { encoding })
232
-
233
- // blank files seeded by `set` should contain only the key being set
234
- if (row.key && envSrc.trim().length === 0) {
235
- envSrc = `${row.key}="${this.value}"\n`
236
- seededWithInitialKey = true
237
- }
238
-
239
- const envParsed = dotenvParse(envSrc)
240
- row.originalValue = envParsed[row.key] || null
241
- if (seededWithInitialKey) {
242
- row.originalValue = null
243
- }
244
- const wasPlainText = !encrypted(row.originalValue)
245
- this.readableFilepaths.add(envFilepath)
246
-
247
- if (this.encrypt) {
248
- let publicKey
249
- let privateKey
250
-
251
- const { publicKeyName, privateKeyName } = keyNamesForEnvFile(filepath)
252
- const { publicKeyValue, privateKeyValue } = await keyValues(filepath, {
253
- keysFilepath: this.envKeysFilepath,
254
- noArmor: this.noArmor,
255
- command: this.command
256
- })
257
-
258
- // first pass - provision
259
- if (!privateKeyValue && !publicKeyValue) {
260
- const prov = await provision({
261
- envSrc,
262
- envFilepath,
263
- keysFilepath: this.envKeysFilepath,
264
- noArmor: this.noArmor,
265
- command: this.command
266
- })
267
- envSrc = prov.envSrc
268
- publicKey = prov.publicKey
269
- privateKey = prov.privateKey
270
- row.envKeysFilepath = prov.envKeysFilepath
271
- row.localPrivateKeyAdded = prov.localPrivateKeyAdded
272
- row.remotePrivateKeyAdded = prov.remotePrivateKeyAdded
273
- } else if (privateKeyValue) {
274
- const prov = provisionWithPrivateKey({ envSrc, envFilepath, keysFilepath: this.envKeysFilepath, privateKeyValue, publicKeyValue, publicKeyName })
275
- publicKey = prov.publicKey
276
- privateKey = prov.privateKey
277
- envSrc = prov.envSrc
278
-
279
- if (row.originalValue) {
280
- row.originalValue = decryptKeyValue(row.key, row.originalValue, privateKeyName, privateKey)
281
- }
282
- } else if (publicKeyValue) {
283
- publicKey = publicKeyValue
284
- }
285
-
286
- row.publicKey = publicKey
287
- row.privateKey = privateKey
288
- try {
289
- row.encryptedValue = encryptValue(this.value, publicKey)
290
- } catch {
291
- throw new Errors({ publicKeyName, publicKey }).invalidPublicKey()
292
- }
293
- row.privateKeyName = privateKeyName
294
- }
295
-
296
- const goingFromPlainTextToEncrypted = wasPlainText && this.encrypt
297
- const valueChanged = this.value !== row.originalValue
298
- const duplicateKey = allValuesForKey(envSrc, row.key).length > 1
299
- const shouldPersistSeededPlainValue = seededWithInitialKey && !this.encrypt
300
-
301
- if (shouldPersistSeededPlainValue) {
302
- row.envSrc = envSrc
303
- this.changedFilepaths.add(envFilepath)
304
- row.changed = true
305
- } else if (goingFromPlainTextToEncrypted || valueChanged || duplicateKey) {
306
- row.envSrc = replace(envSrc, this.key, row.encryptedValue || this.value)
307
- this.changedFilepaths.add(envFilepath)
308
- row.changed = true
309
- } else {
310
- row.envSrc = envSrc
311
- this.unchangedFilepaths.add(envFilepath)
312
- row.changed = false
313
- }
314
- } catch (e) {
315
- if (e.code === 'ENOENT') {
316
- row.error = new Errors({ envFilepath, filepath }).missingEnvFile()
317
- } else {
318
- row.error = e
319
- }
320
- }
321
-
322
- this.processedEnvs.push(row)
323
- }
324
- }
325
-
326
- module.exports = Sets