structure-validation
Version:
A Node.js CLI tool for validating codebase folder and file structure using a clean declarative configuration. Part of the guardz ecosystem for comprehensive TypeScript development.
132 lines • 4.56 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.SmartInputService = void 0;
class SmartInputService {
constructor(rl) {
this.rl = rl;
}
/**
* Get user input with smart Enter key handling
*/
async getSmartInput(options) {
const { validChoices, choiceRange, timeoutMs = 3000 } = options;
const totalOptions = validChoices.length;
return new Promise((resolve) => {
const timeout = setTimeout(() => {
resolve({
choice: '',
requiresEnter: true,
isValid: false,
errorMessage: 'Input timeout. Please press Enter to continue.'
});
}, timeoutMs);
this.rl.question(`\nEnter your choice (${choiceRange}): `, (answer) => {
clearTimeout(timeout);
const choice = answer.trim();
const result = this.processInput(choice, validChoices, totalOptions);
resolve(result);
});
});
}
/**
* Process input and determine if Enter is required
*/
processInput(input, validChoices, totalOptions) {
// Handle empty input
if (input === '') {
return {
choice: '',
requiresEnter: true,
isValid: false,
errorMessage: 'Empty input. Please enter a valid choice.'
};
}
// Handle invalid input
if (!validChoices.includes(input)) {
return {
choice: input,
requiresEnter: true,
isValid: false,
errorMessage: `Invalid choice. Please enter ${validChoices[0]}-${validChoices[validChoices.length - 1]}.`
};
}
// Smart input logic
const requiresEnter = this.shouldRequireEnter(input, totalOptions);
return {
choice: input,
requiresEnter,
isValid: true
};
}
/**
* Determine if Enter key is required based on input and total options
*/
shouldRequireEnter(input, totalOptions) {
// Single digit input (1-9)
if (input.length === 1) {
const inputNum = parseInt(input);
// If there are 10+ options and input is 1-9, require Enter (ambiguous)
if (totalOptions >= 10 && inputNum >= 1 && inputNum <= 9) {
return true;
}
// If there are < 10 options, don't require Enter (unambiguous)
if (totalOptions < 10) {
return false;
}
}
// Double digit input (10+)
if (input.length > 1) {
const inputNum = parseInt(input);
// If input matches an option exactly, don't require Enter
if (inputNum >= 1 && inputNum <= totalOptions) {
return false;
}
}
// Default: require Enter for safety
return true;
}
/**
* Display confirmation prompt and wait for Enter
*/
async waitForConfirmation(message = 'Press Enter to confirm') {
return new Promise((resolve) => {
this.rl.question(`\n${message}: `, () => {
resolve();
});
});
}
/**
* Display error message and wait for Enter
*/
async displayErrorAndWait(errorMessage) {
console.log(`❌ ${errorMessage}`);
return this.waitForConfirmation('Press Enter to continue');
}
/**
* Get additional input (like new filename or pattern)
*/
async getAdditionalInput(prompt) {
return new Promise((resolve) => {
this.rl.question(`\n${prompt}: `, (answer) => {
resolve(answer.trim());
});
});
}
/**
* Process input with smart handling and confirmation if needed
*/
async processInputWithConfirmation(options, onValidInput) {
const result = await this.getSmartInput(options);
if (!result.isValid) {
await this.displayErrorAndWait(result.errorMessage || 'Invalid input');
return this.processInputWithConfirmation(options, onValidInput);
}
if (result.requiresEnter) {
console.log(`\nSelected: ${result.choice}`);
await this.waitForConfirmation();
}
await onValidInput(result.choice);
}
}
exports.SmartInputService = SmartInputService;
//# sourceMappingURL=SmartInputService.js.map