UNPKG

@elsikora/setup-wizard

Version:

Setup Wizard - CLI scaffolding utility

178 lines (175 loc) 7.82 kB
#!/usr/bin/env node import { IDE_CONFIG } from '../../domain/constant/ide-config.constant.js'; import { EIde } from '../../domain/enum/ide.enum.js'; import { EModule } from '../../domain/enum/module.enum.js'; /** * Service for setting up and managing IDE-specific configurations. * Provides functionality to generate editor configurations for different IDEs * to ensure consistent code style and linting settings. */ class IdeModuleService { /** CLI interface service for user interaction */ CLI_INTERFACE_SERVICE; /** Configuration service for managing app configuration */ CONFIG_SERVICE; /** File system service for file operations */ FILE_SYSTEM_SERVICE; /** Cached IDE configuration */ config = null; /** Selected IDEs to configure */ selectedIdes = []; /** * Initializes a new instance of the IdeModuleService. * @param cliInterfaceService - Service for CLI user interactions * @param fileSystemService - Service for file system operations * @param configService - Service for managing app configuration */ constructor(cliInterfaceService, fileSystemService, configService) { this.CLI_INTERFACE_SERVICE = cliInterfaceService; this.FILE_SYSTEM_SERVICE = fileSystemService; this.CONFIG_SERVICE = configService; } /** * Handles existing IDE configuration setup. * Checks for existing configuration files and asks for user confirmation if found. * @returns Promise resolving to true if setup should proceed, false otherwise */ async handleExistingSetup() { const existingFiles = await this.findExistingConfigFiles(); if (existingFiles.length === 0) { return true; } this.CLI_INTERFACE_SERVICE.warn("Found existing IDE configuration files that might be modified:\n" + existingFiles.map((file) => `- ${file}`).join("\n")); return await this.CLI_INTERFACE_SERVICE.confirm("Do you want to continue? This might overwrite existing files.", false); } /** * Installs and configures IDE-specific settings. * Guides the user through selecting IDEs and generating configuration files. * @returns Promise resolving to the module setup result */ async install() { try { this.config = await this.CONFIG_SERVICE.getModuleConfig(EModule.IDE); if (!(await this.shouldInstall())) { return { wasInstalled: false }; } this.selectedIdes = await this.selectIdes(this.config?.ides ?? []); if (this.selectedIdes.length === 0) { this.CLI_INTERFACE_SERVICE.warn("No IDEs selected."); return { wasInstalled: false }; } if (!(await this.handleExistingSetup())) { this.CLI_INTERFACE_SERVICE.warn("Setup cancelled by user."); return { wasInstalled: false }; } await this.setupSelectedIdes(); return { customProperties: { ides: this.selectedIdes, }, wasInstalled: true, }; } catch (error) { this.CLI_INTERFACE_SERVICE.handleError("Failed to complete IDE setup", error); throw error; } } /** * Determines if IDE configuration should be installed. * Asks the user if they want to set up IDE configurations for their project. * Uses the saved config value as default if it exists. * @returns Promise resolving to true if the module should be installed, false otherwise */ async shouldInstall() { return await this.CLI_INTERFACE_SERVICE.confirm("Would you like to set up ESLint and Prettier configurations for your code editors?", await this.CONFIG_SERVICE.isModuleEnabled(EModule.IDE)); } /** * Displays a summary of successful and failed IDE configuration setups. * @param successful - Array of successfully set up IDE configurations * @param failed - Array of IDE configurations that failed to set up */ displaySetupSummary(successful, failed) { const summary = [ "Successfully created configurations:", ...successful.map(({ ide }) => { const files = IDE_CONFIG[ide].content.map((config) => ` - ${config.filePath}`).join("\n"); return `✓ ${IDE_CONFIG[ide].name}:\n${files}`; }), ]; if (failed.length > 0) { summary.push("Failed configurations:", ...failed.map(({ error, ide }) => `✗ ${IDE_CONFIG[ide].name} - ${error?.message ?? "Unknown error"}`)); } this.CLI_INTERFACE_SERVICE.note("IDE Setup Summary", summary.join("\n")); } /** * Finds existing IDE configuration files that might be overwritten. * @returns Promise resolving to an array of file paths for existing configuration files */ async findExistingConfigFiles() { const existingFiles = []; for (const ide of this.selectedIdes) { const configContent = IDE_CONFIG[ide].content; for (const config of configContent) { if (await this.FILE_SYSTEM_SERVICE.isPathExists(config.filePath)) { existingFiles.push(config.filePath); } } } return existingFiles; } /** * Prompts the user to select which IDEs they want to configure. * @param savedIdes - Previously saved IDE selections * @returns Promise resolving to an array of selected IDE enum values */ async selectIdes(savedIdes = []) { const choices = Object.entries(IDE_CONFIG).map(([ide, config]) => ({ description: config.description, label: config.name, value: ide, })); const validSavedIdes = savedIdes.filter((ide) => Object.values(EIde).includes(ide)); const initialSelection = validSavedIdes.length > 0 ? validSavedIdes : undefined; return await this.CLI_INTERFACE_SERVICE.multiselect("Select your code editor(s):", choices, true, initialSelection); } /** * Sets up configuration for a specific IDE. * Creates necessary directories and configuration files. * @param ide - The IDE to set up configuration for * @returns Promise resolving to an object indicating success or failure with optional error */ async setupIde(ide) { try { const configContent = IDE_CONFIG[ide].content; for (const config of configContent) { await this.FILE_SYSTEM_SERVICE.createDirectory(config.filePath, { isRecursive: true }); await this.FILE_SYSTEM_SERVICE.writeFile(config.filePath, config.template()); } return { ide, isSuccess: true }; } catch (error) { return { error: error, ide, isSuccess: false }; } } /** * Sets up configuration for all selected IDEs. * Creates and writes IDE-specific configuration files. */ async setupSelectedIdes() { this.CLI_INTERFACE_SERVICE.startSpinner("Setting up IDE configurations..."); try { const results = await Promise.all(this.selectedIdes.map((ide) => this.setupIde(ide))); this.CLI_INTERFACE_SERVICE.stopSpinner("IDE configuration completed successfully!"); const successfulSetups = results.filter((r) => r.isSuccess); const failedSetups = results.filter((r) => !r.isSuccess); this.displaySetupSummary(successfulSetups, failedSetups); } catch (error) { this.CLI_INTERFACE_SERVICE.stopSpinner(); throw error; } } } export { IdeModuleService }; //# sourceMappingURL=ide-module.service.js.map