diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 2c6564b..5e1c78e 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -1,14 +1,16 @@ import React, { useState, useEffect, useRef } from 'react' -import { - Excalidraw, - convertToExcalidrawElements, - CaptureUpdateAction +import { + Excalidraw, + convertToExcalidrawElements, + CaptureUpdateAction, + ExcalidrawImperativeAPI } from '@excalidraw/excalidraw' +import type { ExcalidrawElement, NonDeleted, NonDeletedExcalidrawElement } from '@excalidraw/excalidraw/types/element/types' import { convertMermaidToExcalidraw, DEFAULT_MERMAID_CONFIG } from './utils/mermaidConverter' +import type { MermaidConfig } from '@excalidraw/mermaid-to-excalidraw' // Type definitions -type ExcalidrawAPIRefValue = any; -type ExcalidrawElement = any; +type ExcalidrawAPIRefValue = ExcalidrawImperativeAPI; interface ServerElement { id: string; @@ -47,6 +49,8 @@ interface WebSocketMessage { count?: number; timestamp?: string; source?: string; + mermaidDiagram?: string; + config?: MermaidConfig; } interface ApiResponse { @@ -58,11 +62,6 @@ interface ApiResponse { message?: string; } -interface ElementBinding { - id: string; - type: 'text' | 'arrow'; -} - type SyncStatus = 'idle' | 'syncing' | 'success' | 'error'; // Helper function to clean elements for Excalidraw @@ -165,7 +164,7 @@ function App(): JSX.Element { if (result.success && result.elements && result.elements.length > 0) { const cleanedElements = result.elements.map(cleanElementForExcalidraw) - const convertedElements = convertToExcalidrawElements(cleanedElements as any, { regenerateIds: false }) + const convertedElements = convertToExcalidrawElements(cleanedElements, { regenerateIds: false }) excalidrawAPI?.updateScene({ elements: convertedElements }) } } catch (error) { @@ -229,18 +228,18 @@ function App(): JSX.Element { if (data.elements && data.elements.length > 0) { const cleanedElements = data.elements.map(cleanElementForExcalidraw) const validatedElements = validateAndFixBindings(cleanedElements) - const convertedElements = convertToExcalidrawElements(validatedElements as any) - excalidrawAPI.updateScene({ + const convertedElements = convertToExcalidrawElements(validatedElements) + excalidrawAPI.updateScene({ elements: convertedElements, captureUpdate: CaptureUpdateAction.NEVER }) } break - + case 'element_created': if (data.element) { const cleanedNewElement = cleanElementForExcalidraw(data.element) - const newElement = convertToExcalidrawElements([cleanedNewElement] as any) + const newElement = convertToExcalidrawElements([cleanedNewElement]) const updatedElementsAfterCreate = [...currentElements, ...newElement] excalidrawAPI.updateScene({ elements: updatedElementsAfterCreate, @@ -252,31 +251,31 @@ function App(): JSX.Element { case 'element_updated': if (data.element) { const cleanedUpdatedElement = cleanElementForExcalidraw(data.element) - const convertedUpdatedElement = convertToExcalidrawElements([cleanedUpdatedElement] as any)[0] - const updatedElements = currentElements.map((el: any) => + const convertedUpdatedElement = convertToExcalidrawElements([cleanedUpdatedElement])[0] + const updatedElements = currentElements.map(el => el.id === data.element!.id ? convertedUpdatedElement : el ) - excalidrawAPI.updateScene({ + excalidrawAPI.updateScene({ elements: updatedElements, captureUpdate: CaptureUpdateAction.NEVER }) } break - + case 'element_deleted': if (data.elementId) { - const filteredElements = currentElements.filter((el: any) => el.id !== data.elementId) - excalidrawAPI.updateScene({ + const filteredElements = currentElements.filter(el => el.id !== data.elementId) + excalidrawAPI.updateScene({ elements: filteredElements, captureUpdate: CaptureUpdateAction.NEVER }) } break - + case 'elements_batch_created': if (data.elements) { const cleanedBatchElements = data.elements.map(cleanElementForExcalidraw) - const batchElements = convertToExcalidrawElements(cleanedBatchElements as any) + const batchElements = convertToExcalidrawElements(cleanedBatchElements) const updatedElementsAfterBatch = [...currentElements, ...batchElements] excalidrawAPI.updateScene({ elements: updatedElementsAfterBatch, @@ -296,28 +295,28 @@ function App(): JSX.Element { case 'mermaid_convert': console.log('Received Mermaid conversion request from MCP') - if ((data as any).mermaidDiagram) { + if (data.mermaidDiagram) { try { - const result = await convertMermaidToExcalidraw((data as any).mermaidDiagram, (data as any).config || DEFAULT_MERMAID_CONFIG) - + const result = await convertMermaidToExcalidraw(data.mermaidDiagram, data.config || DEFAULT_MERMAID_CONFIG) + if (result.error) { console.error('Mermaid conversion error:', result.error) return } - + if (result.elements && result.elements.length > 0) { - const convertedElements = convertToExcalidrawElements(result.elements as any, { regenerateIds: false }) - excalidrawAPI.updateScene({ + const convertedElements = convertToExcalidrawElements(result.elements, { regenerateIds: false }) + excalidrawAPI.updateScene({ elements: convertedElements, captureUpdate: CaptureUpdateAction.IMMEDIATELY }) - + if (result.files) { excalidrawAPI.addFiles(Object.values(result.files)) } - + console.log('Mermaid diagram converted successfully:', result.elements.length, 'elements') - + // Sync to backend automatically after creating elements await syncToBackend() } @@ -367,7 +366,7 @@ function App(): JSX.Element { console.log(`Syncing ${currentElements.length} elements to backend`) // Filter out deleted elements - const activeElements = currentElements.filter((el: any) => !el.isDeleted) + const activeElements = currentElements.filter(el => !el.isDeleted) // 3. Convert to backend format const backendElements = activeElements.map(convertToBackendFormat) diff --git a/frontend/src/utils/mermaidConverter.ts b/frontend/src/utils/mermaidConverter.ts index d6103b7..a52ea7a 100644 --- a/frontend/src/utils/mermaidConverter.ts +++ b/frontend/src/utils/mermaidConverter.ts @@ -1,8 +1,10 @@ import { parseMermaidToExcalidraw, MermaidConfig } from '@excalidraw/mermaid-to-excalidraw'; +import type { ExcalidrawElement } from '@excalidraw/excalidraw/types/element/types'; +import type { BinaryFiles } from '@excalidraw/excalidraw/types/types'; export interface MermaidConversionResult { - elements: any[]; - files?: any; + elements: readonly ExcalidrawElement[]; + files?: BinaryFiles; error?: string; } diff --git a/package-lock.json b/package-lock.json index 84709ca..34436ef 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7321,9 +7321,9 @@ } }, "node_modules/vite": { - "version": "6.3.5", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.3.5.tgz", - "integrity": "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==", + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.1.tgz", + "integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==", "dev": true, "license": "MIT", "dependencies": {