import { createGraphStore, createRawGraphFromRecords, parseRawGraphJson, serializeRawGraph, snapshotToRawGraph } from '@graphora/core' import { createGraphEngine, type GraphEngine } from '@graphora/engine' import { createCircularLayout } from '@graphora/layouts' import { CanvasGraphRenderer, createViewport } from '@graphora/renderer' import './style.css' interface ServiceRecord { readonly key: string readonly name: string readonly team: string } interface DependencyRecord { readonly from: string readonly to: string readonly protocol: string } const services: readonly ServiceRecord[] = [ { key: 'gateway', name: 'Gateway', team: 'edge' }, { key: 'catalog', name: 'Catalog', team: 'commerce' }, { key: 'database', name: 'Database', team: 'platform' } ] const dependencies: readonly DependencyRecord[] = [ { from: 'gateway', to: 'catalog', protocol: 'HTTPS' }, { from: 'catalog', to: 'database', protocol: 'SQL' } ] const mapped = createRawGraphFromRecords({ nodes: services, edges: dependencies, node: { id: (service) => service.key, label: (service) => service.name, data: (service) => service, attributes: (service) => ({ team: service.team }) }, edge: { source: (dependency) => dependency.from, target: (dependency) => dependency.to, label: (dependency) => dependency.protocol, data: (dependency) => dependency } }) // Normalization assigns stable IDs to the two id-less business edges before save. const savedJson = serializeRawGraph( snapshotToRawGraph(createGraphStore(mapped).snapshot()), { space: 2 } ) const container = requiredElement('#graph') const editor = requiredElement('#saved-json') const reload = requiredElement('#reload') const status = requiredElement('#status') let engine: GraphEngine | undefined let reloadCount = 0 editor.value = savedJson reload.addEventListener('click', () => void renderSavedJson()) window.addEventListener('pagehide', () => engine?.destroy(), { once: true }) void renderSavedJson() async function renderSavedJson(): Promise { reload.disabled = true status.textContent = 'Reloading saved JSON…' try { const graph = parseRawGraphJson( editor.value ) engine?.destroy() engine = createGraphEngine({ graph, renderer: new CanvasGraphRenderer(), layout: createCircularLayout({ radius: 120 }), viewport: createViewport({ width: container.clientWidth, height: container.clientHeight }), theme: { backgroundColor: '#f8fafc', node: { radius: 24 }, label: { fontSize: 13 } } }) engine.mount(container) await engine.runLayout({ fitToView: { padding: 72 } }) reloadCount += 1 container.dataset.ready = 'true' container.dataset.reloadCount = String(reloadCount) status.textContent = `Reloaded ${graph.nodes.length} nodes and ${graph.edges?.length ?? 0} edges from JSON.` } catch (error) { status.textContent = error instanceof Error ? error.message : String(error) } finally { reload.disabled = false } } function requiredElement( selector: string ): ElementType { const element = document.querySelector(selector) if (element === null) throw new Error(`Missing element ${selector}.`) return element }