Adding as a Streamable HTTP MCP Server
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
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
This commit is contained in:
@ -1,7 +1,11 @@
|
||||
import { DiagramType, DiagramFormat, DiagramConfig } from '../types/diagram-types.js';
|
||||
import { createFileConfig, createDiagramFile } from '../utils/file-manager.js';
|
||||
import { generateDrawioXML } from '../utils/xml-parser.js';
|
||||
import { generateLinearBPMNProcess, generateBPMNProcessWithGateway } from '../generators/bpmn-generator.js';
|
||||
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<{
|
||||
@ -9,16 +13,16 @@ type CreateDiagramInput = Readonly<{
|
||||
type: DiagramType;
|
||||
format?: DiagramFormat;
|
||||
description?: string;
|
||||
template?: string;
|
||||
outputPath?: string;
|
||||
workspaceRoot?: string;
|
||||
// Specific parameters for different diagram types
|
||||
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[];
|
||||
// BPMN specific
|
||||
processName?: string;
|
||||
gatewayType?: 'exclusive' | 'parallel';
|
||||
branches?: readonly (readonly string[])[];
|
||||
@ -29,24 +33,23 @@ type CreateDiagramInput = Readonly<{
|
||||
type CreateDiagramResult = Readonly<{
|
||||
success: boolean;
|
||||
filePath?: string;
|
||||
content?: string;
|
||||
message: string;
|
||||
diagramType: DiagramType;
|
||||
format: DiagramFormat;
|
||||
}>;
|
||||
|
||||
type DiagramGenerator = (input: CreateDiagramInput) => any;
|
||||
|
||||
type DiagramGeneratorMap = Readonly<Record<DiagramType, DiagramGenerator>>;
|
||||
|
||||
// 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
|
||||
@ -59,206 +62,69 @@ const createErrorResult = (
|
||||
format: DiagramFormat
|
||||
): CreateDiagramResult => ({
|
||||
success: false,
|
||||
message: `Failed to create diagram: ${error}`,
|
||||
message: `Failed to create diagram: ${error instanceof Error ? error.message : String(error)}`,
|
||||
diagramType,
|
||||
format
|
||||
});
|
||||
|
||||
// Higher-order function for diagram creation with error handling
|
||||
const withDiagramErrorHandling = <T extends any[], R>(
|
||||
operation: (...args: T) => Promise<R>
|
||||
) => async (...args: T): Promise<R> => {
|
||||
try {
|
||||
return await operation(...args);
|
||||
} catch (error) {
|
||||
throw new Error(`Diagram creation failed: ${error}`);
|
||||
// Pure function to ensure directory exists
|
||||
const ensureDirectoryExists = (dirPath: string): void => {
|
||||
if (!fs.existsSync(dirPath)) {
|
||||
fs.mkdirSync(dirPath, { recursive: true });
|
||||
}
|
||||
};
|
||||
|
||||
// Pure function to generate BPMN diagram
|
||||
const generateBPMNDiagram = (input: CreateDiagramInput) => {
|
||||
const processName = input.processName || input.name;
|
||||
const tasks = input.tasks || ['Task 1', 'Task 2', 'Task 3'];
|
||||
// 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');
|
||||
};
|
||||
|
||||
if (input.branches && input.branches.length > 0) {
|
||||
return generateBPMNProcessWithGateway(
|
||||
processName,
|
||||
Array.from(input.beforeGateway || []),
|
||||
input.gatewayType || 'exclusive',
|
||||
input.branches.map(branch => Array.from(branch)),
|
||||
Array.from(input.afterGateway || [])
|
||||
);
|
||||
} else {
|
||||
return generateLinearBPMNProcess(processName, Array.from(tasks));
|
||||
// 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');
|
||||
}
|
||||
};
|
||||
|
||||
// Pure function to generate UML Class diagram
|
||||
const generateUMLClassDiagram = (input: CreateDiagramInput) => {
|
||||
const classes = input.classes || ['Class1', 'Class2', 'Class3'];
|
||||
// Analyze the description
|
||||
const analysis = await analyzeDiagramDescription(input.description);
|
||||
|
||||
return {
|
||||
elements: classes.map((className, index) => ({
|
||||
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;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;fillColor=#dae8fc;strokeColor=#6c8ebf;',
|
||||
properties: { isClass: true }
|
||||
})),
|
||||
connections: [],
|
||||
metadata: {
|
||||
type: DiagramType.UML_CLASS,
|
||||
format: DiagramFormat.DRAWIO,
|
||||
created: new Date().toISOString(),
|
||||
modified: new Date().toISOString(),
|
||||
version: '1.0'
|
||||
}
|
||||
// Generate diagram based on type
|
||||
const preferences = {
|
||||
complexity: input.complexity || 'detailed',
|
||||
language: input.language || 'es'
|
||||
};
|
||||
};
|
||||
|
||||
// Pure function to generate ER diagram
|
||||
const generateERDiagram = (input: CreateDiagramInput) => {
|
||||
const entities = input.entities || ['User', 'Order', 'Product'];
|
||||
|
||||
return {
|
||||
elements: entities.map((entityName, index) => ({
|
||||
id: `entity-${index}`,
|
||||
type: 'er-entity',
|
||||
label: entityName,
|
||||
geometry: {
|
||||
x: 100 + (index * 200),
|
||||
y: 100,
|
||||
width: 120,
|
||||
height: 80
|
||||
},
|
||||
style: 'whiteSpace=wrap;html=1;align=center;treeFolding=1;treeMoving=1;newEdgeStyle={"edgeStyle":"entityRelationEdgeStyle","startArrow":"none","endArrow":"none","segment":10,"curved":1};fillColor=#e1d5e7;strokeColor=#9673a6;',
|
||||
properties: { isEntity: true }
|
||||
})),
|
||||
connections: [],
|
||||
metadata: {
|
||||
type: DiagramType.ER_DIAGRAM,
|
||||
format: DiagramFormat.DRAWIO,
|
||||
created: new Date().toISOString(),
|
||||
modified: new Date().toISOString(),
|
||||
version: '1.0'
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// Pure function to generate Network diagram
|
||||
const generateNetworkDiagram = (input: CreateDiagramInput) => {
|
||||
const components = input.components || ['Router', 'Switch', 'Server'];
|
||||
|
||||
return {
|
||||
elements: components.map((componentName, index) => ({
|
||||
id: `network-${index}`,
|
||||
type: `network-${componentName.toLowerCase()}`,
|
||||
label: componentName,
|
||||
geometry: {
|
||||
x: 100 + (index * 200),
|
||||
y: 100,
|
||||
width: 100,
|
||||
height: 80
|
||||
},
|
||||
style: 'rounded=0;whiteSpace=wrap;html=1;fillColor=#f8cecc;strokeColor=#b85450;',
|
||||
properties: { isNetworkComponent: true }
|
||||
})),
|
||||
connections: [],
|
||||
metadata: {
|
||||
type: DiagramType.NETWORK_TOPOLOGY,
|
||||
format: DiagramFormat.DRAWIO,
|
||||
created: new Date().toISOString(),
|
||||
modified: new Date().toISOString(),
|
||||
version: '1.0'
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// Pure function to generate Architecture diagram
|
||||
const generateArchitectureDiagram = (input: CreateDiagramInput) => {
|
||||
const components = input.components || ['Frontend', 'API Gateway', 'Backend', 'Database'];
|
||||
|
||||
return {
|
||||
elements: components.map((componentName, index) => ({
|
||||
id: `arch-${index}`,
|
||||
type: 'architecture-component',
|
||||
label: componentName,
|
||||
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: { isArchComponent: true }
|
||||
})),
|
||||
connections: [],
|
||||
metadata: {
|
||||
type: DiagramType.SYSTEM_ARCHITECTURE,
|
||||
format: DiagramFormat.DRAWIO,
|
||||
created: new Date().toISOString(),
|
||||
modified: new Date().toISOString(),
|
||||
version: '1.0'
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// Pure function to generate Flowchart diagram
|
||||
const generateFlowchartDiagram = (input: CreateDiagramInput) => {
|
||||
const processes = input.processes || ['Start', 'Process 1', 'Decision', 'Process 2', 'End'];
|
||||
|
||||
return {
|
||||
elements: processes.map((processName, index) => {
|
||||
const isDecision = processName.toLowerCase().includes('decision');
|
||||
const isStart = processName.toLowerCase().includes('start');
|
||||
const isEnd = processName.toLowerCase().includes('end');
|
||||
|
||||
return {
|
||||
id: `flow-${index}`,
|
||||
type: isDecision ? 'diamond' : (isStart || isEnd ? 'ellipse' : 'rectangle'),
|
||||
label: processName,
|
||||
geometry: {
|
||||
x: 100,
|
||||
y: 100 + (index * 120),
|
||||
width: isDecision ? 100 : 120,
|
||||
height: isDecision ? 80 : 60
|
||||
},
|
||||
style: isDecision
|
||||
? 'rhombus;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;'
|
||||
: isStart
|
||||
? 'ellipse;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;'
|
||||
: isEnd
|
||||
? 'ellipse;whiteSpace=wrap;html=1;fillColor=#f8cecc;strokeColor=#b85450;'
|
||||
: 'rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;',
|
||||
properties: { isFlowElement: true }
|
||||
};
|
||||
}),
|
||||
connections: processes.slice(0, -1).map((_, index) => ({
|
||||
id: `conn-${index}`,
|
||||
source: `flow-${index}`,
|
||||
target: `flow-${index + 1}`,
|
||||
label: '',
|
||||
style: 'edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;endArrow=classic;',
|
||||
properties: {}
|
||||
})),
|
||||
metadata: {
|
||||
type: DiagramType.FLOWCHART,
|
||||
format: DiagramFormat.DRAWIO,
|
||||
created: new Date().toISOString(),
|
||||
modified: new Date().toISOString(),
|
||||
version: '1.0'
|
||||
}
|
||||
};
|
||||
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) => {
|
||||
const generateBasicDiagram = (input: CreateDiagramInput): DiagramData => {
|
||||
return {
|
||||
elements: [{
|
||||
id: 'basic-1',
|
||||
@ -276,7 +142,7 @@ const generateBasicDiagram = (input: CreateDiagramInput) => {
|
||||
connections: [],
|
||||
metadata: {
|
||||
type: input.type,
|
||||
format: DiagramFormat.DRAWIO,
|
||||
format: input.format || DiagramFormat.DRAWIO,
|
||||
created: new Date().toISOString(),
|
||||
modified: new Date().toISOString(),
|
||||
version: '1.0'
|
||||
@ -284,65 +150,145 @@ const generateBasicDiagram = (input: CreateDiagramInput) => {
|
||||
};
|
||||
};
|
||||
|
||||
// Pure function to get diagram generator map
|
||||
const getDiagramGeneratorMap = (): DiagramGeneratorMap => ({
|
||||
[DiagramType.BPMN_PROCESS]: generateBPMNDiagram,
|
||||
[DiagramType.BPMN_COLLABORATION]: generateBPMNDiagram,
|
||||
[DiagramType.BPMN_CHOREOGRAPHY]: generateBPMNDiagram,
|
||||
[DiagramType.UML_CLASS]: generateUMLClassDiagram,
|
||||
[DiagramType.UML_SEQUENCE]: generateUMLClassDiagram,
|
||||
[DiagramType.UML_USE_CASE]: generateUMLClassDiagram,
|
||||
[DiagramType.UML_ACTIVITY]: generateUMLClassDiagram,
|
||||
[DiagramType.UML_STATE]: generateUMLClassDiagram,
|
||||
[DiagramType.UML_COMPONENT]: generateUMLClassDiagram,
|
||||
[DiagramType.UML_DEPLOYMENT]: generateUMLClassDiagram,
|
||||
[DiagramType.ER_DIAGRAM]: generateERDiagram,
|
||||
[DiagramType.DATABASE_SCHEMA]: generateERDiagram,
|
||||
[DiagramType.CONCEPTUAL_MODEL]: generateERDiagram,
|
||||
[DiagramType.NETWORK_TOPOLOGY]: generateNetworkDiagram,
|
||||
[DiagramType.INFRASTRUCTURE]: generateNetworkDiagram,
|
||||
[DiagramType.CLOUD_ARCHITECTURE]: generateArchitectureDiagram,
|
||||
[DiagramType.SYSTEM_ARCHITECTURE]: generateArchitectureDiagram,
|
||||
[DiagramType.MICROSERVICES]: generateArchitectureDiagram,
|
||||
[DiagramType.LAYERED_ARCHITECTURE]: generateArchitectureDiagram,
|
||||
[DiagramType.C4_CONTEXT]: generateArchitectureDiagram,
|
||||
[DiagramType.C4_CONTAINER]: generateArchitectureDiagram,
|
||||
[DiagramType.C4_COMPONENT]: generateArchitectureDiagram,
|
||||
[DiagramType.FLOWCHART]: generateFlowchartDiagram,
|
||||
[DiagramType.ORGCHART]: generateBasicDiagram,
|
||||
[DiagramType.MINDMAP]: generateBasicDiagram,
|
||||
[DiagramType.WIREFRAME]: generateBasicDiagram,
|
||||
[DiagramType.GANTT]: generateBasicDiagram
|
||||
});
|
||||
// Pure function to generate legacy diagram (for backward compatibility)
|
||||
const generateLegacyDiagram = (input: CreateDiagramInput): DiagramData => {
|
||||
const elements: any[] = [];
|
||||
const connections: any[] = [];
|
||||
|
||||
// Pure function to generate diagram data based on type and input
|
||||
const generateDiagramData = (input: CreateDiagramInput) => {
|
||||
const generatorMap = getDiagramGeneratorMap();
|
||||
const generator = generatorMap[input.type] || generateBasicDiagram;
|
||||
return generator(input);
|
||||
// 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 based on type and configuration
|
||||
export const createDiagram = withDiagramErrorHandling(async (input: CreateDiagramInput): Promise<CreateDiagramResult> => {
|
||||
// Main function to create a new diagram
|
||||
export const createDiagram = async (input: CreateDiagramInput): Promise<CreateDiagramResult> => {
|
||||
try {
|
||||
const config = createFileConfig(input.workspaceRoot);
|
||||
const format = input.format || DiagramFormat.DRAWIO;
|
||||
const workspaceRoot = input.workspaceRoot || process.cwd();
|
||||
|
||||
// Generate diagram data based on type
|
||||
const diagramData = generateDiagramData(input);
|
||||
// Generate diagram data
|
||||
let diagramData: DiagramData;
|
||||
|
||||
// Convert to XML
|
||||
const xmlContent = generateDrawioXML(diagramData);
|
||||
if (input.description) {
|
||||
// Use AI-powered generation
|
||||
diagramData = await generateAIDiagram(input);
|
||||
} else {
|
||||
// Use legacy generation for backward compatibility
|
||||
diagramData = generateLegacyDiagram(input);
|
||||
}
|
||||
|
||||
// Create file
|
||||
const createFile = createDiagramFile(config);
|
||||
const filePath = await createFile(input.name)(xmlContent)(format)(input.outputPath);
|
||||
// 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, input.type, format, input.name);
|
||||
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 => {
|
||||
@ -361,7 +307,7 @@ export const getSupportedDiagramTypes = (): readonly 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',
|
||||
[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',
|
||||
@ -371,13 +317,13 @@ const getDiagramTypeDescriptions = (): Readonly<Record<DiagramType, string>> =>
|
||||
[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',
|
||||
[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',
|
||||
[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',
|
||||
@ -395,61 +341,3 @@ export const getDiagramTypeDescription = (diagramType: DiagramType): string => {
|
||||
const descriptions = getDiagramTypeDescriptions();
|
||||
return descriptions[diagramType] || 'Generic diagram type';
|
||||
};
|
||||
|
||||
// Utility functions for functional composition
|
||||
export const pipe = <T>(...fns: Array<(arg: T) => T>) => (value: T): T =>
|
||||
fns.reduce((acc, fn) => fn(acc), value);
|
||||
|
||||
export const compose = <T>(...fns: Array<(arg: T) => T>) => (value: T): T =>
|
||||
fns.reduceRight((acc, fn) => fn(acc), value);
|
||||
|
||||
// Higher-order function for operations with retry logic
|
||||
export const withRetry = <T extends any[], R>(
|
||||
operation: (...args: T) => Promise<R>,
|
||||
maxRetries: number = 3,
|
||||
delay: number = 1000
|
||||
) => async (...args: T): Promise<R> => {
|
||||
let lastError: Error;
|
||||
|
||||
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
||||
try {
|
||||
return await operation(...args);
|
||||
} catch (error) {
|
||||
lastError = error as Error;
|
||||
if (attempt === maxRetries) break;
|
||||
|
||||
await new Promise(resolve => setTimeout(resolve, delay * attempt));
|
||||
}
|
||||
}
|
||||
|
||||
throw lastError!;
|
||||
};
|
||||
|
||||
// Functional diagram creation with retry
|
||||
export const createDiagramWithRetry = withRetry(createDiagram);
|
||||
|
||||
// Pure function to create diagram configuration
|
||||
export const createDiagramConfig = (
|
||||
name: string,
|
||||
type: DiagramType,
|
||||
options: Partial<CreateDiagramInput> = {}
|
||||
): CreateDiagramInput => ({
|
||||
name,
|
||||
type,
|
||||
format: DiagramFormat.DRAWIO,
|
||||
...options
|
||||
});
|
||||
|
||||
// Higher-order function to transform diagram input
|
||||
export const transformDiagramInput = <T>(
|
||||
transformer: (input: CreateDiagramInput) => T
|
||||
) => (input: CreateDiagramInput): T => transformer(input);
|
||||
|
||||
// Pure function to merge diagram inputs
|
||||
export const mergeDiagramInputs = (
|
||||
base: CreateDiagramInput,
|
||||
additional: Partial<CreateDiagramInput>
|
||||
): CreateDiagramInput => ({
|
||||
...base,
|
||||
...additional
|
||||
});
|
||||
|
Reference in New Issue
Block a user