@fromsvenwithlove/devops-issues-cli
Version:
AI-powered CLI tool and library for Azure DevOps work item management with Claude agents
127 lines (107 loc) • 3.04 kB
JavaScript
/**
* Manages stdin state to prevent conflicts between different input handlers
* This ensures proper isolation between keypress and inquirer
*/
class StdinStateManager {
constructor() {
this.originalState = null;
this.savedListeners = new Map();
}
/**
* Save the current state of stdin
*/
saveState() {
if (!process.stdin.isTTY) {
return;
}
this.originalState = {
rawMode: process.stdin.isRaw || false,
paused: process.stdin.isPaused(),
encoding: process.stdin.readableEncoding,
listeners: new Map(),
};
// Save all event listeners
const events = ["data", "keypress", "end", "error", "close"];
events.forEach((event) => {
const listeners = process.stdin.listeners(event);
if (listeners.length > 0) {
this.originalState.listeners.set(event, listeners.slice());
}
});
}
/**
* Restore stdin to its original state
*/
restoreState() {
if (!this.originalState || !process.stdin.isTTY) {
return;
}
// Remove all current listeners
process.stdin.removeAllListeners();
// Restore original listeners
this.originalState.listeners.forEach((listeners, event) => {
listeners.forEach((listener) => {
process.stdin.on(event, listener);
});
});
// Restore encoding
if (this.originalState.encoding) {
process.stdin.setEncoding(this.originalState.encoding);
}
// Restore raw mode and pause state
if (process.stdin.setRawMode) {
try {
process.stdin.setRawMode(this.originalState.rawMode);
} catch (e) {
// Ignore errors if stdin is no longer in a valid state
}
}
if (this.originalState.paused) {
process.stdin.pause();
} else {
process.stdin.resume();
}
this.originalState = null;
}
/**
* Fully reset stdin to a clean state for inquirer
*/
resetForInquirer() {
if (!process.stdin.isTTY) {
return;
}
// Remove all keypress-related listeners
process.stdin.removeAllListeners("keypress");
// Ensure stdin is not in raw mode for inquirer
if (process.stdin.setRawMode) {
try {
process.stdin.setRawMode(false);
} catch (e) {
// Ignore errors
}
}
// Pause first to ensure clean state
process.stdin.pause();
// Clear any buffered input
if (process.stdin.read) {
while (process.stdin.read() !== null) {
// Drain any buffered input
}
}
// 🔧 IMPORTANT: resume stdin so Inquirer can listen cleanly
process.stdin.resume();
}
/**
* Check if stdin has been modified from its default state
*/
isModified() {
if (!process.stdin.isTTY) {
return false;
}
// Check for keypress listeners (indicator of keypress module usage)
const keypressListeners = process.stdin.listeners("keypress");
return keypressListeners.length > 0;
}
}
// Export singleton instance
export const stdinStateManager = new StdinStateManager();