@statelyai/graph 0.3.0 → 0.4.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.
Files changed (41) hide show
  1. package/README.md +12 -11
  2. package/dist/{adjacency-list-A4_Eiwj3.mjs → adjacency-list-Bv4tfiM3.mjs} +33 -0
  3. package/dist/{algorithms-DBU7nmIV.mjs → algorithms-CnTmuX9t.mjs} +682 -24
  4. package/dist/algorithms.d.mts +479 -10
  5. package/dist/algorithms.mjs +1 -1
  6. package/dist/converter-C5DlzzHs.mjs +67 -0
  7. package/dist/{edge-list-DuHMz8hf.mjs → edge-list-R1SUbHwe.mjs} +32 -0
  8. package/dist/formats/adjacency-list/index.d.mts +35 -1
  9. package/dist/formats/adjacency-list/index.mjs +1 -1
  10. package/dist/formats/converter/index.d.mts +37 -3
  11. package/dist/formats/converter/index.mjs +1 -1
  12. package/dist/formats/cytoscape/index.d.mts +50 -2
  13. package/dist/formats/cytoscape/index.mjs +53 -5
  14. package/dist/formats/d3/index.d.mts +48 -2
  15. package/dist/formats/d3/index.mjs +48 -2
  16. package/dist/formats/dot/index.d.mts +56 -2
  17. package/dist/formats/dot/index.mjs +55 -2
  18. package/dist/formats/edge-list/index.d.mts +34 -1
  19. package/dist/formats/edge-list/index.mjs +1 -1
  20. package/dist/formats/gexf/index.d.mts +1 -1
  21. package/dist/formats/gexf/index.mjs +5 -5
  22. package/dist/formats/gml/index.d.mts +58 -2
  23. package/dist/formats/gml/index.mjs +59 -4
  24. package/dist/formats/graphml/index.d.mts +1 -1
  25. package/dist/formats/graphml/index.mjs +2 -2
  26. package/dist/formats/jgf/index.d.mts +51 -2
  27. package/dist/formats/jgf/index.mjs +54 -5
  28. package/dist/formats/mermaid/index.d.mts +201 -8
  29. package/dist/formats/mermaid/index.mjs +365 -26
  30. package/dist/formats/tgf/index.d.mts +47 -2
  31. package/dist/formats/tgf/index.mjs +46 -2
  32. package/dist/formats/xyflow/index.d.mts +73 -0
  33. package/dist/formats/xyflow/index.mjs +133 -0
  34. package/dist/index.d.mts +320 -14
  35. package/dist/index.mjs +117 -9
  36. package/dist/{indexing-BFFVMnjF.mjs → indexing-DitHphT7.mjs} +37 -7
  37. package/dist/queries.d.mts +353 -8
  38. package/dist/queries.mjs +359 -15
  39. package/dist/{types-B6Tpeerk.d.mts → types-Bq_fmLwW.d.mts} +15 -4
  40. package/package.json +3 -1
  41. package/dist/converter-DnbeyE_p.mjs +0 -33
@@ -1,4 +1,4 @@
1
- import { n as createFormatConverter } from "../../converter-DnbeyE_p.mjs";
1
+ import { n as createFormatConverter } from "../../converter-C5DlzzHs.mjs";
2
2
 
3
3
  //#region src/formats/mermaid/shared.ts
4
4
  const MERMAID_TO_DIRECTION = {
@@ -123,6 +123,18 @@ function parseArrow(arrow) {
123
123
  for (const [pattern, info] of ARROW_PATTERNS) if (arrow === pattern) return info;
124
124
  }
125
125
  const MESSAGE_RE = /^(\S+?)\s*(<<-->>|<<->>|-->>|-->|--x|--\)|->>|->|-x|-\))\s*(\S+?)\s*:\s*(.*)$/;
126
+ /**
127
+ * Parses a Mermaid sequence diagram string into a Graph.
128
+ *
129
+ * @example
130
+ * const graph = fromMermaidSequence(`
131
+ * sequenceDiagram
132
+ * participant Alice
133
+ * participant Bob
134
+ * Alice->>Bob: Hello
135
+ * Bob-->>Alice: Hi back
136
+ * `);
137
+ */
126
138
  function fromMermaidSequence(input) {
127
139
  validateInput(input, "Mermaid sequence");
128
140
  const { lines } = prepareLines(input);
@@ -420,9 +432,17 @@ const ARROW_MAP = {
420
432
  async: "--)"
421
433
  }
422
434
  };
