Skip to content

Instantly share code, notes, and snippets.

@zillwc
Created September 25, 2020 07:22
Show Gist options
  • Select an option

  • Save zillwc/c8e05d4301e70adda7c4ea8e8dd9625e to your computer and use it in GitHub Desktop.

Select an option

Save zillwc/c8e05d4301e70adda7c4ea8e8dd9625e to your computer and use it in GitHub Desktop.
Module to prompt for masked input and test against predicates
const stdout = process.stdout;
const stdin = process.stdin;
module.exports = (specifiedPromptString = 'input', predicateFns = []) =>
new Promise((resolve, reject) => {
const prompt = specifiedPromptString.endsWith(': ') ? '' : specifiedPromptString + ': ';
const predicates = Array.isArray(predicateFns) ? predicateFns : [predicateFns];
stdout.write(prompt);
stdin.setRawMode(true);
stdin.resume();
stdin.setEncoding('utf-8');
let input = '';
function enter() {
stdin.removeListener('data', inputHandler);
stdin.setRawMode(false);
stdin.pause();
// checking against specified predicates
try {
for (let i = 0; i < predicates.length; i++) {
if (typeof predicates[i] === 'function') {
predicates[i](input);
}
}
} catch (err) {
// give back user input only if in debug
if (process.env.NODE_DEBUG) {
err.input = input;
}
return reject(err);
}
return resolve(input);
}
function ctrlc() {
stdin.removeListener('data', inputHandler);
stdin.setRawMode(false);
stdin.pause();
return reject('User exited prompt with ctrl-c');
}
function newchar(c) {
input += c;
}
function backspace() {
input = input.slice(0, input.length - 1);
}
function inputHandler(data, key) {
const c = data;
switch (c) {
case '\u0004': // Ctrl-d
case '\r':
case '\n':
return enter();
case '\u0003': // Ctrl-c
return ctrlc();
default:
// backspace
if (c.charCodeAt(0) === 8) return backspace();
else return newchar(c);
}
}
stdin.on('data', inputHandler);
});
const maskedPrompt = require('./masked-prompt.js');
// make sure password is at least 8 characters in length
const ensureProperLength = (input) => {
if (input.length < 8) {
throw new Error('Password must be at least 8 characters');
}
};
// make sure password contains at least 1 upper case character
const ensureCapitalLetter = (input) => {
const isUpperCase = (chr) =>
/[A-Z]|[\u0080-\u024F]/.test(chr) && chr === chr.toUpperCase();
let counter = 0;
for (c of input) {
if (isUpperCase(c)) {
counter++;
}
}
if (counter === 0) {
throw new Error('Password should contain at least one capital letter');
}
};
const passwordRules = [ ensureProperLength, ensureCapitalLetter ];
maskedPrompt('Password', passwordRules)
.then((passwd) => {
console.log(`\nUser password: ${passwd}`);
})
.catch(console.error);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment