83 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			83 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
import * as plugins from './mod.plugins.js';
 | 
						|
import { FormatContext } from './classes.formatcontext.js';
 | 
						|
import type { IPlannedChange } from './interfaces.format.js';
 | 
						|
import { Project } from '../classes.project.js';
 | 
						|
 | 
						|
export abstract class BaseFormatter {
 | 
						|
  protected context: FormatContext;
 | 
						|
  protected project: Project;
 | 
						|
  protected stats: any; // Will be FormatStats from context
 | 
						|
 | 
						|
  constructor(context: FormatContext, project: Project) {
 | 
						|
    this.context = context;
 | 
						|
    this.project = project;
 | 
						|
    this.stats = context.getFormatStats();
 | 
						|
  }
 | 
						|
 | 
						|
  abstract get name(): string;
 | 
						|
  abstract analyze(): Promise<IPlannedChange[]>;
 | 
						|
  abstract applyChange(change: IPlannedChange): Promise<void>;
 | 
						|
 | 
						|
  async execute(changes: IPlannedChange[]): Promise<void> {
 | 
						|
    const startTime = this.stats.moduleStartTime(this.name);
 | 
						|
    this.stats.startModule(this.name);
 | 
						|
 | 
						|
    try {
 | 
						|
      await this.preExecute();
 | 
						|
 | 
						|
      for (const change of changes) {
 | 
						|
        try {
 | 
						|
          await this.applyChange(change);
 | 
						|
          this.stats.recordFileOperation(this.name, change.type, true);
 | 
						|
        } catch (error) {
 | 
						|
          this.stats.recordFileOperation(this.name, change.type, false);
 | 
						|
          throw error;
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      await this.postExecute();
 | 
						|
    } catch (error) {
 | 
						|
      // Don't rollback here - let the FormatPlanner handle it
 | 
						|
      throw error;
 | 
						|
    } finally {
 | 
						|
      this.stats.endModule(this.name, startTime);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  protected async preExecute(): Promise<void> {
 | 
						|
    // Override in subclasses if needed
 | 
						|
  }
 | 
						|
 | 
						|
  protected async postExecute(): Promise<void> {
 | 
						|
    // Override in subclasses if needed
 | 
						|
  }
 | 
						|
 | 
						|
  protected async modifyFile(filepath: string, content: string): Promise<void> {
 | 
						|
    // Validate filepath before writing
 | 
						|
    if (!filepath || filepath.trim() === '') {
 | 
						|
      throw new Error(`Invalid empty filepath in modifyFile`);
 | 
						|
    }
 | 
						|
 | 
						|
    // Ensure we have a proper path with directory component
 | 
						|
    // If the path has no directory component (e.g., "package.json"), prepend "./"
 | 
						|
    let normalizedPath = filepath;
 | 
						|
    if (!plugins.path.parse(filepath).dir) {
 | 
						|
      normalizedPath = './' + filepath;
 | 
						|
    }
 | 
						|
 | 
						|
    await plugins.smartfile.memory.toFs(content, normalizedPath);
 | 
						|
  }
 | 
						|
 | 
						|
  protected async createFile(filepath: string, content: string): Promise<void> {
 | 
						|
    await plugins.smartfile.memory.toFs(content, filepath);
 | 
						|
  }
 | 
						|
 | 
						|
  protected async deleteFile(filepath: string): Promise<void> {
 | 
						|
    await plugins.smartfile.fs.remove(filepath);
 | 
						|
  }
 | 
						|
 | 
						|
  protected async shouldProcessFile(filepath: string): Promise<boolean> {
 | 
						|
    return true;
 | 
						|
  }
 | 
						|
}
 |