/** * @angular-modernizer/plugin-architecture - Service Bag Transform Rule * * Automatically splits Service Bag anti-patterns into focused services * by grouping methods by responsibility domain. * * Transformation Strategy: * 1. Detect Service Bags (>10 methods, >3 responsibilities) * 2. Group methods by responsibility patterns * 3. Create focused service files (one per responsibility) * 4. Update original service to delegate to focused services * 5. Add imports and constructor injection * * This transformation follows the "Thin Rule, Thick Orchestrator" pattern: * - Rule: Thin wrapper (≤50 lines) delegating to orchestrator * - Orchestrator: Contains all business logic for transformation * * Guarantees: * - Idempotent: Safe to run multiple times * - Atomic: All or nothing (uses git rollback) * - Reversible: Can be undone via git reset */ import type { TransformRule, TransformContext, TransformResult, } from '@angular-modernizer/plugin-system'; import type { PublicApi } from '@angular-modernizer/api'; import { ServiceBagTransformOrchestrator } from '../orchestrators/service-bag-transform.orchestrator.js'; /** * Service Bag Transform Rule - splits Service Bags into focused services. * * This is a thin wrapper that delegates all business logic to the * ServiceBagTransformOrchestrator following the recommended pattern. * * @example * ```typescript * const rule = new ServiceBagTransformRule(); * const context = ContextFactory.createTransformContext({ sourceFile, project, api }); * const result = await rule.transform(context); * * if (result.modified) { * console.info('Service Bag split into focused services'); * console.info(`Changes: ${result.changeCount}`); * } * ``` */ export class ServiceBagTransformRule implements TransformRule { public readonly id = 'refactor:service-bag-split'; public readonly name = 'Service Bag Split'; public readonly description = 'Automatically splits Service Bag into focused services'; public readonly category = 'refactoring'; public readonly tags = ['service', 'refactoring', 'srp', 'service-bag']; /** * Orchestrator instance containing all transformation business logic. * @private */ private readonly orchestrator = new ServiceBagTransformOrchestrator(); /** * Transforms Service Bag into focused services. * * @param context - Transform context with source file and PublicApi * @returns Transform result with modification status */ async transform( context: TransformContext, ): Promise { const { sourceFile, filePath } = context; // Capture initial state for change detection const initialText = sourceFile.getFullText(); // Delegate ALL business logic to orchestrator await this.orchestrator.run(context); // Detect if modifications were made const modified = sourceFile.getFullText() !== initialText; return { ruleId: this.id, modified, message: modified ? 'Successfully split Service Bag into focused services' : 'No Service Bag detected or already split', filePath, changeCount: modified ? 1 : 0, }; } }