import { DiagramType, DiagramFormat, DiagramData } from '../types/diagram-types.js'; import { convertToDrawioXML, createDiagramFile, getDefaultStyle, generateId } from '../utils/drawio-converter.js'; import { analyzeDiagramDescription } from '../ai/diagram-analyzer.js'; import { generateSmartBPMNDiagram } from '../generators/smart-bpmn-generator.js'; import { generateSmartERDiagram } from '../generators/smart-er-generator.js'; import { generateSmartArchitectureDiagram } from '../generators/smart-architecture-generator.js'; import * as fs from 'fs'; import * as path from 'path'; // Functional types type CreateDiagramInput = Readonly<{ name: string; type: DiagramType; format?: DiagramFormat; description?: string; outputPath?: string; workspaceRoot?: string; complexity?: 'simple' | 'detailed'; language?: string; // Legacy parameters for backward compatibility tasks?: readonly string[]; entities?: readonly string[]; classes?: readonly string[]; components?: readonly string[]; processes?: readonly string[]; processName?: string; gatewayType?: 'exclusive' | 'parallel'; branches?: readonly (readonly string[])[]; beforeGateway?: readonly string[]; afterGateway?: readonly string[]; }>; type CreateDiagramResult = Readonly<{ success: boolean; filePath?: string; content?: string; message: string; diagramType: DiagramType; format: DiagramFormat; }>; // Pure function to create successful result const createSuccessResult = ( filePath: string, content: string, diagramType: DiagramType, format: DiagramFormat, name: string ): CreateDiagramResult => ({ success: true, filePath, content, message: `Successfully created ${diagramType} diagram: ${name}`, diagramType, format }); // Pure function to create error result const createErrorResult = ( error: unknown, diagramType: DiagramType, format: DiagramFormat ): CreateDiagramResult => ({ success: false, message: `Failed to create diagram: ${error instanceof Error ? error.message : String(error)}`, diagramType, format }); // Pure function to ensure directory exists const ensureDirectoryExists = (dirPath: string): void => { if (!fs.existsSync(dirPath)) { fs.mkdirSync(dirPath, { recursive: true }); } }; // Pure function to write file const writeFile = async (filePath: string, content: string): Promise => { const dir = path.dirname(filePath); ensureDirectoryExists(dir); await fs.promises.writeFile(filePath, content, 'utf8'); }; // Pure function to generate diagram using AI const generateAIDiagram = async (input: CreateDiagramInput): Promise => { if (!input.description) { throw new Error('Description is required for AI-powered diagram generation'); } // Analyze the description const analysis = await analyzeDiagramDescription(input.description); // Generate diagram based on type const preferences = { complexity: input.complexity || 'detailed', language: input.language || 'es' }; switch (input.type) { case DiagramType.BPMN_PROCESS: case DiagramType.BPMN_COLLABORATION: case DiagramType.BPMN_CHOREOGRAPHY: return generateSmartBPMNDiagram(input.description, analysis, preferences); case DiagramType.ER_DIAGRAM: case DiagramType.DATABASE_SCHEMA: case DiagramType.CONCEPTUAL_MODEL: return generateSmartERDiagram(input.description, analysis, preferences); case DiagramType.SYSTEM_ARCHITECTURE: case DiagramType.MICROSERVICES: case DiagramType.LAYERED_ARCHITECTURE: case DiagramType.C4_CONTEXT: case DiagramType.C4_CONTAINER: case DiagramType.C4_COMPONENT: case DiagramType.CLOUD_ARCHITECTURE: case DiagramType.INFRASTRUCTURE: return generateSmartArchitectureDiagram(input.description, analysis, preferences); default: // Fallback to basic diagram generation return generateBasicDiagram(input); } }; // Pure function to generate basic diagram (fallback) const generateBasicDiagram = (input: CreateDiagramInput): DiagramData => { return { elements: [{ id: 'basic-1', type: 'rectangle', label: input.name, geometry: { x: 100, y: 100, width: 200, height: 100 }, style: 'rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;', properties: {} }], connections: [], metadata: { type: input.type, format: input.format || DiagramFormat.DRAWIO, created: new Date().toISOString(), modified: new Date().toISOString(), version: '1.0' } }; }; // Pure function to generate legacy diagram (for backward compatibility) const generateLegacyDiagram = (input: CreateDiagramInput): DiagramData => { const elements: any[] = []; const connections: any[] = []; // Handle legacy parameters if (input.tasks && input.tasks.length > 0) { // Generate BPMN-like diagram from tasks input.tasks.forEach((task, index) => { elements.push({ id: `task-${index}`, type: 'bpmn-task', label: task, geometry: { x: 100, y: 100 + (index * 120), width: 120, height: 80 }, style: 'rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;', properties: { isTask: true } }); if (index > 0) { connections.push({ id: `conn-${index}`, source: `task-${index - 1}`, target: `task-${index}`, label: '', style: 'edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;endArrow=classic;', properties: {} }); } }); } else if (input.entities && input.entities.length > 0) { // Generate ER diagram from entities input.entities.forEach((entity, index) => { elements.push({ id: `entity-${index}`, type: 'er-entity', label: entity, geometry: { x: 100 + (index * 200), y: 100, width: 120, height: 80 }, style: 'whiteSpace=wrap;html=1;align=center;fillColor=#e1d5e7;strokeColor=#9673a6;', properties: { isEntity: true } }); }); } else if (input.classes && input.classes.length > 0) { // Generate UML class diagram from classes input.classes.forEach((className, index) => { elements.push({ id: `class-${index}`, type: 'uml-class', label: className, geometry: { x: 100 + (index * 200), y: 100, width: 160, height: 120 }, style: 'swimlane;fontStyle=1;align=center;verticalAlign=top;childLayout=stackLayout;horizontal=1;startSize=26;fillColor=#dae8fc;strokeColor=#6c8ebf;', properties: { isClass: true } }); }); } else if (input.components && input.components.length > 0) { // Generate architecture diagram from components input.components.forEach((component, index) => { elements.push({ id: `comp-${index}`, type: 'architecture-component', label: component, geometry: { x: 100 + (index % 2) * 300, y: 100 + Math.floor(index / 2) * 150, width: 200, height: 100 }, style: 'rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;', properties: { isComponent: true } }); }); } else { // Fallback to basic diagram return generateBasicDiagram(input); } return { elements, connections, metadata: { type: input.type, format: input.format || DiagramFormat.DRAWIO, created: new Date().toISOString(), modified: new Date().toISOString(), version: '1.0' } }; }; // Main function to create a new diagram export const createDiagram = async (input: CreateDiagramInput): Promise => { try { const format = input.format || DiagramFormat.DRAWIO; const workspaceRoot = input.workspaceRoot || process.cwd(); // Generate diagram data let diagramData: DiagramData; if (input.description) { // Use AI-powered generation diagramData = await generateAIDiagram(input); } else { // Use legacy generation for backward compatibility diagramData = generateLegacyDiagram(input); } // Convert to the requested format const { content, filename } = createDiagramFile(diagramData, format, input.name); // Determine output path const outputDir = input.outputPath ? path.resolve(workspaceRoot, input.outputPath) : workspaceRoot; const filePath = path.join(outputDir, filename); // Write file await writeFile(filePath, content); return createSuccessResult(filePath, content, input.type, format, input.name); } catch (error) { console.error('Error creating diagram:', error); return createErrorResult(error, input.type, input.format || DiagramFormat.DRAWIO); } }; // Pure function to validate create diagram input export const validateCreateDiagramInput = (input: any): input is CreateDiagramInput => { return ( typeof input === 'object' && input !== null && typeof input.name === 'string' && Object.values(DiagramType).includes(input.type) ); }; // Pure function to get supported diagram types export const getSupportedDiagramTypes = (): readonly DiagramType[] => { return Object.values(DiagramType); }; // Pure function to get diagram type descriptions const getDiagramTypeDescriptions = (): Readonly> => ({ [DiagramType.BPMN_PROCESS]: 'Business Process Model and Notation diagram for modeling business processes with AI-powered generation', [DiagramType.BPMN_COLLABORATION]: 'BPMN collaboration diagram showing interactions between participants', [DiagramType.BPMN_CHOREOGRAPHY]: 'BPMN choreography diagram for modeling message exchanges', [DiagramType.UML_CLASS]: 'UML Class diagram showing classes, attributes, methods, and relationships', [DiagramType.UML_SEQUENCE]: 'UML Sequence diagram showing object interactions over time', [DiagramType.UML_USE_CASE]: 'UML Use Case diagram showing system functionality and user interactions', [DiagramType.UML_ACTIVITY]: 'UML Activity diagram showing workflow and business processes', [DiagramType.UML_STATE]: 'UML State diagram showing object states and transitions', [DiagramType.UML_COMPONENT]: 'UML Component diagram showing software components and dependencies', [DiagramType.UML_DEPLOYMENT]: 'UML Deployment diagram showing hardware and software deployment', [DiagramType.ER_DIAGRAM]: 'Entity-Relationship diagram for database design with AI-powered generation', [DiagramType.DATABASE_SCHEMA]: 'Database schema diagram showing tables and relationships', [DiagramType.CONCEPTUAL_MODEL]: 'Conceptual data model diagram', [DiagramType.NETWORK_TOPOLOGY]: 'Network topology diagram showing network infrastructure', [DiagramType.INFRASTRUCTURE]: 'Infrastructure diagram showing system components', [DiagramType.CLOUD_ARCHITECTURE]: 'Cloud architecture diagram showing cloud services and components', [DiagramType.SYSTEM_ARCHITECTURE]: 'System architecture diagram showing high-level system design with AI-powered generation', [DiagramType.MICROSERVICES]: 'Microservices architecture diagram', [DiagramType.LAYERED_ARCHITECTURE]: 'Layered architecture diagram showing application layers', [DiagramType.C4_CONTEXT]: 'C4 Context diagram showing system context', [DiagramType.C4_CONTAINER]: 'C4 Container diagram showing application containers', [DiagramType.C4_COMPONENT]: 'C4 Component diagram showing component details', [DiagramType.FLOWCHART]: 'Flowchart diagram showing process flow', [DiagramType.ORGCHART]: 'Organizational chart showing hierarchy', [DiagramType.MINDMAP]: 'Mind map diagram for brainstorming and organizing ideas', [DiagramType.WIREFRAME]: 'Wireframe diagram for UI/UX design', [DiagramType.GANTT]: 'Gantt chart for project management and scheduling' }); // Pure function to get description for a specific diagram type export const getDiagramTypeDescription = (diagramType: DiagramType): string => { const descriptions = getDiagramTypeDescriptions(); return descriptions[diagramType] || 'Generic diagram type'; };