@elsikora/setup-wizard
Version:
Setup Wizard - CLI scaffolding utility
178 lines (175 loc) • 7.82 kB
JavaScript
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