diff options
author | Julian Møller Ellehauge <jumoel@github.com> | 2022-06-22 23:58:41 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-06-22 23:58:41 +0300 |
commit | 06fd788f79e16da04d6e96aa56416cd2698f057a (patch) | |
tree | 7ca9e6a884b2b64cb65ac791fda52b8d2b963ea6 /lib | |
parent | aab4079e810c06ff5fa847cbd53b5d7bab3dd24f (diff) |
feat: prompt before opening web-login URL when performing `login`/`adduser` (#4960)
Prompt before opening web-login URL when performing login/adduser
Diffstat (limited to 'lib')
-rw-r--r-- | lib/auth/legacy.js | 12 | ||||
-rw-r--r-- | lib/utils/open-url-prompt.js | 69 |
2 files changed, 79 insertions, 2 deletions
diff --git a/lib/auth/legacy.js b/lib/auth/legacy.js index d1401ce14..9aed12f39 100644 --- a/lib/auth/legacy.js +++ b/lib/auth/legacy.js @@ -1,6 +1,6 @@ const profile = require('npm-profile') const log = require('../utils/log-shim') -const openUrl = require('../utils/open-url.js') +const openUrlPrompt = require('../utils/open-url-prompt.js') const read = require('../utils/read-user-info.js') const loginPrompter = async (creds) => { @@ -47,7 +47,15 @@ const login = async (npm, opts) => { return newUser } - const openerPromise = (url) => openUrl(npm, url, 'to complete your login please visit') + const openerPromise = (url, emitter) => + openUrlPrompt( + npm, + url, + 'Authenticate your account at', + 'Press ENTER to open in the browser...', + emitter + ) + try { res = await profile.login(openerPromise, loginPrompter, opts) } catch (err) { diff --git a/lib/utils/open-url-prompt.js b/lib/utils/open-url-prompt.js new file mode 100644 index 000000000..3eb3ac288 --- /dev/null +++ b/lib/utils/open-url-prompt.js @@ -0,0 +1,69 @@ +const readline = require('readline') +const opener = require('opener') + +function print (npm, title, url) { + const json = npm.config.get('json') + + const message = json ? JSON.stringify({ title, url }) : `${title}:\n${url}` + + npm.output(message) +} + +// Prompt to open URL in browser if possible +const promptOpen = async (npm, url, title, prompt, emitter) => { + const browser = npm.config.get('browser') + const isInteractive = process.stdin.isTTY === true && process.stdout.isTTY === true + + try { + if (!/^https?:$/.test(new URL(url).protocol)) { + throw new Error() + } + } catch (_) { + throw new Error('Invalid URL: ' + url) + } + + print(npm, title, url) + + if (browser === false || !isInteractive) { + return + } + + const rl = readline.createInterface({ + input: process.stdin, + output: process.stdout, + }) + + const tryOpen = await new Promise(resolve => { + rl.question(prompt, () => { + resolve(true) + }) + + if (emitter && emitter.addListener) { + emitter.addListener('abort', () => { + rl.close() + + // clear the prompt line + npm.output('') + + resolve(false) + }) + } + }) + + if (!tryOpen) { + return + } + + const command = browser === true ? null : browser + await new Promise((resolve, reject) => { + opener(url, { command }, err => { + if (err) { + return reject(err) + } + + return resolve() + }) + }) +} + +module.exports = promptOpen |