UNPKG

javaprompt

Version:

The javaprompt package which includes several dynamic input functions created by upsided.

195 lines (170 loc) 7.08 kB
import { rl } from "./rl.js" import { promisify } from 'util'; import chalk from 'chalk'; type StringTypes = 'string' | 'boolean' | 'integer' | 'float' | 'array' | 'number' | 'set' type InputTypes = string | boolean | number | any[] | Record<string | number | symbol, any> type InputOptions = { /** * Input return type, which includes: * `string` (1.0.0), `number` (1.0.0), `integer` (1.0.0), * `boolean` (1.0.1), `float` (1.0.2), * `array` (1.0.3), `set` (1.0.3) */ type: StringTypes } /** * Creates an input prompt in the console which can return several types depending on which specified * @param message The message to print when requesting input. * @param options {@link InputOptions} Input options * @example ```js * import { input } from 'javaprompt'; * * // Example is number * const response = await input('Give a number! ', { type: number }); * ``` * Console: * ```node * $ node . * ? Give a number! * ``` * Input typing follows the message. * @since 1.0.0 * @returns {Promise<InputTypes>} One of the types in StringTypes. Some have been yet to be implemented */ export async function input(message: string, options?: InputOptions): Promise<InputTypes | undefined> { // Resumes stream rl.resume() // Ignore the 'as' just making the type work out because typescript treats it as void const question = promisify(rl.question).bind(rl) as (message: string) => Promise<unknown> as (message: string) => Promise<string> process.stdout.write(`${chalk.green('?')} ${message}`) const response = (await question(message)).trim() // Pauses stream so it doesn't glitch out and be wierd rl.pause() if (!options) { // If no type is provided, the default is string return response } else if (options.type === 'string') { // Same as default return response } else if (options.type === 'integer') { // Checks if the string only contains numerical characters (0-9), meaning its an integer. if (!/[^1-9]/.test(response)) { return Number.parseInt(response) } else { // Isn't integer // Keeps prompting until input finally is an integer while (true) { console.log(`${chalk.green('!')} Invalid input. please provide an integer.`) process.stdout.write(`${chalk.green('?')} ${message}`) rl.resume() const res = await question(message) rl.pause() // If it's finally an integer if (Number.isInteger(parseFloat(res)) && !/[^1-9]/.test(res)) { return Number.parseInt(res) } } } } else if (options.type === 'number') { // Is a number if (!/[^1-9.]/.test(response)) { return Number.parseFloat(response) } else { // Keeps prompting until input is a number while (true) { console.log(`${chalk.green('!')} Invalid input. please provide a number.`) process.stdout.write(`${chalk.green('?')} ${message}`) rl.resume() const res = await question(message) rl.pause() // If it is finally a number if (!/[^1-9.]/.test(res)) return Number.parseFloat(res) } } } else if (options.type === 'boolean') { // If response is the boolean words/characters if (['t', 'f', 'true', 'false'].includes(response.toLowerCase())) { // True? if (['t', 'true'].includes(response.toLowerCase())) { return true } else { return false } } else { // Keeps prompting until it gives on of the boolean words/characters while (true) { console.log(`${chalk.green('!')} Invalid input. please provide a boolean. [t, f, true, false]`) process.stdout.write(`${chalk.green('?')} ${message}`) rl.resume() const res = await question(message) rl.pause() // Is one of the words/characters if (['t', 'f', 'true', 'false'].includes(res.toLowerCase())) { if (['t', 'true'].includes(res.toLowerCase())) { return true } else { return false } } } } } else if (options.type === 'float') { // Is a number and is not an integer if (!/[^1-9.]/.test(response) && !Number.isInteger(Number.parseFloat(response))) { return Number.parseFloat(response) } else { // Keeps prompting until a float is given while (true) { console.log(`${chalk.green('!')} Invalid input. please provide a float. (decimal number)`) process.stdout.write(`${chalk.green('?')} ${message}`) rl.resume() const res = await question(message) rl.pause() // If it is finally a float if (!/[^1-9.]/.test(res) && !Number.isInteger(parseFloat(res))) { return Number.parseFloat(res) } } } } else if (options.type === 'array') { try { // Parses array const parsedArray = JSON.parse(`[${response}]`) return parsedArray } catch { // Cannot parse array // Keeps prompting until given parseable array while (true) { try { process.stdout.write(`${chalk.green('?')} ${message}`) rl.resume() const res = await question(message) rl.pause() const pArray = JSON.parse(`[${res}]`) return pArray } catch { // Still not parseable console.log(`${chalk.green('!')} Invalid input. please provide an array. (list of elements, separated by a comma )`) } } } } else if (options.type === 'set') { try { // Parses array const parsedArray = JSON.parse(`{${response}}`) return parsedArray } catch { // Cannot parse array // Keeps prompting until given parseable array while (true) { try { process.stdout.write(`${chalk.green('?')} ${message}`) rl.resume() const res = await question(message) rl.pause() const pArray = JSON.parse(`{${res}}`) return pArray } catch { // Still not parseable console.log(`${chalk.green('!')} Invalid input. please provide a set (list of key: value pairs, separated by comma.).`) } } } } } export default { input }