Build Core Utils
This commit is contained in:
@@ -87,6 +87,121 @@ function bareOsEmitRaw(ctx, chunk) {
|
||||
return false
|
||||
}
|
||||
|
||||
function loginDecodeChunk(chunk) {
|
||||
if (typeof chunk === 'string') return chunk
|
||||
if (chunk instanceof Uint8Array) return new TextDecoder().decode(chunk)
|
||||
if (
|
||||
typeof Buffer !== 'undefined' &&
|
||||
typeof Buffer.isBuffer === 'function' &&
|
||||
Buffer.isBuffer(chunk)
|
||||
) {
|
||||
return chunk.toString('utf8')
|
||||
}
|
||||
return String(chunk)
|
||||
}
|
||||
|
||||
async function loginReadMaskedLine(ctx, prompt) {
|
||||
const stdin = ctx.stdin
|
||||
const stdout = ctx.stdout || globalThis.process?.stdout
|
||||
if (!stdin || !stdout || typeof stdin.on !== 'function' || typeof stdout.write !== 'function') {
|
||||
if (typeof ctx.readLine === 'function') return String((await ctx.readLine(prompt)) || '')
|
||||
return ''
|
||||
}
|
||||
stdout.write(prompt)
|
||||
const ttyIn = stdin
|
||||
if (!ttyIn.isTTY || typeof ttyIn.setRawMode !== 'function') {
|
||||
return await new Promise((resolve) => {
|
||||
let acc = ''
|
||||
function onData(chunk) {
|
||||
const s = loginDecodeChunk(chunk)
|
||||
acc += s
|
||||
const nl = acc.indexOf('\n')
|
||||
if (nl >= 0) {
|
||||
cleanup()
|
||||
resolve(acc.slice(0, nl).replace(/\r$/, ''))
|
||||
}
|
||||
}
|
||||
function onEnd() {
|
||||
cleanup()
|
||||
resolve(acc.replace(/\r$/, ''))
|
||||
}
|
||||
function cleanup() {
|
||||
stdin.removeListener('data', onData)
|
||||
stdin.removeListener('end', onEnd)
|
||||
stdin.removeListener('error', onEnd)
|
||||
}
|
||||
stdin.on('data', onData)
|
||||
stdin.once('end', onEnd)
|
||||
stdin.once('error', onEnd)
|
||||
if (typeof stdin.resume === 'function') stdin.resume()
|
||||
})
|
||||
}
|
||||
return await new Promise((resolve, reject) => {
|
||||
const chars = []
|
||||
let done = false
|
||||
function finish(ok, err) {
|
||||
if (done) return
|
||||
done = true
|
||||
cleanup()
|
||||
stdout.write('\n')
|
||||
if (ok) resolve(chars.join(''))
|
||||
else reject(err || new Error('masked_input_failed'))
|
||||
}
|
||||
function cleanup() {
|
||||
stdin.removeListener('data', onData)
|
||||
stdin.removeListener('end', onEnd)
|
||||
stdin.removeListener('error', onErr)
|
||||
try {
|
||||
ttyIn.setRawMode(false)
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
}
|
||||
function onEnd() {
|
||||
finish(true)
|
||||
}
|
||||
function onErr(e) {
|
||||
finish(false, e instanceof Error ? e : new Error(String(e)))
|
||||
}
|
||||
function onData(chunk) {
|
||||
if (done) return
|
||||
const s = loginDecodeChunk(chunk)
|
||||
for (const ch of s) {
|
||||
const code = ch.charCodeAt(0)
|
||||
if (ch === '\r' || ch === '\n') {
|
||||
finish(true)
|
||||
return
|
||||
}
|
||||
if (ch === '\u0003') {
|
||||
finish(false, new Error('interrupted'))
|
||||
return
|
||||
}
|
||||
if (ch === '\u007f' || ch === '\b') {
|
||||
if (chars.length) {
|
||||
chars.pop()
|
||||
stdout.write('\b \b')
|
||||
}
|
||||
continue
|
||||
}
|
||||
if (code >= 32 && code !== 127) {
|
||||
chars.push(ch)
|
||||
stdout.write('*')
|
||||
}
|
||||
}
|
||||
}
|
||||
try {
|
||||
ttyIn.setRawMode(true)
|
||||
} catch {
|
||||
finish(true)
|
||||
return
|
||||
}
|
||||
stdin.on('data', onData)
|
||||
stdin.once('end', onEnd)
|
||||
stdin.once('error', onErr)
|
||||
if (typeof stdin.resume === 'function') stdin.resume()
|
||||
})
|
||||
}
|
||||
|
||||
async function run(ctx, argv) {
|
||||
const rest = argv.slice(1)
|
||||
let createNew = false
|
||||
@@ -94,9 +209,11 @@ async function run(ctx, argv) {
|
||||
createNew = true
|
||||
rest.shift()
|
||||
}
|
||||
const passphrase = rest.join(' ')
|
||||
const passphrase = rest.length
|
||||
? rest.join(' ')
|
||||
: await loginReadMaskedLine(ctx, createNew ? 'New passphrase: ' : 'Passphrase: ')
|
||||
if (!passphrase) {
|
||||
ctx.console.error('usage: login [--new] <passphrase>')
|
||||
ctx.console.error('usage: login [--new] [passphrase]')
|
||||
return
|
||||
}
|
||||
const reg = ctx.applyRegister
|
||||
|
||||
Reference in New Issue
Block a user