@angular-modernizer/orchestration
v0.1.3
Published
Orchestration layer for the Angular Modernization Platform (Placeholder)
Maintainers
Readme
@angular-modernizer/orchestration
Multi-step migration workflows that coordinate analysis, planning, transformation, and validation across the Angular Modernization Platform.
Overview
The @angular-modernizer/orchestration package provides workflow management for complex multi-plugin operations. It handles scenarios that require coordinating multiple plugins, managing execution pipelines, and running transformation workflows with checkpointing and automatic rollback.
Activated via the orchestrate-migration MCP tool.
Architecture
The orchestration layer sits above the plugin system:
User Request
|
Orchestration Layer (Workflows and Pipelines)
|
Plugin Coordination (Multi-plugin operations)
|
Individual Plugins (Analysis and Transform)
|
Core Platform (Kernel and API)Workflow Engine
The orchestration layer uses a declarative workflow system:
interface Workflow {
id: string;
name: string;
description: string;
steps: WorkflowStep[];
conditions?: WorkflowCondition[];
errorHandling?: ErrorStrategy;
}
interface WorkflowStep {
id: string;
name: string;
type: 'analysis' | 'transform' | 'validation' | 'conditional';
plugin?: string;
rule?: string;
config?: Record<string, unknown>;
dependencies?: string[];
onSuccess?: string[];
onFailure?: string[];
}Predefined Workflows
Standalone Migration Workflow
Migrates an entire Angular application from NgModule-based to standalone architecture.
const standaloneMigrationWorkflow: Workflow = {
id: 'standalone-migration',
name: 'Complete Standalone Migration',
description: 'Migrate entire Angular application to standalone architecture',
steps: [
{
id: 'analyze-dependencies',
name: 'Analyze Component Dependencies',
type: 'analysis',
plugin: '@angular-modernizer/plugin-analyzer',
rule: 'dependency-analysis',
},
{
id: 'detect-ngmodules',
name: 'Detect NgModule Usage',
type: 'analysis',
plugin: '@angular-modernizer/api',
rule: 'ngmodule-detection',
},
{
id: 'plan-migration',
name: 'Create Migration Plan',
type: 'transform',
plugin: '@angular-modernizer/orchestration',
rule: 'migration-planner',
dependencies: ['analyze-dependencies', 'detect-ngmodules'],
},
{
id: 'migrate-components',
name: 'Migrate Components',
type: 'transform',
plugin: '@angular-modernizer/plugin-standalone',
rule: 'component-migration',
dependencies: ['plan-migration'],
},
{
id: 'migrate-services',
name: 'Migrate Services to Inject',
type: 'transform',
plugin: '@angular-modernizer/plugin-solid',
rule: 'constructor-to-inject',
dependencies: ['migrate-components'],
},
{
id: 'validate-build',
name: 'Validate Build',
type: 'validation',
plugin: '@angular-modernizer/adapter-mcp',
rule: 'build-validation',
dependencies: ['migrate-services'],
},
],
};SOLID Compliance Workflow
Systematically improves SOLID principle compliance across the codebase.
const solidComplianceWorkflow: Workflow = {
id: 'solid-compliance',
name: 'SOLID Principle Compliance',
description: 'Achieve full SOLID compliance through systematic improvements',
steps: [
{
id: 'scan-solid-violations',
name: 'Scan for SOLID Violations',
type: 'analysis',
plugin: '@angular-modernizer/plugin-solid',
rule: 'comprehensive-solid-scan',
},
{
id: 'prioritize-violations',
name: 'Prioritize Violations',
type: 'analysis',
plugin: '@angular-modernizer/orchestration',
rule: 'violation-prioritizer',
dependencies: ['scan-solid-violations'],
},
{
id: 'create-interfaces',
name: 'Create Missing Interfaces',
type: 'transform',
plugin: '@angular-modernizer/plugin-solid',
rule: 'interface-generator',
dependencies: ['prioritize-violations'],
},
{
id: 'fix-dip-violations',
name: 'Fix DIP Violations',
type: 'transform',
plugin: '@angular-modernizer/plugin-solid',
rule: 'dip-fixer',
dependencies: ['create-interfaces'],
},
{
id: 'validate-compliance',
name: 'Validate SOLID Compliance',
type: 'validation',
plugin: '@angular-modernizer/plugin-solid',
rule: 'solid-validator',
dependencies: ['fix-dip-violations'],
},
],
};Workflow Execution Engine
WorkflowExecutor
Executes complex workflows with dependency management and error handling.
class WorkflowExecutor {
async executeWorkflow(
workflow: Workflow,
context: WorkflowContext,
): Promise<WorkflowResult> {
const executionPlan = this.buildExecutionPlan(workflow);
const results = new Map<string, StepResult>();
for (const step of executionPlan) {
if (!this.areDependenciesMet(step, results)) {
throw new Error(`Dependencies not met for step: ${step.id}`);
}
const result = await this.executeStep(step, context);
results.set(step.id, result);
if (!result.success) {
await this.handleStepFailure(step, result, workflow.errorHandling);
}
}
return {
success: this.isWorkflowSuccessful(results),
results,
summary: this.generateSummary(results),
};
}
private buildExecutionPlan(workflow: Workflow): WorkflowStep[] {
return this.topologicalSort(workflow.steps);
}
private async executeStep(
step: WorkflowStep,
context: WorkflowContext,
): Promise<StepResult> {
const plugin = context.kernel.getPlugin(step.plugin!);
const rule = this.getRuleFromPlugin(plugin, step.rule!);
const stepContext = this.createStepContext(step, context);
return await rule.execute(stepContext);
}
}Context Management
interface WorkflowContext {
kernel: Kernel;
project: Project;
api: PublicApi;
config: Record<string, unknown>;
variables: Map<string, unknown>;
progressCallback?: (step: WorkflowStep, result: StepResult) => void;
}
interface StepResult {
stepId: string;
success: boolean;
result?: unknown;
error?: string;
duration: number;
metadata?: Record<string, unknown>;
}Advanced Features
Conditional Execution
Execute steps based on runtime conditions:
interface WorkflowCondition {
id: string;
expression: string;
context: Record<string, unknown>;
trueSteps: string[];
falseSteps: string[];
}
const conditionalWorkflow: Workflow = {
conditions: [
{
id: 'high-violation-count',
expression: 'results.scan-violations.violations.length > 50',
trueSteps: ['aggressive-migration'],
falseSteps: ['incremental-migration'],
},
],
};Error Handling Strategies
interface ErrorStrategy {
type: 'fail-fast' | 'continue' | 'retry' | 'compensate';
maxRetries?: number;
retryDelay?: number;
compensationSteps?: string[];
}
const resilientWorkflow: Workflow = {
errorHandling: {
type: 'retry',
maxRetries: 3,
retryDelay: 1000,
compensationSteps: ['rollback-changes'],
},
};Parallel Execution
Independent steps execute concurrently:
class ParallelExecutor {
async executeParallel(
steps: WorkflowStep[],
context: WorkflowContext,
): Promise<StepResult[]> {
return await Promise.all(steps.map((step) => this.executeStep(step, context)));
}
}
const parallelWorkflow: Workflow = {
steps: [
{ id: 'analyze-a', dependencies: [] },
{ id: 'analyze-b', dependencies: [] },
{ id: 'merge-results', dependencies: ['analyze-a', 'analyze-b'] },
],
};Usage Examples
Executing a Workflow
import { WorkflowExecutor } from '@angular-modernizer/orchestration';
import { Kernel, RealFileSystemAdapter } from '@angular-modernizer/core';
import { standaloneMigrationWorkflow } from '@angular-modernizer/orchestration';
async function runStandaloneMigration(projectPath: string) {
const kernel = new Kernel({
tsConfigPath: `${projectPath}/tsconfig.json`,
fileSystem: new RealFileSystemAdapter(),
plugins: [/* all necessary plugins */],
});
await kernel.initialize();
const executor = new WorkflowExecutor();
const context: WorkflowContext = {
kernel,
project: kernel.getProject(),
api: createPublicApi(),
config: {
autoAddCommonModule: true,
preserveExistingImports: false,
},
variables: new Map(),
progressCallback: (step, result) => {
console.log(`${step.name}: ${result.success ? 'Success' : 'Failed'}`);
},
};
const result = await executor.executeWorkflow(standaloneMigrationWorkflow, context);
if (result.success) {
console.log('Standalone migration completed.');
console.log('Summary:', result.summary);
} else {
console.error('Migration failed');
console.error('Failed steps:', result.results);
}
}Custom Workflow Creation
import { type Workflow } from '@angular-modernizer/orchestration';
const customWorkflow: Workflow = {
id: 'custom-cleanup',
name: 'Custom Code Cleanup',
description: 'Custom workflow for code cleanup and optimization',
steps: [
{
id: 'analyze-unused-imports',
name: 'Analyze Unused Imports',
type: 'analysis',
plugin: '@angular-modernizer/api',
rule: 'unused-imports-analysis',
},
{
id: 'remove-unused-imports',
name: 'Remove Unused Imports',
type: 'transform',
plugin: '@angular-modernizer/api',
rule: 'import-cleanup',
dependencies: ['analyze-unused-imports'],
},
{
id: 'format-code',
name: 'Format Code',
type: 'transform',
plugin: '@angular-modernizer/core',
rule: 'code-formatter',
dependencies: ['remove-unused-imports'],
},
],
};Workflow Monitoring
const context: WorkflowContext = {
progressCallback: (step, result) => {
console.log(`[${new Date().toISOString()}] ${step.name}`);
if (result.success) {
console.log(` Completed (${result.duration}ms)`);
} else {
console.log(` Failed: ${result.error}`);
}
},
};Package Structure
packages/orchestration/
src/
workflows/
standalone-migration.workflow.ts
solid-compliance.workflow.ts
custom-workflow.builder.ts
executors/
workflow-executor.ts
parallel-executor.ts
conditional-executor.ts
strategies/
error-handling.strategy.ts
dependency-resolution.strategy.ts
orchestration-plugin.ts
index.ts
types.ts
__tests__/
workflows/
standalone-migration.workflow.test.ts
executors/
workflow-executor.test.ts
integration.test.ts
package.json
tsconfig.json
jest.config.js
README.mdTesting
pnpm --filter @angular-modernizer/orchestration test
pnpm --filter @angular-modernizer/orchestration test --testPathPattern=integrationTest Example
describe('WorkflowExecutor', () => {
let executor: WorkflowExecutor;
let context: WorkflowContext;
beforeEach(() => {
executor = new WorkflowExecutor();
context = createMockWorkflowContext();
});
it('should execute workflow steps in dependency order', async () => {
const workflow: Workflow = {
id: 'test-workflow',
name: 'Test Workflow',
steps: [
{ id: 'step1', name: 'Step 1', type: 'analysis' },
{ id: 'step2', name: 'Step 2', type: 'transform', dependencies: ['step1'] },
],
};
const result = await executor.executeWorkflow(workflow, context);
expect(result.success).toBe(true);
expect(result.results.get('step1')).toBeDefined();
expect(result.results.get('step2')).toBeDefined();
});
it('should handle step failures according to error strategy', async () => {
const workflow: Workflow = {
errorHandling: { type: 'continue' },
};
const result = await executor.executeWorkflow(workflow, context);
expect(result.success).toBe(false);
});
});Workflow Patterns
Sequential Execution
const sequentialWorkflow: Workflow = {
steps: [
{ id: 'analyze', dependencies: [] },
{ id: 'transform', dependencies: ['analyze'] },
{ id: 'validate', dependencies: ['transform'] },
],
};Parallel Execution
const parallelWorkflow: Workflow = {
steps: [
{ id: 'analyze-a', dependencies: [] },
{ id: 'analyze-b', dependencies: [] },
{ id: 'merge-results', dependencies: ['analyze-a', 'analyze-b'] },
],
};Conditional Branching
const conditionalWorkflow: Workflow = {
steps: [
{ id: 'check-condition', dependencies: [] },
{ id: 'path-a', dependencies: ['check-condition'], condition: 'result > 10' },
{ id: 'path-b', dependencies: ['check-condition'], condition: 'result <= 10' },
],
};Dependencies
@angular-modernizer/core- Kernel and infrastructure@angular-modernizer/api- Public API tools@angular-modernizer/plugin-system- Plugin contracts@angular-modernizer/plugin-analyzer- Analysis rules@angular-modernizer/plugin-solid- SOLID analysis rules@angular-modernizer/plugin-standalone- Transformation rules
Contributing
- Design for composability — workflows should be modular and reusable
- Handle errors gracefully — provide clear error messages and recovery options
- Write workflow tests — test complete workflow execution scenarios
- Document workflow schemas — provide clear workflow definition examples
- Consider performance — optimize for large-scale codebase operations
Adding a New Workflow
// 1. Define the workflow
const myWorkflow: Workflow = {
id: 'my-custom-workflow',
name: 'My Custom Workflow',
description: 'Does something specific',
steps: [],
};
// 2. Add to exports
export { myWorkflow } from './workflows/my-workflow';
// 3. Add tests
describe('MyWorkflow', () => {
it('should execute successfully', async () => {
const result = await executor.executeWorkflow(myWorkflow, context);
expect(result.success).toBe(true);
});
});See Also
- packages/core/README.md - Kernel infrastructure
- packages/plugin-system/README.md - Plugin contracts