435
+ /**
436
+ * Converts a sequence diagram Graph to a Mermaid sequence diagram string.
437
+ *
438
+ * @example
439
+ * const mermaid = toMermaidSequence(graph);
440
+ * // "sequenceDiagram\n participant Alice\n ..."
441
+ */
423
442
  function toMermaidSequence(graph) {
424
443
  const lines = ["sequenceDiagram"];
425
- if (graph.data?.autonumber) lines.push(" autonumber");
444
+ const gd = graph.data;
445
+ if (gd?.autonumber) lines.push(" autonumber");
426
446
  for (const node of graph.nodes) {
427
447
  const d = node.data;
428
448
  const keyword = d?.actorType === "actor" ? "actor" : "participant";
@@ -430,28 +450,182 @@ function toMermaidSequence(graph) {
430
450
  if (d?.created) lines.push(` create ${keyword} ${node.id}${alias}`);
431
451
  else lines.push(` ${keyword} ${node.id}${alias}`);
432
452
  }
453
+ const blocks = gd?.blocks ?? [];
454
+ const edgeIdSet = new Set(graph.edges.map((e) => e.id));
455
+ const beforeEdge = /* @__PURE__ */ new Map();
456
+ const afterEdge = /* @__PURE__ */ new Map();
457
+ for (const block of blocks) if (block.type === "alt") {
458
+ const firstEdge = block.branches[0]?.edgeIds[0];
459
+ if (firstEdge && edgeIdSet.has(firstEdge)) {
460
+ const events = beforeEdge.get(firstEdge) ?? [];
461
+ events.push({
462
+ type: "open",
463
+ block
464
+ });
465
+ beforeEdge.set(firstEdge, events);
466
+ }
467
+ for (let bi = 1; bi < block.branches.length; bi++) {
468
+ const branchFirstEdge = block.branches[bi]?.edgeIds[0];
469
+ if (branchFirstEdge && edgeIdSet.has(branchFirstEdge)) {
470
+ const events = beforeEdge.get(branchFirstEdge) ?? [];
471
+ events.push({
472
+ type: "branch",
473
+ block,
474
+ branchIndex: bi,
475
+ label: block.branches[bi].label
476
+ });
477
+ beforeEdge.set(branchFirstEdge, events);
478
+ }
479
+ }
480
+ const lastBranch = block.branches[block.branches.length - 1];
481
+ const lastEdge = lastBranch?.edgeIds[lastBranch.edgeIds.length - 1];
482
+ if (lastEdge && edgeIdSet.has(lastEdge)) {
483
+ const events = afterEdge.get(lastEdge) ?? [];
484
+ events.push({
485
+ type: "close",
486
+ block
487
+ });
488
+ afterEdge.set(lastEdge, events);
489
+ }
490
+ } else if (block.type === "par") {
491
+ const firstEdge = block.branches[0]?.edgeIds[0];
492
+ if (firstEdge && edgeIdSet.has(firstEdge)) {
493
+ const events = beforeEdge.get(firstEdge) ?? [];
494
+ events.push({
495
+ type: "open",
496
+ block
497
+ });
498
+ beforeEdge.set(firstEdge, events);
499
+ }
500
+ for (let bi = 1; bi < block.branches.length; bi++) {
501
+ const branchFirstEdge = block.branches[bi]?.edgeIds[0];
502
+ if (branchFirstEdge && edgeIdSet.has(branchFirstEdge)) {
503
+ const events = beforeEdge.get(branchFirstEdge) ?? [];
504
+ events.push({
505
+ type: "branch",
506
+ block,
507
+ branchIndex: bi,
508
+ label: block.branches[bi].label
509
+ });
510
+ beforeEdge.set(branchFirstEdge, events);
511
+ }
512
+ }
513
+ const lastBranch = block.branches[block.branches.length - 1];
514
+ const lastEdge = lastBranch?.edgeIds[lastBranch.edgeIds.length - 1];
515
+ if (lastEdge && edgeIdSet.has(lastEdge)) {
516
+ const events = afterEdge.get(lastEdge) ?? [];
517
+ events.push({
518
+ type: "close",
519
+ block
520
+ });
521
+ afterEdge.set(lastEdge, events);
522
+ }
523
+ } else if (block.type === "critical") {
524
+ const firstEdge = block.edgeIds[0];
525
+ if (firstEdge && edgeIdSet.has(firstEdge)) {
526
+ const events = beforeEdge.get(firstEdge) ?? [];
527
+ events.push({
528
+ type: "open",
529
+ block
530
+ });
531
+ beforeEdge.set(firstEdge, events);
532
+ }
533
+ if (block.options) for (const opt of block.options) {
534
+ const optFirstEdge = opt.edgeIds[0];
535
+ if (optFirstEdge && edgeIdSet.has(optFirstEdge)) {
536
+ const events = beforeEdge.get(optFirstEdge) ?? [];
537
+ events.push({
538
+ type: "branch",
539
+ block,
540
+ label: opt.label
541
+ });
542
+ beforeEdge.set(optFirstEdge, events);
543
+ }
544
+ }
545
+ const allEdgeIds = [...block.edgeIds, ...block.options?.flatMap((o) => o.edgeIds) ?? []];
546
+ const lastEdge = allEdgeIds[allEdgeIds.length - 1];
547
+ if (lastEdge && edgeIdSet.has(lastEdge)) {
548
+ const events = afterEdge.get(lastEdge) ?? [];
549
+ events.push({
550
+ type: "close",
551
+ block
552
+ });
553
+ afterEdge.set(lastEdge, events);
554
+ }
555
+ } else {
556
+ const edgeIds = block.edgeIds;
557
+ const firstEdge = edgeIds[0];
558
+ const lastEdge = edgeIds[edgeIds.length - 1];
559
+ if (firstEdge && edgeIdSet.has(firstEdge)) {
560
+ const events = beforeEdge.get(firstEdge) ?? [];
561
+ events.push({
562
+ type: "open",
563
+ block
564
+ });
565
+ beforeEdge.set(firstEdge, events);
566
+ }
567
+ if (lastEdge && edgeIdSet.has(lastEdge)) {
568
+ const events = afterEdge.get(lastEdge) ?? [];
569
+ events.push({
570
+ type: "close",
571
+ block
572
+ });
573
+ afterEdge.set(lastEdge, events);
574
+ }
575
+ }
576
+ let depth = 1;
577
+ const indent = () => " ".repeat(depth);
433
578
  for (const edge of graph.edges) {
579
+ const befores = beforeEdge.get(edge.id);
580
+ if (befores) {
581
+ for (const ev of befores) if (ev.type === "open") {
582
+ const b = ev.block;
583
+ if (b.type === "alt") lines.push(`${indent()}alt ${b.label}`);
584
+ else if (b.type === "par") lines.push(`${indent()}par ${b.branches[0].label}`);
585
+ else if (b.type === "critical") lines.push(`${indent()}critical ${b.label}`);
586
+ else if (b.type === "rect") lines.push(`${indent()}rect ${b.color}`);
587
+ else if (b.type === "loop" || b.type === "opt" || b.type === "break") lines.push(`${indent()}${b.type} ${b.label}`);
588
+ depth++;
589
+ } else if (ev.type === "branch") {
590
+ depth--;
591
+ const b = ev.block;
592
+ if (b.type === "alt") lines.push(`${indent()}else${ev.label ? ` ${ev.label}` : ""}`);
593
+ else if (b.type === "par") lines.push(`${indent()}and ${ev.label ?? ""}`);
594
+ else if (b.type === "critical") lines.push(`${indent()}option ${ev.label ?? ""}`);
595
+ depth++;
596
+ }
597
+ }
434
598
  const d = edge.data;
435
599
  if (!d) continue;
436
- if (d.kind === "activation") {
437
- lines.push(` activate ${edge.sourceId}`);
438
- continue;
600
+ if (d.kind === "activation") lines.push(`${indent()}activate ${edge.sourceId}`);
601
+ else if (d.kind === "deactivation") lines.push(`${indent()}deactivate ${edge.sourceId}`);
602
+ else {
603
+ const stroke = d.stroke ?? "solid";
604
+ const arrowType = d.arrowType ?? "filled";
605
+ let arrow;
606
+ if (d.bidirectional) arrow = stroke === "dotted" ? "<<-->>" : "<<->>";
607
+ else arrow = ARROW_MAP[stroke]?.[arrowType] ?? "->>";
608
+ const label = edge.label ? `: ${escapeMermaidLabel(edge.label)}` : ":";
609
+ lines.push(`${indent()}${edge.sourceId}${arrow}${edge.targetId}${label}`);
439
610
  }
440
- if (d.kind === "deactivation") {
441
- lines.push(` deactivate ${edge.sourceId}`);
442
- continue;
611
+ const afters = afterEdge.get(edge.id);
612
+ if (afters) for (const _ev of afters) {
613
+ depth--;
614
+ lines.push(`${indent()}end`);
443
615
  }
444
- const stroke = d.stroke ?? "solid";
445
- const arrowType = d.arrowType ?? "filled";
446
- let arrow;
447
- if (d.bidirectional) arrow = stroke === "dotted" ? "<<-->>" : "<<->>";
448
- else arrow = ARROW_MAP[stroke]?.[arrowType] ?? "->>";
449
- const label = edge.label ? `: ${escapeMermaidLabel(edge.label)}` : ":";
450
- lines.push(` ${edge.sourceId}${arrow}${edge.targetId}${label}`);
451
616
  }
452
617
  return lines.join("\n");
453
618
  }
454
- /** Bidirectional converter for Mermaid sequence diagram format. */
619
+ /**
620
+ * Bidirectional converter for Mermaid sequence diagram format.
621
+ *
622
+ * @example
623
+ * const graph = mermaidSequenceConverter.from(`
624
+ * sequenceDiagram
625
+ * Alice->>Bob: Hello
626
+ * `);
627
+ * const str = mermaidSequenceConverter.to(graph);
628
+ */
455
629
  const mermaidSequenceConverter = createFormatConverter(toMermaidSequence, fromMermaidSequence);
456
630
 
457
631
  //#endregion
@@ -707,6 +881,16 @@ function findEdge(line) {
707
881
  }
708
882
  return null;
709
883
  }
884
+ /**
885
+ * Parses a Mermaid flowchart string into a Graph.
886
+ *
887
+ * @example
888
+ * const graph = fromMermaidFlowchart(`
889
+ * flowchart TD
890
+ * A[Start] --> B{Decision}
891
+ * B -->|Yes| C[End]
892
+ * `);
893
+ */
710
894
  function fromMermaidFlowchart(input) {
711
895
  validateInput(input, "Mermaid flowchart");
712
896
  const { lines } = prepareLines(input);
@@ -897,6 +1081,13 @@ function fromMermaidFlowchart(input) {
897
1081
  direction
898
1082
  };
899
1083
  }
1084
+ /**
1085
+ * Converts a flowchart Graph to a Mermaid flowchart string.
1086
+ *
1087
+ * @example
1088
+ * const mermaid = toMermaidFlowchart(graph);
1089
+ * // "flowchart TD\n A[Start] --> B{Decision}\n ..."
1090
+ */
900
1091
  function toMermaidFlowchart(graph) {
901
1092
  const lines = [`flowchart ${DIRECTION_TO_MERMAID[graph.direction ?? "down"] ?? "TD"}`];
902
1093
  const gd = graph.data;
@@ -906,7 +1097,7 @@ function toMermaidFlowchart(graph) {
906
1097
  }
907
1098
  const childrenMap = /* @__PURE__ */ new Map();
908
1099
  for (const node of graph.nodes) {
909
- const pid = node.parentId;
1100
+ const pid = node.parentId ?? null;
910
1101
  if (!childrenMap.has(pid)) childrenMap.set(pid, []);
911
1102
  childrenMap.get(pid).push(node);
912
1103
  }
@@ -951,11 +1142,31 @@ function toMermaidFlowchart(graph) {
951
1142
  }
952
1143
  return lines.join("\n");
953
1144
  }
954
- /** Bidirectional converter for Mermaid flowchart format. */
1145
+ /**
1146
+ * Bidirectional converter for Mermaid flowchart format.
1147
+ *
1148
+ * @example
1149
+ * const graph = mermaidFlowchartConverter.from(`
1150
+ * flowchart TD
1151
+ * A --> B
1152
+ * `);
1153
+ * const str = mermaidFlowchartConverter.to(graph);
1154
+ */
955
1155
  const mermaidFlowchartConverter = createFormatConverter(toMermaidFlowchart, fromMermaidFlowchart);
956
1156
 
957
1157
  //#endregion
958
1158
  //#region src/formats/mermaid/state.ts
1159
+ /**
1160
+ * Parses a Mermaid state diagram string into a Graph.
1161
+ *
1162
+ * @example
1163
+ * const graph = fromMermaidState(`
1164
+ * stateDiagram-v2
1165
+ * [*] --> Idle
1166
+ * Idle --> Running : start
1167
+ * Running --> [*]
1168
+ * `);
1169
+ */
959
1170
  function fromMermaidState(input) {
960
1171
  validateInput(input, "Mermaid state");
961
1172
  const { lines } = prepareLines(input);
@@ -1082,11 +1293,18 @@ function fromMermaidState(input) {
1082
1293
  data: { diagramType: "stateDiagram" }
1083
1294
  };
1084
1295
  }
1296
+ /**
1297
+ * Converts a state diagram Graph to a Mermaid state diagram string.
1298
+ *
1299
+ * @example
1300
+ * const mermaid = toMermaidState(graph);
1301
+ * // "stateDiagram-v2\n [*] --> Idle\n ..."
1302
+ */
1085
1303
  function toMermaidState(graph) {
1086
1304
  const lines = ["stateDiagram-v2"];
1087
1305
  const childrenMap = /* @__PURE__ */ new Map();
1088
1306
  for (const node of graph.nodes) {
1089
- const pid = node.parentId;
1307
+ const pid = node.parentId ?? null;
1090
1308
  if (!childrenMap.has(pid)) childrenMap.set(pid, []);
1091
1309
  childrenMap.get(pid).push(node);
1092
1310
  }
@@ -1119,7 +1337,16 @@ function toMermaidState(graph) {
1119
1337
  }
1120
1338
  return lines.join("\n");
1121
1339
  }
1122
- /** Bidirectional converter for Mermaid state diagram format. */
1340
+ /**
1341
+ * Bidirectional converter for Mermaid state diagram format.
1342
+ *
1343
+ * @example
1344
+ * const graph = mermaidStateConverter.from(`
1345
+ * stateDiagram-v2
1346
+ * [*] --> Active
1347
+ * `);
1348
+ * const str = mermaidStateConverter.to(graph);
1349
+ */
1123
1350
  const mermaidStateConverter = createFormatConverter(toMermaidState, fromMermaidState);
1124
1351
 
1125
1352
  //#endregion
@@ -1283,6 +1510,19 @@ function parseMember(line) {
1283
1510
  isMethod
1284
1511
  };
1285
1512
  }
1513
+ /**
1514
+ * Parses a Mermaid class diagram string into a Graph.
1515
+ *
1516
+ * @example
1517
+ * const graph = fromMermaidClass(`
1518
+ * classDiagram
1519
+ * class Animal {
1520
+ * +String name
1521
+ * +eat() void
1522
+ * }
1523
+ * Animal <|-- Dog
1524
+ * `);
1525
+ */
1286
1526
  function fromMermaidClass(input) {
1287
1527
  validateInput(input, "Mermaid class");
1288
1528
  const { lines } = prepareLines(input);
@@ -1402,6 +1642,13 @@ const VISIBILITY_SYMBOLS = {
1402
1642
  "#": "#",
1403
1643
  "~": "~"
1404
1644
  };
1645
+ /**
1646
+ * Converts a class diagram Graph to a Mermaid class diagram string.
1647
+ *
1648
+ * @example
1649
+ * const mermaid = toMermaidClass(graph);
1650
+ * // "classDiagram\n class Animal {\n ..."
1651
+ */
1405
1652
  function toMermaidClass(graph) {
1406
1653
  const lines = ["classDiagram"];
1407
1654
  for (const node of graph.nodes) if (node.data?.members && node.data.members.length > 0) {
@@ -1429,7 +1676,16 @@ function toMermaidClass(graph) {
1429
1676
  }
1430
1677
  return lines.join("\n");
1431
1678
  }
1432
- /** Bidirectional converter for Mermaid class diagram format. */
1679
+ /**
1680
+ * Bidirectional converter for Mermaid class diagram format.
1681
+ *
1682
+ * @example
1683
+ * const graph = mermaidClassConverter.from(`
1684
+ * classDiagram
1685
+ * Animal <|-- Dog
1686
+ * `);
1687
+ * const str = mermaidClassConverter.to(graph);
1688
+ */
1433
1689
  const mermaidClassConverter = createFormatConverter(toMermaidClass, fromMermaidClass);
1434
1690
 
1435
1691
  //#endregion
@@ -1477,6 +1733,16 @@ function parseERRelationship(symbol) {
1477
1733
  };
1478
1734
  }
1479
1735
  const ER_LINE_RE = /^(\S+)\s+([|}{o.][|}{o.][-.][-.][|}{o.][|}{o.])\s+(\S+)\s*:\s*"?([^"]*)"?\s*$/;
