Some checks failed
Main Workflow / Security Audit (push) Successful in 4m39s
Main Workflow / Test and Build (20.x) (push) Failing after 4m56s
Main Workflow / Test and Build (18.x) (push) Failing after 5m9s
Main Workflow / Build Release Artifacts (push) Has been skipped
Main Workflow / Code Quality Check (push) Successful in 1m33s
Main Workflow / Notification (push) Failing after 21s
344 lines
12 KiB
TypeScript
344 lines
12 KiB
TypeScript
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<void> => {
|
|
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<DiagramData> => {
|
|
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<CreateDiagramResult> => {
|
|
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<Record<DiagramType, string>> => ({
|
|
[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';
|
|
};
|