UNPKG

@elsikora/setup-wizard

Version:

Setup Wizard - CLI scaffolding utility

529 lines (526 loc) 27.9 kB
#!/usr/bin/env node import { ECommitlintMode } from '../../domain/enum/commitlint-mode.enum.js'; import { ECommitlintProvider } from '../../domain/enum/commitlint-provider.enum.js'; import { ECommitlintTicketMissingBranchLintBehavior } from '../../domain/enum/commitlint-ticket-missing-branch-lint-behavior.enum.js'; import { ECommitlintTicketNormalization } from '../../domain/enum/commitlint-ticket-normalization.enum.js'; import { ECommitlintTicketSource } from '../../domain/enum/commitlint-ticket-source.enum.js'; import { EModule } from '../../domain/enum/module.enum.js'; import { EPackageJsonDependencyType } from '../../domain/enum/package-json-dependency-type.enum.js'; import { NodeCommandService } from '../../infrastructure/service/node-command.service.js'; import { COMMITLINT_AI_DEFAULTS, COMMITLINT_AI_CONFIG } from '../constant/commitlint/ai-config.constant.js'; import { COMMITLINT_CONFIG } from '../constant/commitlint/config.constant.js'; import { COMMITLINT_CONFIG_CORE_DEPENDENCIES } from '../constant/commitlint/core-dependencies.constant.js'; import { COMMITLINT_CONFIG_FILE_NAMES } from '../constant/commitlint/file-names.constant.js'; import { COMMITLINT_CONFIG_FILE_PATHS } from '../constant/commitlint/file-paths.constant.js'; import { COMMITLINT_CONFIG_HUSKY_COMMIT_MSG_SCRIPT } from '../constant/commitlint/husky-commit-msg-script.constant.js'; import { COMMITLINT_CONFIG_HUSKY } from '../constant/commitlint/husky-config.constant.js'; import { COMMITLINT_CONFIG_MESSAGES } from '../constant/commitlint/messages.constant.js'; import { COMMITLINT_CONFIG_SCRIPTS } from '../constant/commitlint/scripts.constant.js'; import { COMMITLINT_CONFIG_SUMMARY } from '../constant/commitlint/summary.constant.js'; import { PackageJsonService } from './package-json.service.js'; const MAX_RETRY_COUNT = 10; const MIN_RETRY_COUNT = 1; /** * Service for setting up and managing Commitlint and Commitizen configuration. * Provides functionality to enforce consistent commit message formats using Commitlint * and simplify commit creation using Commitizen. */ class CommitlintModuleService { /** CLI interface service for user interaction */ CLI_INTERFACE_SERVICE; /** Command service for executing shell commands */ COMMAND_SERVICE; /** Configuration service for managing app configuration */ CONFIG_SERVICE; /** File system service for file operations */ FILE_SYSTEM_SERVICE; /** Service for managing package.json */ PACKAGE_JSON_SERVICE; /** Cached commitlint module configuration */ config = null; /** * Initializes a new instance of the CommitlintModuleService. * @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.COMMAND_SERVICE = new NodeCommandService(cliInterfaceService); this.PACKAGE_JSON_SERVICE = new PackageJsonService(fileSystemService, this.COMMAND_SERVICE); this.CONFIG_SERVICE = configService; } /** * Handles existing Commitlint/Commitizen setup. * Checks for existing configuration files and asks if user wants to remove them. * @returns Promise resolving to true if setup should proceed, false otherwise */ async handleExistingSetup() { const existingFiles = await this.findExistingConfigFiles(); if (existingFiles.length > 0) { const messageLines = [COMMITLINT_CONFIG_MESSAGES.existingFilesDetected]; messageLines.push(""); if (existingFiles.length > 0) { for (const file of existingFiles) { messageLines.push(`- ${file}`); } } messageLines.push("", COMMITLINT_CONFIG_MESSAGES.deleteFilesQuestion); const shouldDelete = await this.CLI_INTERFACE_SERVICE.confirm(messageLines.join("\n"), true); if (shouldDelete) { await Promise.all(existingFiles.map((file) => this.FILE_SYSTEM_SERVICE.deleteFile(file))); } else { this.CLI_INTERFACE_SERVICE.warn(COMMITLINT_CONFIG_MESSAGES.existingFilesAborted); return false; } } return true; } /** * Installs and configures Commitlint and Commitizen. * Sets up configuration files, git hooks, and package.json scripts. * @returns Promise resolving to the module setup result */ async install() { try { this.config = await this.CONFIG_SERVICE.getModuleConfig(EModule.COMMITLINT); if (!(await this.shouldInstall())) { return { wasInstalled: false }; } if (!(await this.handleExistingSetup())) { return { wasInstalled: false }; } const isCommitCommandEnabled = await this.shouldEnableCommitCommand(); const commitlintAiConfig = await this.resolveCommitlintAiConfig(); await this.setupCommitlint(commitlintAiConfig, isCommitCommandEnabled); return { wasInstalled: true }; } catch (error) { this.CLI_INTERFACE_SERVICE.handleError(COMMITLINT_CONFIG_MESSAGES.failedSetupError, error); throw error; } } /** * Reads generation model. * @param defaultModel - Default model value * @returns Promise resolving to configured model */ async readGenerationModel(defaultModel) { try { const model = await this.CLI_INTERFACE_SERVICE.text(COMMITLINT_CONFIG_MESSAGES.modelPrompt, "", defaultModel, (value) => (value.trim().length === 0 ? "Model is required" : undefined)); return model.trim().length > 0 ? model.trim() : defaultModel; } catch (error) { this.CLI_INTERFACE_SERVICE.handleError(COMMITLINT_CONFIG_MESSAGES.modelPromptError, error); return defaultModel; } } /** * Reads retry count with range validation. * @param prompt - Prompt message * @param errorPrompt - Error message * @param defaultValue - Default retry value * @returns Promise resolving to retry count */ async readRetryCount(prompt, errorPrompt, defaultValue) { try { const value = await this.CLI_INTERFACE_SERVICE.text(prompt, "", String(defaultValue), (retryCount) => { const parsedValue = Number.parseInt(retryCount, 10); return Number.isNaN(parsedValue) || parsedValue < MIN_RETRY_COUNT || parsedValue > MAX_RETRY_COUNT ? `Please enter a number between ${MIN_RETRY_COUNT} and ${MAX_RETRY_COUNT}` : undefined; }); const parsedValue = Number.parseInt(value, 10); return Number.isNaN(parsedValue) ? defaultValue : parsedValue; } catch (error) { this.CLI_INTERFACE_SERVICE.handleError(errorPrompt, error); return defaultValue; } } /** * Reads regex pattern for ticket extraction. * @param defaultPattern - Default regex pattern * @returns Promise resolving to configured regex pattern */ async readTicketPattern(defaultPattern) { try { const pattern = await this.CLI_INTERFACE_SERVICE.text(COMMITLINT_CONFIG_MESSAGES.ticketPatternPrompt, "", defaultPattern); return pattern.trim().length > 0 ? pattern.trim() : defaultPattern; } catch (error) { this.CLI_INTERFACE_SERVICE.handleError(COMMITLINT_CONFIG_MESSAGES.ticketPatternPromptError, error); return defaultPattern; } } /** * Reads regex flags for ticket pattern. * @param defaultPatternFlags - Default regex flags * @returns Promise resolving to configured regex flags */ async readTicketPatternFlags(defaultPatternFlags) { try { const patternFlags = await this.CLI_INTERFACE_SERVICE.text(COMMITLINT_CONFIG_MESSAGES.ticketPatternFlagsPrompt, "", defaultPatternFlags); return patternFlags.trim().length > 0 ? patternFlags.trim() : defaultPatternFlags; } catch (error) { this.CLI_INTERFACE_SERVICE.handleError(COMMITLINT_CONFIG_MESSAGES.ticketPatternFlagsPromptError, error); return defaultPatternFlags; } } /** * Resolves commitlint-ai settings using config defaults and setup prompts. * @returns Promise resolving to effective commitlint-ai settings */ async resolveCommitlintAiConfig() { const defaultCommitlintAiConfig = this.getDefaultCommitlintAiConfig(); const mode = await this.selectGenerationMode(defaultCommitlintAiConfig.mode ?? COMMITLINT_AI_DEFAULTS.mode); const provider = await this.selectGenerationProvider(defaultCommitlintAiConfig.provider ?? COMMITLINT_AI_DEFAULTS.provider); const model = await this.readGenerationModel(this.config?.model ?? this.getDefaultModelByProvider(provider)); const maxRetries = await this.readRetryCount(COMMITLINT_CONFIG_MESSAGES.maxRetriesPrompt, COMMITLINT_CONFIG_MESSAGES.maxRetriesPromptError, defaultCommitlintAiConfig.maxRetries ?? COMMITLINT_AI_DEFAULTS.maxRetries); const validationMaxRetries = await this.readRetryCount(COMMITLINT_CONFIG_MESSAGES.validationMaxRetriesPrompt, COMMITLINT_CONFIG_MESSAGES.validationMaxRetriesPromptError, defaultCommitlintAiConfig.validationMaxRetries ?? COMMITLINT_AI_DEFAULTS.validationMaxRetries); const ticketDefaults = { missingBranchLintBehavior: defaultCommitlintAiConfig.ticket?.missingBranchLintBehavior ?? COMMITLINT_AI_DEFAULTS.ticket.missingBranchLintBehavior, normalization: defaultCommitlintAiConfig.ticket?.normalization ?? COMMITLINT_AI_DEFAULTS.ticket.normalization, pattern: defaultCommitlintAiConfig.ticket?.pattern ?? COMMITLINT_AI_DEFAULTS.ticket.pattern, patternFlags: defaultCommitlintAiConfig.ticket?.patternFlags ?? COMMITLINT_AI_DEFAULTS.ticket.patternFlags, source: defaultCommitlintAiConfig.ticket?.source ?? COMMITLINT_AI_DEFAULTS.ticket.source, }; const isTicketEnabled = await this.shouldEnableTicketIntegration(ticketDefaults.source); if (!isTicketEnabled) { return { maxRetries, mode, model, provider, ticket: { ...ticketDefaults, source: ECommitlintTicketSource.NONE, }, validationMaxRetries, }; } const ticketSource = await this.selectTicketSource(ticketDefaults.source); const ticketNormalization = await this.selectTicketNormalization(ticketDefaults.normalization); let ticketPattern = ticketDefaults.pattern; let ticketPatternFlags = ticketDefaults.patternFlags; let ticketMissingBranchLintBehavior = ticketDefaults.missingBranchLintBehavior; if (ticketSource === ECommitlintTicketSource.AUTO || ticketSource === ECommitlintTicketSource.PATTERN) { ticketPattern = await this.readTicketPattern(ticketDefaults.pattern); ticketPatternFlags = await this.readTicketPatternFlags(ticketDefaults.patternFlags); } if (ticketSource === ECommitlintTicketSource.BRANCH_LINT) { ticketMissingBranchLintBehavior = await this.selectMissingBranchLintBehavior(ticketDefaults.missingBranchLintBehavior); } return { maxRetries, mode, model, provider, ticket: { missingBranchLintBehavior: ticketMissingBranchLintBehavior, normalization: ticketNormalization, pattern: ticketPattern, patternFlags: ticketPatternFlags, source: ticketSource, }, validationMaxRetries, }; } /** * Selects generation mode. * @param defaultMode - Default mode value * @returns Promise resolving to selected mode */ async selectGenerationMode(defaultMode) { const options = [ { label: "auto - AI-powered generation", value: ECommitlintMode.AUTO }, { label: "manual - guided commit composition", value: ECommitlintMode.MANUAL }, ]; try { return await this.CLI_INTERFACE_SERVICE.select(COMMITLINT_CONFIG_MESSAGES.modePrompt, options, defaultMode); } catch (error) { this.CLI_INTERFACE_SERVICE.handleError(COMMITLINT_CONFIG_MESSAGES.modePromptError, error); return defaultMode; } } /** * Selects generation provider. * @param defaultProvider - Default provider value * @returns Promise resolving to selected provider */ async selectGenerationProvider(defaultProvider) { const options = [ { label: "anthropic", value: ECommitlintProvider.ANTHROPIC }, { label: "aws-bedrock", value: ECommitlintProvider.AWS_BEDROCK }, { label: "azure-openai", value: ECommitlintProvider.AZURE_OPENAI }, { label: "google", value: ECommitlintProvider.GOOGLE }, { label: "ollama", value: ECommitlintProvider.OLLAMA }, { label: "openai", value: ECommitlintProvider.OPENAI }, ]; try { return await this.CLI_INTERFACE_SERVICE.select(COMMITLINT_CONFIG_MESSAGES.providerPrompt, options, defaultProvider); } catch (error) { this.CLI_INTERFACE_SERVICE.handleError(COMMITLINT_CONFIG_MESSAGES.providerPromptError, error); return defaultProvider; } } /** * Selects missing branch-lint behavior. * @param defaultBehavior - Default behavior * @returns Promise resolving to selected behavior */ async selectMissingBranchLintBehavior(defaultBehavior) { const options = [ { label: "fallback - use local regex pattern as fallback", value: ECommitlintTicketMissingBranchLintBehavior.FALLBACK }, { label: "error - stop setup when branch-lint config is unavailable", value: ECommitlintTicketMissingBranchLintBehavior.ERROR }, ]; try { return await this.CLI_INTERFACE_SERVICE.select(COMMITLINT_CONFIG_MESSAGES.branchLintMissingBehaviorPrompt, options, defaultBehavior); } catch (error) { this.CLI_INTERFACE_SERVICE.handleError(COMMITLINT_CONFIG_MESSAGES.branchLintMissingBehaviorPromptError, error); return defaultBehavior; } } /** * Selects ticket normalization mode. * @param defaultNormalization - Default normalization mode * @returns Promise resolving to selected normalization mode */ async selectTicketNormalization(defaultNormalization) { const options = [ { label: "preserve - keep ticket case as detected", value: ECommitlintTicketNormalization.PRESERVE }, { label: "upper - convert ticket to upper case", value: ECommitlintTicketNormalization.UPPER }, { label: "lower - convert ticket to lower case", value: ECommitlintTicketNormalization.LOWER }, ]; try { return await this.CLI_INTERFACE_SERVICE.select(COMMITLINT_CONFIG_MESSAGES.ticketNormalizationPrompt, options, defaultNormalization); } catch (error) { this.CLI_INTERFACE_SERVICE.handleError(COMMITLINT_CONFIG_MESSAGES.ticketNormalizationPromptError, error); return defaultNormalization; } } /** * Selects ticket source strategy. * @param defaultSource - Default source strategy * @returns Promise resolving to selected source strategy */ async selectTicketSource(defaultSource) { const options = [ { label: "branch-lint - parse ticket by git-branch-lint pattern", value: ECommitlintTicketSource.BRANCH_LINT }, { label: "auto - branch-lint first, then local regex fallback", value: ECommitlintTicketSource.AUTO }, { label: "pattern - parse ticket only by local regex pattern", value: ECommitlintTicketSource.PATTERN }, ]; const normalizedDefaultSource = defaultSource === ECommitlintTicketSource.NONE ? ECommitlintTicketSource.BRANCH_LINT : defaultSource; try { return await this.CLI_INTERFACE_SERVICE.select(COMMITLINT_CONFIG_MESSAGES.ticketSourcePrompt, options, normalizedDefaultSource); } catch (error) { this.CLI_INTERFACE_SERVICE.handleError(COMMITLINT_CONFIG_MESSAGES.ticketSourcePromptError, error); return normalizedDefaultSource; } } /** * Determines whether commit command script should be added. * @returns Promise resolving to true when commit command should be added */ async shouldEnableCommitCommand() { const isCommitCommandEnabledByDefault = this.config?.isCommitCommandEnabled ?? true; try { return await this.CLI_INTERFACE_SERVICE.confirm(COMMITLINT_CONFIG_MESSAGES.commitCommandPrompt, isCommitCommandEnabledByDefault); } catch (error) { this.CLI_INTERFACE_SERVICE.handleError(COMMITLINT_CONFIG_MESSAGES.commitCommandPromptError, error); return isCommitCommandEnabledByDefault; } } /** * Determines whether ticket extraction should be enabled. * @param defaultSource - Default ticket source * @returns Promise resolving to true when ticket extraction should be enabled */ async shouldEnableTicketIntegration(defaultSource) { const isTicketEnabledByDefault = defaultSource !== ECommitlintTicketSource.NONE; try { return await this.CLI_INTERFACE_SERVICE.confirm(COMMITLINT_CONFIG_MESSAGES.ticketEnabledPrompt, isTicketEnabledByDefault); } catch (error) { this.CLI_INTERFACE_SERVICE.handleError(COMMITLINT_CONFIG_MESSAGES.ticketEnabledPromptError, error); return isTicketEnabledByDefault; } } /** * Determines if Commitlint/Commitizen should be installed. * Asks the user if they want to set up these tools 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() { try { return await this.CLI_INTERFACE_SERVICE.confirm(COMMITLINT_CONFIG_MESSAGES.confirmSetup, await this.CONFIG_SERVICE.isModuleEnabled(EModule.COMMITLINT)); } catch (error) { this.CLI_INTERFACE_SERVICE.handleError(COMMITLINT_CONFIG_MESSAGES.failedConfirmation, error); return false; } } /** * Creates the Commitlint configuration file. * @param commitlintAiConfig - Commitlint AI configuration */ async createConfigs(commitlintAiConfig = this.getDefaultCommitlintAiConfig()) { await this.FILE_SYSTEM_SERVICE.writeFile(COMMITLINT_CONFIG_FILE_PATHS.configFile, COMMITLINT_CONFIG, "utf8"); await this.FILE_SYSTEM_SERVICE.writeFile(COMMITLINT_CONFIG_FILE_PATHS.aiConfigFile, COMMITLINT_AI_CONFIG.template(commitlintAiConfig), "utf8"); } /** * Displays a summary of the setup results. * @param commitlintAiConfig - Commitlint AI configuration * @param isCommitCommandEnabled - Whether commit command was enabled */ displaySetupSummary(commitlintAiConfig = this.getDefaultCommitlintAiConfig(), isCommitCommandEnabled = true) { const commitScriptDescription = isCommitCommandEnabled ? COMMITLINT_CONFIG_SUMMARY.commitDescription : COMMITLINT_CONFIG_SUMMARY.commitCommandDisabledDescription; const generationMode = commitlintAiConfig.mode ?? COMMITLINT_AI_DEFAULTS.mode; const generationProvider = commitlintAiConfig.provider ?? COMMITLINT_AI_DEFAULTS.provider; const generationModel = commitlintAiConfig.model ?? COMMITLINT_AI_DEFAULTS.model; const generationMaxRetries = commitlintAiConfig.maxRetries ?? COMMITLINT_AI_DEFAULTS.maxRetries; const generationValidationMaxRetries = commitlintAiConfig.validationMaxRetries ?? COMMITLINT_AI_DEFAULTS.validationMaxRetries; const ticketSource = commitlintAiConfig.ticket?.source ?? COMMITLINT_AI_DEFAULTS.ticket.source; const ticketNormalization = commitlintAiConfig.ticket?.normalization ?? COMMITLINT_AI_DEFAULTS.ticket.normalization; const ticketMissingBranchLintBehavior = commitlintAiConfig.ticket?.missingBranchLintBehavior ?? COMMITLINT_AI_DEFAULTS.ticket.missingBranchLintBehavior; const generationDescription = COMMITLINT_CONFIG_SUMMARY.generationConfigurationDescription.replace("{mode}", generationMode).replace("{provider}", generationProvider).replace("{model}", generationModel).replace("{maxRetries}", String(generationMaxRetries)).replace("{validationMaxRetries}", String(generationValidationMaxRetries)); const ticketDescription = COMMITLINT_CONFIG_SUMMARY.ticketConfigurationDescription.replace("{source}", ticketSource).replace("{normalization}", ticketNormalization).replace("{missingBranchLintBehavior}", ticketMissingBranchLintBehavior); const summary = [COMMITLINT_CONFIG_MESSAGES.configurationCreated, "", generationDescription, ticketDescription, "", COMMITLINT_CONFIG_MESSAGES.generatedScriptsLabel, commitScriptDescription, "", COMMITLINT_CONFIG_MESSAGES.configurationFilesLabel, COMMITLINT_CONFIG_SUMMARY.configFileDescription, COMMITLINT_CONFIG_SUMMARY.aiConfigFileDescription, COMMITLINT_CONFIG_SUMMARY.huskyCommitMsgDescription, "", COMMITLINT_CONFIG_MESSAGES.huskyGitHooksInfo]; if (isCommitCommandEnabled) { summary.push(COMMITLINT_CONFIG_MESSAGES.commitizenDescription); } this.CLI_INTERFACE_SERVICE.note(COMMITLINT_CONFIG_MESSAGES.setupCompleteTitle, summary.join("\n")); } /** * Finds existing Commitlint/Commitizen configuration files. * @returns Promise resolving to an array of file paths for existing configuration files */ async findExistingConfigFiles() { const existingFiles = []; for (const file of COMMITLINT_CONFIG_FILE_NAMES) { if (await this.FILE_SYSTEM_SERVICE.isPathExists(file)) { existingFiles.push(file); } } if (await this.FILE_SYSTEM_SERVICE.isPathExists(COMMITLINT_CONFIG_FILE_PATHS.huskyCommitMsgHook)) { existingFiles.push(COMMITLINT_CONFIG_FILE_PATHS.huskyCommitMsgHook); } return existingFiles; } /** * Builds commitlint-ai config with defaults merged from setup-wizard config. * @returns Defaulted commitlint-ai config */ getDefaultCommitlintAiConfig() { return { maxRetries: this.config?.maxRetries ?? COMMITLINT_AI_DEFAULTS.maxRetries, mode: this.config?.mode ?? COMMITLINT_AI_DEFAULTS.mode, model: this.config?.model ?? COMMITLINT_AI_DEFAULTS.model, provider: this.config?.provider ?? COMMITLINT_AI_DEFAULTS.provider, ticket: { missingBranchLintBehavior: this.config?.ticket?.missingBranchLintBehavior ?? COMMITLINT_AI_DEFAULTS.ticket.missingBranchLintBehavior, normalization: this.config?.ticket?.normalization ?? COMMITLINT_AI_DEFAULTS.ticket.normalization, pattern: this.config?.ticket?.pattern ?? COMMITLINT_AI_DEFAULTS.ticket.pattern, patternFlags: this.config?.ticket?.patternFlags ?? COMMITLINT_AI_DEFAULTS.ticket.patternFlags, source: this.config?.ticket?.source ?? COMMITLINT_AI_DEFAULTS.ticket.source, }, validationMaxRetries: this.config?.validationMaxRetries ?? COMMITLINT_AI_DEFAULTS.validationMaxRetries, }; } /** * Returns default model for selected provider. * @param provider - Selected provider * @returns Default model name */ getDefaultModelByProvider(provider) { switch (provider) { case ECommitlintProvider.ANTHROPIC: { return "claude-opus-4-5"; } case ECommitlintProvider.AWS_BEDROCK: { return "claude-sonnet-4-5"; } case ECommitlintProvider.AZURE_OPENAI: { return "gpt-4o"; } case ECommitlintProvider.GOOGLE: { return "gemini-2.5-pro-preview-05-06"; } case ECommitlintProvider.OLLAMA: { return "llama3"; } case ECommitlintProvider.OPENAI: { return "gpt-4o-mini"; } default: { return COMMITLINT_AI_DEFAULTS.model; } } } /** * Sets up Commitlint and Commitizen. * Installs dependencies, creates configuration files, and configures git hooks. * @param commitlintAiConfig - Commitlint AI configuration * @param isCommitCommandEnabled - Whether commit command should be configured */ async setupCommitlint(commitlintAiConfig = this.getDefaultCommitlintAiConfig(), isCommitCommandEnabled = true) { this.CLI_INTERFACE_SERVICE.startSpinner(COMMITLINT_CONFIG_MESSAGES.settingUpSpinner); try { await this.PACKAGE_JSON_SERVICE.installPackages(COMMITLINT_CONFIG_CORE_DEPENDENCIES, "latest", EPackageJsonDependencyType.DEV); await this.createConfigs(commitlintAiConfig); await this.setupHusky(); if (isCommitCommandEnabled) { await this.setupPackageJsonConfigs(); await this.setupScripts(); } this.CLI_INTERFACE_SERVICE.stopSpinner(COMMITLINT_CONFIG_MESSAGES.configurationCompleted); this.displaySetupSummary(commitlintAiConfig, isCommitCommandEnabled); } catch (error) { this.CLI_INTERFACE_SERVICE.stopSpinner(COMMITLINT_CONFIG_MESSAGES.failedSetupConfiguration); throw error; } } /** * Sets up Husky git hooks. * Initializes Husky, adds prepare script, and creates commit-msg and pre-push hooks. */ async setupHusky() { // Initialize husky await this.COMMAND_SERVICE.execute(COMMITLINT_CONFIG_HUSKY.initCommand); // Add prepare script if it doesn't exist await this.PACKAGE_JSON_SERVICE.addScript(COMMITLINT_CONFIG_SCRIPTS.prepare.name, COMMITLINT_CONFIG_SCRIPTS.prepare.command); await this.COMMAND_SERVICE.execute(COMMITLINT_CONFIG_HUSKY.mkdirCommand); // Create commit-msg hook await this.FILE_SYSTEM_SERVICE.writeFile(COMMITLINT_CONFIG_FILE_PATHS.huskyCommitMsgHook, COMMITLINT_CONFIG_HUSKY_COMMIT_MSG_SCRIPT, "utf8"); await this.COMMAND_SERVICE.execute(COMMITLINT_CONFIG_HUSKY.chmodCommand); } /** * Sets up Commitizen configuration in package.json. */ async setupPackageJsonConfigs() { const packageJson = await this.PACKAGE_JSON_SERVICE.get(); packageJson.config ??= {}; packageJson.config.commitizen = { path: COMMITLINT_CONFIG_MESSAGES.commitizenPath, }; await this.PACKAGE_JSON_SERVICE.set(packageJson); } /** * Sets up npm scripts for Commitizen. * Adds 'commit' script for starting the Commitizen CLI. */ async setupScripts() { await this.PACKAGE_JSON_SERVICE.addScript(COMMITLINT_CONFIG_SCRIPTS.commit.name, COMMITLINT_CONFIG_SCRIPTS.commit.command); } } export { CommitlintModuleService }; //# sourceMappingURL=commitlint-module.service.js.map