1736
+ /**
1737
+ * Parses a Mermaid ER diagram string into a Graph.
1738
+ *
1739
+ * @example
1740
+ * const graph = fromMermaidER(`
1741
+ * erDiagram
1742
+ * CUSTOMER ||--o{ ORDER : places
1743
+ * ORDER ||--|{ LINE_ITEM : contains
1744
+ * `);
1745
+ */
1480
1746
  function fromMermaidER(input) {
1481
1747
  validateInput(input, "Mermaid ER");
1482
1748
  const { lines } = prepareLines(input);
@@ -1560,6 +1826,13 @@ function fromMermaidER(input) {
1560
1826
  data: { diagramType: "erDiagram" }
1561
1827
  };
1562
1828
  }
1829
+ /**
1830
+ * Converts an ER diagram Graph to a Mermaid ER diagram string.
1831
+ *
1832
+ * @example
1833
+ * const mermaid = toMermaidER(graph);
1834
+ * // "erDiagram\n CUSTOMER ||--o{ ORDER : \"places\"\n ..."
1835
+ */
1563
1836
  function toMermaidER(graph) {
1564
1837
  const lines = ["erDiagram"];
1565
1838
  for (const node of graph.nodes) if (node.data?.attributes && node.data.attributes.length > 0) {
@@ -1582,7 +1855,16 @@ function toMermaidER(graph) {
1582
1855
  }
1583
1856
  return lines.join("\n");
1584
1857
  }
1585
- /** Bidirectional converter for Mermaid ER diagram format. */
1858
+ /**
1859
+ * Bidirectional converter for Mermaid ER diagram format.
1860
+ *
1861
+ * @example
1862
+ * const graph = mermaidERConverter.from(`
1863
+ * erDiagram
1864
+ * CUSTOMER ||--o{ ORDER : places
1865
+ * `);
1866
+ * const str = mermaidERConverter.to(graph);
1867
+ */
1586
1868
  const mermaidERConverter = createFormatConverter(toMermaidER, fromMermaidER);
1587
1869
 
1588
1870
  //#endregion
@@ -1628,6 +1910,18 @@ function parseNodeText(text) {
1628
1910
  };
1629
1911
  return { label: text.trim() };
1630
1912
  }
