@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
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "1.
|
|
2
|
+
"version": "1.60.0",
|
|
3
3
|
"name": "@dotenvx/dotenvx",
|
|
4
|
-
"description": "
|
|
4
|
+
"description": "secrets for agents–from the creator of `dotenv`",
|
|
5
5
|
"author": "@motdotla",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"dotenv",
|
|
@@ -35,8 +35,8 @@
|
|
|
35
35
|
"scripts": {
|
|
36
36
|
"standard": "standard",
|
|
37
37
|
"standard:fix": "standard --fix",
|
|
38
|
-
"test": "tap run --test-env=
|
|
39
|
-
"test-coverage": "tap run --test-env=
|
|
38
|
+
"test": "tap run --test-env=DOTENVX_NO_OPS=true --allow-empty-coverage --disable-coverage --timeout=60000",
|
|
39
|
+
"test-coverage": "tap run --test-env=DOTENVX_NO_OPS=true --show-full-coverage --timeout=60000",
|
|
40
40
|
"testshell": "bash shellspec",
|
|
41
41
|
"prerelease": "npm test && npm run testshell",
|
|
42
42
|
"release": "standard-version"
|
|
@@ -51,10 +51,11 @@
|
|
|
51
51
|
"ignore": "^5.3.0",
|
|
52
52
|
"object-treeify": "1.1.33",
|
|
53
53
|
"picomatch": "^4.0.2",
|
|
54
|
-
"which": "^4.0.0"
|
|
54
|
+
"which": "^4.0.0",
|
|
55
|
+
"yocto-spinner": "^1.1.0"
|
|
55
56
|
},
|
|
56
57
|
"devDependencies": {
|
|
57
|
-
"@yao-pkg/pkg": "^
|
|
58
|
+
"@yao-pkg/pkg": "^6.14.2",
|
|
58
59
|
"capture-console": "^1.0.2",
|
|
59
60
|
"esbuild": "^0.25.8",
|
|
60
61
|
"proxyquire": "^2.1.3",
|
|
@@ -3,13 +3,18 @@ const { logger } = require('./../../shared/logger')
|
|
|
3
3
|
|
|
4
4
|
const Decrypt = require('./../../lib/services/decrypt')
|
|
5
5
|
const catchAndLog = require('../../lib/helpers/catchAndLog')
|
|
6
|
+
const createSpinner = require('../../lib/helpers/createSpinner')
|
|
7
|
+
const Session = require('../../db/session')
|
|
6
8
|
|
|
7
|
-
function decrypt () {
|
|
9
|
+
async function decrypt () {
|
|
8
10
|
const options = this.opts()
|
|
11
|
+
const spinner = await createSpinner({ ...options, text: 'decrypting' })
|
|
12
|
+
|
|
9
13
|
logger.debug(`options: ${JSON.stringify(options)}`)
|
|
10
14
|
|
|
15
|
+
const sesh = new Session()
|
|
11
16
|
const envs = this.envs
|
|
12
|
-
const
|
|
17
|
+
const noOps = options.ops === false || (await sesh.noOps())
|
|
13
18
|
|
|
14
19
|
let errorCount = 0
|
|
15
20
|
|
|
@@ -17,8 +22,8 @@ function decrypt () {
|
|
|
17
22
|
if (options.stdout) {
|
|
18
23
|
const {
|
|
19
24
|
processedEnvs
|
|
20
|
-
} = new Decrypt(envs, options.key, options.excludeKey, options.envKeysFile,
|
|
21
|
-
|
|
25
|
+
} = await new Decrypt(envs, options.key, options.excludeKey, options.envKeysFile, noOps).run()
|
|
26
|
+
if (spinner) spinner.stop()
|
|
22
27
|
for (const processedEnv of processedEnvs) {
|
|
23
28
|
if (processedEnv.error) {
|
|
24
29
|
errorCount += 1
|
|
@@ -39,7 +44,7 @@ function decrypt () {
|
|
|
39
44
|
processedEnvs,
|
|
40
45
|
changedFilepaths,
|
|
41
46
|
unchangedFilepaths
|
|
42
|
-
} = new Decrypt(envs, options.key, options.excludeKey, options.envKeysFile,
|
|
47
|
+
} = await new Decrypt(envs, options.key, options.excludeKey, options.envKeysFile, noOps).run()
|
|
43
48
|
|
|
44
49
|
for (const processedEnv of processedEnvs) {
|
|
45
50
|
logger.verbose(`decrypting ${processedEnv.envFilepath} (${processedEnv.filepath})`)
|
|
@@ -48,18 +53,19 @@ function decrypt () {
|
|
|
48
53
|
errorCount += 1
|
|
49
54
|
logger.error(processedEnv.error.messageWithHelp)
|
|
50
55
|
} else if (processedEnv.changed) {
|
|
51
|
-
fsx.writeFileX(processedEnv.filepath, processedEnv.envSrc)
|
|
56
|
+
await fsx.writeFileX(processedEnv.filepath, processedEnv.envSrc)
|
|
52
57
|
|
|
53
58
|
logger.verbose(`decrypted ${processedEnv.envFilepath} (${processedEnv.filepath})`)
|
|
54
59
|
} else {
|
|
55
|
-
logger.verbose(`no
|
|
60
|
+
logger.verbose(`no change ${processedEnv.envFilepath} (${processedEnv.filepath})`)
|
|
56
61
|
}
|
|
57
62
|
}
|
|
58
63
|
|
|
64
|
+
if (spinner) spinner.stop()
|
|
59
65
|
if (changedFilepaths.length > 0) {
|
|
60
66
|
logger.success(`◇ decrypted (${changedFilepaths.join(',')})`)
|
|
61
67
|
} else if (unchangedFilepaths.length > 0) {
|
|
62
|
-
logger.info(`○ no
|
|
68
|
+
logger.info(`○ no change (${unchangedFilepaths})`)
|
|
63
69
|
} else {
|
|
64
70
|
// do nothing - scenario when no .env files found
|
|
65
71
|
}
|
|
@@ -68,6 +74,7 @@ function decrypt () {
|
|
|
68
74
|
process.exit(1)
|
|
69
75
|
}
|
|
70
76
|
} catch (error) {
|
|
77
|
+
if (spinner) spinner.stop()
|
|
71
78
|
catchAndLog(error)
|
|
72
79
|
process.exit(1)
|
|
73
80
|
}
|
|
@@ -5,21 +5,26 @@ const Encrypt = require('./../../lib/services/encrypt')
|
|
|
5
5
|
|
|
6
6
|
const catchAndLog = require('../../lib/helpers/catchAndLog')
|
|
7
7
|
const localDisplayPath = require('../../lib/helpers/localDisplayPath')
|
|
8
|
+
const createSpinner = require('../../lib/helpers/createSpinner')
|
|
9
|
+
const Session = require('../../db/session')
|
|
8
10
|
|
|
9
|
-
function encrypt () {
|
|
11
|
+
async function encrypt () {
|
|
10
12
|
const options = this.opts()
|
|
13
|
+
const spinner = await createSpinner({ ...options, text: 'encrypting' })
|
|
14
|
+
|
|
11
15
|
logger.debug(`options: ${JSON.stringify(options)}`)
|
|
12
16
|
|
|
17
|
+
const sesh = new Session()
|
|
13
18
|
const envs = this.envs
|
|
14
|
-
const
|
|
19
|
+
const noOps = options.ops === false || (await sesh.noOps())
|
|
15
20
|
const noCreate = options.create === false
|
|
16
21
|
|
|
17
22
|
// stdout - should not have a try so that exit codes can surface to stdout
|
|
18
23
|
if (options.stdout) {
|
|
19
24
|
const {
|
|
20
25
|
processedEnvs
|
|
21
|
-
} = new Encrypt(envs, options.key, options.excludeKey, options.envKeysFile,
|
|
22
|
-
|
|
26
|
+
} = await new Encrypt(envs, options.key, options.excludeKey, options.envKeysFile, noOps, noCreate).run()
|
|
27
|
+
if (spinner) spinner.stop()
|
|
23
28
|
for (const processedEnv of processedEnvs) {
|
|
24
29
|
console.log(processedEnv.envSrc)
|
|
25
30
|
}
|
|
@@ -30,21 +35,22 @@ function encrypt () {
|
|
|
30
35
|
processedEnvs,
|
|
31
36
|
changedFilepaths,
|
|
32
37
|
unchangedFilepaths
|
|
33
|
-
} = new Encrypt(envs, options.key, options.excludeKey, options.envKeysFile,
|
|
38
|
+
} = await new Encrypt(envs, options.key, options.excludeKey, options.envKeysFile, noOps, noCreate).run()
|
|
34
39
|
|
|
35
40
|
for (const processedEnv of processedEnvs) {
|
|
36
41
|
logger.verbose(`encrypting ${processedEnv.envFilepath} (${processedEnv.filepath})`)
|
|
37
42
|
if (processedEnv.error) {
|
|
38
43
|
logger.warn(processedEnv.error.messageWithHelp)
|
|
39
44
|
} else if (processedEnv.changed) {
|
|
40
|
-
fsx.writeFileX(processedEnv.filepath, processedEnv.envSrc)
|
|
45
|
+
await fsx.writeFileX(processedEnv.filepath, processedEnv.envSrc)
|
|
41
46
|
|
|
42
47
|
logger.verbose(`encrypted ${processedEnv.envFilepath} (${processedEnv.filepath})`)
|
|
43
48
|
} else {
|
|
44
|
-
logger.verbose(`no
|
|
49
|
+
logger.verbose(`no change ${processedEnv.envFilepath} (${processedEnv.filepath})`)
|
|
45
50
|
}
|
|
46
51
|
}
|
|
47
52
|
|
|
53
|
+
if (spinner) spinner.stop()
|
|
48
54
|
if (changedFilepaths.length > 0) {
|
|
49
55
|
const keyAddedEnv = processedEnvs.find((processedEnv) => processedEnv.privateKeyAdded)
|
|
50
56
|
let msg = `◈ encrypted (${changedFilepaths.join(',')})`
|
|
@@ -54,7 +60,7 @@ function encrypt () {
|
|
|
54
60
|
}
|
|
55
61
|
logger.success(msg)
|
|
56
62
|
} else if (unchangedFilepaths.length > 0) {
|
|
57
|
-
logger.info(`○ no
|
|
63
|
+
logger.info(`○ no change (${unchangedFilepaths})`)
|
|
58
64
|
} else {
|
|
59
65
|
// do nothing - scenario when no .env files found
|
|
60
66
|
}
|
|
@@ -65,6 +71,7 @@ function encrypt () {
|
|
|
65
71
|
}
|
|
66
72
|
}
|
|
67
73
|
} catch (error) {
|
|
74
|
+
if (spinner) spinner.stop()
|
|
68
75
|
catchAndLog(error)
|
|
69
76
|
process.exit(1)
|
|
70
77
|
}
|
|
@@ -20,12 +20,12 @@ function genexample (directory) {
|
|
|
20
20
|
|
|
21
21
|
logger.verbose(`loading env from ${envFile}`)
|
|
22
22
|
|
|
23
|
-
fsx.
|
|
23
|
+
fsx.writeFileXSync(exampleFilepath, envExampleFile)
|
|
24
24
|
|
|
25
25
|
if (addedKeys.length > 0) {
|
|
26
26
|
logger.success(`▣ generated (${path.basename(exampleFilepath)})`)
|
|
27
27
|
} else {
|
|
28
|
-
logger.info('○ no
|
|
28
|
+
logger.info('○ no change (.env.example)')
|
|
29
29
|
}
|
|
30
30
|
} catch (error) {
|
|
31
31
|
catchAndLog(error)
|
|
@@ -18,13 +18,13 @@ class Generic {
|
|
|
18
18
|
const changedPatterns = []
|
|
19
19
|
if (!fsx.existsSync(this.filename)) {
|
|
20
20
|
if (this.touchFile === true && this.patterns.length > 0) {
|
|
21
|
-
fsx.
|
|
21
|
+
fsx.writeFileXSync(this.filename, '')
|
|
22
22
|
} else {
|
|
23
23
|
return
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
const lines = fsx.
|
|
27
|
+
const lines = fsx.readFileXSync(this.filename).split(/\r?\n/)
|
|
28
28
|
this.patterns.forEach(pattern => {
|
|
29
29
|
if (!lines.includes(pattern.trim())) {
|
|
30
30
|
this.append(pattern)
|
|
@@ -36,7 +36,7 @@ class Generic {
|
|
|
36
36
|
if (changedPatterns.length > 0) {
|
|
37
37
|
logger.success(`▣ ignored ${this.patterns} (${this.filename})`)
|
|
38
38
|
} else {
|
|
39
|
-
logger.info(`○ no
|
|
39
|
+
logger.info(`○ no change (${this.filename})`)
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
42
|
}
|
package/src/cli/actions/get.js
CHANGED
|
@@ -3,18 +3,20 @@ const { logger } = require('./../../shared/logger')
|
|
|
3
3
|
const conventions = require('./../../lib/helpers/conventions')
|
|
4
4
|
const escape = require('./../../lib/helpers/escape')
|
|
5
5
|
const catchAndLog = require('./../../lib/helpers/catchAndLog')
|
|
6
|
-
|
|
6
|
+
const createSpinner = require('../../lib/helpers/createSpinner')
|
|
7
|
+
const Session = require('../../db/session')
|
|
7
8
|
const Get = require('./../../lib/services/get')
|
|
8
9
|
|
|
9
|
-
function get (key) {
|
|
10
|
+
async function get (key) {
|
|
11
|
+
const options = this.opts()
|
|
12
|
+
const spinner = await createSpinner({ ...options, text: 'decrypting' })
|
|
13
|
+
|
|
14
|
+
logger.debug(`options: ${JSON.stringify(options)}`)
|
|
10
15
|
if (key) {
|
|
11
16
|
logger.debug(`key: ${key}`)
|
|
12
17
|
}
|
|
13
18
|
|
|
14
|
-
const options = this.opts()
|
|
15
|
-
logger.debug(`options: ${JSON.stringify(options)}`)
|
|
16
19
|
const prettyPrint = options.prettyPrint || options.pp
|
|
17
|
-
|
|
18
20
|
const ignore = options.ignore || []
|
|
19
21
|
|
|
20
22
|
let envs = []
|
|
@@ -26,8 +28,9 @@ function get (key) {
|
|
|
26
28
|
}
|
|
27
29
|
|
|
28
30
|
try {
|
|
29
|
-
const
|
|
30
|
-
const
|
|
31
|
+
const sesh = new Session()
|
|
32
|
+
const noOps = options.ops === false || (await sesh.noOps())
|
|
33
|
+
const { parsed, errors } = await new Get(key, envs, options.overload, options.all, options.envKeysFile, noOps).run()
|
|
31
34
|
|
|
32
35
|
for (const error of errors || []) {
|
|
33
36
|
if (options.strict) throw error // throw immediately if strict
|
|
@@ -39,6 +42,7 @@ function get (key) {
|
|
|
39
42
|
logger.error(error.messageWithHelp)
|
|
40
43
|
}
|
|
41
44
|
|
|
45
|
+
if (spinner) spinner.stop()
|
|
42
46
|
if (key) {
|
|
43
47
|
const single = parsed[key]
|
|
44
48
|
if (single === undefined) {
|
|
@@ -73,6 +77,7 @@ function get (key) {
|
|
|
73
77
|
}
|
|
74
78
|
}
|
|
75
79
|
} catch (error) {
|
|
80
|
+
if (spinner) spinner.stop()
|
|
76
81
|
catchAndLog(error)
|
|
77
82
|
process.exit(1)
|
|
78
83
|
}
|
|
@@ -1,18 +1,26 @@
|
|
|
1
1
|
const { logger } = require('./../../shared/logger')
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const Keypair = require('./../../lib/services/keypair')
|
|
4
|
+
const createSpinner = require('../../lib/helpers/createSpinner')
|
|
5
|
+
const Session = require('../../db/session')
|
|
4
6
|
|
|
5
|
-
function keypair (key) {
|
|
7
|
+
async function keypair (key) {
|
|
8
|
+
const options = this.opts()
|
|
9
|
+
const spinner = await createSpinner({ ...options, text: 'retrieving' })
|
|
10
|
+
|
|
11
|
+
logger.debug(`options: ${JSON.stringify(options)}`)
|
|
6
12
|
if (key) {
|
|
7
13
|
logger.debug(`key: ${key}`)
|
|
8
14
|
}
|
|
9
15
|
|
|
10
|
-
const options = this.opts()
|
|
11
|
-
logger.debug(`options: ${JSON.stringify(options)}`)
|
|
12
16
|
const prettyPrint = options.prettyPrint || options.pp
|
|
13
17
|
|
|
14
|
-
const
|
|
18
|
+
const sesh = new Session()
|
|
19
|
+
const noOps = options.ops === false || await sesh.noOps()
|
|
20
|
+
const keypairs = await new Keypair(options.envFile, options.envKeysFile, noOps).run()
|
|
21
|
+
const results = key ? keypairs[key] : keypairs
|
|
15
22
|
|
|
23
|
+
if (spinner) spinner.stop()
|
|
16
24
|
if (typeof results === 'object' && results !== null) {
|
|
17
25
|
// inline shell format - env $(dotenvx keypair --format=shell) your-command
|
|
18
26
|
if (options.format === 'shell') {
|
|
@@ -4,21 +4,26 @@ const { logger } = require('./../../shared/logger')
|
|
|
4
4
|
const Rotate = require('./../../lib/services/rotate')
|
|
5
5
|
|
|
6
6
|
const catchAndLog = require('../../lib/helpers/catchAndLog')
|
|
7
|
+
const createSpinner = require('../../lib/helpers/createSpinner')
|
|
7
8
|
const localDisplayPath = require('../../lib/helpers/localDisplayPath')
|
|
9
|
+
const Session = require('../../db/session')
|
|
8
10
|
|
|
9
|
-
function rotate () {
|
|
11
|
+
async function rotate () {
|
|
10
12
|
const options = this.opts()
|
|
13
|
+
const spinner = await createSpinner({ ...options, text: 'rotating', frames: ['⟳', '⤾', '⥁'] })
|
|
14
|
+
|
|
11
15
|
logger.debug(`options: ${JSON.stringify(options)}`)
|
|
12
16
|
|
|
13
17
|
const envs = this.envs
|
|
14
|
-
const
|
|
18
|
+
const sesh = new Session()
|
|
19
|
+
const noOps = options.ops === false || (await sesh.noOps())
|
|
15
20
|
|
|
16
21
|
// stdout - should not have a try so that exit codes can surface to stdout
|
|
17
22
|
if (options.stdout) {
|
|
18
23
|
const {
|
|
19
24
|
processedEnvs
|
|
20
|
-
} = new Rotate(envs, options.key, options.excludeKey, options.envKeysFile,
|
|
21
|
-
|
|
25
|
+
} = await new Rotate(envs, options.key, options.excludeKey, options.envKeysFile, noOps).run()
|
|
26
|
+
if (spinner) spinner.stop()
|
|
22
27
|
for (const processedEnv of processedEnvs) {
|
|
23
28
|
console.log(processedEnv.envSrc)
|
|
24
29
|
if (processedEnv.privateKeyAdded) {
|
|
@@ -33,24 +38,25 @@ function rotate () {
|
|
|
33
38
|
processedEnvs,
|
|
34
39
|
changedFilepaths,
|
|
35
40
|
unchangedFilepaths
|
|
36
|
-
} = new Rotate(envs, options.key, options.excludeKey, options.envKeysFile,
|
|
41
|
+
} = await new Rotate(envs, options.key, options.excludeKey, options.envKeysFile, noOps).run()
|
|
37
42
|
|
|
38
43
|
for (const processedEnv of processedEnvs) {
|
|
39
44
|
logger.verbose(`rotating ${processedEnv.envFilepath} (${processedEnv.filepath})`)
|
|
40
45
|
if (processedEnv.error) {
|
|
41
46
|
logger.warn(processedEnv.error.messageWithHelp)
|
|
42
47
|
} else if (processedEnv.changed) {
|
|
43
|
-
fsx.writeFileX(processedEnv.filepath, processedEnv.envSrc)
|
|
48
|
+
await fsx.writeFileX(processedEnv.filepath, processedEnv.envSrc)
|
|
44
49
|
if (processedEnv.privateKeyAdded) {
|
|
45
|
-
fsx.writeFileX(processedEnv.envKeysFilepath, processedEnv.envKeysSrc)
|
|
50
|
+
await fsx.writeFileX(processedEnv.envKeysFilepath, processedEnv.envKeysSrc)
|
|
46
51
|
}
|
|
47
52
|
|
|
48
53
|
logger.verbose(`rotated ${processedEnv.envFilepath} (${processedEnv.filepath})`)
|
|
49
54
|
} else {
|
|
50
|
-
logger.verbose(`no
|
|
55
|
+
logger.verbose(`no change ${processedEnv.envFilepath} (${processedEnv.filepath})`)
|
|
51
56
|
}
|
|
52
57
|
}
|
|
53
58
|
|
|
59
|
+
if (spinner) spinner.stop()
|
|
54
60
|
if (changedFilepaths.length > 0) {
|
|
55
61
|
const keyAddedEnv = processedEnvs.find((processedEnv) => processedEnv.privateKeyAdded)
|
|
56
62
|
let msg = `⟳ rotated (${changedFilepaths.join(',')})`
|
|
@@ -60,11 +66,12 @@ function rotate () {
|
|
|
60
66
|
}
|
|
61
67
|
logger.success(msg)
|
|
62
68
|
} else if (unchangedFilepaths.length > 0) {
|
|
63
|
-
logger.info(`○ no
|
|
69
|
+
logger.info(`○ no change (${unchangedFilepaths})`)
|
|
64
70
|
} else {
|
|
65
71
|
// do nothing - scenario when no .env files found
|
|
66
72
|
}
|
|
67
73
|
} catch (error) {
|
|
74
|
+
if (spinner) spinner.stop()
|
|
68
75
|
catchAndLog(error)
|
|
69
76
|
process.exit(1)
|
|
70
77
|
}
|
package/src/cli/actions/run.js
CHANGED
|
@@ -4,22 +4,27 @@ const { logger } = require('./../../shared/logger')
|
|
|
4
4
|
const executeCommand = require('./../../lib/helpers/executeCommand')
|
|
5
5
|
const Run = require('./../../lib/services/run')
|
|
6
6
|
const catchAndLog = require('./../../lib/helpers/catchAndLog')
|
|
7
|
+
const createSpinner = require('../../lib/helpers/createSpinner')
|
|
8
|
+
const Session = require('../../db/session')
|
|
7
9
|
|
|
8
10
|
const conventions = require('./../../lib/helpers/conventions')
|
|
9
11
|
|
|
10
12
|
async function run () {
|
|
13
|
+
const options = this.opts()
|
|
11
14
|
const commandArgs = this.args
|
|
12
|
-
|
|
15
|
+
const spinner = await createSpinner({ ...options, text: 'injecting' })
|
|
13
16
|
|
|
14
|
-
const options = this.opts()
|
|
15
17
|
logger.debug(`options: ${JSON.stringify(options)}`)
|
|
18
|
+
logger.debug(`process command [${commandArgs.join(' ')}]`)
|
|
16
19
|
|
|
17
20
|
const ignore = options.ignore || []
|
|
18
21
|
|
|
19
|
-
|
|
20
|
-
const
|
|
22
|
+
const sesh = new Session()
|
|
23
|
+
const noOps = options.ops === false || options.opsOff === true || (await sesh.noOps())
|
|
21
24
|
|
|
22
25
|
if (commandArgs.length < 1) {
|
|
26
|
+
if (spinner) spinner.stop()
|
|
27
|
+
|
|
23
28
|
const hasSeparator = process.argv.indexOf('--') !== -1
|
|
24
29
|
|
|
25
30
|
if (hasSeparator) {
|
|
@@ -46,7 +51,7 @@ async function run () {
|
|
|
46
51
|
readableStrings,
|
|
47
52
|
readableFilepaths,
|
|
48
53
|
uniqueInjectedKeys
|
|
49
|
-
} = new Run(envs, options.overload, process.env, options.envKeysFile,
|
|
54
|
+
} = await new Run(envs, options.overload, process.env, options.envKeysFile, noOps).run()
|
|
50
55
|
|
|
51
56
|
for (const processedEnv of processedEnvs) {
|
|
52
57
|
if (processedEnv.type === 'envFile') {
|
|
@@ -88,7 +93,7 @@ async function run () {
|
|
|
88
93
|
}
|
|
89
94
|
}
|
|
90
95
|
|
|
91
|
-
let msg = `
|
|
96
|
+
let msg = `injected env (${uniqueInjectedKeys.length})`
|
|
92
97
|
if (readableFilepaths.length > 0 && readableStrings.length > 0) {
|
|
93
98
|
msg += ` from ${readableFilepaths.join(', ')}, and --env flag${readableStrings.length > 1 ? 's' : ''}`
|
|
94
99
|
} else if (readableFilepaths.length > 0) {
|
|
@@ -97,8 +102,10 @@ async function run () {
|
|
|
97
102
|
msg += ` from --env flag${readableStrings.length > 1 ? 's' : ''}`
|
|
98
103
|
}
|
|
99
104
|
|
|
105
|
+
if (spinner) spinner.stop()
|
|
100
106
|
logger.successv(msg)
|
|
101
107
|
} catch (error) {
|
|
108
|
+
if (spinner) spinner.stop()
|
|
102
109
|
catchAndLog(error)
|
|
103
110
|
process.exit(1)
|
|
104
111
|
}
|
package/src/cli/actions/set.js
CHANGED
|
@@ -1,35 +1,40 @@
|
|
|
1
1
|
const fsx = require('./../../lib/helpers/fsx')
|
|
2
2
|
const { logger } = require('./../../shared/logger')
|
|
3
3
|
|
|
4
|
-
const Sets = require('./../../lib/services/sets')
|
|
5
|
-
|
|
6
4
|
const catchAndLog = require('../../lib/helpers/catchAndLog')
|
|
5
|
+
const createSpinner = require('../../lib/helpers/createSpinner')
|
|
7
6
|
const localDisplayPath = require('../../lib/helpers/localDisplayPath')
|
|
7
|
+
const Session = require('../../db/session')
|
|
8
|
+
const Sets = require('./../../lib/services/sets')
|
|
8
9
|
|
|
9
|
-
function set (key, value) {
|
|
10
|
-
logger.debug(`key: ${key}`)
|
|
11
|
-
logger.debug(`value: ${value}`)
|
|
12
|
-
|
|
10
|
+
async function set (key, value) {
|
|
13
11
|
const options = this.opts()
|
|
14
|
-
logger.debug(`options: ${JSON.stringify(options)}`)
|
|
15
12
|
|
|
16
|
-
// encrypt
|
|
17
13
|
let encrypt = true
|
|
14
|
+
let settingMessage = 'encrypting'
|
|
18
15
|
if (options.plain) {
|
|
19
16
|
encrypt = false
|
|
17
|
+
settingMessage = 'setting'
|
|
20
18
|
}
|
|
21
19
|
|
|
20
|
+
const spinner = await createSpinner({ ...options, text: settingMessage })
|
|
21
|
+
|
|
22
|
+
logger.debug(`key: ${key}`)
|
|
23
|
+
logger.debug(`value: ${value}`)
|
|
24
|
+
logger.debug(`options: ${JSON.stringify(options)}`)
|
|
25
|
+
|
|
22
26
|
try {
|
|
27
|
+
const sesh = new Session()
|
|
23
28
|
const envs = this.envs
|
|
24
29
|
const envKeysFilepath = options.envKeysFile
|
|
25
|
-
const
|
|
30
|
+
const noOps = options.ops === false || (await sesh.noOps())
|
|
26
31
|
const noCreate = options.create === false
|
|
27
32
|
|
|
28
33
|
const {
|
|
29
34
|
processedEnvs,
|
|
30
35
|
changedFilepaths,
|
|
31
36
|
unchangedFilepaths
|
|
32
|
-
} = new Sets(key, value, envs, encrypt, envKeysFilepath,
|
|
37
|
+
} = await new Sets(key, value, envs, encrypt, envKeysFilepath, noOps, noCreate).run()
|
|
33
38
|
|
|
34
39
|
let withEncryption = ''
|
|
35
40
|
|
|
@@ -43,7 +48,7 @@ function set (key, value) {
|
|
|
43
48
|
if (processedEnv.error) {
|
|
44
49
|
logger.warn(processedEnv.error.messageWithHelp)
|
|
45
50
|
} else {
|
|
46
|
-
fsx.writeFileX(processedEnv.filepath, processedEnv.envSrc)
|
|
51
|
+
await fsx.writeFileX(processedEnv.filepath, processedEnv.envSrc)
|
|
47
52
|
|
|
48
53
|
logger.verbose(`${processedEnv.key} set${withEncryption} (${processedEnv.envFilepath})`)
|
|
49
54
|
logger.debug(`${processedEnv.key} set${withEncryption} to ${processedEnv.value} (${processedEnv.envFilepath})`)
|
|
@@ -53,6 +58,7 @@ function set (key, value) {
|
|
|
53
58
|
const keyAddedEnv = processedEnvs.find((processedEnv) => processedEnv.privateKeyAdded)
|
|
54
59
|
const keyAddedSuffix = keyAddedEnv ? ` + key (${localDisplayPath(keyAddedEnv.envKeysFilepath)})` : ''
|
|
55
60
|
|
|
61
|
+
if (spinner) spinner.stop()
|
|
56
62
|
if (changedFilepaths.length > 0) {
|
|
57
63
|
if (encrypt) {
|
|
58
64
|
logger.success(`◈ encrypted ${key} (${changedFilepaths.join(',')})${keyAddedSuffix}`)
|
|
@@ -63,13 +69,14 @@ function set (key, value) {
|
|
|
63
69
|
const keyAddedEnvFilepath = keyAddedEnv.envFilepath || changedFilepaths[0] || '.env'
|
|
64
70
|
logger.success(`◈ encrypted ${key} (${keyAddedEnvFilepath})${keyAddedSuffix}`)
|
|
65
71
|
} else if (unchangedFilepaths.length > 0) {
|
|
66
|
-
logger.info(`○ no
|
|
72
|
+
logger.info(`○ no change (${unchangedFilepaths})`)
|
|
67
73
|
} else {
|
|
68
74
|
// do nothing
|
|
69
75
|
}
|
|
70
76
|
|
|
71
77
|
// intentionally quiet: success line communicates key creation
|
|
72
78
|
} catch (error) {
|
|
79
|
+
if (spinner) spinner.stop()
|
|
73
80
|
catchAndLog(error)
|
|
74
81
|
process.exit(1)
|
|
75
82
|
}
|
package/src/cli/dotenvx.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
/* c8 ignore start */
|
|
4
|
-
const { Command } = require('commander')
|
|
4
|
+
const { Command, Option } = require('commander')
|
|
5
5
|
const program = new Command()
|
|
6
6
|
|
|
7
7
|
const { setLogLevel, logger } = require('../shared/logger')
|
|
@@ -13,9 +13,6 @@ const executeDynamic = require('./../lib/helpers/executeDynamic')
|
|
|
13
13
|
const removeDynamicHelpSection = require('./../lib/helpers/removeDynamicHelpSection')
|
|
14
14
|
const removeOptionsHelpParts = require('./../lib/helpers/removeOptionsHelpParts')
|
|
15
15
|
|
|
16
|
-
const Session = require('./../db/session')
|
|
17
|
-
const sesh = new Session()
|
|
18
|
-
|
|
19
16
|
// for use with run
|
|
20
17
|
const envs = []
|
|
21
18
|
function collectEnvs (type) {
|
|
@@ -74,10 +71,11 @@ program.command('run')
|
|
|
74
71
|
.option('--strict', 'process.exit(1) on any errors', false)
|
|
75
72
|
.option('--convention <name>', 'load a .env convention (available conventions: [\'nextjs\', \'flow\'])')
|
|
76
73
|
.option('--ignore <errorCodes...>', 'error code(s) to ignore (example: --ignore=MISSING_ENV_FILE)')
|
|
77
|
-
.option('--ops
|
|
74
|
+
.option('--no-ops', 'disable dotenvx-ops features')
|
|
75
|
+
.addOption(new Option('--ops-off', 'DEPRECATED: use --no-ops').hideHelp())
|
|
78
76
|
.action(function (...args) {
|
|
79
77
|
this.envs = envs
|
|
80
|
-
runAction.apply(this, args)
|
|
78
|
+
return runAction.apply(this, args)
|
|
81
79
|
})
|
|
82
80
|
|
|
83
81
|
// dotenvx get
|
|
@@ -97,10 +95,10 @@ program.command('get')
|
|
|
97
95
|
.option('-pp, --pretty-print', 'pretty print output')
|
|
98
96
|
.option('--pp', 'pretty print output (alias)')
|
|
99
97
|
.option('--format <type>', 'format of the output (json, shell, eval)', 'json')
|
|
100
|
-
.option('--ops
|
|
98
|
+
.option('--no-ops', 'disable dotenvx-ops features')
|
|
101
99
|
.action(function (...args) {
|
|
102
100
|
this.envs = envs
|
|
103
|
-
getAction.apply(this, args)
|
|
101
|
+
return getAction.apply(this, args)
|
|
104
102
|
})
|
|
105
103
|
|
|
106
104
|
// dotenvx set
|
|
@@ -117,10 +115,10 @@ program.command('set')
|
|
|
117
115
|
.option('-c, --encrypt', 'encrypt value', true)
|
|
118
116
|
.option('-p, --plain', 'store value as plain text', false)
|
|
119
117
|
.option('--no-create', 'do not create .env file(s) when missing')
|
|
120
|
-
.option('--ops
|
|
118
|
+
.option('--no-ops', 'disable dotenvx-ops features')
|
|
121
119
|
.action(function (...args) {
|
|
122
120
|
this.envs = envs
|
|
123
|
-
setAction.apply(this, args)
|
|
121
|
+
return setAction.apply(this, args)
|
|
124
122
|
})
|
|
125
123
|
|
|
126
124
|
// dotenvx encrypt
|
|
@@ -131,12 +129,12 @@ program.command('encrypt')
|
|
|
131
129
|
.option('-fk, --env-keys-file <path>', 'path to your .env.keys file (default: same path as your env file)')
|
|
132
130
|
.option('-k, --key <keys...>', 'keys(s) to encrypt (default: all keys in file)')
|
|
133
131
|
.option('-ek, --exclude-key <excludeKeys...>', 'keys(s) to exclude from encryption (default: none)')
|
|
134
|
-
.option('--no-create', 'do not create .env file(s) when missing')
|
|
135
|
-
.option('--ops-off', 'disable dotenvx-ops features', sesh.opsOff())
|
|
136
132
|
.option('--stdout', 'send to stdout')
|
|
133
|
+
.option('--no-create', 'do not create .env file(s) when missing')
|
|
134
|
+
.option('--no-ops', 'disable dotenvx-ops features')
|
|
137
135
|
.action(function (...args) {
|
|
138
136
|
this.envs = envs
|
|
139
|
-
encryptAction.apply(this, args)
|
|
137
|
+
return encryptAction.apply(this, args)
|
|
140
138
|
})
|
|
141
139
|
|
|
142
140
|
// dotenvx decrypt
|
|
@@ -147,11 +145,11 @@ program.command('decrypt')
|
|
|
147
145
|
.option('-fk, --env-keys-file <path>', 'path to your .env.keys file (default: same path as your env file)')
|
|
148
146
|
.option('-k, --key <keys...>', 'keys(s) to decrypt (default: all keys in file)')
|
|
149
147
|
.option('-ek, --exclude-key <excludeKeys...>', 'keys(s) to exclude from decryption (default: none)')
|
|
150
|
-
.option('--ops
|
|
148
|
+
.option('--no-ops', 'disable dotenvx-ops features')
|
|
151
149
|
.option('--stdout', 'send to stdout')
|
|
152
150
|
.action(function (...args) {
|
|
153
151
|
this.envs = envs
|
|
154
|
-
decryptAction.apply(this, args)
|
|
152
|
+
return decryptAction.apply(this, args)
|
|
155
153
|
})
|
|
156
154
|
|
|
157
155
|
// dotenvx rotate
|
|
@@ -162,11 +160,11 @@ program.command('rotate')
|
|
|
162
160
|
.option('-fk, --env-keys-file <path>', 'path to your .env.keys file (default: same path as your env file)')
|
|
163
161
|
.option('-k, --key <keys...>', 'keys(s) to encrypt (default: all keys in file)')
|
|
164
162
|
.option('-ek, --exclude-key <excludeKeys...>', 'keys(s) to exclude from encryption (default: none)')
|
|
165
|
-
.option('--ops
|
|
163
|
+
.option('--no-ops', 'disable dotenvx-ops features')
|
|
166
164
|
.option('--stdout', 'send to stdout')
|
|
167
165
|
.action(function (...args) {
|
|
168
166
|
this.envs = envs
|
|
169
|
-
rotateAction.apply(this, args)
|
|
167
|
+
return rotateAction.apply(this, args)
|
|
170
168
|
})
|
|
171
169
|
|
|
172
170
|
// dotenvx keypair
|
|
@@ -177,7 +175,7 @@ program.command('keypair')
|
|
|
177
175
|
.argument('[KEY]', 'environment variable key name')
|
|
178
176
|
.option('-f, --env-file <paths...>', 'path(s) to your env file(s)')
|
|
179
177
|
.option('-fk, --env-keys-file <path>', 'path to your .env.keys file (default: same path as your env file)')
|
|
180
|
-
.option('--ops
|
|
178
|
+
.option('--no-ops', 'disable dotenvx-ops features')
|
|
181
179
|
.option('-pp, --pretty-print', 'pretty print output')
|
|
182
180
|
.option('--pp', 'pretty print output (alias)')
|
|
183
181
|
.option('--format <type>', 'format of the output (json, shell)', 'json')
|
|
@@ -208,11 +206,11 @@ program.command('help [command]')
|
|
|
208
206
|
}
|
|
209
207
|
})
|
|
210
208
|
|
|
211
|
-
// dotenvx
|
|
209
|
+
// dotenvx ops
|
|
212
210
|
program.addHelpText('after', ' ')
|
|
213
211
|
program.addHelpText('after', 'Advanced: ')
|
|
214
|
-
program.addHelpText('after', ' ops
|
|
215
|
-
program.addHelpText('after', ' ext
|
|
212
|
+
program.addHelpText('after', ' ops ⛨ Ops [www.dotenvx.com/ops]')
|
|
213
|
+
program.addHelpText('after', ' ext 🔌 extensions')
|
|
216
214
|
|
|
217
215
|
// dotenvx ext
|
|
218
216
|
program.addCommand(require('./commands/ext'))
|
package/src/cli/examples.js
CHANGED