0.11.0: arc42 and ArchiMate examples; ref in every diagram kind
Six example models next to the three C4 ones: arc42 (Cinema Tickets, IoT Telemetry, Team Wiki) by section, ArchiMate (Insurance Claims, HR Onboarding, Logistics Tracking) by layer, each validated with 0 errors and 0 warnings. resolveRefs and the editor schemas now take ref: in workflow and dataflow nodes, sequence participants and lifecycle states, as the skill already did. Example tests check each framework's folders.
This commit is contained in:
1 parent
f4df6a0834
commit
0745de822a
85 files changed
+2945
-67
No files matched your search
+23
-11
@@ -163,13 +163,21 @@ export interface DecisionRef {
|
||||
|
||||
/** Collections whose items may carry `decisions` (and `diagram` links), per diagram kind. */
|
||||
const NODE_COLLECTIONS = ['components', 'nodes', 'participants', 'states'] as const;
|
||||
/** The list that holds a diagram kind's nodes, where `ref` is resolved. */
|
||||
const NODE_COLLECTION_OF: Record<string, (typeof NODE_COLLECTIONS)[number]> = {
|
||||
architecture: 'components',
|
||||
workflow: 'nodes',
|
||||
dataflow: 'nodes',
|
||||
sequence: 'participants',
|
||||
lifecycle: 'states',
|
||||
};
|
||||
const EDGE_COLLECTIONS = ['connections', 'edges', 'flows', 'transitions', 'messages'] as const;
|
||||
|
||||
export interface ResolvedDiagram {
|
||||
/** The diagram as Archify expects it: refs expanded, model block and links removed. */
|
||||
diagram: Obj;
|
||||
problems: ModelProblem[];
|
||||
/** Component index → the registry element it came from. */
|
||||
/** Node index (in the kind's node list) → the registry element it came from. */
|
||||
refs: Map<number, RegistryElement>;
|
||||
/** Node id → diagram path (relative to the model root) it links to. */
|
||||
links: Map<string, string>;
|
||||
@@ -253,10 +261,14 @@ export function resolveRefs(doc: unknown, options: ResolveOptions): ResolvedDiag
|
||||
delete diagram.model;
|
||||
const decisionRefs = takeDecisionRefs(diagram, options, problems);
|
||||
const { registry } = options;
|
||||
const components = Array.isArray(diagram.components) ? diagram.components : undefined;
|
||||
if (!components) return { diagram, problems, refs, links, used, descriptions, decisionRefs };
|
||||
// Each kind keeps its nodes in its own list; sequence participants have no tag.
|
||||
const kind = str(diagram.diagram_type);
|
||||
const collection = (kind && NODE_COLLECTION_OF[kind]) ?? NODE_COLLECTIONS.find((key) => Array.isArray(diagram[key]));
|
||||
const nodes = collection && Array.isArray(diagram[collection]) ? (diagram[collection] as unknown[]) : undefined;
|
||||
if (!collection || !nodes) return { diagram, problems, refs, links, used, descriptions, decisionRefs };
|
||||
const copied: readonly string[] = kind === 'sequence' ? COPIED_FIELDS.filter((key) => key !== 'tag') : COPIED_FIELDS;
|
||||
|
||||
diagram.components = components.map((raw, index) => {
|
||||
diagram[collection] = nodes.map((raw, index) => {
|
||||
if (!isObj(raw)) return raw;
|
||||
const ref = str(raw.ref);
|
||||
const linkFromComponent = str(raw.diagram);
|
||||
@@ -275,7 +287,7 @@ export function resolveRefs(doc: unknown, options: ResolveOptions): ResolvedDiag
|
||||
? `Unknown element "${ref}": no registry of this model defines it.`
|
||||
: `"${ref}" cannot be resolved: ${options.fileName.split(/[\\/]/).pop()} is not inside a model (no ${MAIN_FILE} above it).`,
|
||||
severity: 'error',
|
||||
pointer: `/components/${index}/ref`,
|
||||
pointer: `/${collection}/${index}/ref`,
|
||||
});
|
||||
return { type: 'external', label: ref, ...own, id };
|
||||
}
|
||||
@@ -283,19 +295,19 @@ export function resolveRefs(doc: unknown, options: ResolveOptions): ResolvedDiag
|
||||
refs.set(index, element);
|
||||
if (element.description) descriptions.set(id, element.description.trim());
|
||||
for (const key of Object.keys(own)) {
|
||||
if ((COPIED_FIELDS as readonly string[]).includes(key) && !(OVERRIDABLE_FIELDS as readonly string[]).includes(key)) {
|
||||
if (copied.includes(key) && !(OVERRIDABLE_FIELDS as readonly string[]).includes(key)) {
|
||||
problems.push({
|
||||
message: `"${key}" comes from the registry element "${ref}" and cannot be changed in a diagram.`,
|
||||
severity: 'error',
|
||||
pointer: `/components/${index}/${key}`,
|
||||
pointer: `/${collection}/${index}/${key}`,
|
||||
});
|
||||
}
|
||||
}
|
||||
const merged: Obj = { id };
|
||||
for (const key of COPIED_FIELDS) if (element[key] !== undefined) merged[key] = element[key];
|
||||
for (const key of copied) if (element[key as (typeof COPIED_FIELDS)[number]] !== undefined) merged[key] = element[key as (typeof COPIED_FIELDS)[number]];
|
||||
for (const [key, value] of Object.entries(own)) {
|
||||
if (key === 'id') continue;
|
||||
if (!(COPIED_FIELDS as readonly string[]).includes(key) || (OVERRIDABLE_FIELDS as readonly string[]).includes(key)) merged[key] = value;
|
||||
if (!copied.includes(key) || (OVERRIDABLE_FIELDS as readonly string[]).includes(key)) merged[key] = value;
|
||||
}
|
||||
const link = linkFromComponent ?? element.diagram;
|
||||
if (link) links.set(id, link);
|
||||
@@ -353,8 +365,8 @@ export function summarizeDiagram(text: string, relativePath: string): DiagramSum
|
||||
}
|
||||
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 items = NODE_COLLECTIONS.flatMap((key) => (Array.isArray(obj[key]) ? (obj[key] as unknown[]) : []));
|
||||
const used = [...new Set(items.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 }, []);
|
||||
const nodes: DiagramNode[] = [];
|
||||
const seen = new Set<string>();
|
||||
|
||||
Reference in new issue
Block a user