@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/src/db/session.js
CHANGED
|
@@ -1,20 +1,24 @@
|
|
|
1
1
|
const Ops = require('./../lib/extensions/ops')
|
|
2
|
+
const { logger } = require('./../shared/logger')
|
|
2
3
|
|
|
3
4
|
class Session {
|
|
4
5
|
constructor () {
|
|
5
6
|
this.ops = new Ops()
|
|
6
|
-
this.opsStatus = this.ops.status()
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
//
|
|
10
|
-
//
|
|
10
|
+
// ops status helpers
|
|
11
11
|
//
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
async noOps () {
|
|
13
|
+
const status = await this.ops.status()
|
|
14
|
+
logger.debug(`ops: ${status}`)
|
|
15
|
+
return status === 'off'
|
|
14
16
|
}
|
|
15
17
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
+
noOpsSync () {
|
|
19
|
+
const status = this.ops.statusSync()
|
|
20
|
+
logger.debug(`ops: ${status}`)
|
|
21
|
+
return status === 'off'
|
|
18
22
|
}
|
|
19
23
|
}
|
|
20
24
|
|
|
@@ -1,97 +1,146 @@
|
|
|
1
1
|
const path = require('path')
|
|
2
2
|
const childProcess = require('child_process')
|
|
3
|
+
const util = require('util')
|
|
3
4
|
|
|
4
|
-
|
|
5
|
+
const execFile = util.promisify(childProcess.execFile)
|
|
5
6
|
|
|
6
7
|
class Ops {
|
|
7
|
-
|
|
8
|
-
this.
|
|
8
|
+
async status () {
|
|
9
|
+
if (this._isForcedOff()) return 'off'
|
|
9
10
|
|
|
10
|
-
|
|
11
|
-
|
|
11
|
+
const binary = await this._resolveBinary()
|
|
12
|
+
if (!binary) return 'off'
|
|
13
|
+
|
|
14
|
+
try {
|
|
15
|
+
return await this._exec(binary, ['status'])
|
|
16
|
+
} catch (_e) {
|
|
17
|
+
return 'off'
|
|
12
18
|
}
|
|
19
|
+
}
|
|
13
20
|
|
|
14
|
-
|
|
15
|
-
|
|
21
|
+
statusSync () {
|
|
22
|
+
if (this._isForcedOff()) return 'off'
|
|
16
23
|
|
|
17
|
-
|
|
18
|
-
if (!
|
|
19
|
-
try { this.opsLib = this._opsCli() } catch (_e) {}
|
|
20
|
-
}
|
|
24
|
+
const binary = this._resolveBinarySync()
|
|
25
|
+
if (!binary) return 'off'
|
|
21
26
|
|
|
22
|
-
|
|
23
|
-
|
|
27
|
+
try {
|
|
28
|
+
return this._execSync(binary, ['status'])
|
|
29
|
+
} catch (_e) {
|
|
30
|
+
return 'off'
|
|
24
31
|
}
|
|
25
32
|
}
|
|
26
33
|
|
|
27
|
-
|
|
28
|
-
if (this._isForcedOff()
|
|
29
|
-
return 'off'
|
|
30
|
-
}
|
|
34
|
+
async keypair (publicKey) {
|
|
35
|
+
if (this._isForcedOff()) return {}
|
|
31
36
|
|
|
32
|
-
|
|
33
|
-
|
|
37
|
+
const binary = await this._resolveBinary()
|
|
38
|
+
if (!binary) return {}
|
|
39
|
+
|
|
40
|
+
const args = ['keypair']
|
|
41
|
+
if (publicKey) args.push(publicKey)
|
|
34
42
|
|
|
35
|
-
|
|
36
|
-
|
|
43
|
+
try {
|
|
44
|
+
return JSON.parse(await this._exec(binary, args))
|
|
45
|
+
} catch (_e) {
|
|
37
46
|
return {}
|
|
38
47
|
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
keypairSync (publicKey) {
|
|
51
|
+
if (this._isForcedOff()) return {}
|
|
39
52
|
|
|
40
|
-
|
|
53
|
+
const binary = this._resolveBinarySync()
|
|
54
|
+
if (!binary) return {}
|
|
55
|
+
|
|
56
|
+
const args = ['keypair']
|
|
57
|
+
if (publicKey) args.push(publicKey)
|
|
58
|
+
|
|
59
|
+
try {
|
|
60
|
+
return JSON.parse(this._execSync(binary, args))
|
|
61
|
+
} catch (_e) {
|
|
62
|
+
return {}
|
|
63
|
+
}
|
|
41
64
|
}
|
|
42
65
|
|
|
43
66
|
observe (payload) {
|
|
44
|
-
if (
|
|
45
|
-
|
|
46
|
-
|
|
67
|
+
if (this._isForcedOff()) return
|
|
68
|
+
|
|
69
|
+
const binary = this._resolveBinarySync()
|
|
70
|
+
if (!binary) return
|
|
71
|
+
|
|
72
|
+
let status = 'off'
|
|
73
|
+
try {
|
|
74
|
+
status = this._execSync(binary, ['status'])
|
|
75
|
+
} catch (_e) {
|
|
76
|
+
return
|
|
77
|
+
}
|
|
78
|
+
if (status === 'off') return
|
|
79
|
+
|
|
80
|
+
const encoded = Buffer.from(JSON.stringify(payload)).toString('base64')
|
|
81
|
+
try {
|
|
82
|
+
const subprocess = childProcess.spawn(binary, ['observe', encoded], {
|
|
83
|
+
stdio: 'ignore',
|
|
84
|
+
detached: true
|
|
85
|
+
})
|
|
86
|
+
subprocess.unref()
|
|
87
|
+
} catch (_e) {
|
|
88
|
+
// noop
|
|
47
89
|
}
|
|
48
90
|
}
|
|
49
91
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
_opsNpm () {
|
|
54
|
-
const npmBin = path.resolve(process.cwd(), 'node_modules/.bin/dotenvx-ops')
|
|
55
|
-
return this._opsLib(npmBin)
|
|
92
|
+
async _exec (binary, args) {
|
|
93
|
+
const { stdout } = await execFile(binary, args)
|
|
94
|
+
return stdout.toString().trim()
|
|
56
95
|
}
|
|
57
96
|
|
|
58
|
-
|
|
59
|
-
return
|
|
97
|
+
_execSync (binary, args) {
|
|
98
|
+
return childProcess.execFileSync(binary, args).toString().trim()
|
|
60
99
|
}
|
|
61
100
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
101
|
+
async _resolveBinary () {
|
|
102
|
+
if (this._binaryPromise) return this._binaryPromise
|
|
103
|
+
|
|
104
|
+
this._binaryPromise = (async () => {
|
|
105
|
+
const npmBin = path.resolve(process.cwd(), 'node_modules/.bin/dotenvx-ops')
|
|
106
|
+
try {
|
|
107
|
+
await this._exec(npmBin, ['--version'])
|
|
108
|
+
return npmBin
|
|
109
|
+
} catch (_e) {}
|
|
110
|
+
|
|
111
|
+
try {
|
|
112
|
+
await this._exec('dotenvx-ops', ['--version'])
|
|
113
|
+
return 'dotenvx-ops'
|
|
114
|
+
} catch (_e) {}
|
|
115
|
+
|
|
116
|
+
return null
|
|
117
|
+
})()
|
|
118
|
+
|
|
119
|
+
return this._binaryPromise
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
_resolveBinarySync () {
|
|
123
|
+
if (this._binarySync !== undefined) return this._binarySync
|
|
124
|
+
|
|
125
|
+
const npmBin = path.resolve(process.cwd(), 'node_modules/.bin/dotenvx-ops')
|
|
126
|
+
try {
|
|
127
|
+
this._execSync(npmBin, ['--version'])
|
|
128
|
+
this._binarySync = npmBin
|
|
129
|
+
return this._binarySync
|
|
130
|
+
} catch (_e) {}
|
|
131
|
+
|
|
132
|
+
try {
|
|
133
|
+
this._execSync('dotenvx-ops', ['--version'])
|
|
134
|
+
this._binarySync = 'dotenvx-ops'
|
|
135
|
+
return this._binarySync
|
|
136
|
+
} catch (_e) {}
|
|
137
|
+
|
|
138
|
+
this._binarySync = null
|
|
139
|
+
return null
|
|
91
140
|
}
|
|
92
141
|
|
|
93
142
|
_isForcedOff () {
|
|
94
|
-
return process.env.
|
|
143
|
+
return process.env.DOTENVX_NO_OPS === 'true'
|
|
95
144
|
}
|
|
96
145
|
}
|
|
97
146
|
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
const FRAMES = ['◇', '⬖', '◆', '⬗']
|
|
2
|
+
const FRAME_INTERVAL_MS = 80
|
|
3
|
+
|
|
4
|
+
async function createSpinner (options = {}) {
|
|
5
|
+
const stream = process.stderr
|
|
6
|
+
const hasCursorControls = typeof stream.cursorTo === 'function' && typeof stream.clearLine === 'function'
|
|
7
|
+
const enabled = Boolean(stream.isTTY && hasCursorControls && !options.quiet && !options.verbose && !options.debug)
|
|
8
|
+
if (!enabled) return null
|
|
9
|
+
|
|
10
|
+
const text = options.text || 'thinking'
|
|
11
|
+
const frames = options.frames || FRAMES
|
|
12
|
+
|
|
13
|
+
const { default: yoctoSpinner } = await import('yocto-spinner')
|
|
14
|
+
return yoctoSpinner({
|
|
15
|
+
text,
|
|
16
|
+
spinner: {
|
|
17
|
+
frames,
|
|
18
|
+
interval: FRAME_INTERVAL_MS
|
|
19
|
+
},
|
|
20
|
+
stream
|
|
21
|
+
}).start()
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
module.exports = createSpinner
|
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
module.exports = {
|
|
2
2
|
opsKeypair: require('./opsKeypair'),
|
|
3
|
+
opsKeypairSync: require('./opsKeypairSync'),
|
|
3
4
|
localKeypair: require('./localKeypair'),
|
|
4
5
|
encryptValue: require('./encryptValue'),
|
|
5
6
|
decryptKeyValue: require('./decryptKeyValue'),
|
|
6
7
|
isEncrypted: require('./isEncrypted'),
|
|
7
8
|
isPublicKey: require('./isPublicKey'),
|
|
9
|
+
mutateKeysSrc: require('./mutateKeysSrc'),
|
|
10
|
+
mutateKeysSrcSync: require('./mutateKeysSrcSync'),
|
|
8
11
|
provision: require('./provision'),
|
|
12
|
+
provisionSync: require('./provisionSync'),
|
|
9
13
|
provisionWithPrivateKey: require('./provisionWithPrivateKey'),
|
|
10
14
|
mutateSrc: require('./mutateSrc'),
|
|
11
15
|
|
|
@@ -9,7 +9,7 @@ const FIRST_TIME_KEYS_SRC = [
|
|
|
9
9
|
const path = require('path')
|
|
10
10
|
const fsx = require('./../fsx')
|
|
11
11
|
|
|
12
|
-
function mutateKeysSrc ({ envFilepath, keysFilepath, privateKeyName, privateKeyValue }) {
|
|
12
|
+
async function mutateKeysSrc ({ envFilepath, keysFilepath, privateKeyName, privateKeyValue }) {
|
|
13
13
|
const filename = path.basename(envFilepath)
|
|
14
14
|
const filepath = path.resolve(envFilepath)
|
|
15
15
|
let resolvedKeysFilepath = path.join(path.dirname(filepath), '.env.keys')
|
|
@@ -19,13 +19,13 @@ function mutateKeysSrc ({ envFilepath, keysFilepath, privateKeyName, privateKeyV
|
|
|
19
19
|
const appendPrivateKey = [`# ${filename}`, `${privateKeyName}=${privateKeyValue}`, ''].join('\n')
|
|
20
20
|
|
|
21
21
|
let keysSrc = ''
|
|
22
|
-
if (fsx.
|
|
23
|
-
keysSrc = fsx.readFileX(resolvedKeysFilepath)
|
|
22
|
+
if (await fsx.exists(resolvedKeysFilepath)) {
|
|
23
|
+
keysSrc = await fsx.readFileX(resolvedKeysFilepath)
|
|
24
24
|
}
|
|
25
25
|
keysSrc = keysSrc.length > 1 ? keysSrc : `${FIRST_TIME_KEYS_SRC}\n`
|
|
26
26
|
keysSrc = `${keysSrc}\n${appendPrivateKey}`
|
|
27
27
|
|
|
28
|
-
fsx.writeFileX(resolvedKeysFilepath, keysSrc) // TODO: don't write if ops
|
|
28
|
+
await fsx.writeFileX(resolvedKeysFilepath, keysSrc) // TODO: don't write if ops
|
|
29
29
|
|
|
30
30
|
const envKeysFilepath = keysFilepath || path.join(path.dirname(envFilepath), path.basename(resolvedKeysFilepath))
|
|
31
31
|
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
const FIRST_TIME_KEYS_SRC = [
|
|
2
|
+
'#/------------------!DOTENV_PRIVATE_KEYS!-------------------/',
|
|
3
|
+
'#/ private decryption keys. DO NOT commit to source control /',
|
|
4
|
+
'#/ [how it works](https://dotenvx.com/encryption) /',
|
|
5
|
+
// '#/ backup with: `dotenvx ops backup` /',
|
|
6
|
+
'#/----------------------------------------------------------/'
|
|
7
|
+
].join('\n')
|
|
8
|
+
|
|
9
|
+
const path = require('path')
|
|
10
|
+
const fsx = require('./../fsx')
|
|
11
|
+
|
|
12
|
+
function mutateKeysSrcSync ({ envFilepath, keysFilepath, privateKeyName, privateKeyValue }) {
|
|
13
|
+
const filename = path.basename(envFilepath)
|
|
14
|
+
const filepath = path.resolve(envFilepath)
|
|
15
|
+
let resolvedKeysFilepath = path.join(path.dirname(filepath), '.env.keys')
|
|
16
|
+
if (keysFilepath) {
|
|
17
|
+
resolvedKeysFilepath = path.resolve(keysFilepath)
|
|
18
|
+
}
|
|
19
|
+
const appendPrivateKey = [`# ${filename}`, `${privateKeyName}=${privateKeyValue}`, ''].join('\n')
|
|
20
|
+
|
|
21
|
+
let keysSrc = ''
|
|
22
|
+
if (fsx.existsSync(resolvedKeysFilepath)) {
|
|
23
|
+
keysSrc = fsx.readFileXSync(resolvedKeysFilepath)
|
|
24
|
+
}
|
|
25
|
+
keysSrc = keysSrc.length > 1 ? keysSrc : `${FIRST_TIME_KEYS_SRC}\n`
|
|
26
|
+
keysSrc = `${keysSrc}\n${appendPrivateKey}`
|
|
27
|
+
|
|
28
|
+
fsx.writeFileXSync(resolvedKeysFilepath, keysSrc) // TODO: don't write if ops
|
|
29
|
+
|
|
30
|
+
const envKeysFilepath = keysFilepath || path.join(path.dirname(envFilepath), path.basename(resolvedKeysFilepath))
|
|
31
|
+
|
|
32
|
+
return {
|
|
33
|
+
keysSrc,
|
|
34
|
+
envKeysFilepath
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
module.exports = mutateKeysSrcSync
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const Ops = require('../../extensions/ops')
|
|
2
2
|
|
|
3
|
-
function opsKeypair (existingPublicKey) {
|
|
4
|
-
const kp = new Ops().keypair(existingPublicKey)
|
|
3
|
+
async function opsKeypair (existingPublicKey) {
|
|
4
|
+
const kp = await new Ops().keypair(existingPublicKey)
|
|
5
5
|
const publicKey = kp.public_key
|
|
6
6
|
const privateKey = kp.private_key
|
|
7
7
|
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
const Ops = require('../../extensions/ops')
|
|
2
|
+
|
|
3
|
+
function opsKeypairSync (existingPublicKey) {
|
|
4
|
+
const kp = new Ops().keypairSync(existingPublicKey)
|
|
5
|
+
const publicKey = kp.public_key
|
|
6
|
+
const privateKey = kp.private_key
|
|
7
|
+
|
|
8
|
+
return {
|
|
9
|
+
publicKey,
|
|
10
|
+
privateKey
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
module.exports = opsKeypairSync
|
|
@@ -4,8 +4,8 @@ const opsKeypair = require('./opsKeypair')
|
|
|
4
4
|
const localKeypair = require('./localKeypair')
|
|
5
5
|
const { keyNames } = require('../keyResolution')
|
|
6
6
|
|
|
7
|
-
function provision ({ envSrc, envFilepath, keysFilepath,
|
|
8
|
-
|
|
7
|
+
async function provision ({ envSrc, envFilepath, keysFilepath, noOps }) {
|
|
8
|
+
noOps = noOps !== false
|
|
9
9
|
const { publicKeyName, privateKeyName } = keyNames(envFilepath)
|
|
10
10
|
|
|
11
11
|
let publicKey
|
|
@@ -14,12 +14,12 @@ function provision ({ envSrc, envFilepath, keysFilepath, opsOn }) {
|
|
|
14
14
|
let envKeysFilepath
|
|
15
15
|
let privateKeyAdded = false
|
|
16
16
|
|
|
17
|
-
if (
|
|
18
|
-
const kp =
|
|
17
|
+
if (noOps) {
|
|
18
|
+
const kp = localKeypair()
|
|
19
19
|
publicKey = kp.publicKey
|
|
20
20
|
privateKey = kp.privateKey
|
|
21
21
|
} else {
|
|
22
|
-
const kp =
|
|
22
|
+
const kp = await opsKeypair()
|
|
23
23
|
publicKey = kp.publicKey
|
|
24
24
|
privateKey = kp.privateKey
|
|
25
25
|
}
|
|
@@ -27,8 +27,8 @@ function provision ({ envSrc, envFilepath, keysFilepath, opsOn }) {
|
|
|
27
27
|
const mutated = mutateSrc({ envSrc, envFilepath, keysFilepath, publicKeyName, publicKeyValue: publicKey })
|
|
28
28
|
envSrc = mutated.envSrc
|
|
29
29
|
|
|
30
|
-
if (
|
|
31
|
-
const mutated = mutateKeysSrc({ envFilepath, keysFilepath, privateKeyName, privateKeyValue: privateKey })
|
|
30
|
+
if (noOps) {
|
|
31
|
+
const mutated = await mutateKeysSrc({ envFilepath, keysFilepath, privateKeyName, privateKeyValue: privateKey })
|
|
32
32
|
keysSrc = mutated.keysSrc
|
|
33
33
|
envKeysFilepath = mutated.envKeysFilepath
|
|
34
34
|
privateKeyAdded = true
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
const mutateSrc = require('./mutateSrc')
|
|
2
|
+
const mutateKeysSrcSync = require('./mutateKeysSrcSync')
|
|
3
|
+
const opsKeypairSync = require('./opsKeypairSync')
|
|
4
|
+
const localKeypair = require('./localKeypair')
|
|
5
|
+
const { keyNames } = require('../keyResolution')
|
|
6
|
+
|
|
7
|
+
function provisionSync ({ envSrc, envFilepath, keysFilepath, noOps }) {
|
|
8
|
+
noOps = noOps !== false
|
|
9
|
+
const { publicKeyName, privateKeyName } = keyNames(envFilepath)
|
|
10
|
+
|
|
11
|
+
let publicKey
|
|
12
|
+
let privateKey
|
|
13
|
+
let keysSrc
|
|
14
|
+
let envKeysFilepath
|
|
15
|
+
let privateKeyAdded = false
|
|
16
|
+
|
|
17
|
+
if (noOps) {
|
|
18
|
+
const kp = localKeypair()
|
|
19
|
+
publicKey = kp.publicKey
|
|
20
|
+
privateKey = kp.privateKey
|
|
21
|
+
} else {
|
|
22
|
+
const kp = opsKeypairSync()
|
|
23
|
+
publicKey = kp.publicKey
|
|
24
|
+
privateKey = kp.privateKey
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const mutated = mutateSrc({ envSrc, envFilepath, keysFilepath, publicKeyName, publicKeyValue: publicKey })
|
|
28
|
+
envSrc = mutated.envSrc
|
|
29
|
+
|
|
30
|
+
if (noOps) {
|
|
31
|
+
const mutated = mutateKeysSrcSync({ envFilepath, keysFilepath, privateKeyName, privateKeyValue: privateKey })
|
|
32
|
+
keysSrc = mutated.keysSrc
|
|
33
|
+
envKeysFilepath = mutated.envKeysFilepath
|
|
34
|
+
privateKeyAdded = true
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return {
|
|
38
|
+
envSrc,
|
|
39
|
+
keysSrc,
|
|
40
|
+
publicKey,
|
|
41
|
+
privateKey,
|
|
42
|
+
privateKeyAdded,
|
|
43
|
+
envKeysFilepath
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
module.exports = provisionSync
|
|
@@ -3,7 +3,7 @@ const mutateSrc = require('./mutateSrc')
|
|
|
3
3
|
const localKeypair = require('./localKeypair')
|
|
4
4
|
|
|
5
5
|
function provisionWithPrivateKey ({ envSrc, envFilepath, keysFilepath, privateKeyValue, publicKeyValue, publicKeyName }) {
|
|
6
|
-
const { publicKey, privateKey } = localKeypair(privateKeyValue) //
|
|
6
|
+
const { publicKey, privateKey } = localKeypair(privateKeyValue) // noOps doesn't matter here since privateKeyValue was already discovered prior (via ops and local) and passed as privateKeyValue
|
|
7
7
|
|
|
8
8
|
// if derivation doesn't match what's in the file (or preset in env)
|
|
9
9
|
if (publicKeyValue && publicKeyValue !== publicKey) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const fs = require('fs')
|
|
2
2
|
|
|
3
|
-
function detectEncoding (filepath) {
|
|
4
|
-
const buffer = fs.
|
|
3
|
+
async function detectEncoding (filepath) {
|
|
4
|
+
const buffer = await fs.promises.readFile(filepath)
|
|
5
5
|
|
|
6
6
|
// check for UTF-16LE BOM (Byte Order Mark)
|
|
7
7
|
if (buffer.length >= 2 && buffer[0] === 0xFF && buffer[1] === 0xFE) {
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
const fs = require('fs')
|
|
2
|
+
|
|
3
|
+
function detectEncodingSync (filepath) {
|
|
4
|
+
const buffer = fs.readFileSync(filepath)
|
|
5
|
+
|
|
6
|
+
// check for UTF-16LE BOM (Byte Order Mark)
|
|
7
|
+
if (buffer.length >= 2 && buffer[0] === 0xFF && buffer[1] === 0xFE) {
|
|
8
|
+
return 'utf16le'
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/* c8 ignore start */
|
|
12
|
+
// check for UTF-8 BOM
|
|
13
|
+
if (buffer.length >= 3 && buffer[0] === 0xEF && buffer[1] === 0xBB && buffer[2] === 0xBF) {
|
|
14
|
+
return 'utf8'
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/* c8 ignore stop */
|
|
18
|
+
|
|
19
|
+
return 'utf8'
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
module.exports = detectEncodingSync
|
|
@@ -13,6 +13,7 @@ const ISSUE_BY_CODE = {
|
|
|
13
13
|
MISPAIRED_PRIVATE_KEY: 'https://github.com/dotenvx/dotenvx/issues/752',
|
|
14
14
|
MISSING_DIRECTORY: 'https://github.com/dotenvx/dotenvx/issues/758',
|
|
15
15
|
MISSING_ENV_FILE: 'https://github.com/dotenvx/dotenvx/issues/484',
|
|
16
|
+
MISSING_ENV_KEYS_FILE: 'https://github.com/dotenvx/dotenvx/issues/775',
|
|
16
17
|
MISSING_ENV_FILES: 'https://github.com/dotenvx/dotenvx/issues/760',
|
|
17
18
|
MISSING_KEY: 'https://github.com/dotenvx/dotenvx/issues/759',
|
|
18
19
|
MISSING_LOG_LEVEL: 'must be valid log level',
|
|
@@ -25,6 +26,7 @@ class Errors {
|
|
|
25
26
|
constructor (options = {}) {
|
|
26
27
|
this.filepath = options.filepath
|
|
27
28
|
this.envFilepath = options.envFilepath
|
|
29
|
+
this.envKeysFilepath = options.envKeysFilepath
|
|
28
30
|
|
|
29
31
|
this.key = options.key
|
|
30
32
|
this.privateKey = options.privateKey
|
|
@@ -202,6 +204,19 @@ class Errors {
|
|
|
202
204
|
return e
|
|
203
205
|
}
|
|
204
206
|
|
|
207
|
+
missingEnvKeysFile () {
|
|
208
|
+
const code = 'MISSING_ENV_KEYS_FILE'
|
|
209
|
+
const envKeysFilepath = this.envKeysFilepath || '.env.keys'
|
|
210
|
+
const message = `[${code}] missing file (${envKeysFilepath})`
|
|
211
|
+
const help = `fix: [${ISSUE_BY_CODE[code]}]`
|
|
212
|
+
|
|
213
|
+
const e = new Error(message)
|
|
214
|
+
e.code = code
|
|
215
|
+
e.help = help
|
|
216
|
+
e.messageWithHelp = `${message}. ${help}`
|
|
217
|
+
return e
|
|
218
|
+
}
|
|
219
|
+
|
|
205
220
|
missingEnvFiles () {
|
|
206
221
|
const code = 'MISSING_ENV_FILES'
|
|
207
222
|
const message = `[${code}] no .env* files found`
|
package/src/lib/helpers/fsx.js
CHANGED
|
@@ -2,7 +2,15 @@ const fs = require('fs')
|
|
|
2
2
|
|
|
3
3
|
const ENCODING = 'utf8'
|
|
4
4
|
|
|
5
|
-
function readFileX (filepath, encoding = null) {
|
|
5
|
+
async function readFileX (filepath, encoding = null) {
|
|
6
|
+
if (!encoding) {
|
|
7
|
+
encoding = ENCODING
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
return fs.promises.readFile(filepath, encoding)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function readFileXSync (filepath, encoding = null) {
|
|
6
14
|
if (!encoding) {
|
|
7
15
|
encoding = ENCODING
|
|
8
16
|
}
|
|
@@ -10,12 +18,26 @@ function readFileX (filepath, encoding = null) {
|
|
|
10
18
|
return fs.readFileSync(filepath, encoding) // utf8 default so it returns a string
|
|
11
19
|
}
|
|
12
20
|
|
|
13
|
-
function
|
|
21
|
+
function writeFileXSync (filepath, str) {
|
|
14
22
|
return fs.writeFileSync(filepath, str, ENCODING) // utf8 always
|
|
15
23
|
}
|
|
16
24
|
|
|
25
|
+
async function writeFileX (filepath, str) {
|
|
26
|
+
return fs.promises.writeFile(filepath, str, ENCODING)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async function exists (filepath) {
|
|
30
|
+
try {
|
|
31
|
+
await fs.promises.access(filepath)
|
|
32
|
+
return true
|
|
33
|
+
} catch (_e) {
|
|
34
|
+
return false
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
17
38
|
const fsx = {
|
|
18
39
|
chmodSync: fs.chmodSync,
|
|
40
|
+
exists,
|
|
19
41
|
existsSync: fs.existsSync,
|
|
20
42
|
readdirSync: fs.readdirSync,
|
|
21
43
|
readFileSync: fs.readFileSync,
|
|
@@ -24,7 +46,9 @@ const fsx = {
|
|
|
24
46
|
|
|
25
47
|
// fsx special commands
|
|
26
48
|
readFileX,
|
|
27
|
-
|
|
49
|
+
readFileXSync,
|
|
50
|
+
writeFileX,
|
|
51
|
+
writeFileXSync
|
|
28
52
|
}
|
|
29
53
|
|
|
30
54
|
module.exports = fsx
|
|
@@ -55,12 +55,12 @@ class InstallPrecommitHook {
|
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
_currentHook () {
|
|
58
|
-
return fsx.
|
|
58
|
+
return fsx.readFileXSync(this.hookPath)
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
_createHook () {
|
|
62
62
|
// If the pre-commit file doesn't exist, create a new one with the hookScript
|
|
63
|
-
fsx.
|
|
63
|
+
fsx.writeFileXSync(this.hookPath, HOOK_SCRIPT)
|
|
64
64
|
fsx.chmodSync(this.hookPath, '755') // Make the file executable
|
|
65
65
|
}
|
|
66
66
|
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
module.exports = {
|
|
2
2
|
keyNames: require('./keyNames'),
|
|
3
3
|
keyValues: require('./keyValues'),
|
|
4
|
+
keyValuesSync: require('./keyValuesSync'),
|
|
4
5
|
|
|
5
6
|
// private
|
|
6
|
-
// private keys are resolved via
|
|
7
|
+
// private keys are resolved via keyValuesSync()
|
|
7
8
|
|
|
8
9
|
// other
|
|
9
10
|
readProcessKey: require('./readProcessKey'),
|
|
10
11
|
readFileKey: require('./readFileKey'),
|
|
12
|
+
readFileKeySync: require('./readFileKeySync'),
|
|
11
13
|
guessPrivateKeyFilename: require('./../guessPrivateKeyFilename'),
|
|
12
14
|
dotenvPrivateKeyNames: require('./../dotenvPrivateKeyNames')
|
|
13
15
|
}
|