1913
+ /**
1914
+ * Parses a Mermaid mindmap string into a Graph.
1915
+ *
1916
+ * @example
1917
+ * const graph = fromMermaidMindmap(`
1918
+ * mindmap
1919
+ * Root
1920
+ * Child A
1921
+ * Grandchild
1922
+ * Child B
1923
+ * `);
1924
+ */
1631
1925
  function fromMermaidMindmap(input) {
1632
1926
  validateInput(input, "Mermaid mindmap");
1633
1927
  const { lines } = prepareLines(input);
@@ -1690,11 +1984,18 @@ function fromMermaidMindmap(input) {
1690
1984
  data: { diagramType: "mindmap" }
1691
1985
  };
1692
1986
  }
1987
+ /**
1988
+ * Converts a mindmap Graph to a Mermaid mindmap string.
1989
+ *
1990
+ * @example
1991
+ * const mermaid = toMermaidMindmap(graph);
1992
+ * // "mindmap\n Root\n Child A\n ..."
1993
+ */
1693
1994
  function toMermaidMindmap(graph) {
1694
1995
  const lines = ["mindmap"];
1695
1996
  const childrenMap = /* @__PURE__ */ new Map();
1696
1997
  for (const node of graph.nodes) {
1697
- const pid = node.parentId;
1998
+ const pid = node.parentId ?? null;
1698
1999
  if (!childrenMap.has(pid)) childrenMap.set(pid, []);
1699
2000
  childrenMap.get(pid).push(node);
1700
2001
  }
@@ -1715,7 +2016,17 @@ function toMermaidMindmap(graph) {
1715
2016
  writeNode(null, 0);
1716
2017
  return lines.join("\n");
1717
2018
  }
1718
- /** Bidirectional converter for Mermaid mindmap format. */
2019
+ /**
2020
+ * Bidirectional converter for Mermaid mindmap format.
2021
+ *
2022
+ * @example
2023
+ * const graph = mermaidMindmapConverter.from(`
2024
+ * mindmap
2025
+ * Root
2026
+ * Branch
2027
+ * `);
2028
+ * const str = mermaidMindmapConverter.to(graph);
2029
+ */
1719
2030
  const mermaidMindmapConverter = createFormatConverter(toMermaidMindmap, fromMermaidMindmap);
1720
2031
 
1721
2032
  //#endregion
@@ -1772,6 +2083,17 @@ function parseBlockNode(text) {
1772
2083
  };
1773
2084
  return null;
1774
2085
  }
