readtastic
Version:
Readtastic is a fast, minimaslitic, light-weight, promise based tool for interacting with input stream line by line.
171 lines (153 loc) • 4.98 kB
JavaScript
// Copyright (c) 2026 BlazeInferno64 --> https://github.com/blazeinferno64.
//
// Author(s) -> BlazeInferno64
//
// Last updated: 27/05/2026
;
const readline = require("readline");
const process = require("process");
const { EventEmitter } = require("events");
const emitter = new EventEmitter();
const packageJson = require("../package.json");
let rl;
// Store listeners added before rl is initialized
const pendingListeners = [];
/**
* Helper to attach all queued listeners to a newly created readline interface.
*/
const attachPendingListeners = (readlineInterface) => {
while (pendingListeners.length > 0) {
const { event, listener } = pendingListeners.shift();
readlineInterface.on(event, listener);
}
};
/**
* Creates a new interface for reading of input stream line by line.
*
* @param {*} interfaceObject - The interface object containing the input, output respectively.
*/
const parseInterface = (interfaceObject) => {
const input = interfaceObject.input;
const output = interfaceObject.output;
if (!rl) {
rl = readline.createInterface({
input: input || process.stdin,
output: output || process.stdout
});
attachPendingListeners(rl); // ⭐ FIXED: Flush the pending listeners here too!
}
}
const evaluatePrompt = (question) => {
return new Promise((resolve) => {
if (!rl) {
rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
attachPendingListeners(rl); // ⭐ FIXED: Flush the pending listeners here!
}
rl.question(question, (answer) => {
try {
const parsedAnswer = JSON.parse(answer);
resolve(parsedAnswer);
} catch (error) {
resolve(answer);
} finally {
rl.close(); // Close the interface here, after resolving the promise
}
});
});
}
const resume = () => {
if (rl) {
rl.resume();
}
}
const pause = () => {
if (rl) {
rl.pause();
}
}
const close = () => {
if (rl) {
rl.close();
rl = null; // Reset rl to null after closing
}
}
const on = (event, listener) => {
if (rl) {
// If the interface already exists, attach it directly
rl.on(event, listener);
} else {
// Otherwise, save it for when the interface gets spawned
pendingListeners.push({ event, listener });
}
}
/**
*
* @returns {string} returns the package version
*/
const version = Object.freeze({
get value() {
if (!packageJson) throw new Error(`package.json files seems to be missing!\nPlease try again by downloading 'netport' again with the following command\n''npm i netport''\nin your terminal!`);
return packageJson.version;
}
}).value;
/**
* @returns {Object} Returns a object which contains some info regarding blazed.js.
*/
const about = Object.freeze({
get value() {
if (!packageJson) throw new Error(`package.json file seems to be missing!\nPlease try again by downloading 'blazed.js' again with the following command\n''npm i blazed.js''\nor\n''yarn add blazed.js''\nin your terminal!`);
const aboutObject = {
"Name": packageJson.name,
"Author": packageJson.author,
"Version": packageJson.version,
"Description": packageJson.description,
"Repository": packageJson.repository
};
return aboutObject;
}
}).value;
module.exports = {
/**
* Creates a new interface for reading of input stream line by line.
*
* @param {*} interfaceObject - The interface object containing the input, output respectively (eg. process.stdin, process.stdout).
*/
parse_interface: (interfaceObject) => parseInterface(interfaceObject),
/**
* Prompts a specified question.
*
* @param {any} question - The specified question.
* @returns {any} - The answer of the prompted question.
*/
prompt: (question) => evaluatePrompt(question),
/**
* Resume the interface.
*/
resume: () => resume(),
/**
* Pause the interface.
*/
pause: () => pause(),
/**
* Close the interface.
*/
close: () => close(),
/**
* Returns info about the package.
*/
ABOUT: about,
/**
* Returns the package version number.
*/
VERSION: version,
/**
* Adds a listener for the specified event.
* @param {string} event - The name of the event to listen for.
* @param {Function} listener - The listener function to call when the event occurs.
* @returns {void}
*/
on: (event, listener) => on(event, listener)
}