@dotenvx/dotenvx 0.30.1 → 0.31.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/package.json +1 -1
- package/src/cli/actions/decrypt.js +6 -4
- package/src/cli/actions/encrypt.js +5 -3
- package/src/cli/actions/genexample.js +3 -2
- package/src/cli/actions/hub/logout.js +43 -0
- package/src/cli/actions/hub/open.js +40 -10
- package/src/cli/actions/hub/pull.js +4 -3
- package/src/cli/actions/hub/push.js +4 -3
- package/src/cli/actions/prebuild.js +2 -2
- package/src/cli/commands/hub.js +6 -0
- package/src/lib/helpers/extractUsernameName.js +10 -0
- package/src/lib/helpers/gitUrl.js +2 -3
- package/src/lib/helpers/resolvePath.js +8 -0
- package/src/lib/helpers/sleep.js +5 -0
- package/src/shared/store.js +19 -0
- package/src/cli/helpers.js +0 -46
package/package.json
CHANGED
|
@@ -2,9 +2,11 @@ const fs = require('fs')
|
|
|
2
2
|
const dotenv = require('dotenv')
|
|
3
3
|
|
|
4
4
|
const logger = require('./../../shared/logger')
|
|
5
|
-
const helpers = require('./../helpers')
|
|
6
5
|
const createSpinner = require('./../../shared/createSpinner')
|
|
6
|
+
|
|
7
7
|
const libDecrypt = require('./../../lib/helpers/decrypt')
|
|
8
|
+
const sleep = require('./../../lib/helpers/sleep')
|
|
9
|
+
const resolvePath = require('./../../lib/helpers/resolvePath')
|
|
8
10
|
|
|
9
11
|
const spinner = createSpinner('decrypting')
|
|
10
12
|
|
|
@@ -13,13 +15,13 @@ const ENCODING = 'utf8'
|
|
|
13
15
|
|
|
14
16
|
async function decrypt () {
|
|
15
17
|
spinner.start()
|
|
16
|
-
await
|
|
18
|
+
await sleep(500) // better dx
|
|
17
19
|
|
|
18
20
|
const options = this.opts()
|
|
19
21
|
logger.debug(`options: ${JSON.stringify(options)}`)
|
|
20
22
|
|
|
21
|
-
const vaultFilepath =
|
|
22
|
-
const keysFilepath =
|
|
23
|
+
const vaultFilepath = resolvePath('.env.vault')
|
|
24
|
+
const keysFilepath = resolvePath('.env.keys')
|
|
23
25
|
const changedEnvFilenames = new Set()
|
|
24
26
|
const unchangedEnvFilenames = new Set()
|
|
25
27
|
|
|
@@ -3,13 +3,15 @@ const path = require('path')
|
|
|
3
3
|
|
|
4
4
|
const main = require('./../../lib/main')
|
|
5
5
|
const logger = require('./../../shared/logger')
|
|
6
|
-
const helpers = require('./../helpers')
|
|
7
6
|
const createSpinner = require('./../../shared/createSpinner')
|
|
7
|
+
const sleep = require('./../../lib/helpers/sleep')
|
|
8
|
+
const pluralize = require('./../../lib/helpers/pluralize')
|
|
9
|
+
|
|
8
10
|
const spinner = createSpinner('encrypting')
|
|
9
11
|
|
|
10
12
|
async function encrypt (directory) {
|
|
11
13
|
spinner.start()
|
|
12
|
-
await
|
|
14
|
+
await sleep(500) // better dx
|
|
13
15
|
|
|
14
16
|
logger.debug(`directory: ${directory}`)
|
|
15
17
|
|
|
@@ -55,7 +57,7 @@ async function encrypt (directory) {
|
|
|
55
57
|
}
|
|
56
58
|
|
|
57
59
|
if (addedKeys.length > 0) {
|
|
58
|
-
spinner.succeed(`${
|
|
60
|
+
spinner.succeed(`${pluralize('key', addedKeys.length)} added to .env.keys (${addedKeys})`)
|
|
59
61
|
logger.help2('ℹ push .env.keys up to hub: [dotenvx hub push]')
|
|
60
62
|
}
|
|
61
63
|
|
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
const fs = require('fs')
|
|
2
2
|
const main = require('./../../lib/main')
|
|
3
|
-
const helpers = require('./../helpers')
|
|
4
3
|
const logger = require('./../../shared/logger')
|
|
5
4
|
const createSpinner = require('./../../shared/createSpinner')
|
|
6
5
|
|
|
6
|
+
const sleep = require('./../../lib/helpers/sleep')
|
|
7
|
+
|
|
7
8
|
const spinner = createSpinner('generating')
|
|
8
9
|
|
|
9
10
|
const ENCODING = 'utf8'
|
|
10
11
|
|
|
11
12
|
async function genexample (directory) {
|
|
12
13
|
spinner.start()
|
|
13
|
-
await
|
|
14
|
+
await sleep(500) // better dx
|
|
14
15
|
|
|
15
16
|
logger.debug(`directory: ${directory}`)
|
|
16
17
|
|
|
@@ -0,0 +1,43 @@
|
|
|
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
|
|
@@ -3,29 +3,59 @@ const confirm = require('@inquirer/confirm').default
|
|
|
3
3
|
|
|
4
4
|
const createSpinner = require('./../../../shared/createSpinner')
|
|
5
5
|
const logger = require('./../../../shared/logger')
|
|
6
|
-
|
|
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')
|
|
7
15
|
|
|
8
16
|
async function open () {
|
|
17
|
+
// debug opts
|
|
9
18
|
const options = this.opts()
|
|
10
19
|
logger.debug(`options: ${JSON.stringify(options)}`)
|
|
11
20
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
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
|
+
}
|
|
15
48
|
|
|
16
|
-
const
|
|
49
|
+
const usernameName = extractUsernameName(giturl)
|
|
50
|
+
const openUrl = `${options.hostname}/gh/${usernameName}`
|
|
17
51
|
|
|
18
52
|
// optionally allow user to open browser
|
|
19
53
|
const answer = await confirm({ message: `press Enter to open [${openUrl}]...` })
|
|
20
54
|
|
|
21
55
|
if (answer) {
|
|
22
|
-
const spinner = createSpinner('opening')
|
|
23
56
|
spinner.start()
|
|
24
|
-
|
|
25
|
-
await helpers.sleep(500) // better dx
|
|
26
|
-
|
|
57
|
+
await sleep(500) // better dx
|
|
27
58
|
await openBrowser(openUrl)
|
|
28
|
-
|
|
29
59
|
spinner.succeed(`opened [${usernameName}]`)
|
|
30
60
|
}
|
|
31
61
|
}
|
|
@@ -4,13 +4,14 @@ const { request } = require('undici')
|
|
|
4
4
|
|
|
5
5
|
const store = require('./../../../shared/store')
|
|
6
6
|
const logger = require('./../../../shared/logger')
|
|
7
|
-
const helpers = require('./../../helpers')
|
|
8
7
|
const createSpinner = require('./../../../shared/createSpinner')
|
|
9
8
|
|
|
10
9
|
const isGitRepo = require('./../../../lib/helpers/isGitRepo')
|
|
11
10
|
const isGithub = require('./../../../lib/helpers/isGithub')
|
|
12
11
|
const gitUrl = require('./../../../lib/helpers/gitUrl')
|
|
13
12
|
const gitRoot = require('./../../../lib/helpers/gitRoot')
|
|
13
|
+
const extractUsernameName = require('./../../../lib/helpers/extractUsernameName')
|
|
14
|
+
const sleep = require('./../../../lib/helpers/sleep')
|
|
14
15
|
|
|
15
16
|
const spinner = createSpinner('pulling')
|
|
16
17
|
|
|
@@ -20,7 +21,7 @@ const ENCODING = 'utf8'
|
|
|
20
21
|
// Create a simple-git instance for the current directory
|
|
21
22
|
async function pull (directory) {
|
|
22
23
|
spinner.start()
|
|
23
|
-
await
|
|
24
|
+
await sleep(500) // better dx
|
|
24
25
|
|
|
25
26
|
// debug args
|
|
26
27
|
logger.debug(`directory: ${directory}`)
|
|
@@ -61,7 +62,7 @@ async function pull (directory) {
|
|
|
61
62
|
const hostname = options.hostname
|
|
62
63
|
const pullUrl = `${hostname}/v1/pull`
|
|
63
64
|
const oauthToken = store.getToken()
|
|
64
|
-
const usernameName =
|
|
65
|
+
const usernameName = extractUsernameName(giturl)
|
|
65
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
|
|
66
67
|
|
|
67
68
|
try {
|
|
@@ -4,13 +4,14 @@ const { request } = require('undici')
|
|
|
4
4
|
|
|
5
5
|
const store = require('./../../../shared/store')
|
|
6
6
|
const logger = require('./../../../shared/logger')
|
|
7
|
-
const helpers = require('./../../helpers')
|
|
8
7
|
const createSpinner = require('./../../../shared/createSpinner')
|
|
9
8
|
|
|
10
9
|
const isGitRepo = require('./../../../lib/helpers/isGitRepo')
|
|
11
10
|
const isGithub = require('./../../../lib/helpers/isGithub')
|
|
12
11
|
const gitUrl = require('./../../../lib/helpers/gitUrl')
|
|
13
12
|
const gitRoot = require('./../../../lib/helpers/gitRoot')
|
|
13
|
+
const extractUsernameName = require('./../../../lib/helpers/extractUsernameName')
|
|
14
|
+
const sleep = require('./../../../lib/helpers/sleep')
|
|
14
15
|
|
|
15
16
|
const spinner = createSpinner('pushing')
|
|
16
17
|
|
|
@@ -20,7 +21,7 @@ const ENCODING = 'utf8'
|
|
|
20
21
|
// Create a simple-git instance for the current directory
|
|
21
22
|
async function push (directory) {
|
|
22
23
|
spinner.start()
|
|
23
|
-
await
|
|
24
|
+
await sleep(500) // better dx
|
|
24
25
|
|
|
25
26
|
// debug args
|
|
26
27
|
logger.debug(`directory: ${directory}`)
|
|
@@ -69,7 +70,7 @@ async function push (directory) {
|
|
|
69
70
|
const pushUrl = `${hostname}/v1/push`
|
|
70
71
|
const oauthToken = store.getToken()
|
|
71
72
|
const dotenvKeysContent = fs.readFileSync(envKeysFilepath, ENCODING)
|
|
72
|
-
const usernameName =
|
|
73
|
+
const usernameName = extractUsernameName(giturl)
|
|
73
74
|
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
|
|
74
75
|
|
|
75
76
|
try {
|
|
@@ -3,7 +3,7 @@ const fs = require('fs')
|
|
|
3
3
|
const ignore = require('ignore')
|
|
4
4
|
|
|
5
5
|
const logger = require('./../../shared/logger')
|
|
6
|
-
const
|
|
6
|
+
const pluralize = require('./../../lib/helpers/pluralize')
|
|
7
7
|
|
|
8
8
|
function prebuild () {
|
|
9
9
|
const options = this.opts()
|
|
@@ -55,7 +55,7 @@ function prebuild () {
|
|
|
55
55
|
|
|
56
56
|
// 3. outpout success
|
|
57
57
|
if (warningCount > 0) {
|
|
58
|
-
logger.successvpb(`success (with ${
|
|
58
|
+
logger.successvpb(`success (with ${pluralize('warning', warningCount)})`)
|
|
59
59
|
} else {
|
|
60
60
|
logger.successvpb('success')
|
|
61
61
|
}
|
package/src/cli/commands/hub.js
CHANGED
|
@@ -44,4 +44,10 @@ hub
|
|
|
44
44
|
.description('display logged in user')
|
|
45
45
|
.action(require('./../actions/hub/status'))
|
|
46
46
|
|
|
47
|
+
hub
|
|
48
|
+
.command('logout')
|
|
49
|
+
.description('log out this machine from dotenvx hub')
|
|
50
|
+
.option('-h, --hostname <url>', 'set hostname', store.getHostname())
|
|
51
|
+
.action(require('./../actions/hub/logout'))
|
|
52
|
+
|
|
47
53
|
module.exports = hub
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
function extractUsernameName (url) {
|
|
2
|
+
// Removing the protocol part and splitting by slashes and colons
|
|
3
|
+
// Removing the protocol part and .git suffix, then splitting by slashes and colons
|
|
4
|
+
const parts = url.replace(/(^\w+:|^)\/\//, '').replace(/\.git$/, '').split(/[/:]/)
|
|
5
|
+
|
|
6
|
+
// Extract the 'username/repository' part
|
|
7
|
+
return parts.slice(-2).join('/')
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
module.exports = extractUsernameName
|
|
@@ -2,10 +2,9 @@ const execa = require('execa')
|
|
|
2
2
|
|
|
3
3
|
function gitUrl () {
|
|
4
4
|
try {
|
|
5
|
-
// Redirect standard error to null to suppress Git error messages
|
|
6
5
|
const raw = execa.sync('git', ['remote', 'get-url', 'origin'])
|
|
7
|
-
|
|
8
|
-
return
|
|
6
|
+
|
|
7
|
+
return raw.stdout.toString().trim()
|
|
9
8
|
} catch (_error) {
|
|
10
9
|
return null
|
|
11
10
|
}
|
package/src/shared/store.js
CHANGED
|
@@ -108,6 +108,23 @@ const setLatestVersionLastChecked = function (dateNow) {
|
|
|
108
108
|
return dateNow
|
|
109
109
|
}
|
|
110
110
|
|
|
111
|
+
const deleteToken = function () {
|
|
112
|
+
// memory user
|
|
113
|
+
const key = findFirstMatchingKey(confStore.store) // GH_MOTDOTLA_DOTENVX_TOKEN
|
|
114
|
+
confStore.delete(key)
|
|
115
|
+
|
|
116
|
+
// current logged in user
|
|
117
|
+
confStore.delete('DOTENVX_TOKEN')
|
|
118
|
+
|
|
119
|
+
return true
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const deleteHostname = function () {
|
|
123
|
+
confStore.delete('DOTENVX_HOSTNAME')
|
|
124
|
+
|
|
125
|
+
return true
|
|
126
|
+
}
|
|
127
|
+
|
|
111
128
|
const configPath = function () {
|
|
112
129
|
return confStore.path
|
|
113
130
|
}
|
|
@@ -123,5 +140,7 @@ module.exports = {
|
|
|
123
140
|
setToken,
|
|
124
141
|
setLatestVersion,
|
|
125
142
|
setLatestVersionLastChecked,
|
|
143
|
+
deleteToken,
|
|
144
|
+
deleteHostname,
|
|
126
145
|
configPath
|
|
127
146
|
}
|
package/src/cli/helpers.js
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
const path = require('path')
|
|
2
|
-
const childProcess = require('child_process')
|
|
3
|
-
|
|
4
|
-
const sleep = function (ms) {
|
|
5
|
-
return new Promise(resolve => setTimeout(resolve, ms))
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
// resolve path based on current running process location
|
|
9
|
-
const resolvePath = function (filepath) {
|
|
10
|
-
return path.resolve(process.cwd(), filepath)
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
const pluralize = function (word, count) {
|
|
14
|
-
// simple pluralization: add 's' at the end
|
|
15
|
-
if (count === 0 || count > 1) {
|
|
16
|
-
return word + 's'
|
|
17
|
-
} else {
|
|
18
|
-
return word
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
const getRemoteOriginUrl = function () {
|
|
23
|
-
try {
|
|
24
|
-
const url = childProcess.execSync('git remote get-url origin 2> /dev/null').toString().trim()
|
|
25
|
-
return url
|
|
26
|
-
} catch (_error) {
|
|
27
|
-
return null
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
const extractUsernameName = function (url) {
|
|
32
|
-
// Removing the protocol part and splitting by slashes and colons
|
|
33
|
-
// Removing the protocol part and .git suffix, then splitting by slashes and colons
|
|
34
|
-
const parts = url.replace(/(^\w+:|^)\/\//, '').replace(/\.git$/, '').split(/[/:]/)
|
|
35
|
-
|
|
36
|
-
// Extract the 'username/repository' part
|
|
37
|
-
return parts.slice(-2).join('/')
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
module.exports = {
|
|
41
|
-
sleep,
|
|
42
|
-
resolvePath,
|
|
43
|
-
pluralize,
|
|
44
|
-
getRemoteOriginUrl,
|
|
45
|
-
extractUsernameName
|
|
46
|
-
}
|