UNPKG

claude-git-hooks

Version:

Git hooks with Claude CLI for code analysis and automatic commit messages

146 lines (131 loc) 5.06 kB
/** * File: installation-diagnostics.js * Purpose: Reusable error diagnostics and formatting utilities * * Key features: * - Generic error formatting with installation diagnostics * - Detects common installation issues * - Provides actionable remediation steps * - Extensible for future diagnostic checks * * Usage: * import { formatError } from './installation-diagnostics.js'; * * try { * // ... operation that might fail * } catch (error) { * console.error(formatError('Presets not found')); * process.exit(1); * } */ import fs from 'fs'; import path from 'path'; import { getRepoRoot } from './git-operations.js'; /** * Gets installation diagnostics * Why: Centralized logic to detect common installation issues * * Future enhancements: * - Check file permissions * - Verify Claude CLI installation * - Check Node.js version compatibility * - Validate .gitignore entries * - Check hook file integrity * - Verify template files exist * - Check config.json validity * * @returns {Object} Diagnostic information */ export const getInstallationDiagnostics = () => { const diagnostics = { currentDir: process.cwd(), repoRoot: null, isInRepoRoot: false, claudeDirExists: false, claudeDirPath: null, presetsDirExists: false, presetsDirPath: null, gitHooksExists: false, }; try { diagnostics.repoRoot = getRepoRoot(); diagnostics.isInRepoRoot = diagnostics.currentDir === diagnostics.repoRoot; diagnostics.claudeDirPath = path.join(diagnostics.repoRoot, '.claude'); diagnostics.claudeDirExists = fs.existsSync(diagnostics.claudeDirPath); diagnostics.presetsDirPath = path.join(diagnostics.claudeDirPath, 'presets'); diagnostics.presetsDirExists = fs.existsSync(diagnostics.presetsDirPath); const gitHooksPath = path.join(diagnostics.repoRoot, '.git', 'hooks'); diagnostics.gitHooksExists = fs.existsSync(gitHooksPath); } catch (error) { // Not in a git repository - diagnostics.repoRoot will be null } return diagnostics; }; /** * Formats error message with diagnostics and remediation steps * Why: Provides consistent, actionable error messages across all errors * * @param {string} errorMessage - Description of what failed (e.g., "Presets not found", "Template file missing") * @param {string[]} additionalContext - Optional additional context lines * @returns {string} Formatted error message with diagnostics and remediation steps */ export const formatError = (errorMessage, additionalContext = []) => { const diagnostics = getInstallationDiagnostics(); const lines = []; lines.push(`⚠️ ${errorMessage}`); lines.push(''); // Add any additional context first if (additionalContext.length > 0) { lines.push(...additionalContext); lines.push(''); } // Diagnostic information lines.push('Installation diagnostics:'); lines.push(` Current directory: ${diagnostics.currentDir}`); if (diagnostics.repoRoot) { lines.push(` Repository root: ${diagnostics.repoRoot}`); lines.push(` .claude/ exists: ${diagnostics.claudeDirExists ? '✓' : '✗'}`); lines.push(` presets/ exists: ${diagnostics.presetsDirExists ? '✓' : '✗'}`); } else { lines.push(` Repository root: [Not in a git repository]`); } lines.push(''); // Remediation steps based on detected issues lines.push('Recommended solution:'); if (!diagnostics.repoRoot) { lines.push(' Not in a git repository'); lines.push(' → Navigate to your repository and try again'); } else if (!diagnostics.claudeDirExists) { lines.push(' claude-hooks not installed'); if (!diagnostics.isInRepoRoot) { lines.push(` → cd ${diagnostics.repoRoot}`); lines.push(' → claude-hooks install'); } else { lines.push(' → claude-hooks install'); } } else if (!diagnostics.isInRepoRoot) { lines.push(' Running from subdirectory (may cause path issues)'); lines.push(` → cd ${diagnostics.repoRoot}`); lines.push(' → claude-hooks uninstall'); lines.push(' → claude-hooks install'); } else if (!diagnostics.presetsDirExists) { lines.push(' Incomplete installation (presets missing)'); lines.push(' → claude-hooks install --force'); } else { lines.push(' Unknown issue detected'); lines.push(' → claude-hooks install --force'); } return lines.join('\n'); }; /** * Checks if installation appears healthy * Why: Quick validation before operations that require full installation * * @returns {boolean} True if installation looks healthy */ export const isInstallationHealthy = () => { const diagnostics = getInstallationDiagnostics(); return diagnostics.claudeDirExists && diagnostics.presetsDirExists && diagnostics.gitHooksExists; };