UNPKG

legal-markdown-js

Version:

Node.js implementation of LegalMarkdown for processing legal documents with markdown and YAML - Complete feature parity with Ruby version

191 lines • 7.46 kB
/** * File selection prompt for Interactive CLI * * This module handles the file selection process, providing users with * options to select from discovered files, browse directories, or * manually enter file paths. * * @module */ import { select } from '@inquirer/prompts'; import chalk from 'chalk'; import * as fs from 'fs'; import * as path from 'path'; import { RESOLVED_PATHS } from '../../../constants/index.js'; import { scanDirectory } from '../utils/file-scanner.js'; import { formatWarningMessage } from '../utils/format-helpers.js'; import { handleFirstTimeUserExperience } from './ftux-handler.js'; import { handleBrowseFolder, handleManualInput } from '../utils/file-input-helpers.js'; import { getEnvFilePath } from '../utils/installation-detector.js'; /** Option for browsing alternative directories */ const BROWSE_OPTION = 'šŸ“ Browse other folder...'; /** Option for manual path entry */ const MANUAL_OPTION = 'šŸ“ Enter path manually...'; /** Option for exiting the application */ const EXIT_OPTION = 'āŒ Exit'; /** * Check if a directory exists and is accessible * * @param dirPath - Path to check * @returns True if directory exists and is accessible */ function isDirectoryAccessible(dirPath) { try { return fs.existsSync(dirPath) && fs.statSync(dirPath).isDirectory(); } catch { return false; } } /** * Check if configuration is properly set up * * @returns True if .env exists in the correct location and input directory is configured and accessible */ function isConfigurationValid() { // Check if .env exists in the expected installation-specific location const expectedEnvPath = getEnvFilePath(); const hasCorrectEnvFile = fs.existsSync(expectedEnvPath); if (!hasCorrectEnvFile) { // Fallback: check if there's a .env in the current working directory const localEnvPath = path.join(process.cwd(), '.env'); const hasLocalEnvFile = fs.existsSync(localEnvPath); if (!hasLocalEnvFile) { return false; } // If local .env exists, reload environment variables from it try { const envContent = fs.readFileSync(localEnvPath, 'utf8'); const envVars = envContent .split('\n') .filter(line => line.trim() && !line.startsWith('#')) .reduce((vars, line) => { const [key, ...valueParts] = line.split('='); if (key && valueParts.length > 0) { // Remove quotes if present let value = valueParts.join('=').trim(); if ((value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'"))) { value = value.slice(1, -1); } vars[key.trim()] = value; } return vars; }, {}); // Check if DEFAULT_INPUT_DIR is configured and accessible in local .env const localInputDir = envVars.DEFAULT_INPUT_DIR; if (!localInputDir) { return false; } return isDirectoryAccessible(path.resolve(localInputDir)); } catch { return false; } } // Check if the configured input directory is accessible return isDirectoryAccessible(RESOLVED_PATHS.DEFAULT_INPUT_DIR); } /** * Prompt user for initial setup choice when configuration is missing/invalid */ async function promptInitialSetup() { console.log(chalk.yellow('\nāš ļø Configuration Setup Needed')); console.log(chalk.gray('No valid configuration detected or input directory is not accessible.\n')); const choice = await select({ message: 'How would you like to proceed?', choices: [ { name: 'šŸ› ļø Run First-Time User Experience (recommended)', value: 'ftux', description: 'Set up directories, try examples, and get guided help', }, { name: '⚔ Continue with defaults (current directory)', value: 'defaults', description: 'Use current directory as input, no configuration saved', }, ], }); return choice; } /** * Handle file selection logic */ async function handleFileSelection(selectedFile) { switch (selectedFile) { case BROWSE_OPTION: return await handleBrowseFolder(); case MANUAL_OPTION: return await handleManualInput(); case EXIT_OPTION: console.log(chalk.yellow('šŸ‘‹ Goodbye!')); process.exit(0); break; default: return selectedFile; } } /** * Prompt user to select an input file * * Initiates the file selection process by first checking if configuration is valid. * If not, offers FTUX or defaults. Then scans the input directory and presents * available files to the user, with fallback options for manual input. * * @returns Promise resolving to the absolute path of the selected input file * @throws Error when user cancels or no valid file is selected */ export async function selectInputFile() { // Check if configuration is valid first if (!isConfigurationValid()) { const setupChoice = await promptInitialSetup(); if (setupChoice === 'ftux') { return await handleFirstTimeUserExperience(); } // Continue with defaults - scan current directory instead console.log(chalk.cyan('\nšŸ” Using current directory as input...\n')); const currentDirFiles = scanDirectory(process.cwd(), process.cwd()); if (currentDirFiles.length === 0) { console.log(formatWarningMessage('No supported files found in current directory.')); return await handleFirstTimeUserExperience(); } // Show files from current directory const choices = [ ...currentDirFiles.map(file => ({ name: file.name, value: file.path, })), { name: BROWSE_OPTION, value: BROWSE_OPTION }, { name: MANUAL_OPTION, value: MANUAL_OPTION }, { name: EXIT_OPTION, value: EXIT_OPTION }, ]; const selectedFile = await select({ message: 'Select a file from current directory:', choices, }); return await handleFileSelection(selectedFile); } // Configuration is valid - use configured directory console.log(chalk.cyan(`šŸ” Searching for files in: ${RESOLVED_PATHS.DEFAULT_INPUT_DIR}\n`)); const files = scanDirectory(RESOLVED_PATHS.DEFAULT_INPUT_DIR, RESOLVED_PATHS.DEFAULT_INPUT_DIR); if (files.length === 0) { console.log(formatWarningMessage('No supported files found in the configured directory.')); return await handleFirstTimeUserExperience(); } const choices = [ ...files.map(file => ({ name: file.name, value: file.path, })), { name: BROWSE_OPTION, value: BROWSE_OPTION }, { name: MANUAL_OPTION, value: MANUAL_OPTION }, { name: EXIT_OPTION, value: EXIT_OPTION }, ]; const selectedFile = await select({ message: 'Select an input file:', choices, }); return await handleFileSelection(selectedFile); } //# sourceMappingURL=file-selector.js.map