import mermaid from 'https://unpkg.com/mermaid@9.2.2/dist/mermaid.esm.min.mjs'; import { debounce } from '../util.js'; export class Vertex { constructor(data) { this.data = data; this.edges = { from: [], to: [], }; } getEdges(label, away) { return this.edges[away ? 'from' : 'to'].filter( (edge) => edge.label === label, ); } } export class Edge { constructor(label, from, to, data) { this.from = from; this.to = to; this.label = label; this.data = data; } } export class CategorizedEdges {} export class Graph { constructor() { this.vertices = new Map(); this.edgeLabels = new Map(); this.nextVertexId = 0; } addVertex(id, data) { // Support simple case of auto-incremented numeric ids if (typeof id === 'object') { data = id; id = this.nextVertexId++; } if (this.vertices.has(id)) { throw new Error(`Vertex already exists with id: ${id}`); } const vertex = new Vertex(data); console.log('addVertex', vertex); this.vertices.set(id, vertex); return this; } getVertex(id) { return this.vertices.get(id); } getVertexData(id) { return this.getVertex(id)?.data; } getVertices() { return Array.from(this.vertices.values()).map(({ data }) => data); } getEdge(label, from, to) { const edges = this.edgeLabels.get(label); return edges?.get(JSON.stringify({ from, to })); } setEdge(label, from, to, edge) { let edges = this.edgeLabels.get(label); if (!edges) { edges = new Map(); this.edgeLabels.set(label, edges); } edges.set(JSON.stringify({ from, to }), edge); } addEdge(label, from, to, data) { console.log('addEdge', { from, to }); if (this.getEdge(label, from, to)) { throw new Error(`Edge ${label} from ${from} to ${to} already exists`); } const edge = new Edge(label, from, to, data); this.setEdge(label, from, to, edge); this.getVertex(from).edges.from.push(edge); this.getVertex(to).edges.to.push(edge); return this; } getEdges(label, from, to) { const edgeLabels = label ? [label] : Array.from(this.edgeLabels.keys()); return edgeLabels.flatMap((edgeLabel) => { const edges = this.edgeLabels.get(edgeLabel); return Array.from(edges?.values() || []).filter((edge) => { const matchFrom = from === null || from === undefined || from === edge.from; const matchTo = to === null || to === undefined || to === edge.to; return matchFrom && matchTo; }); }); } countVertices() { return this.vertices.size; } async renderGraph() { const render = async () => { const dateStart = new Date(); const graph = await mermaid.mermaidAPI.render( this.seqDiagramElement.getId(), this.logBox.getInnerText(), ); this.seqDiagramBox.setInnerHTML(graph); if (!this.dateLastRender) { this.dateLastRender = new Date(); } this.dateLastRender = dateStart; }; debounce(render, 100); } }