@eventcatalog/visualiser 5.0.1 → 5.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -20,6 +20,7 @@ import {
20
20
  DataNode_default,
21
21
  DataProduct_default,
22
22
  DiagramBackground_default,
23
+ DiagramMiniMap_default,
23
24
  DomainCard_default,
24
25
  Domain_default,
25
26
  ENTITY_TARGET_HANDLE_ID,
@@ -67,21 +68,19 @@ import {
67
68
  config_default3,
68
69
  config_default4,
69
70
  config_default5,
70
- convertToMermaid,
71
71
  diagramNodeComponents,
72
72
  edgeTypes,
73
73
  exportNodeGraphForStudio,
74
74
  getLegend,
75
75
  getNestedEntityProperties,
76
76
  getPropertyTypeLabel,
77
- isFlowGroupBy,
78
77
  layoutGraph,
79
78
  memoNode,
80
79
  nodeComponents,
81
80
  nodeConfigs,
82
81
  normalizeOwners,
83
82
  pauseEdgeAnimations
84
- } from "./chunk-KVTGV7VK.mjs";
83
+ } from "./chunk-ZHXUMAPK.mjs";
85
84
  import {
86
85
  ACTOR,
87
86
  AGENT,
@@ -94,6 +93,7 @@ import {
94
93
  QUERY,
95
94
  SERVICE,
96
95
  VIEW,
96
+ convertToMermaid,
97
97
  createEdge,
98
98
  createNode,
99
99
  generateIdForNode,
@@ -102,8 +102,9 @@ import {
102
102
  getColorFromString,
103
103
  getEdgeLabelForMessageAsSource,
104
104
  getEdgeLabelForServiceAsTarget,
105
- getEdgeLabelSize
106
- } from "./chunk-NOHQEQD7.mjs";
105
+ getEdgeLabelSize,
106
+ isFlowGroupBy
107
+ } from "./chunk-P2DH6CFV.mjs";
107
108
  export {
108
109
  ACTOR,
109
110
  AGENT,
@@ -132,6 +133,7 @@ export {
132
133
  DataNode_default as Data,
133
134
  DataProduct_default as DataProductNode,
134
135
  DiagramBackground_default as DiagramBackground,
136
+ DiagramMiniMap_default as DiagramMiniMap,
135
137
  DomainCard_default as DomainCardNode,
136
138
  Domain_default as DomainNode,
137
139
  ENTITY_TARGET_HANDLE_ID,
package/dist/layout.d.mts CHANGED
@@ -1,5 +1,6 @@
1
1
  export { C as CopiedEdgeRoute, E as EdgeRoute, L as LayoutGraph, a as LayoutSize, g as getNodeSize, l as layoutWithElk } from './elk-layout-CpbZ6hB9.mjs';
2
2
  import { Node, Edge } from '@xyflow/react';
3
+ export { M as MermaidExportOptions, c as convertToMermaid } from './export-mermaid-CbER9roE.mjs';
3
4
 
4
5
  declare const isMessageNode: (node: Node) => boolean;
5
6
  /**
package/dist/layout.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { C as CopiedEdgeRoute, E as EdgeRoute, L as LayoutGraph, a as LayoutSize, g as getNodeSize, l as layoutWithElk } from './elk-layout-CpbZ6hB9.js';
1
+ export { C as CopiedEdgeRoute, E as EdgeRoute, L as LayoutGraph, a as LayoutSize, M as MermaidExportOptions, c as convertToMermaid, g as getNodeSize, l as layoutWithElk } from './export-mermaid-xL98eL1l.js';
2
2
  import { Node, Edge } from '@xyflow/react';
3
3
 
4
4
  declare const isMessageNode: (node: Node) => boolean;
package/dist/layout.js CHANGED
@@ -30,6 +30,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/layout.ts
31
31
  var layout_exports = {};
32
32
  __export(layout_exports, {
33
+ convertToMermaid: () => convertToMermaid,
33
34
  getMessagesLabel: () => getMessagesLabel,
34
35
  getNodeSize: () => getNodeSize,
35
36
  hideMessageNodes: () => hideMessageNodes,
@@ -418,8 +419,460 @@ var hideNodes = (nodes, edges, isHidden) => {
418
419
  };
419
420
  };
420
421
  var hideMessageNodes = (nodes, edges) => hideNodes(nodes, edges, isCarrier);
422
+
423
+ // src/utils/swimlanes.ts
424
+ var SWIMLANE_NODE_TYPE = "swimlane";
425
+ var isSwimlaneNode = (node) => node.type === SWIMLANE_NODE_TYPE;
426
+
427
+ // src/utils/export-mermaid.ts
428
+ var NODE_SHAPE_MAP = {
429
+ agents: ["[[", "]]"],
430
+ agent: ["[[", "]]"],
431
+ agentTool: ["[", "]"],
432
+ "agent-tool": ["[", "]"],
433
+ services: ["[[", "]]"],
434
+ // stadium shape
435
+ service: ["[[", "]]"],
436
+ events: [">", "]"],
437
+ // flag/asymmetric shape (message-like)
438
+ event: [">", "]"],
439
+ commands: [">", "]"],
440
+ // flag/asymmetric shape (message-like)
441
+ command: [">", "]"],
442
+ queries: ["{{", "}}"],
443
+ // hexagon
444
+ query: ["{{", "}}"],
445
+ // Parallelogram: what messages pass through, not a cylinder, which reads as
446
+ // a database (and is what data stores are drawn as)
447
+ channels: ["[/", "/]"],
448
+ channel: ["[/", "/]"],
449
+ domains: ["[", "]"],
450
+ // rectangle
451
+ domain: ["[", "]"],
452
+ "context-domain": ["[", "]"],
453
+ // another domain, shown as a single card
454
+ flows: ["([", "])"],
455
+ // stadium (rounded)
456
+ flow: ["([", "])"],
457
+ flowExpanded: ["([", "])"],
458
+ systems: ["[[", "]]"],
459
+ // a system shown as a single node
460
+ system: ["[[", "]]"],
461
+ step: ["[", "]"],
462
+ // rectangle
463
+ user: ["((", "))"],
464
+ // circle
465
+ actor: ["((", "))"],
466
+ // circle
467
+ "context-actor": ["((", "))"],
468
+ // circle
469
+ externalSystem: ["[[", "]]"],
470
+ // stadium
471
+ "external-system": ["[[", "]]"],
472
+ data: ["[(", ")]"],
473
+ // cylinder (database)
474
+ container: ["[(", ")]"],
475
+ "data-product": ["[[", "]]"],
476
+ // stadium
477
+ "data-products": ["[[", "]]"],
478
+ entities: ["[", "]"],
479
+ // rectangle
480
+ entity: ["[", "]"],
481
+ custom: ["[", "]"],
482
+ // rectangle
483
+ view: ["[", "]"],
484
+ // rectangle
485
+ note: ["[", "]"],
486
+ // rectangle
487
+ field: ["[(", ")]"],
488
+ // cylinder
489
+ fields: ["[(", ")]"],
490
+ // cylinder
491
+ messageGroup: ["[[", "]]"],
492
+ messageGroupExpanded: ["[[", "]]"]
493
+ };
494
+ var NODE_STYLE_CLASSES = {
495
+ agents: "fill:#0ea5e9,stroke:#0369a1,color:#fff",
496
+ agent: "fill:#0ea5e9,stroke:#0369a1,color:#fff",
497
+ agentTool: "fill:#8b5cf6,stroke:#6d28d9,color:#fff",
498
+ "agent-tool": "fill:#8b5cf6,stroke:#6d28d9,color:#fff",
499
+ services: "fill:#ec4899,stroke:#be185d,color:#fff",
500
+ service: "fill:#ec4899,stroke:#be185d,color:#fff",
501
+ events: "fill:#f97316,stroke:#c2410c,color:#fff",
502
+ event: "fill:#f97316,stroke:#c2410c,color:#fff",
503
+ commands: "fill:#3b82f6,stroke:#1d4ed8,color:#fff",
504
+ command: "fill:#3b82f6,stroke:#1d4ed8,color:#fff",
505
+ queries: "fill:#22c55e,stroke:#15803d,color:#fff",
506
+ query: "fill:#22c55e,stroke:#15803d,color:#fff",
507
+ channels: "fill:#6b7280,stroke:#374151,color:#fff",
508
+ channel: "fill:#6b7280,stroke:#374151,color:#fff",
509
+ domains: "fill:#eab308,stroke:#a16207,color:#000",
510
+ domain: "fill:#eab308,stroke:#a16207,color:#000",
511
+ "context-domain": "fill:#eab308,stroke:#a16207,color:#000",
512
+ flows: "fill:#14b8a6,stroke:#0f766e,color:#fff",
513
+ flow: "fill:#14b8a6,stroke:#0f766e,color:#fff",
514
+ flowExpanded: "fill:#14b8a6,stroke:#0f766e,color:#fff",
515
+ systems: "fill:#8b5cf6,stroke:#6d28d9,color:#fff",
516
+ system: "fill:#8b5cf6,stroke:#6d28d9,color:#fff",
517
+ step: "fill:#374151,stroke:#1f2937,color:#fff",
518
+ user: "fill:#8b5cf6,stroke:#6d28d9,color:#fff",
519
+ actor: "fill:#eab308,stroke:#a16207,color:#000",
520
+ "context-actor": "fill:#eab308,stroke:#a16207,color:#000",
521
+ // yellow, as actors are on the diagram
522
+ externalSystem: "fill:#ec4899,stroke:#be185d,color:#fff",
523
+ "external-system": "fill:#ec4899,stroke:#be185d,color:#fff",
524
+ data: "fill:#3b82f6,stroke:#1d4ed8,color:#fff",
525
+ container: "fill:#3b82f6,stroke:#1d4ed8,color:#fff",
526
+ "data-product": "fill:#6366f1,stroke:#4338ca,color:#fff",
527
+ "data-products": "fill:#6366f1,stroke:#4338ca,color:#fff",
528
+ entities: "fill:#6b7280,stroke:#374151,color:#fff",
529
+ entity: "fill:#6b7280,stroke:#374151,color:#fff",
530
+ custom: "fill:#9ca3af,stroke:#6b7280,color:#000",
531
+ view: "fill:#9ca3af,stroke:#6b7280,color:#000",
532
+ note: "fill:#fef3c7,stroke:#d97706,color:#000",
533
+ field: "fill:#06b6d4,stroke:#0891b2,color:#fff",
534
+ fields: "fill:#06b6d4,stroke:#0891b2,color:#fff",
535
+ messageGroup: "fill:#7c3aed,stroke:#5b21b6,color:#fff",
536
+ messageGroupExpanded: "fill:#7c3aed,stroke:#5b21b6,color:#fff"
537
+ };
538
+ var GROUP_NODE_TYPES = /* @__PURE__ */ new Set(["system-group", "domain-group", "group"]);
539
+ var GROUP_STYLE_CLASSES = {
540
+ domainGroup: "fill:#eab30814,stroke:#ca8a04,stroke-width:2px,stroke-dasharray:6 4,color:#a16207",
541
+ subdomainGroup: "fill:#eab3080d,stroke:#ca8a04,stroke-dasharray:4 4,color:#a16207",
542
+ otherDomainGroup: "fill:#9ca3af14,stroke:#9ca3af,stroke-dasharray:4 4,color:#6b7280",
543
+ systemGroup: "fill:#8b5cf614,stroke:#8b5cf6,stroke-width:2px,color:#7c3aed",
544
+ laneGroup: "fill:#9ca3af0d,stroke:#9ca3af,stroke-dasharray:4 4,color:#6b7280"
545
+ };
546
+ var FOCUSED_STYLE = "stroke-width:4px";
547
+ var CROSS_DOMAIN_LINK_STYLE = "stroke:#4f46e5,stroke-width:3px";
548
+ var RESERVED_IDS = /* @__PURE__ */ new Set([
549
+ "end",
550
+ "subgraph",
551
+ "graph",
552
+ "flowchart",
553
+ "style",
554
+ "class",
555
+ "classdef",
556
+ "click",
557
+ "linkstyle",
558
+ "call",
559
+ "href"
560
+ ]);
561
+ function sanitizeMermaidId(id) {
562
+ const sanitized = id.replace(/[^a-zA-Z0-9_]/g, "_");
563
+ return RESERVED_IDS.has(sanitized.toLowerCase()) ? `node_${sanitized}` : sanitized;
564
+ }
565
+ function normaliseLines(label) {
566
+ return label.split("\n").map((line) => line.replace(/\s+/g, " ").trim()).filter(Boolean);
567
+ }
568
+ function escapeMermaidLabel(label) {
569
+ return label.replace(/#/g, "#35;").replace(/"/g, "#quot;");
570
+ }
571
+ function getMermaidNodeShape(type) {
572
+ return NODE_SHAPE_MAP[type] || ["[", "]"];
573
+ }
574
+ function formatLabelWithVersion(name, version) {
575
+ if (version) {
576
+ return `${name} (${version})`;
577
+ }
578
+ return name;
579
+ }
580
+ function resourceLabel(resource, fallback) {
581
+ const name = resource?.name || resource?.data?.name || resource?.id || resource?.data?.id;
582
+ const version = resource?.version || resource?.data?.version;
583
+ return formatLabelWithVersion(name || fallback, version);
584
+ }
585
+ function getNodeLabel(node) {
586
+ const { type } = node;
587
+ const data = node.data;
588
+ if (!data) return node.id;
589
+ if (type === "agents" || type === "agent") {
590
+ return resourceLabel(data.agent, node.id);
591
+ }
592
+ if (type === "agentTool" || type === "agent-tool") {
593
+ const agentTool = data.agentTool;
594
+ return agentTool?.name || agentTool?.id || node.id;
595
+ }
596
+ if (type === "services" || type === "service") {
597
+ return resourceLabel(data.service, node.id);
598
+ }
599
+ if (type === "events" || type === "event" || type === "commands" || type === "command" || type === "queries" || type === "query") {
600
+ return resourceLabel(data.message, node.id);
601
+ }
602
+ if (type === "channels" || type === "channel") {
603
+ return resourceLabel(data.channel, node.id);
604
+ }
605
+ if (type === "domains" || type === "domain" || type === "context-domain" || type === "domain-group" || type === "group") {
606
+ return resourceLabel(data.domain, node.id);
607
+ }
608
+ if (type === "systems" || type === "system" || type === "system-group") {
609
+ return resourceLabel(data.system, node.id);
610
+ }
611
+ if (type === "flows" || type === "flow") {
612
+ return resourceLabel(data.flow, node.id);
613
+ }
614
+ if (type === "flowExpanded") {
615
+ return formatLabelWithVersion(data.flowName || node.id, data.version);
616
+ }
617
+ if (type === "step") {
618
+ const step = data.step;
619
+ return step?.title || step?.name || step?.id || node.id;
620
+ }
621
+ if (type === "custom") {
622
+ return data.custom?.title || data.step?.title || data.label || node.id;
623
+ }
624
+ if (type === "externalSystem" || type === "external-system") {
625
+ const system = data.externalSystem || data;
626
+ return system?.name || system?.id || node.id;
627
+ }
628
+ if (type === "data" || type === "container") {
629
+ const dataNode = data.data;
630
+ return dataNode?.name || dataNode?.id || node.id;
631
+ }
632
+ if (type === "data-product" || type === "data-products") {
633
+ return resourceLabel(data.dataProduct, node.id);
634
+ }
635
+ if (type === "entities" || type === "entity") {
636
+ const entity = data.entity;
637
+ return entity?.name || entity?.id || node.id;
638
+ }
639
+ if (type === "view") {
640
+ return data.view?.name || data.view?.id || node.id;
641
+ }
642
+ if (type === "note") {
643
+ return data.text || data.label || "Note";
644
+ }
645
+ if (type === "field" || type === "fields") {
646
+ const name = data.name || node.id;
647
+ return data.type ? `${name} (${data.type})` : name;
648
+ }
649
+ if (type === "messageGroup" || type === "messageGroupExpanded") {
650
+ const groupName = data.groupName || node.id;
651
+ const count = data.messageCount || 0;
652
+ return `${groupName} (${count} messages)`;
653
+ }
654
+ return data.name || data.label || data.title || data.id || node.id;
655
+ }
656
+ function getEdgeLabel(edge) {
657
+ if (edge.label && typeof edge.label === "string") {
658
+ return edge.label;
659
+ }
660
+ if (edge.data?.label && typeof edge.data.label === "string") {
661
+ return edge.data.label;
662
+ }
663
+ return void 0;
664
+ }
665
+ function getMermaidIds(nodes) {
666
+ const mermaidIds = /* @__PURE__ */ new Map();
667
+ const usedIds = /* @__PURE__ */ new Set();
668
+ nodes.forEach((node) => {
669
+ const base = sanitizeMermaidId(node.id);
670
+ let id = base;
671
+ for (let n = 2; usedIds.has(id); n++) id = `${base}_${n}`;
672
+ usedIds.add(id);
673
+ mermaidIds.set(node.id, id);
674
+ });
675
+ return mermaidIds;
676
+ }
677
+ var isEntityNode = (node) => node.type === "entities" || node.type === "entity";
678
+ var CARDINALITY_RELATIONS = /* @__PURE__ */ new Set([
679
+ "hasOne",
680
+ "hasMany",
681
+ "belongsTo",
682
+ "references"
683
+ ]);
684
+ var ENTITY_STYLE_CLASSES = {
685
+ externalEntity: "fill:#9ca3af1a,stroke:#9ca3af,stroke-dasharray:4 4",
686
+ aggregateRoot: "stroke-width:3px"
687
+ };
688
+ function sanitizeErToken(value, fallback) {
689
+ const token = value.trim().replace(/[^A-Za-z0-9_\-[\]().]/g, "_");
690
+ return /^[A-Za-z_]/.test(token) ? token : `${fallback}_${token}`;
691
+ }
692
+ function getErCardinality(property) {
693
+ const required = !!property.required;
694
+ if (property.relationType === "hasMany" || property.type === "array") {
695
+ return required ? "||--|{" : "||--o{";
696
+ }
697
+ if (property.relationType === "hasOne") {
698
+ return required ? "||--||" : "||--o|";
699
+ }
700
+ return required ? "}o--||" : "}o--o|";
701
+ }
702
+ function convertEntitiesToMermaid(nodes, edges, { includeStyles = true } = {}) {
703
+ const mermaidIds = getMermaidIds(nodes);
704
+ const lines = ["erDiagram"];
705
+ const classes = /* @__PURE__ */ new Map();
706
+ const addClass = (name, id) => classes.set(name, [...classes.get(name) ?? [], id]);
707
+ nodes.forEach((node) => {
708
+ const data = node.data;
709
+ const entity = data?.entity?.data ?? {};
710
+ const id = mermaidIds.get(node.id);
711
+ const name = entity.name || data?.label || node.id;
712
+ const label = data?.externalToDomain && data?.domainName ? `${name} (${data.domainName})` : name;
713
+ const references = new Set(data?.referencePropertyNames ?? []);
714
+ const properties = entity.properties ?? [];
715
+ const attributes = properties.map((property) => {
716
+ const type = property.type === "array" && property.items?.type ? `${property.items.type}[]` : property.type || "unknown";
717
+ const keys = [
718
+ property.name === entity.identifier && "PK",
719
+ (property.references || references.has(property.name)) && "FK"
720
+ ].filter(Boolean);
721
+ return ` ${sanitizeErToken(type, "t")} ${sanitizeErToken(property.name, "p")}${keys.length ? ` ${keys.join(", ")}` : ""}`;
722
+ });
723
+ const definition = ` ${id}["${escapeMermaidLabel(label)}"]`;
724
+ lines.push(
725
+ ...attributes.length ? [`${definition} {`, ...attributes, " }"] : [definition]
726
+ );
727
+ if (data?.externalToDomain) addClass("externalEntity", id);
728
+ if (entity.aggregateRoot) addClass("aggregateRoot", id);
729
+ });
730
+ const nodesById = new Map(nodes.map((node) => [node.id, node]));
731
+ const relationships = edges.filter(
732
+ (edge) => !edge.hidden && mermaidIds.has(edge.source) && mermaidIds.has(edge.target)
733
+ ).map((edge) => {
734
+ const propertyName = edge.sourceHandle?.replace(/-source$/, "");
735
+ const properties = nodesById.get(edge.source)?.data?.entity?.data?.properties ?? [];
736
+ const property = properties.find((p) => p.name === propertyName);
737
+ const relation = property?.relationType?.trim();
738
+ const label = relation && !CARDINALITY_RELATIONS.has(relation) ? relation : propertyName || getEdgeLabel(edge) || "references";
739
+ const cardinality = property ? getErCardinality(property) : "}o--o|";
740
+ return ` ${mermaidIds.get(edge.source)} ${cardinality} ${mermaidIds.get(edge.target)} : "${escapeMermaidLabel(label)}"`;
741
+ });
742
+ if (relationships.length > 0) lines.push("", ...relationships);
743
+ if (includeStyles && classes.size > 0) {
744
+ lines.push("");
745
+ classes.forEach((ids, name) => {
746
+ lines.push(` classDef ${name} ${ENTITY_STYLE_CLASSES[name]}`);
747
+ lines.push(` class ${ids.join(",")} ${name}`);
748
+ });
749
+ }
750
+ return lines.join("\n");
751
+ }
752
+ function getGroupClass(node) {
753
+ const data = node.data;
754
+ if (isSwimlaneNode(node)) return "laneGroup";
755
+ if (node.type === "system-group") return "systemGroup";
756
+ if (data?.otherDomain) return "otherDomainGroup";
757
+ if (data?.subdomain) return "subdomainGroup";
758
+ return "domainGroup";
759
+ }
760
+ var isCrossDomain2 = (edge) => !!edge.data?.crossDomain;
761
+ function convertToMermaid(graphNodes, graphEdges, options = {}) {
762
+ const { includeStyles = true, direction = "LR" } = options;
763
+ const nodes = graphNodes.filter((node) => !node.hidden);
764
+ if (nodes.length > 0 && nodes.every(isEntityNode)) {
765
+ return convertEntitiesToMermaid(nodes, graphEdges, { includeStyles });
766
+ }
767
+ const mermaidIds = getMermaidIds(nodes);
768
+ const lines = [];
769
+ lines.push(`flowchart ${direction}`);
770
+ const childrenOf = /* @__PURE__ */ new Map();
771
+ const topLevelNodes = [];
772
+ nodes.forEach((node) => {
773
+ if (node.parentId && mermaidIds.has(node.parentId)) {
774
+ childrenOf.set(node.parentId, [
775
+ ...childrenOf.get(node.parentId) ?? [],
776
+ node
777
+ ]);
778
+ } else {
779
+ topLevelNodes.push(node);
780
+ }
781
+ });
782
+ const isGroup = (node) => childrenOf.has(node.id) || GROUP_NODE_TYPES.has(node.type ?? "") || isSwimlaneNode(node);
783
+ const usedTypes = /* @__PURE__ */ new Set();
784
+ const groupsByClass = /* @__PURE__ */ new Map();
785
+ const focusedIds = [];
786
+ nodes.forEach((node) => {
787
+ const id = mermaidIds.get(node.id);
788
+ if (isGroup(node)) {
789
+ const groupClass = getGroupClass(node);
790
+ groupsByClass.set(groupClass, [
791
+ ...groupsByClass.get(groupClass) ?? [],
792
+ id
793
+ ]);
794
+ return;
795
+ }
796
+ if (node.type && NODE_STYLE_CLASSES[node.type]) usedTypes.add(node.type);
797
+ if (node.data?.isFocused) focusedIds.push(id);
798
+ });
799
+ if (includeStyles) {
800
+ lines.push("");
801
+ lines.push(" %% Style definitions");
802
+ usedTypes.forEach((type) => {
803
+ lines.push(
804
+ ` classDef ${sanitizeMermaidId(type)} ${NODE_STYLE_CLASSES[type]}`
805
+ );
806
+ });
807
+ groupsByClass.forEach((_, groupClass) => {
808
+ lines.push(
809
+ ` classDef ${groupClass} ${GROUP_STYLE_CLASSES[groupClass]}`
810
+ );
811
+ });
812
+ if (focusedIds.length > 0) {
813
+ lines.push(` classDef focused ${FOCUSED_STYLE}`);
814
+ }
815
+ }
816
+ lines.push("");
817
+ lines.push(" %% Nodes");
818
+ const addNode = (node, depth) => {
819
+ const indent = " ".repeat(depth);
820
+ const id = mermaidIds.get(node.id);
821
+ const label = escapeMermaidLabel(
822
+ normaliseLines(getNodeLabel(node)).join("<br/>")
823
+ );
824
+ if (isGroup(node)) {
825
+ lines.push(`${indent}subgraph ${id}["${label}"]`);
826
+ childrenOf.get(node.id)?.forEach((child) => addNode(child, depth + 1));
827
+ lines.push(`${indent}end`);
828
+ return;
829
+ }
830
+ const [prefix, suffix] = getMermaidNodeShape(node.type || "custom");
831
+ let nodeLine = `${indent}${id}${prefix}"${label}"${suffix}`;
832
+ if (includeStyles && node.type && usedTypes.has(node.type)) {
833
+ nodeLine += `:::${sanitizeMermaidId(node.type)}`;
834
+ }
835
+ lines.push(nodeLine);
836
+ };
837
+ topLevelNodes.forEach((node) => addNode(node, 1));
838
+ lines.push("");
839
+ lines.push(" %% Edges");
840
+ const crossDomainLinks = [];
841
+ graphEdges.filter(
842
+ (edge) => !edge.hidden && mermaidIds.has(edge.source) && mermaidIds.has(edge.target)
843
+ ).forEach((edge, index) => {
844
+ const sourceId = mermaidIds.get(edge.source);
845
+ const targetId = mermaidIds.get(edge.target);
846
+ const label = normaliseLines(getEdgeLabel(edge) ?? "").join(" ");
847
+ lines.push(
848
+ label ? ` ${sourceId} -->|"${escapeMermaidLabel(label)}"| ${targetId}` : ` ${sourceId} --> ${targetId}`
849
+ );
850
+ if (isCrossDomain2(edge)) crossDomainLinks.push(index);
851
+ });
852
+ if (includeStyles) {
853
+ const styleLines = [];
854
+ groupsByClass.forEach((ids, groupClass) => {
855
+ styleLines.push(` class ${ids.join(",")} ${groupClass}`);
856
+ });
857
+ if (focusedIds.length > 0) {
858
+ styleLines.push(` class ${focusedIds.join(",")} focused`);
859
+ }
860
+ if (crossDomainLinks.length > 0) {
861
+ styleLines.push(
862
+ ` linkStyle ${crossDomainLinks.join(",")} ${CROSS_DOMAIN_LINK_STYLE}`
863
+ );
864
+ }
865
+ if (styleLines.length > 0) {
866
+ lines.push("");
867
+ lines.push(" %% Boundaries and highlights");
868
+ lines.push(...styleLines);
869
+ }
870
+ }
871
+ return lines.join("\n");
872
+ }
421
873
  // Annotate the CommonJS export names for ESM import in node:
422
874
  0 && (module.exports = {
875
+ convertToMermaid,
423
876
  getMessagesLabel,
424
877
  getNodeSize,
425
878
  hideMessageNodes,