@dotenvx/dotenvx 1.4.0 → 1.6.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 +32 -1
- package/README.md +100 -2
- package/package.json +9 -10
- package/src/cli/actions/decrypt.js +71 -0
- package/src/cli/actions/encrypt.js +54 -42
- package/src/cli/actions/ext/genexample.js +4 -12
- package/src/cli/actions/ext/gitignore.js +5 -0
- package/src/cli/actions/ext/prebuild.js +1 -0
- package/src/cli/actions/ext/scan.js +9 -6
- package/src/cli/actions/ext/settings.js +5 -4
- package/src/cli/actions/ext/vault/decrypt.js +6 -13
- package/src/cli/actions/ext/vault/encrypt.js +5 -12
- package/src/cli/actions/ext/vault/migrate.js +22 -39
- package/src/cli/actions/get.js +6 -5
- package/src/cli/actions/run.js +3 -110
- package/src/cli/actions/set.js +2 -2
- package/src/cli/commands/ext.js +12 -1
- package/src/cli/dotenvx.js +16 -15
- package/src/cli/examples.js +17 -1
- package/src/lib/helpers/execute.js +9 -0
- package/src/lib/helpers/executeCommand.js +117 -0
- package/src/lib/helpers/executeExtension.js +38 -0
- package/src/lib/helpers/findOrCreatePublicKey.js +14 -8
- package/src/lib/helpers/isEncrypted.js +1 -2
- package/src/lib/helpers/isFullyEncrypted.js +2 -1
- package/src/lib/helpers/isIgnoringDotenvKeys.js +1 -1
- package/src/lib/helpers/isPublicKey.js +7 -0
- package/src/lib/helpers/keyPair.js +8 -2
- package/src/lib/helpers/smartDotenvPrivateKey.js +64 -6
- package/src/lib/main.js +16 -9
- package/src/lib/services/decrypt.js +79 -98
- package/src/lib/services/encrypt.js +12 -7
- package/src/lib/services/sets.js +9 -2
- package/src/lib/services/status.js +2 -2
- package/src/lib/services/vaultDecrypt.js +126 -0
- package/src/shared/logger.js +0 -3
- package/src/cli/actions/ext/hub/login.js +0 -126
- package/src/cli/actions/ext/hub/logout.js +0 -43
- package/src/cli/actions/ext/hub/open.js +0 -63
- package/src/cli/actions/ext/hub/pull.js +0 -105
- package/src/cli/actions/ext/hub/push.js +0 -112
- package/src/cli/actions/ext/hub/status.js +0 -8
- package/src/cli/actions/ext/hub/token.js +0 -9
- package/src/cli/commands/ext/hub.js +0 -89
- package/src/cli/commands/vault.js +0 -57
- package/src/lib/helpers/clipboardy/fallbacks/linux/xsel +0 -0
- package/src/lib/helpers/clipboardy/fallbacks/windows/clipboard_i686.exe +0 -0
- package/src/lib/helpers/clipboardy/fallbacks/windows/clipboard_x86_64.exe +0 -0
- package/src/lib/helpers/clipboardy/linux.js +0 -57
- package/src/lib/helpers/clipboardy/macos.js +0 -14
- package/src/lib/helpers/clipboardy/termux.js +0 -41
- package/src/lib/helpers/clipboardy/windows.js +0 -16
- package/src/lib/helpers/clipboardy.js +0 -51
- package/src/lib/helpers/extractUsernameName.js +0 -10
- package/src/lib/helpers/forgivingDirectory.js +0 -11
- package/src/lib/helpers/gitRoot.js +0 -14
- package/src/lib/helpers/gitUrl.js +0 -13
- package/src/lib/helpers/isGitRepo.js +0 -13
- package/src/lib/helpers/isGithub.js +0 -5
- package/src/lib/helpers/resolvePath.js +0 -8
- package/src/shared/createSpinner.js +0 -17
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
const open = require('open')
|
|
2
|
-
const { request } = require('undici')
|
|
3
|
-
const clipboardy = require('./../../../../lib/helpers/clipboardy')
|
|
4
|
-
const confirm = require('@inquirer/confirm').default
|
|
5
|
-
|
|
6
|
-
const createSpinner = require('./../../../../shared/createSpinner')
|
|
7
|
-
const store = require('./../../../../shared/store')
|
|
8
|
-
const { logger } = require('./../../../../shared/logger')
|
|
9
|
-
|
|
10
|
-
const OAUTH_CLIENT_ID = 'oac_dotenvxcli'
|
|
11
|
-
|
|
12
|
-
const spinner = createSpinner('waiting on user authorization')
|
|
13
|
-
|
|
14
|
-
const formatCode = function (str) {
|
|
15
|
-
const parts = []
|
|
16
|
-
|
|
17
|
-
for (let i = 0; i < str.length; i += 4) {
|
|
18
|
-
parts.push(str.substring(i, i + 4))
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
return parts.join('-')
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
async function pollTokenUrl (tokenUrl, deviceCode, interval) {
|
|
25
|
-
logger.http(`POST ${tokenUrl} with deviceCode ${deviceCode} at interval ${interval}`)
|
|
26
|
-
|
|
27
|
-
try {
|
|
28
|
-
const response = await request(tokenUrl, {
|
|
29
|
-
method: 'POST',
|
|
30
|
-
headers: {
|
|
31
|
-
'Content-Type': 'application/json'
|
|
32
|
-
},
|
|
33
|
-
body: JSON.stringify({
|
|
34
|
-
client_id: OAUTH_CLIENT_ID,
|
|
35
|
-
device_code: deviceCode,
|
|
36
|
-
grant_type: 'urn:ietf:params:oauth:grant-type:device_code'
|
|
37
|
-
})
|
|
38
|
-
})
|
|
39
|
-
|
|
40
|
-
const responseData = await response.body.json()
|
|
41
|
-
|
|
42
|
-
logger.http(responseData)
|
|
43
|
-
|
|
44
|
-
if (response.statusCode >= 400) {
|
|
45
|
-
// continue polling if authorization_pending
|
|
46
|
-
if (responseData.error === 'authorization_pending') {
|
|
47
|
-
setTimeout(() => pollTokenUrl(tokenUrl, deviceCode, interval), interval * 1000)
|
|
48
|
-
} else {
|
|
49
|
-
spinner.start()
|
|
50
|
-
spinner.fail(responseData.error_description)
|
|
51
|
-
process.exit(1)
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
if (responseData.access_token) {
|
|
56
|
-
spinner.start()
|
|
57
|
-
store.setToken(responseData.full_username, responseData.access_token)
|
|
58
|
-
store.setHostname(responseData.hostname)
|
|
59
|
-
spinner.succeed(`logged in as ${responseData.username}`)
|
|
60
|
-
process.exit(0)
|
|
61
|
-
} else {
|
|
62
|
-
// continue polling if no access_token. shouldn't ever get here it server is implemented correctly
|
|
63
|
-
setTimeout(() => pollTokenUrl(tokenUrl, deviceCode, interval), interval * 1000)
|
|
64
|
-
}
|
|
65
|
-
} catch (error) {
|
|
66
|
-
spinner.start()
|
|
67
|
-
spinner.fail(error.toString())
|
|
68
|
-
process.exit(1)
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
async function login () {
|
|
73
|
-
const options = this.opts()
|
|
74
|
-
logger.debug(`options: ${JSON.stringify(options)}`)
|
|
75
|
-
|
|
76
|
-
const hostname = options.hostname
|
|
77
|
-
const deviceCodeUrl = `${hostname}/oauth/device/code`
|
|
78
|
-
const tokenUrl = `${hostname}/oauth/token`
|
|
79
|
-
|
|
80
|
-
try {
|
|
81
|
-
const response = await request(deviceCodeUrl, {
|
|
82
|
-
method: 'POST',
|
|
83
|
-
headers: {
|
|
84
|
-
'Content-Type': 'application/json'
|
|
85
|
-
},
|
|
86
|
-
body: JSON.stringify({ client_id: OAUTH_CLIENT_ID })
|
|
87
|
-
})
|
|
88
|
-
|
|
89
|
-
const responseData = await response.body.json()
|
|
90
|
-
|
|
91
|
-
if (response.statusCode >= 400) {
|
|
92
|
-
logger.http(responseData)
|
|
93
|
-
|
|
94
|
-
spinner.start()
|
|
95
|
-
spinner.fail(responseData.error_description)
|
|
96
|
-
process.exit(1)
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
const deviceCode = responseData.device_code
|
|
100
|
-
const userCode = responseData.user_code
|
|
101
|
-
const verificationUri = responseData.verification_uri
|
|
102
|
-
const interval = responseData.interval
|
|
103
|
-
|
|
104
|
-
try { clipboardy.writeSync(userCode) } catch (_e) {}
|
|
105
|
-
|
|
106
|
-
// qrcode.generate(verificationUri, { small: true }) // too verbose
|
|
107
|
-
|
|
108
|
-
// begin polling
|
|
109
|
-
pollTokenUrl(tokenUrl, deviceCode, interval)
|
|
110
|
-
|
|
111
|
-
// optionally allow user to open browser
|
|
112
|
-
const answer = await confirm({ message: `press Enter to open [${verificationUri}] and enter code [${formatCode(userCode)}]...` })
|
|
113
|
-
|
|
114
|
-
if (answer) {
|
|
115
|
-
await open(verificationUri)
|
|
116
|
-
|
|
117
|
-
spinner.start()
|
|
118
|
-
}
|
|
119
|
-
} catch (error) {
|
|
120
|
-
spinner.start()
|
|
121
|
-
spinner.fail(error.toString())
|
|
122
|
-
process.exit(1)
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
module.exports = login
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
const openBrowser = require('open')
|
|
2
|
-
const confirm = require('@inquirer/confirm').default
|
|
3
|
-
|
|
4
|
-
const createSpinner = require('./../../../../shared/createSpinner')
|
|
5
|
-
const store = require('./../../../../shared/store')
|
|
6
|
-
const { logger } = require('./../../../../shared/logger')
|
|
7
|
-
const sleep = require('./../../../../lib/helpers/sleep')
|
|
8
|
-
|
|
9
|
-
const username = store.getUsername()
|
|
10
|
-
const usernamePart = username ? ` [${username}]` : ''
|
|
11
|
-
const spinner = createSpinner(`logging off machine${usernamePart}`)
|
|
12
|
-
|
|
13
|
-
async function logout () {
|
|
14
|
-
spinner.start()
|
|
15
|
-
await sleep(500) // better dx
|
|
16
|
-
|
|
17
|
-
// debug opts
|
|
18
|
-
const options = this.opts()
|
|
19
|
-
logger.debug(`options: ${JSON.stringify(options)}`)
|
|
20
|
-
|
|
21
|
-
logger.debug('deleting settings.DOTENVX_TOKEN')
|
|
22
|
-
store.deleteToken()
|
|
23
|
-
|
|
24
|
-
logger.debug('deleting settings.DOTENVX_HOSTNAME')
|
|
25
|
-
store.deleteHostname()
|
|
26
|
-
|
|
27
|
-
spinner.done(`logged off machine${usernamePart}`)
|
|
28
|
-
|
|
29
|
-
const hostname = options.hostname
|
|
30
|
-
const logoutUrl = `${hostname}/logout`
|
|
31
|
-
|
|
32
|
-
// optionally allow user to open browser
|
|
33
|
-
const answer = await confirm({ message: `press Enter to also log off browser [${logoutUrl}]...` })
|
|
34
|
-
|
|
35
|
-
if (answer) {
|
|
36
|
-
spinner.start()
|
|
37
|
-
await sleep(500) // better dx
|
|
38
|
-
await openBrowser(logoutUrl)
|
|
39
|
-
spinner.done(`logged off browser${usernamePart}`)
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
module.exports = logout
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
const openBrowser = require('open')
|
|
2
|
-
const confirm = require('@inquirer/confirm').default
|
|
3
|
-
|
|
4
|
-
const createSpinner = require('./../../../../shared/createSpinner')
|
|
5
|
-
const { logger } = require('./../../../../shared/logger')
|
|
6
|
-
|
|
7
|
-
const isGitRepo = require('./../../../../lib/helpers/isGitRepo')
|
|
8
|
-
const isGithub = require('./../../../../lib/helpers/isGithub')
|
|
9
|
-
const gitUrl = require('./../../../../lib/helpers/gitUrl')
|
|
10
|
-
const gitRoot = require('./../../../../lib/helpers/gitRoot')
|
|
11
|
-
const extractUsernameName = require('./../../../../lib/helpers/extractUsernameName')
|
|
12
|
-
const sleep = require('./../../../../lib/helpers/sleep')
|
|
13
|
-
|
|
14
|
-
const spinner = createSpinner('opening')
|
|
15
|
-
|
|
16
|
-
async function open () {
|
|
17
|
-
// debug opts
|
|
18
|
-
const options = this.opts()
|
|
19
|
-
logger.debug(`options: ${JSON.stringify(options)}`)
|
|
20
|
-
|
|
21
|
-
// must be a git repo
|
|
22
|
-
if (!isGitRepo()) {
|
|
23
|
-
spinner.fail('oops, must be a git repository')
|
|
24
|
-
logger.help('? create one with [git init .]')
|
|
25
|
-
process.exit(1)
|
|
26
|
-
}
|
|
27
|
-
// must be a git root
|
|
28
|
-
const gitroot = gitRoot()
|
|
29
|
-
if (!gitroot) {
|
|
30
|
-
spinner.fail('oops, could not determine git repository\'s root')
|
|
31
|
-
logger.help('? create one with [git init .]')
|
|
32
|
-
process.exit(1)
|
|
33
|
-
}
|
|
34
|
-
// must have a remote origin url
|
|
35
|
-
const giturl = gitUrl()
|
|
36
|
-
if (!giturl) {
|
|
37
|
-
spinner.fail('oops, must have a remote origin (git remote -v)')
|
|
38
|
-
logger.help('? create it at [github.com/new] and then run [git remote add origin git@github.com:username/repository.git]')
|
|
39
|
-
process.exit(1)
|
|
40
|
-
}
|
|
41
|
-
// must be a github remote
|
|
42
|
-
if (!isGithub(giturl)) {
|
|
43
|
-
spinner.fail('oops, must be a github.com remote origin (git remote -v)')
|
|
44
|
-
logger.help('? create it at [github.com/new] and then run [git remote add origin git@github.com:username/repository.git]')
|
|
45
|
-
logger.help2('ℹ need support for other origins? [please tell us](https://github.com/dotenvx/dotenvx/issues)')
|
|
46
|
-
process.exit(1)
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const usernameName = extractUsernameName(giturl)
|
|
50
|
-
const openUrl = `${options.hostname}/gh/${usernameName}`
|
|
51
|
-
|
|
52
|
-
// optionally allow user to open browser
|
|
53
|
-
const answer = await confirm({ message: `press Enter to open [${openUrl}]...` })
|
|
54
|
-
|
|
55
|
-
if (answer) {
|
|
56
|
-
spinner.start()
|
|
57
|
-
await sleep(500) // better dx
|
|
58
|
-
await openBrowser(openUrl)
|
|
59
|
-
spinner.succeed(`opened [${usernameName}]`)
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
module.exports = open
|
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
const fs = require('fs')
|
|
2
|
-
const path = require('path')
|
|
3
|
-
const { request } = require('undici')
|
|
4
|
-
|
|
5
|
-
const store = require('./../../../../shared/store')
|
|
6
|
-
const { logger } = require('./../../../../shared/logger')
|
|
7
|
-
const createSpinner = require('./../../../../shared/createSpinner')
|
|
8
|
-
|
|
9
|
-
const isGitRepo = require('./../../../../lib/helpers/isGitRepo')
|
|
10
|
-
const isGithub = require('./../../../../lib/helpers/isGithub')
|
|
11
|
-
const gitUrl = require('./../../../../lib/helpers/gitUrl')
|
|
12
|
-
const gitRoot = require('./../../../../lib/helpers/gitRoot')
|
|
13
|
-
const extractUsernameName = require('./../../../../lib/helpers/extractUsernameName')
|
|
14
|
-
const sleep = require('./../../../../lib/helpers/sleep')
|
|
15
|
-
|
|
16
|
-
const spinner = createSpinner('pulling')
|
|
17
|
-
|
|
18
|
-
// constants
|
|
19
|
-
const ENCODING = 'utf8'
|
|
20
|
-
|
|
21
|
-
// Create a simple-git instance for the current directory
|
|
22
|
-
async function pull (directory) {
|
|
23
|
-
spinner.start()
|
|
24
|
-
await sleep(500) // better dx
|
|
25
|
-
|
|
26
|
-
// debug args
|
|
27
|
-
logger.debug(`directory: ${directory}`)
|
|
28
|
-
|
|
29
|
-
// debug opts
|
|
30
|
-
const options = this.opts()
|
|
31
|
-
logger.debug(`options: ${JSON.stringify(options)}`)
|
|
32
|
-
|
|
33
|
-
// must be a git repo
|
|
34
|
-
if (!isGitRepo()) {
|
|
35
|
-
spinner.fail('oops, must be a git repository')
|
|
36
|
-
logger.help('? create one with [git init .]')
|
|
37
|
-
process.exit(1)
|
|
38
|
-
}
|
|
39
|
-
// must be a git root
|
|
40
|
-
const gitroot = gitRoot()
|
|
41
|
-
if (!gitroot) {
|
|
42
|
-
spinner.fail('oops, could not determine git repository\'s root')
|
|
43
|
-
logger.help('? create one with [git init .]')
|
|
44
|
-
process.exit(1)
|
|
45
|
-
}
|
|
46
|
-
// must have a remote origin url
|
|
47
|
-
const giturl = gitUrl()
|
|
48
|
-
if (!giturl) {
|
|
49
|
-
spinner.fail('oops, must have a remote origin (git remote -v)')
|
|
50
|
-
logger.help('? create it at [github.com/new] and then run [git remote add origin git@github.com:username/repository.git]')
|
|
51
|
-
process.exit(1)
|
|
52
|
-
}
|
|
53
|
-
// must be a github remote
|
|
54
|
-
if (!isGithub(giturl)) {
|
|
55
|
-
spinner.fail('oops, must be a github.com remote origin (git remote -v)')
|
|
56
|
-
logger.help('? create it at [github.com/new] and then run [git remote add origin git@github.com:username/repository.git]')
|
|
57
|
-
logger.help2('ℹ need support for other origins? [please tell us](https://github.com/dotenvx/dotenvx/issues)')
|
|
58
|
-
process.exit(1)
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
const envKeysFilepath = path.join(directory, '.env.keys')
|
|
62
|
-
const hostname = options.hostname
|
|
63
|
-
const pullUrl = `${hostname}/v1/pull`
|
|
64
|
-
const oauthToken = store.getToken()
|
|
65
|
-
const usernameName = extractUsernameName(giturl)
|
|
66
|
-
const relativeEnvKeysFilepath = path.relative(gitroot, path.join(process.cwd(), directory, '.env.keys')).replace(/\\/g, '/') // smartly determine path/to/.env.keys file from repository root - where user is cd-ed inside a folder or at repo root
|
|
67
|
-
|
|
68
|
-
try {
|
|
69
|
-
const response = await request(pullUrl, {
|
|
70
|
-
method: 'POST',
|
|
71
|
-
headers: {
|
|
72
|
-
Authorization: `Bearer ${oauthToken}`,
|
|
73
|
-
'Content-Type': 'application/json'
|
|
74
|
-
},
|
|
75
|
-
body: JSON.stringify({
|
|
76
|
-
username_name: usernameName,
|
|
77
|
-
filepath: relativeEnvKeysFilepath
|
|
78
|
-
})
|
|
79
|
-
})
|
|
80
|
-
|
|
81
|
-
const responseData = await response.body.json()
|
|
82
|
-
|
|
83
|
-
if (response.statusCode >= 400) {
|
|
84
|
-
logger.http(responseData)
|
|
85
|
-
spinner.fail(responseData.error.message)
|
|
86
|
-
if (response.statusCode === 404) {
|
|
87
|
-
logger.help(`? try visiting [${hostname}/gh/${usernameName}] in your browser`)
|
|
88
|
-
}
|
|
89
|
-
process.exit(1)
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
if (fs.existsSync(envKeysFilepath) && fs.readFileSync(envKeysFilepath, ENCODING) === responseData.DOTENV_KEYS) {
|
|
93
|
-
spinner.done(`no changes (${envKeysFilepath})`)
|
|
94
|
-
} else {
|
|
95
|
-
fs.writeFileSync(envKeysFilepath, responseData.DOTENV_KEYS)
|
|
96
|
-
spinner.succeed(`pulled [${usernameName}]`)
|
|
97
|
-
logger.help2(`ℹ run [cat ${envKeysFilepath}] to view locally`)
|
|
98
|
-
}
|
|
99
|
-
} catch (error) {
|
|
100
|
-
spinner.fail(error.toString())
|
|
101
|
-
process.exit(1)
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
module.exports = pull
|
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
const fs = require('fs')
|
|
2
|
-
const path = require('path')
|
|
3
|
-
const { request } = require('undici')
|
|
4
|
-
|
|
5
|
-
const store = require('./../../../../shared/store')
|
|
6
|
-
const { logger } = require('./../../../../shared/logger')
|
|
7
|
-
const createSpinner = require('./../../../../shared/createSpinner')
|
|
8
|
-
|
|
9
|
-
const isGitRepo = require('./../../../../lib/helpers/isGitRepo')
|
|
10
|
-
const isGithub = require('./../../../../lib/helpers/isGithub')
|
|
11
|
-
const gitUrl = require('./../../../../lib/helpers/gitUrl')
|
|
12
|
-
const gitRoot = require('./../../../../lib/helpers/gitRoot')
|
|
13
|
-
const extractUsernameName = require('./../../../../lib/helpers/extractUsernameName')
|
|
14
|
-
const sleep = require('./../../../../lib/helpers/sleep')
|
|
15
|
-
const forgivingDirectory = require('./../../../../lib/helpers/forgivingDirectory')
|
|
16
|
-
|
|
17
|
-
const spinner = createSpinner('pushing')
|
|
18
|
-
|
|
19
|
-
// constants
|
|
20
|
-
const ENCODING = 'utf8'
|
|
21
|
-
|
|
22
|
-
// Create a simple-git instance for the current directory
|
|
23
|
-
async function push (directory) {
|
|
24
|
-
spinner.start()
|
|
25
|
-
await sleep(500) // better dx
|
|
26
|
-
|
|
27
|
-
directory = forgivingDirectory(directory)
|
|
28
|
-
|
|
29
|
-
// debug args
|
|
30
|
-
logger.debug(`directory: ${directory}`)
|
|
31
|
-
|
|
32
|
-
// debug opts
|
|
33
|
-
const options = this.opts()
|
|
34
|
-
logger.debug(`options: ${JSON.stringify(options)}`)
|
|
35
|
-
|
|
36
|
-
// must be a git repo
|
|
37
|
-
if (!isGitRepo()) {
|
|
38
|
-
spinner.fail('oops, must be a git repository')
|
|
39
|
-
logger.help('? create one with [git init .]')
|
|
40
|
-
process.exit(1)
|
|
41
|
-
}
|
|
42
|
-
// must be a git root
|
|
43
|
-
const gitroot = gitRoot()
|
|
44
|
-
if (!gitroot) {
|
|
45
|
-
spinner.fail('oops, could not determine git repository\'s root')
|
|
46
|
-
logger.help('? create one with [git init .]')
|
|
47
|
-
process.exit(1)
|
|
48
|
-
}
|
|
49
|
-
// must have a remote origin url
|
|
50
|
-
const giturl = gitUrl()
|
|
51
|
-
if (!giturl) {
|
|
52
|
-
spinner.fail('oops, must have a remote origin (git remote -v)')
|
|
53
|
-
logger.help('? create it at [github.com/new] and then run [git remote add origin git@github.com:username/repository.git]')
|
|
54
|
-
process.exit(1)
|
|
55
|
-
}
|
|
56
|
-
// must be a github remote
|
|
57
|
-
if (!isGithub(giturl)) {
|
|
58
|
-
spinner.fail('oops, must be a github.com remote origin (git remote -v)')
|
|
59
|
-
logger.help('? create it at [github.com/new] and then run [git remote add origin git@github.com:username/repository.git]')
|
|
60
|
-
logger.help2('ℹ need support for other origins? [please tell us](https://github.com/dotenvx/dotenvx/issues)')
|
|
61
|
-
process.exit(1)
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
const envKeysFilepath = path.join(directory, '.env.keys')
|
|
65
|
-
if (!fs.existsSync(envKeysFilepath)) {
|
|
66
|
-
spinner.fail('oops, missing .env.keys file')
|
|
67
|
-
logger.help(`? generate one with [dotenvx encrypt${directory ? ` ${directory}` : ''}]`)
|
|
68
|
-
logger.help2('ℹ a .env.keys file holds decryption keys for a .env.vault file')
|
|
69
|
-
process.exit(1)
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
const hostname = options.hostname
|
|
73
|
-
const pushUrl = `${hostname}/v1/push`
|
|
74
|
-
const oauthToken = store.getToken()
|
|
75
|
-
const dotenvKeysContent = fs.readFileSync(envKeysFilepath, ENCODING)
|
|
76
|
-
const usernameName = extractUsernameName(giturl)
|
|
77
|
-
const relativeEnvKeysFilepath = path.relative(gitroot, path.join(process.cwd(), directory, '.env.keys')).replace(/\\/g, '/') // smartly determine path/to/.env.keys file from repository root - where user is cd-ed inside a folder or at repo root
|
|
78
|
-
|
|
79
|
-
try {
|
|
80
|
-
const response = await request(pushUrl, {
|
|
81
|
-
method: 'POST',
|
|
82
|
-
headers: {
|
|
83
|
-
Authorization: `Bearer ${oauthToken}`,
|
|
84
|
-
'Content-Type': 'application/json'
|
|
85
|
-
},
|
|
86
|
-
body: JSON.stringify({
|
|
87
|
-
username_name: usernameName,
|
|
88
|
-
DOTENV_KEYS: dotenvKeysContent,
|
|
89
|
-
filepath: relativeEnvKeysFilepath
|
|
90
|
-
})
|
|
91
|
-
})
|
|
92
|
-
|
|
93
|
-
const responseData = await response.body.json()
|
|
94
|
-
|
|
95
|
-
if (response.statusCode >= 400) {
|
|
96
|
-
logger.http(responseData)
|
|
97
|
-
spinner.fail(responseData.error.message)
|
|
98
|
-
if (response.statusCode === 404) {
|
|
99
|
-
logger.help(`? try visiting [${hostname}/gh/${usernameName}] in your browser`)
|
|
100
|
-
}
|
|
101
|
-
process.exit(1)
|
|
102
|
-
}
|
|
103
|
-
} catch (error) {
|
|
104
|
-
spinner.fail(error.toString())
|
|
105
|
-
process.exit(1)
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
spinner.succeed(`pushed [${usernameName}]`)
|
|
109
|
-
logger.help2('ℹ run [dotenvx ext hub open] to view on hub')
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
module.exports = push
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
const { Command } = require('commander')
|
|
2
|
-
|
|
3
|
-
const store = require('./../../../shared/store')
|
|
4
|
-
const { logger } = require('./../../../shared/logger')
|
|
5
|
-
|
|
6
|
-
const hub = new Command('hub')
|
|
7
|
-
|
|
8
|
-
hub
|
|
9
|
-
.description('🚫 DEPRECATED: to be replaced by [dotenvx pro]')
|
|
10
|
-
|
|
11
|
-
const loginAction = require('./../../actions/ext/hub/login')
|
|
12
|
-
hub
|
|
13
|
-
.command('login')
|
|
14
|
-
.description('authenticate to dotenvx hub')
|
|
15
|
-
.option('-h, --hostname <url>', 'set hostname', store.getHostname())
|
|
16
|
-
.action(function (...args) {
|
|
17
|
-
logger.warn('DEPRECATION NOTICE: to be replaced by [dotenvx pro]')
|
|
18
|
-
|
|
19
|
-
loginAction.apply(this, args)
|
|
20
|
-
})
|
|
21
|
-
|
|
22
|
-
const pushAction = require('./../../actions/ext/hub/push')
|
|
23
|
-
hub
|
|
24
|
-
.command('push')
|
|
25
|
-
.description('push .env.keys to dotenvx hub')
|
|
26
|
-
.argument('[directory]', 'directory to push', '.')
|
|
27
|
-
.option('-h, --hostname <url>', 'set hostname', store.getHostname())
|
|
28
|
-
.action(function (...args) {
|
|
29
|
-
logger.warn('DEPRECATION NOTICE: to be replaced by [dotenvx pro]')
|
|
30
|
-
|
|
31
|
-
pushAction.apply(this, args)
|
|
32
|
-
})
|
|
33
|
-
|
|
34
|
-
const pullAction = require('./../../actions/ext/hub/pull')
|
|
35
|
-
hub
|
|
36
|
-
.command('pull')
|
|
37
|
-
.description('pull .env.keys from dotenvx hub')
|
|
38
|
-
.argument('[directory]', 'directory to pull', '.')
|
|
39
|
-
.option('-h, --hostname <url>', 'set hostname', store.getHostname())
|
|
40
|
-
.action(function (...args) {
|
|
41
|
-
logger.warn('DEPRECATION NOTICE: to be replaced by [dotenvx pro]')
|
|
42
|
-
|
|
43
|
-
pullAction.apply(this, args)
|
|
44
|
-
})
|
|
45
|
-
|
|
46
|
-
const openAction = require('./../../actions/ext/hub/open')
|
|
47
|
-
hub
|
|
48
|
-
.command('open')
|
|
49
|
-
.description('view repository on dotenvx hub')
|
|
50
|
-
.option('-h, --hostname <url>', 'set hostname', store.getHostname())
|
|
51
|
-
.action(function (...args) {
|
|
52
|
-
logger.warn('DEPRECATION NOTICE: to be replaced by [dotenvx pro]')
|
|
53
|
-
|
|
54
|
-
openAction.apply(this, args)
|
|
55
|
-
})
|
|
56
|
-
|
|
57
|
-
const tokenAction = require('./../../actions/ext/hub/token')
|
|
58
|
-
hub
|
|
59
|
-
.command('token')
|
|
60
|
-
.description('print the auth token dotenvx hub is configured to use')
|
|
61
|
-
.option('-h, --hostname <url>', 'set hostname', 'https://hub.dotenvx.com')
|
|
62
|
-
.action(function (...args) {
|
|
63
|
-
logger.warn('DEPRECATION NOTICE: to be replaced by [dotenvx pro]')
|
|
64
|
-
|
|
65
|
-
tokenAction.apply(this, args)
|
|
66
|
-
})
|
|
67
|
-
|
|
68
|
-
const statusAction = require('./../../actions/ext/hub/status')
|
|
69
|
-
hub
|
|
70
|
-
.command('status')
|
|
71
|
-
.description('display logged in user')
|
|
72
|
-
.action(function (...args) {
|
|
73
|
-
logger.warn('DEPRECATION NOTICE: to be replaced by [dotenvx pro]')
|
|
74
|
-
|
|
75
|
-
statusAction.apply(this, args)
|
|
76
|
-
})
|
|
77
|
-
|
|
78
|
-
const logoutAction = require('./../../actions/ext/hub/logout')
|
|
79
|
-
hub
|
|
80
|
-
.command('logout')
|
|
81
|
-
.description('log out this machine from dotenvx hub')
|
|
82
|
-
.option('-h, --hostname <url>', 'set hostname', store.getHostname())
|
|
83
|
-
.action(function (...args) {
|
|
84
|
-
logger.warn('DEPRECATION NOTICE: to be replaced by [dotenvx pro]')
|
|
85
|
-
|
|
86
|
-
logoutAction.apply(this, args)
|
|
87
|
-
})
|
|
88
|
-
|
|
89
|
-
module.exports = hub
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
const { Command } = require('commander')
|
|
2
|
-
|
|
3
|
-
const examples = require('./../examples')
|
|
4
|
-
const { logger } = require('./../../shared/logger')
|
|
5
|
-
|
|
6
|
-
const vault = new Command('vault')
|
|
7
|
-
|
|
8
|
-
vault
|
|
9
|
-
.description('DEPRECATED: moved to [dotenvx ext vault]')
|
|
10
|
-
|
|
11
|
-
// dotenvx vault migrate
|
|
12
|
-
const migrateAction = require('./../actions/ext/vault/migrate')
|
|
13
|
-
vault.command('migrate')
|
|
14
|
-
.description('DEPRECATED: moved to [dotenvx ext vault migrate]')
|
|
15
|
-
.action(function (...args) {
|
|
16
|
-
logger.warn('DEPRECATION NOTICE: [dotenvx vault migrate] moved to [dotenvx ext vault migrate]')
|
|
17
|
-
|
|
18
|
-
migrateAction.apply(this, args)
|
|
19
|
-
})
|
|
20
|
-
|
|
21
|
-
// dotenvx vault encrypt
|
|
22
|
-
const encryptAction = require('./../actions/ext/vault/encrypt')
|
|
23
|
-
vault.command('encrypt')
|
|
24
|
-
.description('DEPRECATED: moved to [dotenvx ext vault encrypt]')
|
|
25
|
-
.addHelpText('after', examples.vaultEncrypt)
|
|
26
|
-
.argument('[directory]', 'directory to encrypt', '.')
|
|
27
|
-
.option('-f, --env-file <paths...>', 'path(s) to your env file(s)')
|
|
28
|
-
.action(function (...args) {
|
|
29
|
-
logger.warn('DEPRECATION NOTICE: [dotenvx vault encrypt] moved to [dotenvx ext vault encrypt]')
|
|
30
|
-
|
|
31
|
-
encryptAction.apply(this, args)
|
|
32
|
-
})
|
|
33
|
-
|
|
34
|
-
// dotenvx vault decrypt
|
|
35
|
-
const decryptAction = require('./../actions/ext/vault/decrypt')
|
|
36
|
-
vault.command('decrypt')
|
|
37
|
-
.description('DEPRECATED: moved to [dotenvx ext vault decrypt]')
|
|
38
|
-
.argument('[directory]', 'directory to decrypt', '.')
|
|
39
|
-
.option('-e, --environment <environments...>', 'environment(s) to decrypt')
|
|
40
|
-
.action(function (...args) {
|
|
41
|
-
logger.warn('DEPRECATION NOTICE: [dotenvx vault decrypt] moved to [dotenvx ext vault decrypt]')
|
|
42
|
-
|
|
43
|
-
decryptAction.apply(this, args)
|
|
44
|
-
})
|
|
45
|
-
|
|
46
|
-
// dotenvx vault status
|
|
47
|
-
const statusAction = require('./../actions/ext/vault/status')
|
|
48
|
-
vault.command('status')
|
|
49
|
-
.description('DEPRECATED: moved to [dotenvx ext vault status]')
|
|
50
|
-
.argument('[directory]', 'directory to check status against', '.')
|
|
51
|
-
.action(function (...args) {
|
|
52
|
-
logger.warn('DEPRECATION NOTICE: [dotenvx vault status] moved to [dotenvx ext vault status]')
|
|
53
|
-
|
|
54
|
-
statusAction.apply(this, args)
|
|
55
|
-
})
|
|
56
|
-
|
|
57
|
-
module.exports = vault
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
const path = require('path')
|
|
3
|
-
const execa = require('execa')
|
|
4
|
-
|
|
5
|
-
const xsel = 'xsel'
|
|
6
|
-
const xselFallback = path.join(__dirname, './fallbacks/linux/xsel')
|
|
7
|
-
|
|
8
|
-
const copyArguments = ['--clipboard', '--input']
|
|
9
|
-
const pasteArguments = ['--clipboard', '--output']
|
|
10
|
-
|
|
11
|
-
const makeError = (xselError, fallbackError) => {
|
|
12
|
-
let error
|
|
13
|
-
if (xselError.code === 'ENOENT') {
|
|
14
|
-
error = new Error('Couldn\'t find the `xsel` binary and fallback didn\'t work. On Debian/Ubuntu you can install xsel with: sudo apt install xsel')
|
|
15
|
-
} else {
|
|
16
|
-
error = new Error('Both xsel and fallback failed')
|
|
17
|
-
error.xselError = xselError
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
error.fallbackError = fallbackError
|
|
21
|
-
return error
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
const xselWithFallback = async (argumentList, options) => {
|
|
25
|
-
try {
|
|
26
|
-
return await execa.stdout(xsel, argumentList, options)
|
|
27
|
-
} catch (xselError) {
|
|
28
|
-
try {
|
|
29
|
-
return await execa.stdout(xselFallback, argumentList, options)
|
|
30
|
-
} catch (fallbackError) {
|
|
31
|
-
throw makeError(xselError, fallbackError)
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
const xselWithFallbackSync = (argumentList, options) => {
|
|
37
|
-
try {
|
|
38
|
-
return execa.sync(xsel, argumentList, options)
|
|
39
|
-
} catch (xselError) {
|
|
40
|
-
try {
|
|
41
|
-
return execa.sync(xselFallback, argumentList, options)
|
|
42
|
-
} catch (fallbackError) {
|
|
43
|
-
throw makeError(xselError, fallbackError)
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
module.exports = {
|
|
49
|
-
copy: async options => {
|
|
50
|
-
await xselWithFallback(copyArguments, options)
|
|
51
|
-
},
|
|
52
|
-
copySync: options => {
|
|
53
|
-
xselWithFallbackSync(copyArguments, options)
|
|
54
|
-
},
|
|
55
|
-
paste: options => xselWithFallback(pasteArguments, options),
|
|
56
|
-
pasteSync: options => xselWithFallbackSync(pasteArguments, options)
|
|
57
|
-
}
|