@dotenvx/dotenvx 1.59.0 → 1.60.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 +18 -1
- package/README.md +130 -137
- package/package.json +7 -6
- package/src/cli/actions/decrypt.js +15 -8
- package/src/cli/actions/encrypt.js +15 -8
- package/src/cli/actions/ext/genexample.js +2 -2
- package/src/cli/actions/ext/gitignore.js +3 -3
- package/src/cli/actions/get.js +12 -7
- package/src/cli/actions/keypair.js +13 -5
- package/src/cli/actions/rotate.js +16 -9
- package/src/cli/actions/run.js +13 -6
- package/src/cli/actions/set.js +19 -12
- package/src/cli/dotenvx.js +19 -21
- package/src/cli/examples.js +1 -1
- package/src/db/session.js +10 -6
- package/src/lib/extensions/ops.js +112 -63
- package/src/lib/helpers/catchAndLog.js +1 -1
- package/src/lib/helpers/createSpinner.js +24 -0
- package/src/lib/helpers/cryptography/index.js +4 -0
- package/src/lib/helpers/cryptography/mutateKeysSrc.js +4 -4
- package/src/lib/helpers/cryptography/mutateKeysSrcSync.js +38 -0
- package/src/lib/helpers/cryptography/opsKeypair.js +2 -2
- package/src/lib/helpers/cryptography/opsKeypairSync.js +14 -0
- package/src/lib/helpers/cryptography/provision.js +7 -7
- package/src/lib/helpers/cryptography/provisionSync.js +47 -0
- package/src/lib/helpers/cryptography/provisionWithPrivateKey.js +1 -1
- package/src/lib/helpers/detectEncoding.js +2 -2
- package/src/lib/helpers/detectEncodingSync.js +22 -0
- package/src/lib/helpers/errors.js +15 -0
- package/src/lib/helpers/fsx.js +27 -3
- package/src/lib/helpers/installPrecommitHook.js +2 -2
- package/src/lib/helpers/isIgnoringDotenvKeys.js +1 -1
- package/src/lib/helpers/keyResolution/index.js +3 -1
- package/src/lib/helpers/keyResolution/keyValues.js +12 -12
- package/src/lib/helpers/keyResolution/keyValuesSync.js +85 -0
- package/src/lib/helpers/keyResolution/readFileKey.js +10 -8
- package/src/lib/helpers/keyResolution/readFileKeySync.js +15 -0
- package/src/lib/helpers/kits/sample.js +11 -21
- package/src/lib/main.d.ts +18 -3
- package/src/lib/main.js +18 -18
- package/src/lib/services/decrypt.js +8 -8
- package/src/lib/services/encrypt.js +17 -11
- package/src/lib/services/genexample.js +2 -2
- package/src/lib/services/get.js +30 -21
- package/src/lib/services/keypair.js +21 -5
- package/src/lib/services/prebuild.js +7 -12
- package/src/lib/services/precommit.js +7 -11
- package/src/lib/services/rotate.js +22 -18
- package/src/lib/services/run.js +82 -9
- package/src/lib/services/sets.js +139 -12
- package/src/shared/logger.js +3 -3
- package/src/lib/helpers/sleep.js +0 -5
|
@@ -7,15 +7,15 @@ const readProcessKey = require('./readProcessKey')
|
|
|
7
7
|
const readFileKey = require('./readFileKey')
|
|
8
8
|
const opsKeypair = require('../cryptography/opsKeypair')
|
|
9
9
|
|
|
10
|
-
function invertForPrivateKeyName (filepath) {
|
|
10
|
+
async function invertForPrivateKeyName (filepath) {
|
|
11
11
|
const PUBLIC_KEY_SCHEMA = 'DOTENV_PUBLIC_KEY'
|
|
12
12
|
const PRIVATE_KEY_SCHEMA = 'DOTENV_PRIVATE_KEY'
|
|
13
13
|
|
|
14
|
-
if (!fsx.
|
|
14
|
+
if (!(await fsx.exists(filepath))) {
|
|
15
15
|
return null
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
const envSrc = fsx.readFileX(filepath)
|
|
18
|
+
const envSrc = await fsx.readFileX(filepath)
|
|
19
19
|
const envParsed = dotenvParse(envSrc)
|
|
20
20
|
|
|
21
21
|
let publicKeyName
|
|
@@ -32,9 +32,9 @@ function invertForPrivateKeyName (filepath) {
|
|
|
32
32
|
return null
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
function keyValues (filepath, opts = {}) {
|
|
35
|
+
async function keyValues (filepath, opts = {}) {
|
|
36
36
|
let keysFilepath = opts.keysFilepath || null
|
|
37
|
-
const
|
|
37
|
+
const noOps = opts.noOps === true
|
|
38
38
|
const names = keyNames(filepath)
|
|
39
39
|
const publicKeyName = names.publicKeyName // DOTENV_PUBLIC_KEY_${ENVIRONMENT}
|
|
40
40
|
let privateKeyName = names.privateKeyName // DOTENV_PRIVATE_KEY_${ENVIRONMENT}
|
|
@@ -45,7 +45,7 @@ function keyValues (filepath, opts = {}) {
|
|
|
45
45
|
// public key: process.env first, then .env*
|
|
46
46
|
publicKey = readProcessKey(publicKeyName)
|
|
47
47
|
if (!publicKey) {
|
|
48
|
-
publicKey = readFileKey(publicKeyName, filepath) || null
|
|
48
|
+
publicKey = await readFileKey(publicKeyName, filepath) || null
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
// private key: process.env first, then .env.keys, then invert public key
|
|
@@ -57,28 +57,28 @@ function keyValues (filepath, opts = {}) {
|
|
|
57
57
|
keysFilepath = path.resolve(path.dirname(filepath), '.env.keys') // typical scenario
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
privateKey = readFileKey(privateKeyName, keysFilepath)
|
|
60
|
+
privateKey = await readFileKey(privateKeyName, keysFilepath)
|
|
61
61
|
}
|
|
62
62
|
// invert
|
|
63
63
|
if (!privateKey) {
|
|
64
|
-
privateKeyName = invertForPrivateKeyName(filepath)
|
|
64
|
+
privateKeyName = await invertForPrivateKeyName(filepath)
|
|
65
65
|
if (privateKeyName) {
|
|
66
66
|
privateKey = readProcessKey(privateKeyName)
|
|
67
67
|
if (!privateKey) {
|
|
68
|
-
privateKey = readFileKey(privateKeyName, keysFilepath)
|
|
68
|
+
privateKey = await readFileKey(privateKeyName, keysFilepath)
|
|
69
69
|
}
|
|
70
70
|
}
|
|
71
71
|
}
|
|
72
72
|
|
|
73
73
|
// ops
|
|
74
|
-
if (
|
|
75
|
-
const kp = opsKeypair(publicKey)
|
|
74
|
+
if (!noOps && !privateKey && publicKey && publicKey.length > 0) {
|
|
75
|
+
const kp = await opsKeypair(publicKey)
|
|
76
76
|
privateKey = kp.privateKey
|
|
77
77
|
}
|
|
78
78
|
|
|
79
79
|
return {
|
|
80
80
|
publicKeyValue: publicKey || null, // important to make sure name is rendered
|
|
81
|
-
privateKeyValue: privateKey || null //
|
|
81
|
+
privateKeyValue: privateKey || null // important to make sure name is rendered
|
|
82
82
|
}
|
|
83
83
|
}
|
|
84
84
|
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
const path = require('path')
|
|
2
|
+
|
|
3
|
+
const fsx = require('./../fsx')
|
|
4
|
+
const dotenvParse = require('./../dotenvParse')
|
|
5
|
+
const keyNames = require('./keyNames')
|
|
6
|
+
const readProcessKey = require('./readProcessKey')
|
|
7
|
+
const readFileKeySync = require('./readFileKeySync')
|
|
8
|
+
const opsKeypairSync = require('../cryptography/opsKeypairSync')
|
|
9
|
+
|
|
10
|
+
function invertForPrivateKeyName (filepath) {
|
|
11
|
+
const PUBLIC_KEY_SCHEMA = 'DOTENV_PUBLIC_KEY'
|
|
12
|
+
const PRIVATE_KEY_SCHEMA = 'DOTENV_PRIVATE_KEY'
|
|
13
|
+
|
|
14
|
+
if (!fsx.existsSync(filepath)) {
|
|
15
|
+
return null
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const envSrc = fsx.readFileXSync(filepath)
|
|
19
|
+
const envParsed = dotenvParse(envSrc)
|
|
20
|
+
|
|
21
|
+
let publicKeyName
|
|
22
|
+
for (const keyName of Object.keys(envParsed)) {
|
|
23
|
+
if (keyName === PUBLIC_KEY_SCHEMA || keyName.startsWith(PUBLIC_KEY_SCHEMA)) {
|
|
24
|
+
publicKeyName = keyName // find DOTENV_PUBLIC_KEY* in filename
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (publicKeyName) {
|
|
29
|
+
return publicKeyName.replace(PUBLIC_KEY_SCHEMA, PRIVATE_KEY_SCHEMA) // return inverted (DOTENV_PUBLIC_KEY* -> DOTENV_PRIVATE_KEY*) if found
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return null
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function keyValuesSync (filepath, opts = {}) {
|
|
36
|
+
let keysFilepath = opts.keysFilepath || null
|
|
37
|
+
const noOps = opts.noOps === true
|
|
38
|
+
const names = keyNames(filepath)
|
|
39
|
+
const publicKeyName = names.publicKeyName // DOTENV_PUBLIC_KEY_${ENVIRONMENT}
|
|
40
|
+
let privateKeyName = names.privateKeyName // DOTENV_PRIVATE_KEY_${ENVIRONMENT}
|
|
41
|
+
|
|
42
|
+
let publicKey = null
|
|
43
|
+
let privateKey = null
|
|
44
|
+
|
|
45
|
+
// public key: process.env first, then .env*
|
|
46
|
+
publicKey = readProcessKey(publicKeyName)
|
|
47
|
+
if (!publicKey) {
|
|
48
|
+
publicKey = readFileKeySync(publicKeyName, filepath) || null
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// private key: process.env first, then .env.keys, then invert public key
|
|
52
|
+
privateKey = readProcessKey(privateKeyName)
|
|
53
|
+
if (!privateKey) {
|
|
54
|
+
if (keysFilepath) { // user specified -fk flag
|
|
55
|
+
keysFilepath = path.resolve(keysFilepath)
|
|
56
|
+
} else {
|
|
57
|
+
keysFilepath = path.resolve(path.dirname(filepath), '.env.keys') // typical scenario
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
privateKey = readFileKeySync(privateKeyName, keysFilepath)
|
|
61
|
+
}
|
|
62
|
+
// invert
|
|
63
|
+
if (!privateKey) {
|
|
64
|
+
privateKeyName = invertForPrivateKeyName(filepath)
|
|
65
|
+
if (privateKeyName) {
|
|
66
|
+
privateKey = readProcessKey(privateKeyName)
|
|
67
|
+
if (!privateKey) {
|
|
68
|
+
privateKey = readFileKeySync(privateKeyName, keysFilepath)
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// ops
|
|
74
|
+
if (!noOps && !privateKey && publicKey && publicKey.length > 0) {
|
|
75
|
+
const kp = opsKeypairSync(publicKey)
|
|
76
|
+
privateKey = kp.privateKey
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return {
|
|
80
|
+
publicKeyValue: publicKey || null, // important to make sure name is rendered
|
|
81
|
+
privateKeyValue: privateKey || null // important to make sure name is rendered
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
module.exports = keyValuesSync
|
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
const fsx = require('./../fsx')
|
|
2
2
|
const dotenvParse = require('./../dotenvParse')
|
|
3
3
|
|
|
4
|
-
function readFileKey (keyName, filepath) {
|
|
5
|
-
if (fsx.
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
4
|
+
async function readFileKey (keyName, filepath) {
|
|
5
|
+
if (!(await fsx.exists(filepath))) {
|
|
6
|
+
return undefined
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const src = await fsx.readFileX(filepath)
|
|
10
|
+
const parsed = dotenvParse(src)
|
|
11
|
+
|
|
12
|
+
if (parsed[keyName] && parsed[keyName].length > 0) {
|
|
13
|
+
return parsed[keyName]
|
|
12
14
|
}
|
|
13
15
|
}
|
|
14
16
|
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
const fsx = require('./../fsx')
|
|
2
|
+
const dotenvParse = require('./../dotenvParse')
|
|
3
|
+
|
|
4
|
+
function readFileKeySync (keyName, filepath) {
|
|
5
|
+
if (fsx.existsSync(filepath)) {
|
|
6
|
+
const src = fsx.readFileXSync(filepath)
|
|
7
|
+
const parsed = dotenvParse(src)
|
|
8
|
+
|
|
9
|
+
if (parsed[keyName] && parsed[keyName].length > 0) {
|
|
10
|
+
return parsed[keyName]
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
module.exports = readFileKeySync
|
|
@@ -1,33 +1,23 @@
|
|
|
1
1
|
const SAMPLE_ENV_KIT = `
|
|
2
|
-
|
|
3
|
-
DATABASE_URL="postgresql://postgres:pass@db.ref.supabase.co:5432/postgres"
|
|
2
|
+
HELLO="Dotenvx"
|
|
4
3
|
|
|
5
|
-
# ──
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
# ── Hosting ──────────────────────────────────────
|
|
5
|
+
AWS_ACCESS_KEY_ID="xxxx"
|
|
6
|
+
AWS_SECRET_ACCESS_KEY="xxxx"
|
|
7
|
+
DATABASE_URL="postgresql://postgres:pass@db.ref.supabase.co:5432/postgres"
|
|
8
|
+
VERCEL_TOKEN="vcp_xxxx"
|
|
8
9
|
|
|
9
|
-
# ── AI
|
|
10
|
+
# ── AI ───────────────────────────────────────────
|
|
10
11
|
OPENAI_API_KEY="sk-xxxx"
|
|
11
12
|
ANTHROPIC_API_KEY="sk-ant-xxxx"
|
|
12
13
|
|
|
13
|
-
# ──
|
|
14
|
+
# ── Infrastructure ───────────────────────────────
|
|
15
|
+
AUTH0_CLIENT_ID="xxxx"
|
|
16
|
+
AUTH0_CLIENT_SECRET="xxxx"
|
|
14
17
|
RESEND_API_KEY="re_xxxx"
|
|
15
|
-
|
|
16
|
-
# ── Cloud Storage ────────────────────────────────
|
|
17
|
-
AWS_ACCESS_KEY_ID="xxxx"
|
|
18
|
-
AWS_SECRET_ACCESS_KEY="xxxx"
|
|
19
|
-
|
|
20
|
-
# ── Analytics / Monitoring ───────────────────────
|
|
21
|
-
SENTRY_DSN="https://hex@o1234.ingest.us.sentry.io/1234567"
|
|
22
|
-
|
|
23
|
-
# ── Payments ─────────────────────────────────────
|
|
24
18
|
STRIPE_API_KEY="sk_test_xxxx"
|
|
25
|
-
|
|
26
|
-
# ── Feature Flags ────────────────────────────────
|
|
27
19
|
FLAGSMITH_ENV_ID="xxxx"
|
|
28
|
-
|
|
29
|
-
# ── CI/CD / Deployment ──────────────────────────
|
|
30
|
-
VERCEL_TOKEN="vcp_xxxx"
|
|
20
|
+
SENTRY_DSN="https://hex@o1234.ingest.us.sentry.io/1234567"
|
|
31
21
|
`.trimStart()
|
|
32
22
|
|
|
33
23
|
module.exports = SAMPLE_ENV_KIT
|
package/src/lib/main.d.ts
CHANGED
|
@@ -151,7 +151,12 @@ export interface DotenvConfigOptions {
|
|
|
151
151
|
* Turn off Dotenvx Ops features - https://dotenvx.com/ops
|
|
152
152
|
*
|
|
153
153
|
* @default false
|
|
154
|
-
* @example require('@dotenvx/dotenvx').config({
|
|
154
|
+
* @example require('@dotenvx/dotenvx').config({ noOps: true })
|
|
155
|
+
*/
|
|
156
|
+
noOps?: boolean;
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* @deprecated use `noOps` instead.
|
|
155
160
|
*/
|
|
156
161
|
opsOff?: boolean;
|
|
157
162
|
}
|
|
@@ -210,7 +215,12 @@ export interface SetOptions {
|
|
|
210
215
|
* Turn off Dotenvx Ops features - https://dotenvx.com/ops
|
|
211
216
|
*
|
|
212
217
|
* @default false
|
|
213
|
-
* @example require('@dotenvx/dotenvx').set(key, value, {
|
|
218
|
+
* @example require('@dotenvx/dotenvx').set(key, value, { noOps: true })
|
|
219
|
+
*/
|
|
220
|
+
noOps?: boolean;
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* @deprecated use `noOps` instead.
|
|
214
224
|
*/
|
|
215
225
|
opsOff?: boolean;
|
|
216
226
|
}
|
|
@@ -285,7 +295,12 @@ export interface GetOptions {
|
|
|
285
295
|
* Turn off Dotenvx Ops features - https://dotenvx.com/ops
|
|
286
296
|
*
|
|
287
297
|
* @default false
|
|
288
|
-
* @example require('@dotenvx/dotenvx').get('KEY', {
|
|
298
|
+
* @example require('@dotenvx/dotenvx').get('KEY', { noOps: true })
|
|
299
|
+
*/
|
|
300
|
+
noOps?: boolean;
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* @deprecated use `noOps` instead.
|
|
289
304
|
*/
|
|
290
305
|
opsOff?: boolean;
|
|
291
306
|
}
|
package/src/lib/main.js
CHANGED
|
@@ -12,6 +12,7 @@ const Sets = require('./services/sets')
|
|
|
12
12
|
const Get = require('./services/get')
|
|
13
13
|
const Keypair = require('./services/keypair')
|
|
14
14
|
const Genexample = require('./services/genexample')
|
|
15
|
+
const Session = require('./../db/session')
|
|
15
16
|
|
|
16
17
|
// helpers
|
|
17
18
|
const buildEnvs = require('./helpers/buildEnvs')
|
|
@@ -39,27 +40,22 @@ const config = function (options = {}) {
|
|
|
39
40
|
// envKeysFile
|
|
40
41
|
const envKeysFile = options.envKeysFile
|
|
41
42
|
|
|
42
|
-
// dotenvx-ops related
|
|
43
|
-
const opsOn = options.opsOff !== true
|
|
44
|
-
|
|
45
43
|
if (options) {
|
|
46
44
|
setLogLevel(options)
|
|
47
45
|
setLogName(options)
|
|
48
46
|
setLogVersion(options)
|
|
49
47
|
}
|
|
50
48
|
|
|
49
|
+
// dotenvx-ops related
|
|
50
|
+
const noOps = resolveNoOps(options)
|
|
51
|
+
|
|
51
52
|
try {
|
|
52
53
|
const envs = buildEnvs(options)
|
|
53
54
|
const {
|
|
54
55
|
processedEnvs,
|
|
55
56
|
readableFilepaths,
|
|
56
57
|
uniqueInjectedKeys
|
|
57
|
-
} = new Run(envs, overload, processEnv, envKeysFile,
|
|
58
|
-
|
|
59
|
-
if (opsOn) {
|
|
60
|
-
// removed radar feature for now. contact me at mot@dotenvx.com if still needed for your organization.
|
|
61
|
-
// try { new Ops().observe({ beforeEnv, processedEnvs, afterEnv }) } catch {}
|
|
62
|
-
}
|
|
58
|
+
} = new Run(envs, overload, processEnv, envKeysFile, noOps).runSync()
|
|
63
59
|
|
|
64
60
|
let lastError
|
|
65
61
|
/** @type {Record<string, string>} */
|
|
@@ -169,13 +165,13 @@ const set = function (key, value, options = {}) {
|
|
|
169
165
|
|
|
170
166
|
const envs = buildEnvs(options)
|
|
171
167
|
const envKeysFilepath = options.envKeysFile
|
|
172
|
-
const
|
|
168
|
+
const noOps = resolveNoOps(options)
|
|
173
169
|
|
|
174
170
|
const {
|
|
175
171
|
processedEnvs,
|
|
176
172
|
changedFilepaths,
|
|
177
173
|
unchangedFilepaths
|
|
178
|
-
} = new Sets(key, value, envs, encrypt, envKeysFilepath,
|
|
174
|
+
} = new Sets(key, value, envs, encrypt, envKeysFilepath, noOps).runSync()
|
|
179
175
|
|
|
180
176
|
let withEncryption = ''
|
|
181
177
|
|
|
@@ -191,7 +187,7 @@ const set = function (key, value, options = {}) {
|
|
|
191
187
|
const message = error.messageWithHelp || (error.help ? `${error.message}. ${error.help}` : error.message)
|
|
192
188
|
logger.warn(message)
|
|
193
189
|
} else {
|
|
194
|
-
fsx.
|
|
190
|
+
fsx.writeFileXSync(processedEnv.filepath, processedEnv.envSrc)
|
|
195
191
|
|
|
196
192
|
logger.verbose(`${processedEnv.key} set${withEncryption} (${processedEnv.envFilepath})`)
|
|
197
193
|
logger.debug(`${processedEnv.key} set${withEncryption} to ${processedEnv.value} (${processedEnv.envFilepath})`)
|
|
@@ -211,7 +207,7 @@ const set = function (key, value, options = {}) {
|
|
|
211
207
|
const keyAddedEnvFilepath = keyAddedEnv.envFilepath || changedFilepaths[0] || '.env'
|
|
212
208
|
logger.success(`◈ encrypted ${key} (${keyAddedEnvFilepath})${keyAddedSuffix}`)
|
|
213
209
|
} else if (unchangedFilepaths.length > 0) {
|
|
214
|
-
logger.info(`○ no
|
|
210
|
+
logger.info(`○ no change (${unchangedFilepaths})`)
|
|
215
211
|
} else {
|
|
216
212
|
// do nothing
|
|
217
213
|
}
|
|
@@ -228,12 +224,12 @@ const set = function (key, value, options = {}) {
|
|
|
228
224
|
/* @type {import('./main').get} */
|
|
229
225
|
const get = function (key, options = {}) {
|
|
230
226
|
const envs = buildEnvs(options)
|
|
231
|
-
const
|
|
227
|
+
const noOps = resolveNoOps(options)
|
|
232
228
|
|
|
233
229
|
// ignore
|
|
234
230
|
const ignore = options.ignore || []
|
|
235
231
|
|
|
236
|
-
const { parsed, errors } = new Get(key, envs, options.overload, options.all, options.envKeysFile,
|
|
232
|
+
const { parsed, errors } = new Get(key, envs, options.overload, options.all, options.envKeysFile, noOps).runSync()
|
|
237
233
|
|
|
238
234
|
for (const error of errors || []) {
|
|
239
235
|
if (ignore.includes(error.code)) {
|
|
@@ -286,9 +282,8 @@ const genexample = function (directory, envFile) {
|
|
|
286
282
|
}
|
|
287
283
|
|
|
288
284
|
/** @type {import('./main').keypair} */
|
|
289
|
-
const keypair = function (envFile, key, envKeysFile = null,
|
|
290
|
-
const
|
|
291
|
-
const keypairs = new Keypair(envFile, envKeysFile, opsOn).run()
|
|
285
|
+
const keypair = function (envFile, key, envKeysFile = null, noOps = false) {
|
|
286
|
+
const keypairs = new Keypair(envFile, envKeysFile, noOps).runSync()
|
|
292
287
|
if (key) {
|
|
293
288
|
return keypairs[key]
|
|
294
289
|
} else {
|
|
@@ -296,6 +291,11 @@ const keypair = function (envFile, key, envKeysFile = null, opsOff = false) {
|
|
|
296
291
|
}
|
|
297
292
|
}
|
|
298
293
|
|
|
294
|
+
function resolveNoOps (options = {}) {
|
|
295
|
+
const sesh = new Session()
|
|
296
|
+
return options.noOps === true || options.opsOff === true || sesh.noOpsSync()
|
|
297
|
+
}
|
|
298
|
+
|
|
299
299
|
module.exports = {
|
|
300
300
|
// dotenv proxies
|
|
301
301
|
config,
|
|
@@ -25,19 +25,19 @@ const dotenvParse = require('./../helpers/dotenvParse')
|
|
|
25
25
|
const detectEncoding = require('./../helpers/detectEncoding')
|
|
26
26
|
|
|
27
27
|
class Decrypt {
|
|
28
|
-
constructor (envs = [], key = [], excludeKey = [], envKeysFilepath = null,
|
|
28
|
+
constructor (envs = [], key = [], excludeKey = [], envKeysFilepath = null, noOps = false) {
|
|
29
29
|
this.envs = determine(envs, process.env)
|
|
30
30
|
this.key = key
|
|
31
31
|
this.excludeKey = excludeKey
|
|
32
32
|
this.envKeysFilepath = envKeysFilepath
|
|
33
|
-
this.
|
|
33
|
+
this.noOps = noOps
|
|
34
34
|
|
|
35
35
|
this.processedEnvs = []
|
|
36
36
|
this.changedFilepaths = new Set()
|
|
37
37
|
this.unchangedFilepaths = new Set()
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
run () {
|
|
40
|
+
async run () {
|
|
41
41
|
// example
|
|
42
42
|
// envs [
|
|
43
43
|
// { type: 'envFile', value: '.env' }
|
|
@@ -51,7 +51,7 @@ class Decrypt {
|
|
|
51
51
|
|
|
52
52
|
for (const env of this.envs) {
|
|
53
53
|
if (env.type === TYPE_ENV_FILE) {
|
|
54
|
-
this._decryptEnvFile(env.value)
|
|
54
|
+
await this._decryptEnvFile(env.value)
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
57
|
|
|
@@ -62,7 +62,7 @@ class Decrypt {
|
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
-
_decryptEnvFile (envFilepath) {
|
|
65
|
+
async _decryptEnvFile (envFilepath) {
|
|
66
66
|
const row = {}
|
|
67
67
|
row.keys = []
|
|
68
68
|
row.type = TYPE_ENV_FILE
|
|
@@ -72,12 +72,12 @@ class Decrypt {
|
|
|
72
72
|
row.envFilepath = envFilepath
|
|
73
73
|
|
|
74
74
|
try {
|
|
75
|
-
const encoding = detectEncoding(filepath)
|
|
76
|
-
let envSrc = fsx.readFileX(filepath, { encoding })
|
|
75
|
+
const encoding = await detectEncoding(filepath)
|
|
76
|
+
let envSrc = await fsx.readFileX(filepath, { encoding })
|
|
77
77
|
const envParsed = dotenvParse(envSrc)
|
|
78
78
|
|
|
79
79
|
const { privateKeyName } = keyNames(envFilepath)
|
|
80
|
-
const { privateKeyValue } = keyValues(envFilepath, { keysFilepath: this.envKeysFilepath,
|
|
80
|
+
const { privateKeyValue } = await keyValues(envFilepath, { keysFilepath: this.envKeysFilepath, noOps: this.noOps })
|
|
81
81
|
|
|
82
82
|
row.privateKey = privateKeyValue
|
|
83
83
|
row.privateKeyName = privateKeyName
|
|
@@ -29,12 +29,12 @@ const detectEncoding = require('./../helpers/detectEncoding')
|
|
|
29
29
|
const SAMPLE_ENV_KIT = require('./../helpers/kits/sample')
|
|
30
30
|
|
|
31
31
|
class Encrypt {
|
|
32
|
-
constructor (envs = [], key = [], excludeKey = [], envKeysFilepath = null,
|
|
32
|
+
constructor (envs = [], key = [], excludeKey = [], envKeysFilepath = null, noOps = false, noCreate = false) {
|
|
33
33
|
this.envs = determine(envs, process.env)
|
|
34
34
|
this.key = key
|
|
35
35
|
this.excludeKey = excludeKey
|
|
36
36
|
this.envKeysFilepath = envKeysFilepath
|
|
37
|
-
this.
|
|
37
|
+
this.noOps = noOps
|
|
38
38
|
this.noCreate = noCreate
|
|
39
39
|
|
|
40
40
|
this.processedEnvs = []
|
|
@@ -42,7 +42,7 @@ class Encrypt {
|
|
|
42
42
|
this.unchangedFilepaths = new Set()
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
run () {
|
|
45
|
+
async run () {
|
|
46
46
|
// example
|
|
47
47
|
// envs [
|
|
48
48
|
// { type: 'envFile', value: '.env' }
|
|
@@ -56,7 +56,7 @@ class Encrypt {
|
|
|
56
56
|
|
|
57
57
|
for (const env of this.envs) {
|
|
58
58
|
if (env.type === TYPE_ENV_FILE) {
|
|
59
|
-
this._encryptEnvFile(env.value)
|
|
59
|
+
await this._encryptEnvFile(env.value)
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
62
|
|
|
@@ -67,10 +67,11 @@ class Encrypt {
|
|
|
67
67
|
}
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
_encryptEnvFile (envFilepath) {
|
|
70
|
+
async _encryptEnvFile (envFilepath) {
|
|
71
71
|
const row = {}
|
|
72
72
|
row.keys = []
|
|
73
73
|
row.type = TYPE_ENV_FILE
|
|
74
|
+
let fileCreated = false
|
|
74
75
|
|
|
75
76
|
const filepath = path.resolve(envFilepath)
|
|
76
77
|
row.filepath = filepath
|
|
@@ -79,14 +80,16 @@ class Encrypt {
|
|
|
79
80
|
try {
|
|
80
81
|
// if noCreate is on then detectEncoding will throw and we'll halt the calls
|
|
81
82
|
// but if noCreate is false then create the file if it doesn't exist
|
|
82
|
-
if (!fsx.
|
|
83
|
-
fsx.writeFileX(filepath, SAMPLE_ENV_KIT)
|
|
83
|
+
if (!(await fsx.exists(filepath)) && !this.noCreate) {
|
|
84
|
+
await fsx.writeFileX(filepath, SAMPLE_ENV_KIT)
|
|
85
|
+
fileCreated = true
|
|
84
86
|
}
|
|
85
|
-
const encoding = detectEncoding(filepath)
|
|
86
|
-
let envSrc = fsx.readFileX(filepath, { encoding })
|
|
87
|
+
const encoding = await detectEncoding(filepath)
|
|
88
|
+
let envSrc = await fsx.readFileX(filepath, { encoding })
|
|
87
89
|
if (envSrc.trim().length === 0) {
|
|
88
90
|
envSrc = SAMPLE_ENV_KIT
|
|
89
91
|
row.kitCreated = 'sample'
|
|
92
|
+
row.changed = true
|
|
90
93
|
}
|
|
91
94
|
const envParsed = dotenvParse(envSrc)
|
|
92
95
|
|
|
@@ -94,11 +97,11 @@ class Encrypt {
|
|
|
94
97
|
let privateKey
|
|
95
98
|
|
|
96
99
|
const { publicKeyName, privateKeyName } = keyNames(envFilepath)
|
|
97
|
-
const { publicKeyValue, privateKeyValue } = keyValues(envFilepath, { keysFilepath: this.envKeysFilepath,
|
|
100
|
+
const { publicKeyValue, privateKeyValue } = await keyValues(envFilepath, { keysFilepath: this.envKeysFilepath, noOps: this.noOps })
|
|
98
101
|
|
|
99
102
|
// first pass - provision
|
|
100
103
|
if (!privateKeyValue && !publicKeyValue) {
|
|
101
|
-
const prov = provision({ envSrc, envFilepath, keysFilepath: this.envKeysFilepath,
|
|
104
|
+
const prov = await provision({ envSrc, envFilepath, keysFilepath: this.envKeysFilepath, noOps: this.noOps })
|
|
102
105
|
envSrc = prov.envSrc
|
|
103
106
|
publicKey = prov.publicKey
|
|
104
107
|
privateKey = prov.privateKey
|
|
@@ -148,6 +151,9 @@ class Encrypt {
|
|
|
148
151
|
}
|
|
149
152
|
|
|
150
153
|
row.envSrc = envSrc
|
|
154
|
+
if (fileCreated) {
|
|
155
|
+
row.changed = true
|
|
156
|
+
}
|
|
151
157
|
if (row.changed) {
|
|
152
158
|
this.changedFilepaths.add(envFilepath)
|
|
153
159
|
} else {
|
|
@@ -39,7 +39,7 @@ class Genexample {
|
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
// get the original src
|
|
42
|
-
let src = fsx.
|
|
42
|
+
let src = fsx.readFileXSync(filepath)
|
|
43
43
|
const parsed = dotenvParse(src)
|
|
44
44
|
for (const key in parsed) {
|
|
45
45
|
// used later
|
|
@@ -63,7 +63,7 @@ class Genexample {
|
|
|
63
63
|
}
|
|
64
64
|
} else {
|
|
65
65
|
// it already exists (which means the user might have it modified a way in which they prefer, so replace exampleSrc with their existing .env.example)
|
|
66
|
-
exampleSrc = fsx.
|
|
66
|
+
exampleSrc = fsx.readFileXSync(this.exampleFilepath)
|
|
67
67
|
|
|
68
68
|
const parsed = dotenvParse(exampleSrc)
|
|
69
69
|
for (const key of [...keys]) {
|
package/src/lib/services/get.js
CHANGED
|
@@ -2,19 +2,28 @@ const Run = require('./run')
|
|
|
2
2
|
const Errors = require('./../helpers/errors')
|
|
3
3
|
|
|
4
4
|
class Get {
|
|
5
|
-
constructor (key, envs = [], overload = false, all = false, envKeysFilepath = null,
|
|
5
|
+
constructor (key, envs = [], overload = false, all = false, envKeysFilepath = null, noOps = false) {
|
|
6
6
|
this.key = key
|
|
7
7
|
this.envs = envs
|
|
8
8
|
this.overload = overload
|
|
9
9
|
this.all = all
|
|
10
10
|
this.envKeysFilepath = envKeysFilepath
|
|
11
|
-
this.
|
|
11
|
+
this.noOps = noOps
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
runSync () {
|
|
15
15
|
const processEnv = { ...process.env }
|
|
16
|
-
const { processedEnvs } = new Run(this.envs, this.overload, processEnv, this.envKeysFilepath, this.
|
|
16
|
+
const { processedEnvs } = new Run(this.envs, this.overload, processEnv, this.envKeysFilepath, this.noOps).runSync()
|
|
17
|
+
return this._result(processedEnvs, processEnv)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
async run () {
|
|
21
|
+
const processEnv = { ...process.env }
|
|
22
|
+
const { processedEnvs } = await new Run(this.envs, this.overload, processEnv, this.envKeysFilepath, this.noOps).run()
|
|
23
|
+
return this._result(processedEnvs, processEnv)
|
|
24
|
+
}
|
|
17
25
|
|
|
26
|
+
_result (processedEnvs, processEnv) {
|
|
18
27
|
const errors = []
|
|
19
28
|
for (const processedEnv of processedEnvs) {
|
|
20
29
|
for (const error of processedEnv.errors) {
|
|
@@ -32,27 +41,27 @@ class Get {
|
|
|
32
41
|
}
|
|
33
42
|
|
|
34
43
|
return { parsed, errors }
|
|
35
|
-
}
|
|
36
|
-
// if user wants to return ALL envs (even prior set on machine)
|
|
37
|
-
if (this.all) {
|
|
38
|
-
return { parsed: processEnv, errors }
|
|
39
|
-
}
|
|
44
|
+
}
|
|
40
45
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
46
|
+
// if user wants to return ALL envs (even prior set on machine)
|
|
47
|
+
if (this.all) {
|
|
48
|
+
return { parsed: processEnv, errors }
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// typical scenario - return only envs that were identified in the .env file
|
|
52
|
+
// iterate over all processedEnvs.parsed and grab from processEnv
|
|
53
|
+
/** @type {Record<string, string>} */
|
|
54
|
+
const parsed = {}
|
|
55
|
+
for (const processedEnv of processedEnvs) {
|
|
56
|
+
// parsed means we saw the key in a file or --env flag. this effectively filters out any preset machine envs - while still respecting complex evaluating, expansion, and overload. in other words, the value might be the machine value because the key was displayed in a .env file
|
|
57
|
+
if (processedEnv.parsed) {
|
|
58
|
+
for (const key of Object.keys(processedEnv.parsed)) {
|
|
59
|
+
parsed[key] = processEnv[key]
|
|
51
60
|
}
|
|
52
61
|
}
|
|
53
|
-
|
|
54
|
-
return { parsed, errors }
|
|
55
62
|
}
|
|
63
|
+
|
|
64
|
+
return { parsed, errors }
|
|
56
65
|
}
|
|
57
66
|
}
|
|
58
67
|
|