@hixbe/otp-pass-kit
Version:
A secure, cryptographically-strong OTP and password generator for Node.js with CLI support. Generate customizable one-time passwords and strong passwords with TypeScript support.
189 lines (183 loc) • 5.99 kB
JavaScript
;
// src/functions.ts
var import_crypto = require("crypto");
var DIGITS = "0123456789";
var LOWERCASE_ALPHABETS = "abcdefghijklmnopqrstuvwxyz";
var UPPERCASE_ALPHABETS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
var SPECIAL_CHARS = "!@#$%^&*()_+-=[]{}|;:,.<>?";
function validateLength(length) {
if (!Number.isInteger(length) || length <= 0) {
throw new Error("Length must be a positive integer");
}
if (length > 1e3) {
throw new Error("Length cannot exceed 1000 characters");
}
}
function buildCharacterPool(options) {
let pool = "";
if (options.digits) pool += DIGITS;
if (options.lowerCaseAlphabets) pool += LOWERCASE_ALPHABETS;
if (options.upperCaseAlphabets) pool += UPPERCASE_ALPHABETS;
if (options.specialChars) pool += SPECIAL_CHARS;
if (!pool) {
throw new Error("At least one character set must be enabled");
}
return pool;
}
function generateRandomString(length, characterPool, options) {
const chars = new Array(length);
if (options?.ensureEachType && length >= 4) {
const sets = [];
if (options.digits) sets.push(DIGITS);
if (options.lowerCaseAlphabets) sets.push(LOWERCASE_ALPHABETS);
if (options.upperCaseAlphabets) sets.push(UPPERCASE_ALPHABETS);
if (options.specialChars) sets.push(SPECIAL_CHARS);
for (let i = 0; i < sets.length && i < length; i++) {
const set = sets[i];
chars[i] = set[(0, import_crypto.randomInt)(0, set.length)];
}
for (let i = sets.length; i < length; i++) {
const randomIndex = (0, import_crypto.randomInt)(0, characterPool.length);
chars[i] = characterPool[randomIndex];
}
for (let i = length - 1; i > 0; i--) {
const j = (0, import_crypto.randomInt)(0, i + 1);
[chars[i], chars[j]] = [chars[j], chars[i]];
}
} else {
for (let i = 0; i < length; i++) {
const randomIndex = (0, import_crypto.randomInt)(0, characterPool.length);
chars[i] = characterPool[randomIndex];
}
}
return chars.join("");
}
function generateOtp(length = 6, options) {
validateLength(length);
const defaultOptions = {
lowerCaseAlphabets: false,
upperCaseAlphabets: false,
specialChars: false,
digits: true,
...options
};
const characterPool = buildCharacterPool(defaultOptions);
return generateRandomString(length, characterPool, defaultOptions);
}
function generatePass(length = 8, options) {
validateLength(length);
const defaultOptions = {
lowerCaseAlphabets: true,
upperCaseAlphabets: true,
specialChars: true,
digits: true,
...options
};
const characterPool = buildCharacterPool(defaultOptions);
return generateRandomString(length, characterPool, defaultOptions);
}
// src/cli.ts
function parseArgs() {
const args = process.argv.slice(2);
if (args.includes("-h") || args.includes("--help")) {
console.log(`
Usage: otp-pass-kit <command> [options]
Commands:
otp Generate an OTP (One-Time Password)
pass Generate a password
Options:
-l, --length <number> Length of the generated string (default: 6 for otp, 8 for pass)
-d, --digits Include digits (default: true for otp, true for pass)
--no-digits Exclude digits
-u, --uppercase Include uppercase letters (default: false for otp, true for pass)
--no-uppercase Exclude uppercase letters
-w, --lowercase Include lowercase letters (default: false for otp, true for pass)
--no-lowercase Exclude lowercase letters
-s, --special Include special characters (default: false for otp, true for pass)
--no-special Exclude special characters
-e, --ensure-each-type Ensure at least one character from each enabled set
-h, --help Show this help message
Examples:
otp-pass-kit otp
otp-pass-kit otp -l 8 -u -d
otp-pass-kit pass
otp-pass-kit pass -l 12 --ensure-each-type
otp-pass-kit pass -l 10 -u -w -d --no-special
`);
process.exit(0);
}
const command = args[0];
if (!command || command !== "otp" && command !== "pass") {
console.error("Error: Invalid command. Use --help for usage information.");
process.exit(1);
}
const options = {};
let length = command === "otp" ? 6 : 8;
for (let i = 1; i < args.length; i++) {
const arg = args[i];
switch (arg) {
case "-l":
case "--length":
length = parseInt(args[++i]);
if (isNaN(length) || length <= 0) {
console.error("Error: Length must be a positive integer");
process.exit(1);
}
break;
case "-d":
case "--digits":
options.digits = true;
break;
case "--no-digits":
options.digits = false;
break;
case "-u":
case "--uppercase":
options.upperCaseAlphabets = true;
break;
case "--no-uppercase":
options.upperCaseAlphabets = false;
break;
case "-w":
case "--lowercase":
options.lowerCaseAlphabets = true;
break;
case "--no-lowercase":
options.lowerCaseAlphabets = false;
break;
case "-s":
case "--special":
options.specialChars = true;
break;
case "--no-special":
options.specialChars = false;
break;
case "-e":
case "--ensure-each-type":
options.ensureEachType = true;
break;
default:
console.error(`Unknown option: ${arg}`);
console.log("Use --help for usage information");
process.exit(1);
}
}
return { command, length, options };
}
function main() {
try {
const { command, length, options } = parseArgs();
let result;
if (command === "otp") {
result = generateOtp(length, options);
} else {
result = generatePass(length, options);
}
console.log(result);
} catch (error) {
console.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
process.exit(1);
}
}
main();