UNPKG

ccguard

Version:

Automated enforcement of net-negative LOC, complexity constraints, and quality standards for Claude code

106 lines 3.71 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CommandFormatter = void 0; const BaseFormatter_1 = require("./formatters/BaseFormatter"); const child_process_1 = require("child_process"); /** * Formatter that executes shell commands to format code */ class CommandFormatter extends BaseFormatter_1.BaseFormatter { config; cache = new Map(); constructor(config) { super(); this.config = config; } /** * Get supported extensions from config */ getSupportedExtensions() { return Object.keys(this.config.commands); } /** * Format content using the configured command */ async format(content, filePath) { const extension = this.getFileExtension(filePath); const commandConfig = this.config.commands[extension]; if (!commandConfig) { // No formatter configured for this file type return content; } // Check cache const cacheKey = `${filePath}:${content.length}:${content.substring(0, 100)}`; const cached = this.cache.get(cacheKey); if (cached) { return cached; } try { const formatted = await this.executeFormatter(content, filePath, commandConfig); // Cache the result this.cache.set(cacheKey, formatted); // Limit cache size if (this.cache.size > 100) { const firstKey = this.cache.keys().next().value; if (firstKey !== undefined) { this.cache.delete(firstKey); } } return formatted; } catch (error) { if (this.config.fallbackOnError !== false) { // Log error but continue with unformatted content console.warn(`Formatter failed for ${filePath}:`, error); return content; } throw error; } } /** * Execute the formatter command */ async executeFormatter(content, filePath, commandConfig) { return new Promise((resolve, reject) => { // Parse command safely without shell const parts = commandConfig.command.split(' '); const cmd = parts[0]; const args = parts.slice(1).map(arg => arg === '{filepath}' ? filePath : arg).concat(commandConfig.args || []); const child = (0, child_process_1.spawn)(cmd, args, { timeout: this.config.timeout || 5000, }); let stdout = ''; let stderr = ''; child.stdout.on('data', (data) => { stdout += data.toString(); }); child.stderr.on('data', (data) => { stderr += data.toString(); }); child.on('error', (error) => { reject(new Error(`Formatter error: ${error.message}`)); }); child.on('close', (code) => { if (code !== 0) { reject(new Error(`Formatter exited with code ${code}: ${stderr}`)); } else { resolve(stdout || content); // Fallback to original if no output } }); // Send content via stdin if configured (default: true) if (commandConfig.stdin !== false) { child.stdin.write(content); child.stdin.end(); } }); } /** * Clear the formatting cache */ clearCache() { this.cache.clear(); } } exports.CommandFormatter = CommandFormatter; //# sourceMappingURL=CommandFormatter.js.map