feat: consolidate database management work
Add catalog-owned logical relationships and runtime snapshots, extend the database-management UI and validation coverage, and document the updated operational workflow. Keep active sensitive-generation status in a tooltip and indicator, and update the layout E2E to follow the history action in its new database-scoped location.
This commit is contained in:
@@ -0,0 +1,299 @@
|
||||
# Visualizzatore ERD nel browser: proposta solo open source
|
||||
|
||||
Data dell'audit: 31 agosto 2026.
|
||||
|
||||
## Decisione
|
||||
|
||||
Per ThothII sceglierei **AntV X6 + ELK.js** come fondazione del visualizzatore ERD.
|
||||
|
||||
- **AntV X6** è MIT, non ha una distinta edizione Professional e include nel progetto OSS
|
||||
le funzioni che servono davvero a un diagramma complesso: nodi e porte personalizzabili,
|
||||
pan/zoom, selezione, minimappa, history, clipboard, tastiera, routing, virtual rendering ed
|
||||
export SVG/PNG/JPEG.
|
||||
- **ELK.js** è il motore di layout automatico, EPL-2.0 e senza tier commerciale. Il layout
|
||||
layered gestisce porte, vincoli sull'ordine delle porte, archi multipli, self-loop e routing
|
||||
ortogonale: proprietà importanti per foreign key composite e schemi affollati.
|
||||
- La combinazione non dipende da esempi o componenti a pagamento. Il lavoro applicativo che
|
||||
resta da fare — semantica ER, livelli di dettaglio, filtri e adattatore X6/ELK — appartiene
|
||||
davvero al dominio di ThothII e non è una funzione nascosta dietro un piano Pro.
|
||||
|
||||
La seconda scelta è **React Flow + ELK.js**. È probabilmente l'integrazione più naturale con
|
||||
l'attuale frontend React e ha una migliore storia documentata per accessibilità. Il runtime è
|
||||
MIT e non viene tecnicamente depotenziato, ma diversi pattern avanzati già implementati
|
||||
(auto-layout, edge routing, undo/redo, copy/paste, expand/collapse) sono pubblicati come esempi
|
||||
con licenza React Flow Pro. Non è quindi la scelta più lineare se il criterio prioritario è
|
||||
evitare anche una dipendenza progettuale da materiale Professional.
|
||||
|
||||
## Cosa significa «open source senza limitazioni Professional»
|
||||
|
||||
L'audit distingue tre casi:
|
||||
|
||||
1. **OSS completo**: licenza OSI e nessun tier commerciale che trattenga funzioni essenziali.
|
||||
2. **OSS con caveat**: il motore è aperto, ma esistono esempi premium, API instabili o limiti
|
||||
architetturali rilevanti. Può essere usato, purché il limite sia accettato esplicitamente.
|
||||
3. **Escluso**: licenza proprietaria oppure core aperto con funzioni necessarie al viewer
|
||||
complesso riservate alla versione commerciale.
|
||||
|
||||
La valutazione riguarda sia la licenza sia ciò che si può effettivamente costruire senza
|
||||
acquistare un prodotto complementare. Le note sulle licenze sono tecniche, non consulenza legale.
|
||||
|
||||
## Matrice di selezione
|
||||
|
||||
| Soluzione | Licenza OSS | Tier Pro rilevante | Adeguatezza a ERD complessi | Verdetto |
|
||||
|---|---|---|---|---|
|
||||
| **AntV X6 + ELK.js** | MIT + EPL-2.0 | Nessuno individuato | Porte per colonna, minimappa, routing, export, virtual rendering e layout avanzato | **Consigliata** |
|
||||
| **React Flow + ELK.js** | MIT + EPL-2.0 | Esempi/pattern avanzati Pro, non runtime separato | Ottima UX React, nodi HTML, minimappa e accessibilità; export SVG non nativo | **Valida con caveat** |
|
||||
| **maxGraph** | Apache-2.0 | Nessuno | Molto completo, SVG, porte, folding e layout; API imperativa e integrazione React costosa | **Valida con caveat** |
|
||||
| **Cytoscape.js + ELK** | MIT | Nessuno | Molto scalabile come grafo, ma meno adatto a tabelle ricche e porte per campo | **Alternativa di nicchia** |
|
||||
| **Liam ERD/CLI** | Apache-2.0 | Nessuno | Viewer ERD già rifinito e self-hostable; il package embeddable è interno e instabile | **Reference o app separata** |
|
||||
| **Graphviz + Viz.js** | EPL-2.0 + MIT | Nessuno | Layout ed SVG eccellenti; non offre da solo un explorer applicativo | **Renderer di export** |
|
||||
| **Mermaid.js + Panzoom** | MIT + MIT/ISC | Mermaid Chart è separato | Facile, ma insufficiente per interazioni e modelli ER ricchi | **Solo preview semplice** |
|
||||
| **Sprotty/GLSP** | EPL-2.0 | Nessuno | Potente e completo, ma è un framework di modeling più pesante del necessario | **Non prioritario** |
|
||||
| **JointJS** | Core MPL-2.0 | Molte funzioni utili sono in JointJS+ | Lo split commerciale intercetta proprio le necessità del viewer | **Esclusa** |
|
||||
| **GoJS** | Proprietaria | Licenza di deployment | Completa tecnicamente, ma non open source | **Esclusa** |
|
||||
| **yFiles** | Proprietaria | Licenza commerciale | Completa tecnicamente, ma non open source | **Esclusa** |
|
||||
|
||||
## 1. Scelta principale: AntV X6 + ELK.js
|
||||
|
||||
### Funzioni disponibili nell'open source
|
||||
|
||||
X6 offre un canvas diagrammatico basato su SVG con supporto anche a nodi HTML/React. Il core
|
||||
espone porte, archi personalizzabili, self-loop e multiedge. I plugin distribuiti dal progetto
|
||||
comprendono Scroller, MiniMap, Selection, History, Clipboard, Keyboard, DnD, Stencil, Snapline,
|
||||
Transform ed Export. La documentazione copre inoltre router `orth`, `manhattan` ed `er`, zoom e
|
||||
panning. Non è emersa un'edizione X6 Pro che renda a pagamento queste capacità.
|
||||
|
||||
Fonti primarie: [repository e licenza X6](https://github.com/antvis/X6),
|
||||
[porte](https://x6.antv.antgroup.com/en/tutorial/basic/port),
|
||||
[router](https://x6.antv.antgroup.com/en/api/registry/router),
|
||||
[minimappa](https://x6.antv.antgroup.com/en/tutorial/plugins/minimap),
|
||||
[scroller](https://x6.antv.antgroup.com/en/tutorial/plugins/scroller) ed
|
||||
[export](https://x6.antv.antgroup.com/en/tutorial/plugins/export).
|
||||
|
||||
ELK non è un renderer: calcola la geometria del grafo. L'algoritmo layered supporta porte e
|
||||
relativi vincoli, archi ortogonali, self-loop e archi multipli. Va eseguito in un Web Worker per
|
||||
non bloccare l'interfaccia sui modelli grandi. L'adattatore dovrà passare a ELK le porte delle
|
||||
colonne e usare anche le `edge sections` e i bend point restituiti, non soltanto le coordinate
|
||||
dei nodi.
|
||||
|
||||
Fonti primarie: [ELK.js e licenza](https://github.com/kieler/elkjs) e
|
||||
[ELK layered](https://eclipse.dev/elk/reference/algorithms/org-eclipse-elk-layered.html).
|
||||
|
||||
### Limiti reali
|
||||
|
||||
- X6 è più imperativo di React Flow: conviene incapsularlo in un singolo componente React con
|
||||
un adapter stabile, evitando di spargere istanze e listener nel resto dell'applicazione.
|
||||
- L'accessibilità per screen reader non è documentata al livello di React Flow; tab order,
|
||||
focus, descrizioni ARIA e navigazione da tastiera richiedono test e lavoro applicativo.
|
||||
- Un nodo React/HTML può introdurre `foreignObject` nell'SVG. Per un export portabile e
|
||||
stampabile è meglio produrre un SVG separato dallo stesso modello e dalla geometria ELK.
|
||||
|
||||
Questi sono costi tecnici, non limitazioni commerciali.
|
||||
|
||||
## 2. Seconda scelta: React Flow + ELK.js
|
||||
|
||||
`@xyflow/react` è MIT. Custom nodes React, handle multipli, pan/zoom, fit view, Controls,
|
||||
MiniMap, selezione e funzioni di accessibilità sono nel runtime OSS. React Flow Pro vende
|
||||
supporto, template ed esempi con relativo codice sorgente; non esiste una libreria runtime Pro
|
||||
che sblocchi il canvas.
|
||||
|
||||
Il caveat è comunque concreto: auto-layout, edge routing, undo/redo, copy/paste ed
|
||||
expand/collapse compaiono nel catalogo degli esempi Pro e quel codice usa la **xyflow Pro
|
||||
License**, non la MIT del core. Le stesse funzioni possono essere sviluppate sopra le API OSS,
|
||||
ma non si può considerare tutto il materiale ufficiale liberamente riutilizzabile.
|
||||
|
||||
Fonti primarie: [package React Flow](https://github.com/xyflow/xyflow/blob/main/packages/react/package.json),
|
||||
[funzioni del core](https://reactflow.dev/index),
|
||||
[catalogo degli esempi Pro](https://reactflow.dev/examples/pro-examples),
|
||||
[auto-layout](https://reactflow.dev/examples/layout/auto-layout) e
|
||||
[termini Pro](https://reactflow.dev/pro).
|
||||
|
||||
È una buona scelta se si privilegiano velocità d'integrazione React, componenti HTML e
|
||||
accessibilità. Non è la prima scelta di questo audit perché l'utente ha chiesto espressamente
|
||||
di minimizzare la distanza fra ciò che è open source e l'offerta Professional.
|
||||
|
||||
Altro limite: React Flow combina nodi DOM e archi SVG. L'esempio ufficiale di download usa
|
||||
`html-to-image`, quindi il diagramma interattivo non si traduce automaticamente in un SVG puro.
|
||||
|
||||
## 3. Altre soluzioni interamente open source
|
||||
|
||||
### maxGraph
|
||||
|
||||
maxGraph, successore TypeScript di mxGraph, è Apache-2.0 e non ha un piano Pro. Offre rendering
|
||||
SVG, connection constraints/porte, loop e multigraph, layout, routing, outline, grouping e
|
||||
folding. Può quindi sostenere un editor ERD ricco.
|
||||
|
||||
Lo terrei come terza scelta: l'API è imperativa, non esiste un wrapper React ufficiale, la
|
||||
virtualizzazione non è documentata e gran parte dell'accessibilità va costruita. Il progetto è
|
||||
ancora pre-1.0. Il costo di integrazione e manutenzione sarebbe maggiore di X6.
|
||||
|
||||
Fonti: [licenza e repository](https://github.com/maxGraph/maxGraph),
|
||||
[guida Vite/TypeScript](https://maxgraph.github.io/maxGraph/docs/getting-started/) e
|
||||
[gestione della complessità](https://maxgraph.github.io/maxGraph/docs/usage/group-and-complexity-management/).
|
||||
|
||||
### Cytoscape.js
|
||||
|
||||
Cytoscape.js e molte estensioni sono MIT, senza tier professionale. È ottimo per grandi grafi,
|
||||
filtri, selezioni e algoritmi di rete. Il rendering Canvas è però meno naturale per schede-tabella
|
||||
ricche, testo selezionabile e handle collegati alle singole colonne. Inoltre l'adapter
|
||||
`cytoscape.js-elk` non passa le porte a ELK né usa le route degli archi: non risolve da solo il
|
||||
problema delle foreign key per colonna.
|
||||
|
||||
È appropriato per una vista di dipendenze ad alto livello, non come renderer ERD principale.
|
||||
L'estensione `cytoscape-svg` è GPL-3.0; in un prodotto che non vuole assorbire quel vincolo è
|
||||
preferibile una pipeline Graphviz/Viz.js o un generatore SVG proprio.
|
||||
|
||||
Fonti: [Cytoscape.js](https://github.com/cytoscape/cytoscape.js),
|
||||
[adapter ELK](https://github.com/cytoscape/cytoscape.js-elk) e
|
||||
[cytoscape-svg](https://github.com/kinimesi/cytoscape-svg).
|
||||
|
||||
### Liam ERD
|
||||
|
||||
Liam ERD è Apache-2.0, self-hostable e già orientato al problema: pan/zoom, ricerca, filtro,
|
||||
command palette e modalità `TABLE_NAME`, `KEY_ONLY`, `ALL_FIELDS`. La documentazione dichiara
|
||||
supporto a schemi con oltre cento tabelle. La CLI può generare un'app Vite statica.
|
||||
|
||||
Non userei però direttamente `@liam-hq/erd-core` dentro ThothII: il maintainer lo definisce una
|
||||
dipendenza interna, ne sconsiglia l'uso diretto e avverte che l'API può cambiare; il package è
|
||||
ancora 0.x. Inoltre occorre verificare la compatibilità con la versione React di ThothII e la
|
||||
fedeltà delle foreign key composite. Liam è quindi un ottimo benchmark UX, una CLI per una vista
|
||||
separata o una base da forkare consapevolmente, non l'interfaccia stabile su cui fondare il
|
||||
prodotto.
|
||||
|
||||
Fonti: [repository Liam](https://github.com/liam-hq/liam),
|
||||
[README di erd-core](https://github.com/liam-hq/liam/blob/main/frontend/packages/erd-core/README.md),
|
||||
[funzioni UI](https://liambx.com/docs/ui-features) e [CLI](https://liambx.com/docs/cli).
|
||||
|
||||
### Sprotty/GLSP
|
||||
|
||||
Sprotty e Eclipse GLSP sono EPL-2.0 e offrono un'infrastruttura seria per diagrammi SVG,
|
||||
layout e protocolli client/server. Sono pensati per strumenti di modeling estensibili, con
|
||||
dependency injection e un'architettura più ampia di un viewer. Restano una soluzione OSS valida,
|
||||
ma sproporzionata per questa esigenza salvo che ThothII evolva in un vero editor di modelli.
|
||||
|
||||
Fonti: [Sprotty](https://github.com/eclipse-sprotty/sprotty) ed
|
||||
[Eclipse GLSP](https://eclipse.dev/glsp/documentation/overview/).
|
||||
|
||||
## 4. Renderer complementari, non fondazioni del viewer
|
||||
|
||||
### Graphviz e Viz.js
|
||||
|
||||
Graphviz è EPL-2.0; `@viz-js/viz`, il port WebAssembly utilizzabile nel browser, è MIT. Graphviz
|
||||
produce SVG di alta qualità, supporta label HTML-like e porte e rimane molto utile per export,
|
||||
stampa o una vista read-only. Non fornisce però da solo ricerca, filtri, livelli di dettaglio,
|
||||
editing o gestione dello stato applicativo.
|
||||
|
||||
Lo userei come renderer di export alternativo, non come UI primaria. Se il layout a schermo
|
||||
deve corrispondere esattamente all'export, è preferibile generare l'SVG direttamente dalla
|
||||
geometria ELK invece di mantenere due motori di layout indipendenti.
|
||||
|
||||
Fonti: [licenza Graphviz](https://graphviz.org/license/),
|
||||
[formati SVG](https://graphviz.org/docs/outputs/svg/) e
|
||||
[Viz.js](https://github.com/mdaines/viz-js).
|
||||
|
||||
### Mermaid.js e librerie di pan/zoom
|
||||
|
||||
Mermaid.js è MIT e non ha feature del renderer open source bloccate. **Mermaid Chart** è invece
|
||||
un servizio commerciale distinto e il suo piano gratuito ha limiti: non va confuso con la
|
||||
libreria self-hosted.
|
||||
|
||||
Si può aggiungere navigazione a un SVG Mermaid con `@panzoom/panzoom` (MIT) o `d3-zoom` (ISC),
|
||||
entrambi senza tier Pro. Questo migliora l'esperienza corrente, ma non supera i limiti strutturali
|
||||
del diagramma ER Mermaid: interazioni a livello di tabella, controllo ridotto delle porte e del
|
||||
routing, assenza di semantic zoom e difficoltà crescente su schemi molto grandi.
|
||||
|
||||
Mermaid resta adatto a preview e documentazione, non al viewer finale.
|
||||
|
||||
Fonti: [Mermaid.js](https://github.com/mermaid-js/mermaid),
|
||||
[distinzione da Mermaid Chart](https://mermaid.ai/open-source/ecosystem/mermaid-chart.html),
|
||||
[Panzoom](https://github.com/timmywil/panzoom) e [d3-zoom](https://github.com/d3/d3-zoom).
|
||||
|
||||
### Python
|
||||
|
||||
SchemaSpy ed ERAlchemy sono open source e possono generare documentazione o grafi attraverso
|
||||
Graphviz, ma non sostituiscono il componente interattivo React. Python è utile lato backend per
|
||||
normalizzare metadati o produrre artefatti batch; pan/zoom, selezione, ricerca e dettagli restano
|
||||
responsabilità del browser. Aggiungere un servizio Python solo per disegnare l'ERD non porta un
|
||||
vantaggio architetturale a ThothII.
|
||||
|
||||
## 5. Soluzioni escluse
|
||||
|
||||
### JointJS / JointJS+
|
||||
|
||||
Il core JointJS è MPL-2.0, ma JointJS+ è commerciale e comprende proprio molte funzioni che
|
||||
servirebbero qui: PaperScroller, Navigator/minimappa, selection, clipboard, keyboard, undo/redo,
|
||||
toolbar, export e layout aggiuntivi. Sarebbe tecnicamente possibile ricostruirle sul core, ma la
|
||||
distanza fra OSS e Professional è troppo grande rispetto al criterio richiesto.
|
||||
|
||||
Fonti: [licenza](https://www.jointjs.com/license),
|
||||
[confronto delle funzioni](https://www.jointjs.com/features) e
|
||||
[prezzi](https://www.jointjs.com/pricing).
|
||||
|
||||
### GoJS e yFiles
|
||||
|
||||
Sono prodotti completi e maturi, ma non open source. GoJS richiede una licenza per il deployment
|
||||
e mostra una filigrana senza chiave; yFiles usa licenze proprietarie, con evaluation temporanea e
|
||||
licenza necessaria per la distribuzione. Non soddisfano il requisito, quindi non entrano nella
|
||||
shortlist.
|
||||
|
||||
Fonti: [licensing GoJS](https://gojs.net/latest/intro/deployment.html) e
|
||||
[licensing yFiles](https://docs.yworks.com/yfiles-html/dguide/deployment/licensing.html).
|
||||
|
||||
## 6. Architettura proposta per ThothII
|
||||
|
||||
Il frontend usa React 18 e oggi `SchemaLinkingViewer.tsx` genera Mermaid con un limite di 45
|
||||
elementi. La resa corrente perde informazione: accorpa più foreign key fra la stessa coppia di
|
||||
tabelle, omette i self-reference e usa cardinalità generiche. Il catalogo espone già tabelle,
|
||||
colonne, chiavi primarie e relazioni con coppie ordinate di colonne, quindi può alimentare un
|
||||
modello più fedele.
|
||||
|
||||
Propongo questa separazione:
|
||||
|
||||
1. **Modello renderer-neutral**: `TableNode`, `ColumnPort` e `RelationEdge` con nome del
|
||||
constraint e lista ordinata delle coppie sorgente/destinazione. Non appiattire le FK composite.
|
||||
2. **Snapshot API**: un endpoint coerente, per esempio
|
||||
`GET /catalog/databases/:databaseId/schema-diagram`, che restituisca tabelle, colonne,
|
||||
relazioni e versione del catalogo in una sola lettura, evitando la richiesta colonne N+1.
|
||||
3. **Layout worker**: ELK.js in Web Worker, con porte per colonna, port constraints, route degli
|
||||
archi e cache per versione del database e filtri correnti.
|
||||
4. **Renderer interattivo**: X6 incapsulato in `DatabaseRelationshipDiagram.tsx`, affiancato
|
||||
alla vista tabellare con un toggle List/Diagram e con riuso del drawer dei dettagli.
|
||||
5. **Export**: generatore SVG separato basato sullo stesso modello e sulla geometria ELK;
|
||||
Graphviz/Viz.js può essere un fallback per layout alternativi o documentazione batch.
|
||||
|
||||
Il catalogo non registra oggi tutti i vincoli UNIQUE né il tipo MATCH delle FK. Senza questi
|
||||
dati non sempre è possibile distinguere correttamente 1:1 da 1:N. Il renderer non deve inventare
|
||||
la cardinalità: deve mostrare una notazione neutra finché il metadato necessario non viene
|
||||
raccolto.
|
||||
|
||||
### Funzioni necessarie per schemi complessi
|
||||
|
||||
- semantic zoom: solo nomi tabella, poi PK/FK, infine tutti i campi;
|
||||
- ricerca e filtri per schema, tabella, colonna e tipo di relazione;
|
||||
- modalità focus con vicinato a uno o due hop;
|
||||
- evidenziazione della relazione e delle due colonne al passaggio/selezione;
|
||||
- minimappa, fit selection, navigazione da tastiera e pannello dettagli;
|
||||
- distinzione visiva di PK, FK, nullable, composite key, self-loop e relazioni parallele;
|
||||
- layout automatico ricalcolabile, ma posizioni manuali persistibili;
|
||||
- rendering progressivo o virtuale e fallback tabellare sempre disponibile;
|
||||
- export dell'intero schema e dell'area filtrata in SVG/PNG.
|
||||
|
||||
## 7. Proof of concept consigliato
|
||||
|
||||
Un POC breve dovrebbe usare **X6 + ELK.js** su tre dataset sintetici: circa 30, 150 e 500
|
||||
tabelle, includendo FK composite, più FK tra la stessa coppia, self-loop, tabelle isolate e hub
|
||||
ad alto grado.
|
||||
|
||||
I criteri di accettazione dovrebbero misurare:
|
||||
|
||||
- tempo di layout nel worker e tempo al primo frame interattivo;
|
||||
- fluidità di pan/zoom e uso memoria sul caso da 500 tabelle;
|
||||
- correttezza di porte, archi paralleli, self-loop e FK composite;
|
||||
- leggibilità nelle tre soglie di semantic zoom;
|
||||
- navigazione completa da tastiera e comportamento con screen reader;
|
||||
- qualità e portabilità dell'SVG esportato;
|
||||
- assenza di codice, esempi o componenti soggetti a licenza commerciale.
|
||||
|
||||
Se X6 non raggiunge il livello di accessibilità richiesto senza un costo eccessivo, il confronto
|
||||
finale va fatto con React Flow + lo stesso adapter ELK e lo stesso modello dati. In questo modo
|
||||
si cambia renderer senza rifare API, semantica delle relazioni o pipeline di export.
|
||||
Reference in New Issue
Block a user