UNPKG

@git.zone/cli

Version:

A comprehensive CLI tool for enhancing and managing local development workflows with gitzone utilities, focusing on project setup, version control, code formatting, and template management.

254 lines 20.5 kB
import { BaseFormatter } from '../classes.baseformatter.js'; import * as plugins from '../mod.plugins.js'; import { logger, logVerbose } from '../../gitzone.logging.js'; export class PrettierFormatter extends BaseFormatter { get name() { return 'prettier'; } async analyze() { const changes = []; // Define directories to format (TypeScript directories by default) const includeDirs = ['ts', 'ts_*', 'test', 'tests']; // File extensions to format const extensions = '{ts,tsx,js,jsx,json,md,css,scss,html,xml,yaml,yml}'; // Also format root-level config files const rootConfigFiles = [ 'package.json', 'tsconfig.json', 'npmextra.json', '.prettierrc', '.prettierrc.json', '.prettierrc.js', 'readme.md', 'README.md', 'changelog.md', 'CHANGELOG.md', // Skip files without extensions as prettier can't infer parser // 'license', // 'LICENSE', '*.md', ]; // Collect all files to format const allFiles = []; // Add files from TypeScript directories for (const dir of includeDirs) { try { const globPattern = `${dir}/**/*.${extensions}`; const dirEntries = await plugins.smartfs .directory('.') .recursive() .filter(globPattern) .list(); const dirFiles = dirEntries.map((entry) => entry.path); // Filter out files in excluded directories const filteredFiles = dirFiles.filter((f) => !f.includes('node_modules/') && !f.includes('.nogit/') && !f.includes('.git/')); allFiles.push(...filteredFiles); } catch (error) { logVerbose(`Skipping directory ${dir}: ${error.message}`); } } // Add root config files (only check root level, no recursive needed) for (const pattern of rootConfigFiles) { try { const rootEntries = await plugins.smartfs .directory('.') .filter(pattern) .list(); const rootFiles = rootEntries.map((entry) => entry.path); // Only include files at root level (no slashes in path) const rootLevelFiles = rootFiles.filter((f) => !f.includes('/')); allFiles.push(...rootLevelFiles); } catch (error) { logVerbose(`Skipping pattern ${pattern}: ${error.message}`); } } // Remove duplicates const uniqueFiles = [...new Set(allFiles)]; // Get all files that match the pattern const files = uniqueFiles; // Ensure we only process actual files (not directories) const validFiles = []; for (const file of files) { try { const stats = await plugins.smartfs.file(file).stat(); if (!stats.isDirectory) { validFiles.push(file); } } catch (error) { // Skip files that can't be accessed logVerbose(`Skipping ${file} - cannot access: ${error.message}`); } } // Check which files need formatting for (const file of validFiles) { // Skip files that haven't changed if (!(await this.shouldProcessFile(file))) { logVerbose(`Skipping ${file} - no changes detected`); continue; } changes.push({ type: 'modify', path: file, module: this.name, description: 'Format with Prettier', }); } logger.log('info', `Found ${changes.length} files to format with Prettier`); return changes; } async execute(changes) { const startTime = this.stats.moduleStartTime(this.name); this.stats.startModule(this.name); try { await this.preExecute(); logVerbose(`Processing ${changes.length} files sequentially`); // Process files sequentially to avoid prettier cache/state issues for (let i = 0; i < changes.length; i++) { const change = changes[i]; logVerbose(`Processing file ${i + 1}/${changes.length}: ${change.path}`); try { await this.applyChange(change); this.stats.recordFileOperation(this.name, change.type, true); } catch (error) { this.stats.recordFileOperation(this.name, change.type, false); logger.log('error', `Failed to format ${change.path}: ${error.message}`); // Don't throw - continue with other files } } await this.postExecute(); } catch (error) { // Rollback removed - no longer tracking operations throw error; } finally { this.stats.endModule(this.name, startTime); } } async applyChange(change) { if (change.type !== 'modify') return; try { // Validate the path before processing if (!change.path || change.path.trim() === '') { logger.log('error', `Invalid empty path in change: ${JSON.stringify(change)}`); throw new Error('Invalid empty path'); } // Read current content const content = (await plugins.smartfs .file(change.path) .encoding('utf8') .read()); // Format with prettier const prettier = await import('prettier'); // Skip files that prettier can't parse without explicit parser const fileExt = plugins.path.extname(change.path).toLowerCase(); if (!fileExt || fileExt === '') { // Files without extensions need explicit parser logVerbose(`Skipping ${change.path} - no file extension for parser inference`); return; } try { const formatted = await prettier.format(content, { filepath: change.path, ...(await this.getPrettierConfig()), }); // Only write if content actually changed if (formatted !== content) { // Debug: log the path being written logVerbose(`Writing formatted content to: ${change.path}`); await this.modifyFile(change.path, formatted); logVerbose(`Formatted ${change.path}`); } else { logVerbose(`No formatting changes for ${change.path}`); } } catch (prettierError) { // Check if it's a parser error if (prettierError.message && prettierError.message.includes('No parser could be inferred')) { logVerbose(`Skipping ${change.path} - ${prettierError.message}`); return; // Skip this file silently } throw prettierError; } } catch (error) { // Log the full error stack for debugging mkdir issues if (error.message && error.message.includes('mkdir')) { logger.log('error', `Failed to format ${change.path}: ${error.message}`); logger.log('error', `Error stack: ${error.stack}`); } else { logger.log('error', `Failed to format ${change.path}: ${error.message}`); } throw error; } } async getPrettierConfig() { // Try to load prettier config from the project const prettierConfig = new plugins.npmextra.Npmextra(); return prettierConfig.dataFor('prettier', { // Default prettier config singleQuote: true, trailingComma: 'all', printWidth: 80, tabWidth: 2, semi: true, arrowParens: 'always', }); } /** * Override check() to compute diffs on-the-fly by running prettier */ async check() { const changes = await this.analyze(); const diffs = []; for (const change of changes) { if (change.type !== 'modify') continue; try { // Read current content const currentContent = (await plugins.smartfs .file(change.path) .encoding('utf8') .read()); // Skip files without extension (prettier can't infer parser) const fileExt = plugins.path.extname(change.path).toLowerCase(); if (!fileExt) continue; // Format with prettier to get what it would produce const prettier = await import('prettier'); const formatted = await prettier.format(currentContent, { filepath: change.path, ...(await this.getPrettierConfig()), }); // Only add to diffs if content differs if (formatted !== currentContent) { diffs.push({ path: change.path, type: 'modify', before: currentContent, after: formatted, }); } } catch (error) { // Skip files that can't be processed logVerbose(`Skipping diff for ${change.path}: ${error.message}`); } } return { hasDiff: diffs.length > 0, diffs, }; } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJldHRpZXIuZm9ybWF0dGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vdHMvbW9kX2Zvcm1hdC9mb3JtYXR0ZXJzL3ByZXR0aWVyLmZvcm1hdHRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFFNUQsT0FBTyxLQUFLLE9BQU8sTUFBTSxtQkFBbUIsQ0FBQztBQUM3QyxPQUFPLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBRTlELE1BQU0sT0FBTyxpQkFBa0IsU0FBUSxhQUFhO0lBQ2xELElBQUksSUFBSTtRQUNOLE9BQU8sVUFBVSxDQUFDO0lBQ3BCLENBQUM7SUFFRCxLQUFLLENBQUMsT0FBTztRQUNYLE1BQU0sT0FBTyxHQUFxQixFQUFFLENBQUM7UUFFckMsbUVBQW1FO1FBQ25FLE1BQU0sV0FBVyxHQUFHLENBQUMsSUFBSSxFQUFFLE1BQU0sRUFBRSxNQUFNLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFFcEQsNEJBQTRCO1FBQzVCLE1BQU0sVUFBVSxHQUFHLG9EQUFvRCxDQUFDO1FBRXhFLHNDQUFzQztRQUN0QyxNQUFNLGVBQWUsR0FBRztZQUN0QixjQUFjO1lBQ2QsZUFBZTtZQUNmLGVBQWU7WUFDZixhQUFhO1lBQ2Isa0JBQWtCO1lBQ2xCLGdCQUFnQjtZQUNoQixXQUFXO1lBQ1gsV0FBVztZQUNYLGNBQWM7WUFDZCxjQUFjO1lBQ2QsK0RBQStEO1lBQy9ELGFBQWE7WUFDYixhQUFhO1lBQ2IsTUFBTTtTQUNQLENBQUM7UUFFRiw4QkFBOEI7UUFDOUIsTUFBTSxRQUFRLEdBQWEsRUFBRSxDQUFDO1FBRTlCLHdDQUF3QztRQUN4QyxLQUFLLE1BQU0sR0FBRyxJQUFJLFdBQVcsRUFBRSxDQUFDO1lBQzlCLElBQUksQ0FBQztnQkFDSCxNQUFNLFdBQVcsR0FBRyxHQUFHLEdBQUcsU0FBUyxVQUFVLEVBQUUs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