Enhanced Node.js utility for reading user input from stdin with features like silent mode, timeouts, and defaults
npx @tessl/cli install tessl/npm-read@4.1.0Enhanced Node.js utility for reading user input from stdin with features like silent mode, timeouts, defaults, and autocomplete. Similar to readline's question() method but with additional functionality for CLI applications.
npm install readimport { read, Options } from "read";For CommonJS:
const { read } = require("read");import { read } from "read";
// Simple input
const name = await read({ prompt: "Name: " });
// Input with default value
const email = await read({
prompt: "Email: ",
default: "user@example.com"
});
// Silent input for passwords
const password = await read({
prompt: "Password: ",
silent: true
});
// Input with timeout
try {
const response = await read({
prompt: "Quick response: ",
timeout: 5000
});
} catch (err) {
console.log("Timed out!");
}Reads user input from stdin with comprehensive configuration options.
/**
* Reads user input from stdin with configurable options
* @param options - Configuration options for input reading
* @returns Promise resolving to user input or default value
*/
function read<T extends string | number = string>(
options: Options<T>
): Promise<T | string>;Usage Examples:
// Basic prompt
const result = await read({ prompt: "Enter value: " });
// With default value
const name = await read({
prompt: "Your name: ",
default: "Anonymous"
});
// Silent mode (for passwords)
const secret = await read({
prompt: "Secret: ",
silent: true,
replace: "*" // Optional: replace with asterisks
});
// With timeout
const quick = await read({
prompt: "Quick: ",
timeout: 3000
});
// Custom streams
const custom = await read({
prompt: "Input: ",
input: customInputStream,
output: customOutputStream
});
// With autocomplete
const withCompletion = await read({
prompt: "Command: ",
completer: (line) => {
const commands = ['help', 'exit', 'list'];
const hits = commands.filter(cmd => cmd.startsWith(line));
return [hits, line];
}
});
// With history
const withHistory = await read({
prompt: "Command: ",
history: previousCommands
});Configuration options for the read function.
interface Options<T extends string | number = string> {
/** Default value if user enters nothing */
default?: T;
/** Input stream (default: process.stdin) */
input?: ReadLineOptions['input'] & {
isTTY?: boolean;
};
/** Output stream (default: process.stdout) */
output?: ReadLineOptions['output'] & {
isTTY?: boolean;
};
/** Text to display before reading input */
prompt?: string;
/** Don't echo output as user types (for passwords) */
silent?: boolean;
/** Milliseconds to wait before giving up */
timeout?: number;
/** Allow user to edit the default value */
edit?: boolean;
/** Treat output as TTY regardless of actual state */
terminal?: boolean;
/** Character to replace silenced characters with */
replace?: string;
/** Autocomplete callback function */
completer?: Completer | AsyncCompleter;
/** History array for command history */
history?: string[];
}The following types are imported from Node.js built-in modules:
// From 'readline' module
type Completer = (line: string) => CompleterResult | Promise<CompleterResult>;
type AsyncCompleter = (
line: string,
callback: (err?: null | Error, result?: CompleterResult) => void
) => void;
type CompleterResult = [string[], string];
interface ReadLineOptions {
input?: NodeJS.ReadableStream;
output?: NodeJS.WritableStream;
completer?: Completer | AsyncCompleter;
terminal?: boolean;
history?: string[];
historySize?: number;
removeHistoryDuplicates?: boolean;
prompt?: string;
crlfDelay?: number;
escapeCodeTimeout?: number;
tabSize?: number;
}The read function can throw the following errors:
try {
const result = await read({
prompt: "Input: ",
default: "valid default", // Must be string or number
timeout: 5000
});
} catch (error) {
if (error.message === 'timed out') {
console.log('User took too long to respond');
} else if (error.message === 'canceled') {
console.log('User canceled input');
} else {
console.log('Invalid configuration:', error.message);
}
}For password input with visual feedback:
const password = await read({
prompt: "Password: ",
silent: true,
replace: "•" // Shows bullets instead of characters
});For testing or alternative interfaces:
import { Readable, Writable } from 'stream';
const customInput = new Readable();
const customOutput = new Writable();
const result = await read({
prompt: "Test: ",
input: customInput,
output: customOutput
});Allow users to modify default values:
const edited = await read({
prompt: "Name: ",
default: "John Doe",
edit: true // User can modify the default
});