Model graph: the whole model as one graph with queries; 0.9.0
- Model | Graph switch on main.archify (Diagram | Graph on diagram pages, narrowed to that diagram) - union graph of every element and connection, registry and inline, built from the model index - query box: text, type:, diagram:, decision:, uses:, near:, from: to:, unused, shared, -shared - side panel per element and connection with diagrams, registry line and decisions one click away - legend chips, Fit, Layout, Labels, Export PNG; Cytoscape.js bundled as dist/graph.js - command Archify | Open Model Graph; integration check; unit tests for graph and queries
This commit is contained in:
1 parent
265f8c57f6
commit
c8645b228b
20 files changed
+1551
-30
No files matched your search
+49
-2
@@ -309,6 +309,23 @@ export function groupOf(relativePath: string): string {
|
||||
return parts.join('/');
|
||||
}
|
||||
|
||||
/** A node as a diagram declares it: a `ref` to the registry, or an inline element. */
|
||||
export interface DiagramNode {
|
||||
id: string;
|
||||
ref?: string;
|
||||
type?: string;
|
||||
label?: string;
|
||||
sublabel?: string;
|
||||
brand?: string;
|
||||
}
|
||||
|
||||
/** A connection, edge, flow, transition or message between two nodes of a diagram. */
|
||||
export interface DiagramEdge {
|
||||
from: string;
|
||||
to: string;
|
||||
label?: string;
|
||||
}
|
||||
|
||||
export interface DiagramSummary {
|
||||
relativePath: string;
|
||||
group: string;
|
||||
@@ -317,6 +334,10 @@ export interface DiagramSummary {
|
||||
used: string[];
|
||||
/** Decisions the diagram points at. */
|
||||
decisions: DecisionRef[];
|
||||
/** Every node the diagram draws, shared or inline, in file order. */
|
||||
nodes: DiagramNode[];
|
||||
/** Every edge between two of those nodes. */
|
||||
edges: DiagramEdge[];
|
||||
parseError?: string;
|
||||
}
|
||||
|
||||
@@ -326,14 +347,40 @@ export function summarizeDiagram(text: string, relativePath: string): DiagramSum
|
||||
try {
|
||||
doc = parseYaml(text, { prettyErrors: false, uniqueKeys: false });
|
||||
} catch (error) {
|
||||
return { relativePath, group: groupOf(relativePath), used: [], decisions: [], parseError: error instanceof Error ? error.message.split('\n')[0] : String(error) };
|
||||
return { relativePath, group: groupOf(relativePath), used: [], decisions: [], nodes: [], edges: [], parseError: error instanceof Error ? error.message.split('\n')[0] : String(error) };
|
||||
}
|
||||
const obj = isObj(doc) ? doc : {};
|
||||
const meta = isObj(obj.meta) ? obj.meta : {};
|
||||
const components = Array.isArray(obj.components) ? obj.components : [];
|
||||
const used = [...new Set(components.map((c) => (isObj(c) ? str(c.ref) : undefined)).filter((r): r is string => !!r))];
|
||||
const decisions = takeDecisionRefs({ ...obj }, { registry: { elements: new Map(), files: [], problems: [] }, fileName: relativePath }, []);
|
||||
return { relativePath, group: groupOf(relativePath), kind: str(obj.diagram_type), title: str(meta.title), used, decisions };
|
||||
const nodes: DiagramNode[] = [];
|
||||
const seen = new Set<string>();
|
||||
for (const key of NODE_COLLECTIONS) {
|
||||
const items = obj[key];
|
||||
if (!Array.isArray(items)) continue;
|
||||
for (const item of items) {
|
||||
if (!isObj(item)) continue;
|
||||
const ref = str(item.ref);
|
||||
const id = str(item.id) ?? ref;
|
||||
if (!id || seen.has(id)) continue;
|
||||
seen.add(id);
|
||||
nodes.push({ id, ref, type: str(item.type), label: str(item.label), sublabel: str(item.sublabel), brand: str(item.brand) });
|
||||
}
|
||||
}
|
||||
const edges: DiagramEdge[] = [];
|
||||
for (const key of EDGE_COLLECTIONS) {
|
||||
const items = obj[key];
|
||||
if (!Array.isArray(items)) continue;
|
||||
for (const item of items) {
|
||||
if (!isObj(item)) continue;
|
||||
const from = str(item.from);
|
||||
const to = str(item.to);
|
||||
if (!from || !to || !seen.has(from) || !seen.has(to)) continue;
|
||||
edges.push({ from, to, label: str(item.label) });
|
||||
}
|
||||
}
|
||||
return { relativePath, group: groupOf(relativePath), kind: str(obj.diagram_type), title: str(meta.title), used, decisions, nodes, edges };
|
||||
}
|
||||
|
||||
/** Groups in display order: the root group first, then folders in path order. */
|
||||
|
||||
Reference in new issue
Block a user