UNPKG

qraft

Version:

A powerful CLI tool to qraft structured project setups from GitHub template repositories

288 lines • 11.6 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.InteractivePrompts = void 0; const chalk_1 = __importDefault(require("chalk")); const inquirer_1 = __importDefault(require("inquirer")); /** * Interactive prompt utilities for the qraft CLI */ class InteractivePrompts { /** * Prompt for box selection from a list of available boxes * @param boxes Array of available boxes * @param registryName Name of the registry * @returns Promise<BoxInfo | null> Selected box or null if cancelled */ async selectBox(boxes, registryName) { if (boxes.length === 0) { console.log(chalk_1.default.yellow('No boxes available in this registry.')); return null; } const choices = boxes.map(box => ({ name: `${chalk_1.default.cyan(box.manifest.name)} ${chalk_1.default.gray(`(${box.manifest.version})`)} - ${box.manifest.description}`, value: box, short: box.manifest.name })); choices.push({ name: chalk_1.default.gray('Cancel'), value: null, short: 'Cancel' }); const { selectedBox } = await inquirer_1.default.prompt([ { type: 'list', name: 'selectedBox', message: `Select a box${registryName ? ` from ${chalk_1.default.yellow(registryName)}` : ''}:`, choices, pageSize: 10 } ]); return selectedBox; } /** * Prompt for registry selection from available registries * @param registries Array of registry information * @returns Promise<string | null> Selected registry name or null if cancelled */ async selectRegistry(registries) { if (registries.length === 0) { console.log(chalk_1.default.yellow('No registries configured.')); return null; } const choices = registries.map(registry => ({ name: `${chalk_1.default.cyan(registry.name)} ${registry.isDefault ? chalk_1.default.green('(default)') : ''} - ${chalk_1.default.gray(registry.repository)}`, value: registry.name, short: registry.name })); choices.push({ name: chalk_1.default.gray('Cancel'), value: null, short: 'Cancel' }); const { selectedRegistry } = await inquirer_1.default.prompt([ { type: 'list', name: 'selectedRegistry', message: 'Select a registry:', choices, pageSize: 10 } ]); return selectedRegistry; } /** * Prompt for target directory with validation * @param defaultPath Default target directory * @returns Promise<string> Target directory path */ async promptTargetDirectory(defaultPath = process.cwd()) { const { targetDirectory } = await inquirer_1.default.prompt([ { type: 'input', name: 'targetDirectory', message: 'Target directory:', default: defaultPath, validate: (input) => { if (!input.trim()) { return 'Target directory cannot be empty'; } return true; } } ]); return targetDirectory; } /** * Prompt for confirmation with customizable message * @param message Confirmation message * @param defaultValue Default value (true/false) * @returns Promise<boolean> User confirmation */ async confirm(message, defaultValue = false) { const { confirmed } = await inquirer_1.default.prompt([ { type: 'confirm', name: 'confirmed', message, default: defaultValue } ]); return confirmed; } /** * Prompt for overwrite confirmation with file details * @param filePaths Array of file paths that would be overwritten * @returns Promise<boolean> Whether to overwrite files */ async confirmOverwrite(filePaths) { if (filePaths.length === 0) { return true; } console.log(chalk_1.default.yellow('\nāš ļø The following files already exist:')); filePaths.slice(0, 10).forEach(file => { console.log(chalk_1.default.gray(` • ${file}`)); }); if (filePaths.length > 10) { console.log(chalk_1.default.gray(` ... and ${filePaths.length - 10} more files`)); } return this.confirm('Do you want to overwrite these files?', false); } /** * Prompt for GitHub token input with validation * @param registryName Optional registry name for context * @returns Promise<string> GitHub token */ async promptGitHubToken(registryName) { console.log(chalk_1.default.blue.bold('šŸ” GitHub Authentication Setup\n')); if (registryName) { console.log(chalk_1.default.gray(`Setting up authentication for registry: ${chalk_1.default.cyan(registryName)}\n`)); } console.log(chalk_1.default.gray('To access private repositories and increase rate limits,')); console.log(chalk_1.default.gray('you need a GitHub Personal Access Token.\n')); console.log(chalk_1.default.gray('Create one at: https://github.com/settings/tokens\n')); console.log(chalk_1.default.gray('Required permissions:')); console.log(chalk_1.default.gray(' • repo (for private repositories)')); console.log(chalk_1.default.gray(' • public_repo (for public repositories)\n')); const { token } = await inquirer_1.default.prompt([ { type: 'password', name: 'token', message: 'Enter your GitHub token:', mask: '*', validate: (input) => { if (!input.trim()) { return 'Token cannot be empty'; } if (input.length < 10) { return 'Token seems too short (should be 40+ characters)'; } return true; } } ]); return token; } /** * Prompt for registry configuration * @returns Promise<{name: string, repository: string, setAsDefault: boolean}> Registry configuration */ async promptRegistryConfig() { console.log(chalk_1.default.blue.bold('šŸ“ Add New Registry\n')); console.log(chalk_1.default.gray('Configure a new GitHub repository as a template registry.\n')); const answers = await inquirer_1.default.prompt([ { type: 'input', name: 'name', message: 'Registry name (e.g., "my-templates"):', validate: (input) => { if (!input.trim()) { return 'Registry name cannot be empty'; } if (!/^[a-zA-Z0-9-_]+$/.test(input)) { return 'Registry name can only contain letters, numbers, hyphens, and underscores'; } return true; } }, { type: 'input', name: 'repository', message: 'GitHub repository (e.g., "username/repo-name"):', validate: (input) => { if (!input.trim()) { return 'Repository cannot be empty'; } if (!/^[a-zA-Z0-9-_.]+\/[a-zA-Z0-9-_.]+$/.test(input)) { return 'Repository must be in format "username/repo-name"'; } return true; } }, { type: 'confirm', name: 'setAsDefault', message: 'Set as default registry?', default: false } ]); return answers; } /** * Display box preview with manifest information * @param boxInfo Box information to preview */ async previewBox(boxInfo) { console.log(chalk_1.default.blue.bold(`\nšŸ“¦ ${boxInfo.manifest.name} Preview\n`)); // Basic information console.log(chalk_1.default.yellow('Basic Information:')); console.log(` Name: ${chalk_1.default.cyan(boxInfo.manifest.name)}`); console.log(` Version: ${chalk_1.default.gray(boxInfo.manifest.version)}`); console.log(` Description: ${boxInfo.manifest.description}`); if (boxInfo.manifest.author) { console.log(` Author: ${chalk_1.default.gray(boxInfo.manifest.author)}`); } if (boxInfo.manifest.tags && boxInfo.manifest.tags.length > 0) { console.log(` Tags: ${chalk_1.default.gray(boxInfo.manifest.tags.join(', '))}`); } // Files information console.log(chalk_1.default.yellow('\nFiles:')); console.log(` Total files: ${chalk_1.default.cyan(boxInfo.files.length)}`); if (boxInfo.files.length > 0) { console.log(` Sample files:`); boxInfo.files.slice(0, 5).forEach(file => { console.log(` ${chalk_1.default.gray('•')} ${file}`); }); if (boxInfo.files.length > 5) { console.log(` ${chalk_1.default.gray(`... and ${boxInfo.files.length - 5} more files`)}`); } } // Exclusions if (boxInfo.manifest.exclude && boxInfo.manifest.exclude.length > 0) { console.log(chalk_1.default.yellow('\nExcluded patterns:')); boxInfo.manifest.exclude.forEach(pattern => { console.log(` ${chalk_1.default.gray('•')} ${pattern}`); }); } // Post-install steps if (boxInfo.manifest.postInstall && boxInfo.manifest.postInstall.length > 0) { console.log(chalk_1.default.yellow('\nPost-installation steps:')); boxInfo.manifest.postInstall.forEach((step, index) => { console.log(` ${chalk_1.default.gray(`${index + 1}.`)} ${step}`); }); } console.log(); // Empty line for spacing } /** * Prompt for search/filter input * @param placeholder Placeholder text for the search * @returns Promise<string> Search query */ async promptSearch(placeholder = 'Search boxes...') { const { searchQuery } = await inquirer_1.default.prompt([ { type: 'input', name: 'searchQuery', message: placeholder, default: '' } ]); return searchQuery.trim(); } /** * Show a loading spinner with message * @param message Loading message * @param promise Promise to wait for * @returns Promise result */ async withSpinner(message, promise) { // For now, just show the message and wait // In the future, we could add a proper spinner library console.log(chalk_1.default.blue(`ā³ ${message}...`)); return promise; } } exports.InteractivePrompts = InteractivePrompts; //# sourceMappingURL=prompts.js.map