2086
+ /**
2087
+ * Parses a Mermaid block diagram string into a Graph.
2088
+ *
2089
+ * @example
2090
+ * const graph = fromMermaidBlock(`
2091
+ * block-beta
2092
+ * columns 2
2093
+ * a["Task A"] b["Task B"]
2094
+ * a --> b
2095
+ * `);
2096
+ */
1775
2097
  function fromMermaidBlock(input) {
1776
2098
  validateInput(input, "Mermaid block");
1777
2099
  const { lines } = prepareLines(input);
@@ -1864,12 +2186,19 @@ function fromMermaidBlock(input) {
1864
2186
  }
1865
2187
  };
1866
2188
  }
2189
+ /**
2190
+ * Converts a block diagram Graph to a Mermaid block diagram string.
2191
+ *
2192
+ * @example
2193
+ * const mermaid = toMermaidBlock(graph);
2194
+ * // "block-beta\n columns 2\n a[\"Task A\"]\n ..."
2195
+ */
1867
2196
  function toMermaidBlock(graph) {
1868
2197
  const lines = ["block-beta"];
1869
2198
  if (graph.data?.columns) lines.push(` columns ${graph.data.columns}`);
1870
2199
  const childrenMap = /* @__PURE__ */ new Map();
1871
2200
  for (const node of graph.nodes) {
1872
- const pid = node.parentId;
2201
+ const pid = node.parentId ?? null;
1873
2202
  if (!childrenMap.has(pid)) childrenMap.set(pid, []);
1874
2203
  childrenMap.get(pid).push(node);
1875
2204
  }
@@ -1891,7 +2220,17 @@ function toMermaidBlock(graph) {
1891
2220
  for (const edge of graph.edges) lines.push(` ${edge.sourceId} --> ${edge.targetId}`);
1892
2221
  return lines.join("\n");
1893
2222
  }
1894
- /** Bidirectional converter for Mermaid block diagram format. */
2223
+ /**
2224
+ * Bidirectional converter for Mermaid block diagram format.
2225
+ *
2226
+ * @example
2227
+ * const graph = mermaidBlockConverter.from(`
2228
+ * block-beta
2229
+ * columns 2
2230
+ * a b
2231
+ * `);
2232
+ * const str = mermaidBlockConverter.to(graph);
2233
+ */
1895
2234
  const mermaidBlockConverter = createFormatConverter(toMermaidBlock, fromMermaidBlock);
1896
2235
 
1897
2236
  //#endregion
@@ -1,9 +1,54 @@
1
- import { c as Graph, f as GraphFormatConverter } from "../../types-B6Tpeerk.mjs";
1
+ import { c as Graph, f as GraphFormatConverter } from "../../types-Bq_fmLwW.mjs";
2
2
 
3
3
  //#region src/formats/tgf/index.d.ts
4
+
5
+ /**
6
+ * Converts a graph to TGF (Trivial Graph Format) string.
7
+ *
8
+ * @example
9
+ * ```ts
10
+ * import { createGraph } from '@statelyai/graph';
11
+ * import { toTGF } from '@statelyai/graph/formats/tgf';
12
+ *
13
+ * const graph = createGraph({
14
+ * nodes: [{ id: 'a', label: 'A' }, { id: 'b', label: 'B' }],
15
+ * edges: [{ id: 'e0', sourceId: 'a', targetId: 'b', label: 'go' }],
16
+ * });
17
+ *
18
+ * const tgf = toTGF(graph);
19
+ * // "a A\nb B\n#\na b go"
20
+ * ```
21
+ */
4
22
  declare function toTGF(graph: Graph): string;
23
+ /**
24
+ * Parses a TGF (Trivial Graph Format) string into a graph.
25
+ *
26
+ * @example
27
+ * ```ts
28
+ * import { fromTGF } from '@statelyai/graph/formats/tgf';
29
+ *
30
+ * const graph = fromTGF('a A\nb B\n#\na b go');
31
+ * // graph.nodes = [{ id: 'a', label: 'A' }, { id: 'b', label: 'B' }]
32
+ * ```
33
+ */
5
34
  declare function fromTGF(tgf: string): Graph;
6
- /** Bidirectional converter for TGF (Trivial Graph Format). */
35
+ /**
36
+ * Bidirectional converter for TGF (Trivial Graph Format).
37
+ *
38
+ * @example
39
+ * ```ts
40
+ * import { createGraph } from '@statelyai/graph';
41
+ * import { tgfConverter } from '@statelyai/graph/formats/tgf';
42
+ *
43
+ * const graph = createGraph({
44
+ * nodes: [{ id: 'a' }, { id: 'b' }],
45
+ * edges: [{ id: 'e0', sourceId: 'a', targetId: 'b' }],
46
+ * });
47
+ *
48
+ * const tgf = tgfConverter.to(graph);
49
+ * const roundTripped = tgfConverter.from(tgf);
50
+ * ```
51
+ */
7
52
  declare const tgfConverter: GraphFormatConverter<string>;
8
53
  //#endregion
9
54
  export { fromTGF, tgfConverter, toTGF };
@@ -1,6 +1,23 @@
1
- import { n as createFormatConverter } from "../../converter-DnbeyE_p.mjs";
1
+ import { n as createFormatConverter } from "../../converter-C5DlzzHs.mjs";
2
2
 
3
3
  //#region src/formats/tgf/index.ts
4
+ /**
5
+ * Converts a graph to TGF (Trivial Graph Format) string.
6
+ *
7
+ * @example
8
+ * ```ts
9
+ * import { createGraph } from '@statelyai/graph';
10
+ * import { toTGF } from '@statelyai/graph/formats/tgf';
11
+ *
12
+ * const graph = createGraph({
13
+ * nodes: [{ id: 'a', label: 'A' }, { id: 'b', label: 'B' }],
14
+ * edges: [{ id: 'e0', sourceId: 'a', targetId: 'b', label: 'go' }],
15
+ * });
16
+ *
17
+ * const tgf = toTGF(graph);
18
+ * // "a A\nb B\n#\na b go"
19
+ * ```
20
+ */
4
21
  function toTGF(graph) {
5
22
  const lines = [];
6
23
  for (const node of graph.nodes) lines.push(node.label ? `${node.id} ${node.label}` : node.id);
@@ -12,6 +29,17 @@ function toTGF(graph) {
12
29
  }
13
30
  return lines.join("\n");
14
31
  }
32
+ /**
33
+ * Parses a TGF (Trivial Graph Format) string into a graph.
34
+ *
35
+ * @example
36
+ * ```ts
37
+ * import { fromTGF } from '@statelyai/graph/formats/tgf';
38
+ *
39
+ * const graph = fromTGF('a A\nb B\n#\na b go');
40
+ * // graph.nodes = [{ id: 'a', label: 'A' }, { id: 'b', label: 'B' }]
41
+ * ```
42
+ */
15
43
  function fromTGF(tgf) {
16
44
  if (typeof tgf !== "string") throw new Error("TGF: expected a string");
17
45
  const lines = tgf.split("\n");
@@ -60,7 +88,23 @@ function fromTGF(tgf) {
60
88
  data: void 0
61
89
  };
62
90
  }
63
- /** Bidirectional converter for TGF (Trivial Graph Format). */
91
+ /**
92
+ * Bidirectional converter for TGF (Trivial Graph Format).
93
+ *
94
+ * @example
95
+ * ```ts
96
+ * import { createGraph } from '@statelyai/graph';
97
+ * import { tgfConverter } from '@statelyai/graph/formats/tgf';
98
+ *
99
+ * const graph = createGraph({
100
+ * nodes: [{ id: 'a' }, { id: 'b' }],
101
+ * edges: [{ id: 'e0', sourceId: 'a', targetId: 'b' }],
102
+ * });
103
+ *
104
+ * const tgf = tgfConverter.to(graph);
105
+ * const roundTripped = tgfConverter.from(tgf);
106
+ * ```
107
+ */
64
108
  const tgfConverter = createFormatConverter(toTGF, fromTGF);
65
109
 
66
110
  //#endregion