hexwright 0.1.0 → 0.3.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/README.md CHANGED
@@ -90,19 +90,63 @@ as a hub with the domains that touch it around it.
90
90
  | `impact` | the above plus everything that depends on a changed type |
91
91
  | `core` | Entity · Service · UseCase · Port · Event — the whole shape |
92
92
  | `all` | everything, adapters and DTOs included |
93
+ | `violations` | only the breaches, and the types they run through |
93
94
  | `domain:<name>` | one bounded context and what it touches |
94
95
 
96
+ `violations` is a **state** view: it draws what is wrong now, not what this branch
97
+ changed. Unlike the toggle in the web UI it is not narrowed by component, because
98
+ a violation with one end hidden reads as no violation at all.
99
+
100
+ ### Before and after
101
+
102
+ A branch that *removes* violations, or swaps one port for another, is not
103
+ described by the delta alone. The picture worth showing is the state it started
104
+ from — which is exactly the state the working tree no longer has. `--at base`
105
+ draws the same types in their pre-branch state:
106
+
107
+ ```bash
108
+ hexwright render --repo . --base main --at base --image before.png
109
+ hexwright render --repo . --base main --image after.png
110
+ ```
111
+
112
+ The before picture carries **no delta styling** — nothing in a picture of the past
113
+ can be added or modified — and violations stay red, which is the question it
114
+ exists to answer. It needs `--base`. A branch that only adds types has no before
115
+ state at all; the command says so and exits 0.
116
+
117
+ A before/after pair **lines up**. Positions, domain boxes, colours and canvas
118
+ width all follow the set of types being laid out, and the two halves differ by
119
+ whatever the branch added or removed — so each render lays out from the union of
120
+ both and draws only its own half. A type keeps its place across the pair, and a
121
+ deletion leaves the gap where it used to be. Neither command needs a flag for
122
+ this and neither can be run "wrong": both derive the union from the same two
123
+ graphs.
124
+
95
125
  There is no browser involved — the coordinates are a pure function, so the SVG
96
126
  is written directly and CI needs no headless Chrome. The same graph always draws
97
- the same file, which is what makes two branches comparable.
127
+ the same file.
98
128
 
99
129
  `--image x.png` also writes `x.svg`. PNG needs the optional `@resvg/resvg-js`;
100
130
  without it the SVG is still written and the command says so. GitHub does not
101
131
  render SVG in comments, so attach the PNG there and keep the SVG as the artifact.
102
132
 
103
- Layout follows the view — `organic` for `delta` and `domain:`, `hex` for `core`
104
- and `all` (concentric rings, read as a shape). `--layout organic|grid|hex`
105
- overrides; `grid` lists domains left to right, ignoring coupling.
133
+ Layout follows the view — `organic` for `delta`, `domain:` and `violations`, `hex`
134
+ for `core` and `all` (concentric rings, read as a shape). `--layout
135
+ organic|grid|hex` overrides; `grid` lists domains left to right, ignoring
136
+ coupling.
137
+
138
+ ## Exit codes
139
+
140
+ | command | 1 | 0 |
141
+ |---|---|---|
142
+ | `check` | the repository has a violation — with `--scope delta`, only one the branch introduced | otherwise |
143
+ | `render` | a bad argument, or a base ref that is not in the clone | an image was written, **or there was nothing to draw** |
144
+ | `extract` | the source root or the base ref cannot be read | otherwise |
145
+
146
+ `render` treats an empty picture as an answer rather than a failure. `--view
147
+ violations` on the branch that removed the last one, and `--at base` on a branch
148
+ that only adds types, both print what happened and exit 0 — a non-zero exit there
149
+ would break the very script that produces the pair.
106
150
 
107
151
  ## MCP
108
152
 
@@ -184,6 +228,22 @@ package prefix, which is inferred automatically:
184
228
  <base>.common Shared
185
229
  ```
186
230
 
231
+ ### What a companion object contributes
232
+
233
+ Nothing. A `companion object` is a separate object with its own type, so what it
234
+ names belongs to it rather than to the class it is written inside. The graph
235
+ models types, and a companion is not one.
236
+
237
+ Attributing its contents to the enclosing class is what made a sealed root appear
238
+ to depend on its own variants — the factory naming them lives in the companion —
239
+ and made a value class wrapping a `UUID` appear to depend on an id generator.
240
+
241
+ The cost is deliberate and worth knowing: **a coupling that exists only inside a
242
+ companion is not reported.** A domain entity whose companion holds
243
+ `fun fromRow(row: JpaRow)` would otherwise be caught as a layer back-reference.
244
+ Mapping belongs in the adapter in this architecture, so it should be rare, but it
245
+ is not impossible.
246
+
187
247
  ## What it produces
188
248
 
189
249
  ```
@@ -320,6 +380,39 @@ domains 16
320
380
  Zero Ports or a domain count of 1 means the paths or the base package are not
321
381
  matching your layout yet.
322
382
 
383
+ ## Identity
384
+
385
+ A type keeping another aggregate's id — `MediaItem` holding a `BlobId`, not a
386
+ `Blob` — is referencing that aggregate, and referencing it the deliberately weaker
387
+ way. That is drawn as `REFERENCES`, pointed at the aggregate rather than at the id,
388
+ and styled lighter than a direct dependency so the two do not read alike. It never
389
+ counts as a boundary violation: pointing at another context by id is how you avoid
390
+ coupling to it, and reporting it would penalise the design that got it right.
391
+
392
+ Nothing in the source says which id belongs to what, so the profile says which
393
+ convention to read:
394
+
395
+ ```yaml
396
+ identity:
397
+ from: property # the type declaring `val id: T` owns T
398
+ property: id
399
+ ```
400
+
401
+ ```yaml
402
+ identity:
403
+ from: suffix # BlobId → Blob
404
+ suffix: Id
405
+ ```
406
+
407
+ `property` is the default because it is structural, and because it survives an
408
+ aggregate whose name is not the identifier's stem — `MediaId` identifies
409
+ `MediaItem`, and stripping the suffix would look for a `Media` that does not
410
+ exist. Use `suffix` when aggregates do not carry their own id.
411
+
412
+ Where an identifier cannot be resolved — its aggregate is outside the analysed
413
+ source, or two unrelated types claim it — the edge stays on the identifier rather
414
+ than being pointed at a guess. Remove the `identity` block and none are resolved.
415
+
323
416
  ## Boundary rules
324
417
 
325
418
  An Entity may be touched by, within the same domain: `Service`, `Port`, `Entity`,
@@ -331,6 +424,30 @@ is a violation:
331
424
  - a DTO or UseCase exposing an Entity — domain model leaked into a contract
332
425
  - application/domain referencing adapter — layer back-reference
333
426
 
427
+ ## Releasing
428
+
429
+ Trunk-based, tag-triggered. There is no release branch: `main` is the only branch
430
+ that ships, and one can always be cut from a tag later if a backport ever needs
431
+ one.
432
+
433
+ ```bash
434
+ npm version minor -m "release: v%s" # bumps package.json, commits, tags
435
+ git push --follow-tags
436
+ ```
437
+
438
+ Pushing the tag runs [`release.yml`](.github/workflows/release.yml), which
439
+ refuses to publish unless the tagged commit is on `main` and the tag matches the
440
+ version in `package.json` — a tag that disagrees with what npm receives is worse
441
+ than a failed release, because it is only found out later. It then runs the same
442
+ gate a pull request has to clear, publishes with provenance, and opens a GitHub
443
+ Release for the tag.
444
+
445
+ There is no npm token. npm is configured to trust this repository and this
446
+ workflow **by filename**, and the OIDC token GitHub mints for the job is exchanged
447
+ for publish rights — so nothing has to be stored, rotated, or kept from expiring.
448
+ The catch is the filename: renaming `release.yml` breaks publishing until npm's
449
+ trusted-publisher entry is updated to match.
450
+
334
451
  ## Status
335
452
 
336
453
  Early. Kotlin extractor only; validated against one production codebase
package/dist/cli.js CHANGED
@@ -146,6 +146,10 @@ async function serveStdio(getQuery, project) {
146
146
  await server.connect(new StdioServerTransport());
147
147
  }
148
148
 
149
+ // src/model.ts
150
+ var nodeIndex = (g) => new Map(g.nodes.map((n) => [n.id, n]));
151
+ var edgeKey = (e) => `${e.src}\0${e.dst}\0${e.rel}`;
152
+
149
153
  // src/output/tsv.ts
150
154
  function toTsv(g) {
151
155
  const prefix = commonPrefix(g.nodes.map((n) => n.id));
@@ -583,7 +587,9 @@ function gridLayout(g, maxWidth = 3e3) {
583
587
  }
584
588
 
585
589
  // src/render/select.ts
586
- function select(g, view, showIdentifiers = false) {
590
+ var NothingToDraw = class extends Error {
591
+ };
592
+ function select(g, view, showIdentifiers = false, changed) {
587
593
  const byId = new Map(g.nodes.map((n) => [n.id, n]));
588
594
  const real = g.edges.filter((e) => showIdentifiers || !e.identifierOnly);
589
595
  const withNeighbours = (seed) => {
@@ -595,6 +601,13 @@ function select(g, view, showIdentifiers = false) {
595
601
  return out;
596
602
  };
597
603
  const changedSet = () => {
604
+ if (changed) {
605
+ const seed2 = new Set([...changed].filter((id) => byId.has(id)));
606
+ if (!seed2.size) {
607
+ throw new NothingToDraw("nothing this branch touches exists here \u2014 nothing to draw");
608
+ }
609
+ return seed2;
610
+ }
598
611
  const seed = new Set(
599
612
  g.nodes.filter((n) => n.status === "added" || n.status === "modified").map((n) => n.id)
600
613
  );
@@ -613,7 +626,18 @@ function select(g, view, showIdentifiers = false) {
613
626
  };
614
627
  let keep;
615
628
  let label;
616
- if (view === "all") {
629
+ let violatingEdgesOnly = false;
630
+ if (view === "violations") {
631
+ keep = /* @__PURE__ */ new Set();
632
+ for (const e of real) {
633
+ if (!e.violation) continue;
634
+ keep.add(e.src);
635
+ keep.add(e.dst);
636
+ }
637
+ if (!keep.size) throw new NothingToDraw("no violations \u2014 nothing to draw");
638
+ violatingEdgesOnly = true;
639
+ label = "every boundary violation, and the types they run through";
640
+ } else if (view === "all") {
617
641
  keep = new Set(g.nodes.map((n) => n.id));
618
642
  label = "all types";
619
643
  } else if (view === "core") {
@@ -632,14 +656,16 @@ function select(g, view, showIdentifiers = false) {
632
656
  keep = changedSet();
633
657
  const linked = real.filter((e) => keep.has(e.src) && keep.has(e.dst)).length;
634
658
  if (linked) {
635
- label = "what this branch added and changed";
659
+ label = changed ? "the types this branch touches, as they stand" : "what this branch added and changed";
636
660
  } else {
637
661
  keep = dependents(keep);
638
- label = "what this branch changed (no new relations \u2014 showing dependents)";
662
+ label = changed ? "the types this branch touches, and their dependents, as they stand" : "what this branch changed (no new relations \u2014 showing dependents)";
639
663
  }
640
664
  }
641
665
  const nodes = g.nodes.filter((n) => keep.has(n.id));
642
- const edges = real.filter((e) => keep.has(e.src) && keep.has(e.dst));
666
+ const edges = real.filter(
667
+ (e) => keep.has(e.src) && keep.has(e.dst) && (!violatingEdgesOnly || e.violation)
668
+ );
643
669
  return { graph: { ...g, nodes, edges }, label };
644
670
  }
645
671
 
@@ -724,6 +750,10 @@ function trim(a, c, b, ab, bb) {
724
750
  }
725
751
  var EDGE = {
726
752
  DEPENDS_ON: { width: 1.9, dash: "", bow: 0, arrow: "vee", scale: 0.95 },
753
+ // Thinner and broken up than DEPENDS_ON, because it is a lighter coupling: the
754
+ // reference runs through an identifier, not the type. The distinction is only
755
+ // worth drawing if it reads as weaker at a glance.
756
+ REFERENCES: { width: 1.4, dash: "2 4", bow: 24, arrow: "vee", scale: 0.9 },
727
757
  IMPLEMENTS: { width: 2.2, dash: "9 5", bow: 42, arrow: "triangle", scale: 1.35 },
728
758
  EXTENDS: { width: 3.4, dash: "3 3", bow: 58, arrow: "triangle", scale: 1.6 }
729
759
  };
@@ -762,16 +792,18 @@ function gridWidthFor(g) {
762
792
  }
763
793
  function renderSvg(g, opt = {}) {
764
794
  const layout = opt.layout ?? "hex";
765
- const hueOf = hueMap(g.nodes.map((n) => n.domain));
766
- const place = layout === "hex" ? hexLayout(g) : layout === "organic" ? organicLayout(g) : gridLayout(g, gridWidthFor(g));
795
+ const frame = opt.frame ?? g;
796
+ const hueOf = hueMap(frame.nodes.map((n) => n.domain));
797
+ const place = layout === "hex" ? hexLayout(frame) : layout === "organic" ? organicLayout(frame) : gridLayout(frame, gridWidthFor(frame));
767
798
  const coords = new Map(place.map((p) => [p.id, p]));
768
- const placed = g.nodes.map((n) => {
799
+ const sit = (n) => {
769
800
  const c = coords.get(n.id) ?? { x: 0, y: 0 };
770
801
  return { n, x: c.x, y: c.y, ...sizeOf(n) };
771
- });
802
+ };
803
+ const placed = g.nodes.map(sit);
772
804
  const at = new Map(placed.map((p) => [p.n.id, p]));
773
805
  const domains = /* @__PURE__ */ new Map();
774
- for (const p of placed) {
806
+ for (const p of frame === g ? placed : frame.nodes.map(sit)) {
775
807
  const b = domains.get(p.n.domain);
776
808
  const x1 = Math.min(b ? b.x : Number.POSITIVE_INFINITY, p.x - p.w / 2);
777
809
  const y1 = Math.min(b ? b.y : Number.POSITIVE_INFINITY, p.y - p.h / 2);
@@ -965,13 +997,15 @@ function legendBlock(g, w, top, hueOf) {
965
997
  `<path d="M${x},${y} L${x + 34},${y}" stroke="${VIOLATION}" stroke-width="3.4" fill="none"/>`,
966
998
  `<text x="${x + 40}" y="${y + 4}" font-size="11" fill="${VIOLATION}">boundary violation</text>`
967
999
  );
968
- x += 150;
969
- rows.push(
970
- `<rect x="${x}" y="${y - 7}" width="14" height="14" rx="3" fill="none" stroke="${ADDED}" stroke-width="3"/>`,
971
- `<text x="${x + 20}" y="${y + 4}" font-size="11" fill="${ADDED}">added</text>`,
972
- `<rect x="${x + 66}" y="${y - 7}" width="14" height="14" rx="3" fill="none" stroke="${MODIFIED}" stroke-width="2.6" stroke-dasharray="7 4"/>`,
973
- `<text x="${x + 86}" y="${y + 4}" font-size="11" fill="${MODIFIED}">modified</text>`
974
- );
1000
+ if (g.nodes.some((n) => n.status === "added" || n.status === "modified")) {
1001
+ x += 150;
1002
+ rows.push(
1003
+ `<rect x="${x}" y="${y - 7}" width="14" height="14" rx="3" fill="none" stroke="${ADDED}" stroke-width="3"/>`,
1004
+ `<text x="${x + 20}" y="${y + 4}" font-size="11" fill="${ADDED}">added</text>`,
1005
+ `<rect x="${x + 66}" y="${y - 7}" width="14" height="14" rx="3" fill="none" stroke="${MODIFIED}" stroke-width="2.6" stroke-dasharray="7 4"/>`,
1006
+ `<text x="${x + 86}" y="${y + 4}" font-size="11" fill="${MODIFIED}">modified</text>`
1007
+ );
1008
+ }
975
1009
  y += 26;
976
1010
  x = 26;
977
1011
  rows.push(`<text x="${x}" y="${y + 4}" font-size="11" fill="${DIM}">domain</text>`);
@@ -998,10 +1032,6 @@ function legendBlock(g, w, top, hueOf) {
998
1032
  import { readdirSync as readdirSync3, statSync as statSync3 } from "fs";
999
1033
  import { join as join4 } from "path";
1000
1034
 
1001
- // src/model.ts
1002
- var nodeIndex = (g) => new Map(g.nodes.map((n) => [n.id, n]));
1003
- var edgeKey = (e) => `${e.src}\0${e.dst}\0${e.rel}`;
1004
-
1005
1035
  // src/delta.ts
1006
1036
  function diff(base, head) {
1007
1037
  const b = nodeIndex(base);
@@ -1088,6 +1118,13 @@ var MODS = "(?:public |internal |private |protected |open |abstract |sealed |dat
1088
1118
  var DECL = new RegExp(
1089
1119
  `^(?<mods>${MODS})(?<kw>class|interface|object)\\s+(?<name>[A-Za-z_]\\w*)`
1090
1120
  );
1121
+ var TOP_MODS = "(?:public |internal |private |expect |actual |external |inline |suspend |operator |infix |tailrec |const |lateinit )*";
1122
+ var TYPEALIAS = new RegExp(
1123
+ `^${TOP_MODS}typealias\\s+(\\w+)(?:<[^>]*>)?\\s*=\\s*(.+?)\\s*$`
1124
+ );
1125
+ var TOP_LEVEL = new RegExp(
1126
+ `^(?:@\\w+(?:\\([^)]*\\))?\\s+)*${TOP_MODS}(?:typealias|fun|va[lr])\\s`
1127
+ );
1091
1128
  var FUN_MODS = "(?:override |open |abstract |suspend |operator |private |internal |protected |inline |final )*";
1092
1129
  var SIG = new RegExp(
1093
1130
  `^\\s+(?:@\\w+(?:\\([^)]*\\))?\\s*)*(?<mods>${FUN_MODS})fun\\s+(?<name>\\w+)\\s*\\(`
@@ -1113,45 +1150,97 @@ function structOf(kind) {
1113
1150
  if (kind === "object") return "Object";
1114
1151
  return "Class";
1115
1152
  }
1116
- function stripComments(text) {
1153
+ function stripNonCode(text) {
1117
1154
  const out = [];
1118
- let inBlock = false;
1119
- let inLine = false;
1120
- let inStr = false;
1121
- for (let i = 0; i < text.length; i++) {
1155
+ const n = text.length;
1156
+ const stack = [{ kind: "code", raw: false, depth: 0 }];
1157
+ const blank = (c) => out.push(c === "\n" ? "\n" : " ");
1158
+ let i = 0;
1159
+ while (i < n) {
1160
+ const f = stack[stack.length - 1];
1122
1161
  const c = text[i];
1123
- if (inLine) {
1124
- if (c === "\n") {
1125
- inLine = false;
1126
- out.push("\n");
1127
- } else out.push(" ");
1128
- continue;
1129
- }
1130
- if (inBlock) {
1131
- if (c === "*" && text[i + 1] === "/") {
1132
- out.push(" ");
1162
+ if (f.kind === "code") {
1163
+ if (c === "/" && text[i + 1] === "/") {
1164
+ while (i < n && text[i] !== "\n") {
1165
+ out.push(" ");
1166
+ i++;
1167
+ }
1168
+ continue;
1169
+ }
1170
+ if (c === "/" && text[i + 1] === "*") {
1171
+ out.push(" ", " ");
1172
+ i += 2;
1173
+ while (i < n && !(text[i] === "*" && text[i + 1] === "/")) blank(text[i++]);
1174
+ if (i < n) {
1175
+ out.push(" ", " ");
1176
+ i += 2;
1177
+ }
1178
+ continue;
1179
+ }
1180
+ if (c === '"') {
1181
+ const raw = text[i + 1] === '"' && text[i + 2] === '"';
1182
+ const q = raw ? 3 : 1;
1183
+ for (let k = 0; k < q; k++) out.push('"');
1184
+ i += q;
1185
+ stack.push({ kind: "str", raw, depth: 0 });
1186
+ continue;
1187
+ }
1188
+ if (c === "'") {
1189
+ out.push("'");
1133
1190
  i++;
1134
- inBlock = false;
1191
+ while (i < n && text[i] !== "'" && text[i] !== "\n") {
1192
+ if (text[i] === "\\" && i + 1 < n) {
1193
+ out.push(" ");
1194
+ i++;
1195
+ }
1196
+ blank(text[i++]);
1197
+ }
1198
+ if (i < n && text[i] === "'") {
1199
+ out.push("'");
1200
+ i++;
1201
+ }
1135
1202
  continue;
1136
1203
  }
1137
- out.push(c === "\n" ? "\n" : " ");
1204
+ if (c === "{") f.depth++;
1205
+ else if (c === "}") {
1206
+ if (f.depth === 0 && stack.length > 1) {
1207
+ out.push("}");
1208
+ stack.pop();
1209
+ i++;
1210
+ continue;
1211
+ }
1212
+ f.depth--;
1213
+ }
1214
+ out.push(c);
1215
+ i++;
1138
1216
  continue;
1139
1217
  }
1140
- if (!inStr && c === "/" && text[i + 1] === "*") {
1141
- inBlock = true;
1142
- out.push(" ");
1143
- i++;
1218
+ if (!f.raw && c === "\\" && i + 1 < n) {
1219
+ out.push(" ", " ");
1220
+ i += 2;
1144
1221
  continue;
1145
1222
  }
1146
- if (!inStr && c === "/" && text[i + 1] === "/") {
1147
- inLine = true;
1148
- out.push(" ");
1223
+ if (!f.raw && c === "\n") {
1224
+ out.push("\n");
1225
+ stack.pop();
1149
1226
  i++;
1150
1227
  continue;
1151
1228
  }
1152
- if (c === '"') inStr = !inStr;
1153
- else if (c === "\n") inStr = false;
1154
- out.push(c);
1229
+ if (c === '"' && (!f.raw || text[i + 1] === '"' && text[i + 2] === '"')) {
1230
+ const q = f.raw ? 3 : 1;
1231
+ for (let k = 0; k < q; k++) out.push('"');
1232
+ i += q;
1233
+ stack.pop();
1234
+ continue;
1235
+ }
1236
+ if (c === "$" && text[i + 1] === "{") {
1237
+ out.push("$", "{");
1238
+ i += 2;
1239
+ stack.push({ kind: "code", raw: false, depth: 0 });
1240
+ continue;
1241
+ }
1242
+ blank(c);
1243
+ i++;
1155
1244
  }
1156
1245
  return out.join("");
1157
1246
  }
@@ -1190,7 +1279,7 @@ function collectSigs(body) {
1190
1279
  }
1191
1280
  return out;
1192
1281
  }
1193
- function ctorParams(header2) {
1282
+ function ctorParts(header2) {
1194
1283
  const i = header2.indexOf("(");
1195
1284
  if (i < 0) return [];
1196
1285
  let depth = 0;
@@ -1216,6 +1305,22 @@ function ctorParams(header2) {
1216
1305
  } else cur.push(ch);
1217
1306
  }
1218
1307
  parts.push(cur.join(""));
1308
+ return parts;
1309
+ }
1310
+ function ctorDeclared(header2) {
1311
+ const out = [];
1312
+ for (let p of ctorParts(header2)) {
1313
+ p = (p.split("=")[0] ?? "").replace(/\s+/g, " ").trim();
1314
+ p = p.replace(/^(?:@\w+(?:\([^)]*\))?\s*)*/, "");
1315
+ const m = /^(?:private |internal |protected |override )*(?:val|var)\s+(\w+)\s*:\s*(.+)$/.exec(
1316
+ p
1317
+ );
1318
+ if (m) out.push({ name: m[1], type: m[2].trim() });
1319
+ }
1320
+ return out;
1321
+ }
1322
+ function ctorParams(header2) {
1323
+ const parts = ctorParts(header2);
1219
1324
  const res = [];
1220
1325
  for (let p of parts) {
1221
1326
  p = (p.split("=")[0] ?? "").replace(/\s+/g, " ").trim();
@@ -1316,6 +1421,47 @@ function supertypeNames(text, seenColon) {
1316
1421
  }
1317
1422
 
1318
1423
  // src/extract/kotlin.ts
1424
+ function bodyEnd(fi, di) {
1425
+ const d = fi.decls[di];
1426
+ let end = di + 1 < fi.decls.length ? fi.decls[di + 1].line : fi.lines.length;
1427
+ for (const s of fi.stops) if (s > d.line && s < end) end = s;
1428
+ return end;
1429
+ }
1430
+ var COMPANION = /^\s+(?:public |internal |private |protected )*companion\s+object\b/;
1431
+ function bodyOf(fi, di) {
1432
+ const d = fi.decls[di];
1433
+ const lines = fi.lines.slice(d.line, bodyEnd(fi, di));
1434
+ for (let i = 0; i < lines.length; i++) {
1435
+ if (!COMPANION.test(lines[i])) continue;
1436
+ let open = lines[i].includes("{") ? i : -1;
1437
+ if (open < 0) {
1438
+ for (let k = i + 1; k < lines.length; k++) {
1439
+ const t = lines[k].trim();
1440
+ if (!t) continue;
1441
+ if (t.startsWith("{")) open = k;
1442
+ break;
1443
+ }
1444
+ }
1445
+ if (open < 0) {
1446
+ lines[i] = "";
1447
+ continue;
1448
+ }
1449
+ let depth = 0;
1450
+ let j = i;
1451
+ for (; j < lines.length; j++) {
1452
+ if (j >= open) {
1453
+ for (const ch of lines[j]) {
1454
+ if (ch === "{") depth++;
1455
+ else if (ch === "}") depth--;
1456
+ }
1457
+ }
1458
+ lines[j] = "";
1459
+ if (j >= open && depth <= 0) break;
1460
+ }
1461
+ i = j;
1462
+ }
1463
+ return lines;
1464
+ }
1319
1465
  function walk(dir, out = []) {
1320
1466
  for (const e of readdirSync2(dir)) {
1321
1467
  const p = join2(dir, e);
@@ -1343,10 +1489,12 @@ function extractKotlin(srcRoot, profile, project, ref) {
1343
1489
  for (const abs of files) {
1344
1490
  const rel = relative2(srcRoot, abs);
1345
1491
  if (isExcluded(profile, `/${rel}`)) continue;
1346
- const lines = stripComments(readFileSync3(abs, "utf8")).split("\n");
1492
+ const lines = stripNonCode(readFileSync3(abs, "utf8")).split("\n");
1347
1493
  let pkg = "";
1348
1494
  const imports = /* @__PURE__ */ new Map();
1349
1495
  const decls = [];
1496
+ const aliases = /* @__PURE__ */ new Map();
1497
+ const stops = [];
1350
1498
  for (let i = 0; i < lines.length; i++) {
1351
1499
  const line = lines[i];
1352
1500
  const pm = PACKAGE.exec(line);
@@ -1367,10 +1515,58 @@ function extractKotlin(srcRoot, profile, project, ref) {
1367
1515
  line: i,
1368
1516
  kind: kindOf(dm.groups.mods ?? "", dm.groups.kw)
1369
1517
  });
1518
+ continue;
1519
+ }
1520
+ const am = TYPEALIAS.exec(line);
1521
+ if (am) {
1522
+ aliases.set(am[1], am[2]);
1523
+ stops.push(i);
1524
+ continue;
1370
1525
  }
1526
+ if (TOP_LEVEL.test(line)) stops.push(i);
1371
1527
  }
1372
1528
  rawPkgs.push(pkg);
1373
- infos.push({ rel, pkg, imports, decls, lines, layer: layerOf(profile, `/${rel}`) });
1529
+ infos.push({
1530
+ rel,
1531
+ pkg,
1532
+ imports,
1533
+ decls,
1534
+ lines,
1535
+ layer: layerOf(profile, `/${rel}`),
1536
+ aliases,
1537
+ stops
1538
+ });
1539
+ }
1540
+ const aliasByFq = /* @__PURE__ */ new Map();
1541
+ for (const fi of infos) {
1542
+ for (const [name, rhs] of fi.aliases) aliasByFq.set(`${fi.pkg}.${name}`, { rhs, from: fi });
1543
+ }
1544
+ for (const fi of infos) {
1545
+ const reach = /* @__PURE__ */ new Map();
1546
+ for (const [name, rhs] of fi.aliases) reach.set(name, { rhs, from: fi });
1547
+ for (const [simple, fq] of fi.imports) {
1548
+ const a = aliasByFq.get(fq);
1549
+ if (a) reach.set(simple, a);
1550
+ }
1551
+ for (const [fq, a] of aliasByFq) {
1552
+ const dot = fq.lastIndexOf(".");
1553
+ const name = fq.slice(dot + 1);
1554
+ if (fq.slice(0, dot) === fi.pkg && !reach.has(name)) reach.set(name, a);
1555
+ }
1556
+ if (!reach.size) continue;
1557
+ for (const { rhs, from } of reach.values()) {
1558
+ if (from === fi) continue;
1559
+ for (const [name] of rhs.matchAll(TYPENAME)) {
1560
+ const nm = name;
1561
+ if (!fi.imports.has(nm)) fi.imports.set(nm, from.imports.get(nm) ?? `${from.pkg}.${nm}`);
1562
+ }
1563
+ }
1564
+ for (let pass = 0; pass < 2; pass++) {
1565
+ for (const [name, a] of reach) {
1566
+ const re = new RegExp(`\\b${name}\\b`, "g");
1567
+ fi.lines = fi.lines.map((l) => TYPEALIAS.test(l) ? l : l.replace(re, a.rhs));
1568
+ }
1569
+ }
1374
1570
  }
1375
1571
  const base = profile.domain.base || inferBasePackage(rawPkgs);
1376
1572
  const domainOf = (pkg) => {
@@ -1388,8 +1584,7 @@ function extractKotlin(srcRoot, profile, project, ref) {
1388
1584
  const domain = domainOf(fi.pkg);
1389
1585
  for (let di = 0; di < fi.decls.length; di++) {
1390
1586
  const d = fi.decls[di];
1391
- const end = di + 1 < fi.decls.length ? fi.decls[di + 1].line : fi.lines.length;
1392
- const body = fi.lines.slice(d.line, end);
1587
+ const body = bodyOf(fi, di);
1393
1588
  const struct = structOf(d.kind);
1394
1589
  const sigs = collectSigs(body);
1395
1590
  const api = [];
@@ -1398,13 +1593,18 @@ function extractKotlin(srcRoot, profile, project, ref) {
1398
1593
  const braceAt = headerFull.indexOf("{");
1399
1594
  const header2 = braceAt >= 0 ? headerFull.slice(0, braceAt) : headerFull;
1400
1595
  const props = ctorParams(header2);
1596
+ const declared = /* @__PURE__ */ new Map();
1597
+ for (const p of ctorDeclared(header2)) declared.set(p.name, p.type);
1401
1598
  if (braceAt >= 0) {
1402
1599
  const rest = body.slice(header2.split("\n").length - 1);
1403
1600
  const first = rest[0];
1404
1601
  if (first !== void 0) rest[0] = first.slice(first.indexOf("{") + 1);
1405
1602
  for (const ln of rest) {
1406
1603
  const pm = PROP.exec(ln);
1407
- if (pm) props.push(`${pm[1]}: ${pm[2].trim().replace(/,$/, "")}`);
1604
+ if (!pm) continue;
1605
+ const type = pm[2].trim().replace(/,$/, "");
1606
+ props.push(`${pm[1]}: ${type}`);
1607
+ declared.set(pm[1], type);
1408
1608
  }
1409
1609
  }
1410
1610
  if (d.kind.includes("enum")) props.push(...enumEntries(body.join("\n")));
@@ -1423,7 +1623,8 @@ function extractKotlin(srcRoot, profile, project, ref) {
1423
1623
  file: fi.rel,
1424
1624
  line: d.line + 1,
1425
1625
  struct,
1426
- sigs
1626
+ sigs,
1627
+ declared
1427
1628
  });
1428
1629
  byPkg.set(fi.pkg, [...byPkg.get(fi.pkg) ?? [], id]);
1429
1630
  }
@@ -1448,8 +1649,7 @@ function extractKotlin(srcRoot, profile, project, ref) {
1448
1649
  for (let di = 0; di < fi.decls.length; di++) {
1449
1650
  const d = fi.decls[di];
1450
1651
  const id = `${fi.pkg}.${d.name}`;
1451
- const end = di + 1 < fi.decls.length ? fi.decls[di + 1].line : fi.lines.length;
1452
- const body = fi.lines.slice(d.line, end).join("\n");
1652
+ const body = bodyOf(fi, di).join("\n");
1453
1653
  for (const sup of parseSupertypes(fi.lines, d.line)) {
1454
1654
  const tgt = visible.get(sup);
1455
1655
  if (tgt) supers.push([id, tgt]);
@@ -1493,8 +1693,7 @@ function extractKotlin(srcRoot, profile, project, ref) {
1493
1693
  for (let di = 0; di < fi.decls.length; di++) {
1494
1694
  const d = fi.decls[di];
1495
1695
  const id = `${fi.pkg}.${d.name}`;
1496
- const end = di + 1 < fi.decls.length ? fi.decls[di + 1].line : fi.lines.length;
1497
- const body = fi.lines.slice(d.line, end).join("\n");
1696
+ const body = bodyOf(fi, di).join("\n");
1498
1697
  const bind = /* @__PURE__ */ new Map();
1499
1698
  for (const m of body.matchAll(FIELD)) {
1500
1699
  const tgt = visible.get(m[2]);
@@ -1533,6 +1732,51 @@ function extractKotlin(srcRoot, profile, project, ref) {
1533
1732
  }
1534
1733
  }
1535
1734
  const supSet = new Set(supers.map(([c, p]) => key(c, p)));
1735
+ const parentsOf = /* @__PURE__ */ new Map();
1736
+ for (const [c, p] of supers) parentsOf.set(c, [...parentsOf.get(c) ?? [], p]);
1737
+ const inherits = (child, ancestor) => {
1738
+ const seen = /* @__PURE__ */ new Set();
1739
+ const walk2 = [child];
1740
+ while (walk2.length) {
1741
+ const cur = walk2.pop();
1742
+ if (cur === ancestor && cur !== child) return true;
1743
+ if (seen.has(cur)) continue;
1744
+ seen.add(cur);
1745
+ walk2.push(...parentsOf.get(cur) ?? []);
1746
+ }
1747
+ return false;
1748
+ };
1749
+ const aggregateOf = /* @__PURE__ */ new Map();
1750
+ const ambiguous = [];
1751
+ const identity = profile.identity;
1752
+ if (identity?.from === "property") {
1753
+ const want = identity.property ?? "id";
1754
+ const claims = /* @__PURE__ */ new Map();
1755
+ for (const [id, t] of types) {
1756
+ const written = t.declared.get(want);
1757
+ if (written === void 0) continue;
1758
+ const bare = written.replace(/[?\s]/g, "");
1759
+ const target = (visCache.get(t.file) ?? /* @__PURE__ */ new Map()).get(bare);
1760
+ if (target) claims.set(target, [...claims.get(target) ?? [], id]);
1761
+ }
1762
+ for (const [idType, holders] of claims) {
1763
+ const roots = holders.filter((h) => !holders.some((o) => o !== h && inherits(h, o)));
1764
+ if (roots.length === 1) aggregateOf.set(idType, roots[0]);
1765
+ else ambiguous.push(idType);
1766
+ }
1767
+ } else if (identity?.from === "suffix") {
1768
+ const suffix = identity.suffix ?? "Id";
1769
+ for (const [id, t] of types) {
1770
+ if (!t.name.endsWith(suffix) || t.name === suffix) continue;
1771
+ const stem = t.name.slice(0, -suffix.length);
1772
+ const pkg = id.slice(0, id.length - t.name.length - 1);
1773
+ const here = (byPkg.get(pkg) ?? []).filter((x) => types.get(x)?.name === stem);
1774
+ const anywhere = [...types.values()].filter((x) => x.name === stem).map((x) => x.id);
1775
+ const hit = here.length === 1 ? here : anywhere;
1776
+ if (hit.length === 1) aggregateOf.set(id, hit[0]);
1777
+ else if (hit.length > 1) ambiguous.push(id);
1778
+ }
1779
+ }
1536
1780
  const edges = [];
1537
1781
  const push2 = (src, dst, rel, weight) => {
1538
1782
  const s = types.get(src);
@@ -1549,20 +1793,47 @@ function extractKotlin(srcRoot, profile, project, ref) {
1549
1793
  rel,
1550
1794
  weight,
1551
1795
  crossDomain: s.domain !== d.domain,
1796
+ // Not "this edge is an identifier reference" — those became REFERENCES and
1797
+ // point at the aggregate. This says the destination is a value type in the
1798
+ // domain model, which nearly everything touches, so the picture folds them
1799
+ // away by default. What lands here is value objects, enums, and identifiers
1800
+ // whose aggregate is outside the analysed source.
1552
1801
  identifierOnly: d.component === "VO" && d.sublayer === "model",
1553
1802
  viaSignature: viaSig.has(k),
1554
1803
  contracts: rel === "DEPENDS_ON" ? contracts : [],
1555
- violation: violationOf(profile, s, d, layerViol.has(k))
1804
+ // Referencing another context's aggregate by id is how you avoid coupling to
1805
+ // it. Reporting that as a breach would penalise the design that got it right,
1806
+ // so REFERENCES carries no verdict — `crossDomain` still marks where it runs.
1807
+ violation: rel === "REFERENCES" ? "" : violationOf(profile, s, d, layerViol.has(k))
1556
1808
  });
1557
1809
  };
1558
1810
  for (const [c, p] of supSet.size ? [...supSet].map((k) => k.split("\0")) : []) {
1559
1811
  const parent = types.get(p);
1560
1812
  push2(c, p, parent.struct === "Interface" ? "IMPLEMENTS" : "EXTENDS", 1);
1561
1813
  }
1814
+ const refs = /* @__PURE__ */ new Map();
1562
1815
  for (const [k, w] of dep) {
1563
1816
  if (supSet.has(k)) continue;
1564
1817
  const [s, d] = k.split("\0");
1565
- push2(s, d, "DEPENDS_ON", w);
1818
+ const g = aggregateOf.get(d);
1819
+ if (g === void 0) {
1820
+ push2(s, d, "DEPENDS_ON", w);
1821
+ continue;
1822
+ }
1823
+ if (g === s || inherits(s, g)) continue;
1824
+ if (dep.has(key(s, g))) continue;
1825
+ const rk = key(s, g);
1826
+ refs.set(rk, (refs.get(rk) ?? 0) + w);
1827
+ }
1828
+ for (const [k, w] of refs) {
1829
+ const [s, d] = k.split("\0");
1830
+ push2(s, d, "REFERENCES", w);
1831
+ }
1832
+ if (ambiguous.length) {
1833
+ process.stderr.write(
1834
+ `warning: cannot tell what these identifiers identify \u2014 ${ambiguous.map((x) => x.split(".").pop()).sort().join(", ")}
1835
+ `
1836
+ );
1566
1837
  }
1567
1838
  const nodes = [...types.values()].map(({ struct: _s, sigs: _g, ...n }) => n);
1568
1839
  nodes.sort((a, b) => a.id.localeCompare(b.id));
@@ -1795,6 +2066,10 @@ var GraphSource = class {
1795
2066
  this.graph();
1796
2067
  return this.last?.delta;
1797
2068
  }
2069
+ /**
2070
+ * The graph as it stands at the base ref. Extracted once and cached — the ref is
2071
+ * immutable, so a base-state render costs nothing a delta has not already paid.
2072
+ */
1798
2073
  base() {
1799
2074
  if (this.baseGraph) return this.baseGraph;
1800
2075
  const { repo, srcRel, profile, project, base } = this.cfg;
@@ -1900,7 +2175,7 @@ var shell = () => `<!doctype html>
1900
2175
  Off = keep the fixed coordinates above.</div></div>
1901
2176
 
1902
2177
  <h2>Edges</h2>
1903
- <label><input type=checkbox id="showId">Show identifier edges</label>
2178
+ <label><input type=checkbox id="showId">Show value-type edges</label>
1904
2179
  <label><input type=checkbox id="crossOnly">Cross-domain edges only</label>
1905
2180
  <div class="sub" style="margin:6px 0 0"><b>Identifier edges</b><div class="d">references like
1906
2181
  FamilyId\xB7UserId \u2014 a shared coordinate system, not coupling. Hidden by default.</div></div>
@@ -1908,6 +2183,8 @@ var shell = () => `<!doctype html>
1908
2183
  <h2>Edge types</h2>
1909
2184
  <label><input type=checkbox class=rf value="DEPENDS_ON" checked>
1910
2185
  <i></i>DEPENDS_ON <span class="mut">straight \xB7 open V</span><span class="n" id="cDEPENDS_ON"></span></label>
2186
+ <label><input type=checkbox class=rf value="REFERENCES" checked>
2187
+ <i class="d"></i>REFERENCES <span class="mut">by id \xB7 fine dots</span><span class="n" id="cREFERENCES"></span></label>
1911
2188
  <label><input type=checkbox class=rf value="IMPLEMENTS" checked>
1912
2189
  <i class="d"></i>IMPLEMENTS <span class="mut">curved \xB7 long dash</span><span class="n" id="cIMPLEMENTS"></span></label>
1913
2190
  <label><input type=checkbox class=rf value="EXTENDS" checked>
@@ -2006,11 +2283,27 @@ check only
2006
2283
  has violations without fixing them all first.
2007
2284
 
2008
2285
  render only
2009
- --view <v> delta | impact | core | all | domain:<name> [delta]
2286
+ --view <v> delta | impact | core | all | violations | domain:<name>
2287
+ [delta]
2288
+ violations = only the breaches and the types they run
2289
+ through. A state view: it draws what is wrong now, not
2290
+ what this branch changed.
2291
+ --at <s> head | base [head]
2292
+ base draws the same types in their pre-branch state, for
2293
+ the "before" half of a before/after pair. Requires --base.
2294
+ Delta styling is dropped \u2014 nothing is added or modified in
2295
+ a picture of the past \u2014 and violations stay in red.
2010
2296
  --layout <l> organic | grid | hex
2011
- [organic for delta\xB7domain, hex for core\xB7all]
2297
+ [organic for delta\xB7domain\xB7violations, hex for core\xB7all]
2012
2298
  --image <file> output path; .svg, or .png to rasterize [graph.svg]
2013
- --identifiers include identifier-only references (FamilyId\xB7UserId)
2299
+ --identifiers include references to domain value types \u2014 value objects,
2300
+ enums, and identifiers whose aggregate is out of scope.
2301
+ A resolved identifier is drawn as REFERENCES at the
2302
+ aggregate instead and is not folded away. Flag name kept
2303
+ for compatibility.
2304
+
2305
+ Nothing to draw \u2014 no violations, or a branch that only adds types and so has
2306
+ no before state \u2014 is reported on stdout and exits 0.
2014
2307
  `;
2015
2308
  function main() {
2016
2309
  const { values: v, positionals } = parseArgs({
@@ -2028,6 +2321,7 @@ function main() {
2028
2321
  mcp: { type: "boolean", default: false },
2029
2322
  scope: { type: "string", default: "all" },
2030
2323
  view: { type: "string", default: "delta" },
2324
+ at: { type: "string", default: "head" },
2031
2325
  layout: { type: "string" },
2032
2326
  // no default — chosen to suit the view
2033
2327
  image: { type: "string" },
@@ -2098,26 +2392,58 @@ function main() {
2098
2392
  }
2099
2393
  if (cmd === "render") {
2100
2394
  const out = v.image ?? "graph.svg";
2395
+ if (v.at !== "head" && v.at !== "base") {
2396
+ process.stderr.write(`--at takes head or base, not '${v.at}'
2397
+ `);
2398
+ return 1;
2399
+ }
2400
+ const atBase = v.at === "base";
2401
+ if (atBase && !v.base) {
2402
+ process.stderr.write("--at base needs --base <ref> to know which state to draw\n");
2403
+ return 1;
2404
+ }
2405
+ const changed = d ? /* @__PURE__ */ new Set([...d.addedNodes, ...d.modifiedNodes, ...d.removedNodes]) : void 0;
2406
+ const target = atBase ? source.base() : graph;
2101
2407
  let sel;
2102
2408
  try {
2103
- sel = select(graph, v.view, v.identifiers);
2409
+ sel = select(target, v.view, v.identifiers, atBase ? changed : void 0);
2104
2410
  } catch (e) {
2411
+ if (e instanceof NothingToDraw) {
2412
+ process.stdout.write(`${project} @ ${target.ref}
2413
+ ${e.message}
2414
+ `);
2415
+ return 0;
2416
+ }
2105
2417
  process.stderr.write(`${e.message}
2106
2418
  `);
2107
2419
  return 1;
2108
2420
  }
2421
+ let frame;
2422
+ if (v.base && changed) {
2423
+ const half = (gr, ch) => {
2424
+ try {
2425
+ return select(gr, v.view, v.identifiers, ch).graph;
2426
+ } catch {
2427
+ return void 0;
2428
+ }
2429
+ };
2430
+ const head = half(graph);
2431
+ const base = half(source.base(), changed);
2432
+ if (head && base) frame = union(head, base);
2433
+ }
2109
2434
  const layout = v.layout === "hex" || v.layout === "grid" || v.layout === "organic" ? v.layout : v.view === "core" || v.view === "all" ? "hex" : "organic";
2110
2435
  const svg = renderSvg(sel.graph, {
2111
2436
  layout,
2112
2437
  viewLabel: sel.label,
2113
- showIdentifiers: v.identifiers
2438
+ showIdentifiers: v.identifiers,
2439
+ ...frame ? { frame } : {}
2114
2440
  });
2115
2441
  const dir = dirname2(resolve(out));
2116
2442
  mkdirSync(dir, { recursive: true });
2117
2443
  const svgPath = out.endsWith(".png") ? `${out.slice(0, -4)}.svg` : out;
2118
2444
  writeFileSync(svgPath, svg);
2119
2445
  process.stdout.write(
2120
- `${project} @ ${graph.ref}
2446
+ `${project} @ ${target.ref}
2121
2447
  view ${sel.label}
2122
2448
  drew ${sel.graph.nodes.length} types \xB7 ${sel.graph.edges.length} relations \xB7 ${sel.graph.edges.filter((e) => e.violation).length} violations
2123
2449
  wrote ${svgPath} (${Math.round(svg.length / 1024)} KB)
@@ -2127,8 +2453,7 @@ function main() {
2127
2453
  const px = toPng(svg, out);
2128
2454
  process.stdout.write(
2129
2455
  px ? ` wrote ${out} (${px})
2130
- ` : ` note PNG skipped \u2014 install @resvg/resvg-js for rasterizing
2131
- `
2456
+ ` : " note PNG skipped \u2014 install @resvg/resvg-js for rasterizing\n"
2132
2457
  );
2133
2458
  }
2134
2459
  return 0;
@@ -2205,6 +2530,19 @@ wrote ${join6(v.out, "graph.json")} \xB7 graph.tsv
2205
2530
  }
2206
2531
  return cmd === "check" && gated.length ? 1 : 0;
2207
2532
  }
2533
+ function union(a, b) {
2534
+ const nodes = new Map(a.nodes.map((n) => [n.id, n]));
2535
+ for (const n of b.nodes) if (!nodes.has(n.id)) nodes.set(n.id, n);
2536
+ const edges = new Map(a.edges.map((e) => [edgeKey(e), e]));
2537
+ for (const e of b.edges) if (!edges.has(edgeKey(e))) edges.set(edgeKey(e), e);
2538
+ return {
2539
+ ...a,
2540
+ nodes: [...nodes.values()].sort((x, y) => x.id.localeCompare(y.id)),
2541
+ edges: [...edges.values()].sort(
2542
+ (x, y) => x.src.localeCompare(y.src) || x.dst.localeCompare(y.dst) || x.rel.localeCompare(y.rel)
2543
+ )
2544
+ };
2545
+ }
2208
2546
  function toPng(svg, out) {
2209
2547
  try {
2210
2548
  const req = createRequire(import.meta.url);
package/dist/client.js CHANGED
@@ -318,7 +318,7 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
318
318
  `).concat(r.picking?`if(outColor.a == 0.0) discard;
319
319
  else outColor = vIndex;`:"",`
320
320
  }
321
- `),s=Jm(a,n,o);s.aPosition=a.getAttribLocation(s,"aPosition"),s.aIndex=a.getAttribLocation(s,"aIndex"),s.aVertType=a.getAttribLocation(s,"aVertType"),s.aTransform=a.getAttribLocation(s,"aTransform"),s.aAtlasId=a.getAttribLocation(s,"aAtlasId"),s.aTex=a.getAttribLocation(s,"aTex"),s.aPointAPointB=a.getAttribLocation(s,"aPointAPointB"),s.aPointCPointD=a.getAttribLocation(s,"aPointCPointD"),s.aLineWidth=a.getAttribLocation(s,"aLineWidth"),s.aColor=a.getAttribLocation(s,"aColor"),s.aCornerRadius=a.getAttribLocation(s,"aCornerRadius"),s.aBorderColor=a.getAttribLocation(s,"aBorderColor"),s.uPanZoomMatrix=a.getUniformLocation(s,"uPanZoomMatrix"),s.uAtlasSize=a.getUniformLocation(s,"uAtlasSize"),s.uBGColor=a.getUniformLocation(s,"uBGColor"),s.uZoom=a.getUniformLocation(s,"uZoom"),s.uTextures=[];for(var u=0;u<this.batchManager.getMaxAtlasesPerBatch();u++)s.uTextures.push(a.getUniformLocation(s,"uTexture".concat(u)));return s}},{key:"_createVAO",value:function(){var r=[0,0,1,0,1,1,0,0,1,1,0,1];this.vertexCount=r.length/2;var a=this.maxInstances,n=this.gl,i=this.program,o=n.createVertexArray();return n.bindVertexArray(o),s0(n,"vec2",i.aPosition,r),this.transformBuffer=l0(n,a,i.aTransform),this.indexBuffer=Zt(n,a,"vec4",i.aIndex),this.vertTypeBuffer=Zt(n,a,"int",i.aVertType),this.atlasIdBuffer=Zt(n,a,"int",i.aAtlasId),this.texBuffer=Zt(n,a,"vec4",i.aTex),this.pointAPointBBuffer=Zt(n,a,"vec4",i.aPointAPointB),this.pointCPointDBuffer=Zt(n,a,"vec4",i.aPointCPointD),this.lineWidthBuffer=Zt(n,a,"vec2",i.aLineWidth),this.colorBuffer=Zt(n,a,"vec4",i.aColor),this.cornerRadiusBuffer=Zt(n,a,"vec4",i.aCornerRadius),this.borderColorBuffer=Zt(n,a,"vec4",i.aBorderColor),n.bindVertexArray(null),o}},{key:"buffers",get:function(){var r=this;return this._buffers||(this._buffers=Object.keys(this).filter(function(a){return yr(a,"Buffer")}).map(function(a){return r[a]})),this._buffers}},{key:"startFrame",value:function(r){var a=arguments.length>1&&arguments[1]!==void 0?arguments[1]:Xa.SCREEN;this.panZoomMatrix=r,this.renderTarget=a,this.batchDebugInfo=[],this.wrappedCount=0,this.simpleCount=0,this.startBatch()}},{key:"startBatch",value:function(){this.instanceCount=0,this.batchManager.startBatch()}},{key:"endFrame",value:function(){this.endBatch()}},{key:"_isVisible",value:function(r,a){return r.visible()?a&&a.isVisible?a.isVisible(r):!0:!1}},{key:"drawTexture",value:function(r,a,n){var i=this.atlasManager,o=this.batchManager,s=i.getRenderTypeOpts(n);if(this._isVisible(r,s)&&!(r.isEdge()&&!this._isValidEdge(r))){if(this.renderTarget.picking&&s.getTexPickingMode){var u=s.getTexPickingMode(r);if(u===oi.IGNORE)return;if(u==oi.USE_BB){this.drawPickingRectangle(r,a,n);return}}var l=i.getAtlasInfo(r,n),f=zt(l),v;try{for(f.s();!(v=f.n()).done;){var c=v.value,h=c.atlas,d=c.tex1,g=c.tex2;o.canAddToCurrentBatch(h)||this.endBatch();for(var m=o.getAtlasIndexForBatch(h),p=0,y=[[d,!0],[g,!1]];p<y.length;p++){var b=dt(y[p],2),E=b[0],C=b[1];if(E.w!=0){var A=this.instanceCount;this.vertTypeBuffer.getView(A)[0]=is;var D=this.indexBuffer.getView(A);sa(a,D);var N=this.atlasIdBuffer.getView(A);N[0]=m;var O=this.texBuffer.getView(A);O[0]=E.x,O[1]=E.y,O[2]=E.w,O[3]=E.h;var R=this.transformBuffer.getMatrixView(A);this.setTransformMatrix(r,R,s,c,C),this.instanceCount++,C||this.wrappedCount++,this.instanceCount>=this.maxInstances&&this.endBatch()}}}}catch(P){f.e(P)}finally{f.f()}}}},{key:"setTransformMatrix",value:function(r,a,n,i){var o=arguments.length>4&&arguments[4]!==void 0?arguments[4]:!0,s=0;if(n.shapeProps&&n.shapeProps.padding&&(s=r.pstyle(n.shapeProps.padding).pfValue),i){var u=i.bb,l=i.tex1,f=i.tex2,v=l.w/(l.w+f.w);o||(v=1-v);var c=this._getAdjustedBB(u,s,o,v);this._applyTransformMatrix(a,c,n,r)}else{var h=n.getBoundingBox(r),d=this._getAdjustedBB(h,s,!0,1);this._applyTransformMatrix(a,d,n,r)}}},{key:"_applyTransformMatrix",value:function(r,a,n,i){var o,s;Uf(r);var u=n.getRotation?n.getRotation(i):0;if(u!==0){var l=n.getRotationPoint(i),f=l.x,v=l.y;$n(r,r,[f,v]),Hf(r,r,u);var c=n.getRotationOffset(i);o=c.x+(a.xOffset||0),s=c.y+(a.yOffset||0)}else o=a.x1,s=a.y1;$n(r,r,[o,s]),Ds(r,r,[a.w,a.h])}},{key:"_getAdjustedBB",value:function(r,a,n,i){var o=r.x1,s=r.y1,u=r.w,l=r.h,f=r.yOffset;a&&(o-=a,s-=a,u+=2*a,l+=2*a);var v=0,c=u*i;return n&&i<1?u=c:!n&&i<1&&(v=u-c,o+=v,u=c),{x1:o,y1:s,w:u,h:l,xOffset:v,yOffset:f}}},{key:"drawPickingRectangle",value:function(r,a,n){var i=this.atlasManager.getRenderTypeOpts(n),o=this.instanceCount;this.vertTypeBuffer.getView(o)[0]=la;var s=this.indexBuffer.getView(o);sa(a,s);var u=this.colorBuffer.getView(o);zr([0,0,0],1,u);var l=this.transformBuffer.getMatrixView(o);this.setTransformMatrix(r,l,i),this.simpleCount++,this.instanceCount++,this.instanceCount>=this.maxInstances&&this.endBatch()}},{key:"drawNode",value:function(r,a,n){var i=this.simpleShapeOptions.get(n);if(this._isVisible(r,i)){var o=i.shapeProps,s=this._getVertTypeForShape(r,o.shape);if(s===void 0||i.isSimple&&!i.isSimple(r,this.renderTarget)){this.drawTexture(r,a,n);return}var u=this.instanceCount;if(this.vertTypeBuffer.getView(u)[0]=s,s===kn||s===Va){var l=i.getBoundingBox(r),f=this._getCornerRadius(r,o.radius,l),v=this.cornerRadiusBuffer.getView(u);v[0]=f,v[1]=f,v[2]=f,v[3]=f,s===Va&&(v[0]=0,v[2]=0)}var c=this.indexBuffer.getView(u);sa(a,c);var h=this.renderTarget.picking?1:n==="node-body"?r.effectiveOpacity():1,d=this.renderTarget.picking?1:r.pstyle(o.opacity).value*h,g=r.pstyle(o.color).value,m=this.colorBuffer.getView(u);zr(g,d,m);var p=this.lineWidthBuffer.getView(u);if(p[0]=0,p[1]=0,o.border){var y=r.pstyle("border-width").value;if(y>0){var b=r.pstyle("border-color").value,E=h*r.pstyle("border-opacity").value,C=this.borderColorBuffer.getView(u);zr(b,E,C);var A=r.pstyle("border-position").value;if(A==="inside")p[0]=0,p[1]=-y;else if(A==="outside")p[0]=y,p[1]=0;else{var D=y/2;p[0]=D,p[1]=-D}}}var N=this.transformBuffer.getMatrixView(u);this.setTransformMatrix(r,N,i),this.simpleCount++,this.instanceCount++,this.instanceCount>=this.maxInstances&&this.endBatch()}}},{key:"_getVertTypeForShape",value:function(r,a){var n=r.pstyle(a).value;switch(n){case"rectangle":return la;case"ellipse":return Ga;case"roundrectangle":case"round-rectangle":return kn;case"bottom-round-rectangle":return Va;default:return}}},{key:"_getCornerRadius",value:function(r,a,n){var i=n.w,o=n.h;if(r.pstyle(a).value==="auto")return Cr(i,o);var s=r.pstyle(a).pfValue,u=i/2,l=o/2;return Math.min(s,l,u)}},{key:"drawEdgeArrow",value:function(r,a,n){if(r.visible()){var i=r._private.rscratch,o,s,u;if(n==="source"?(o=i.arrowStartX,s=i.arrowStartY,u=i.srcArrowAngle):(o=i.arrowEndX,s=i.arrowEndY,u=i.tgtArrowAngle),!(isNaN(o)||o==null||isNaN(s)||s==null||isNaN(u)||u==null)){var l=r.pstyle(n+"-arrow-shape").value;if(l!=="none"){var f=r.pstyle(n+"-arrow-color").value,v=r.pstyle("opacity").value,c=r.pstyle("line-opacity").value,h=v*c,d=r.pstyle("width").pfValue,g=r.pstyle("arrow-scale").value,m=this.r.getArrowWidth(d,g),p=this.instanceCount,y=this.transformBuffer.getMatrixView(p);Uf(y),$n(y,y,[o,s]),Ds(y,y,[m,m]),Hf(y,y,u),this.vertTypeBuffer.getView(p)[0]=os;var b=this.indexBuffer.getView(p);sa(a,b);var E=this.colorBuffer.getView(p);zr(f,h,E),this.instanceCount++,this.instanceCount>=this.maxInstances&&this.endBatch()}}}}},{key:"drawEdgeLine",value:function(r,a){if(r.visible()){var n=this._getEdgePoints(r);if(n){var i=r.pstyle("opacity").value,o=r.pstyle("line-opacity").value,s=r.pstyle("width").pfValue,u=r.pstyle("line-color").value,l=i*o;if(n.length/2+this.instanceCount>this.maxInstances&&this.endBatch(),n.length==4){var f=this.instanceCount;this.vertTypeBuffer.getView(f)[0]=qf;var v=this.indexBuffer.getView(f);sa(a,v);var c=this.colorBuffer.getView(f);zr(u,l,c);var h=this.lineWidthBuffer.getView(f);h[0]=s;var d=this.pointAPointBBuffer.getView(f);d[0]=n[0],d[1]=n[1],d[2]=n[2],d[3]=n[3],this.instanceCount++,this.instanceCount>=this.maxInstances&&this.endBatch()}else for(var g=0;g<n.length-2;g+=2){var m=this.instanceCount;this.vertTypeBuffer.getView(m)[0]=Yf;var p=this.indexBuffer.getView(m);sa(a,p);var y=this.colorBuffer.getView(m);zr(u,l,y);var b=this.lineWidthBuffer.getView(m);b[0]=s;var E=n[g-2],C=n[g-1],A=n[g],D=n[g+1],N=n[g+2],O=n[g+3],R=n[g+4],P=n[g+5];g==0&&(E=2*A-N+.001,C=2*D-O+.001),g==n.length-4&&(R=2*N-A+.001,P=2*O-D+.001);var w=this.pointAPointBBuffer.getView(m);w[0]=E,w[1]=C,w[2]=A,w[3]=D;var x=this.pointCPointDBuffer.getView(m);x[0]=N,x[1]=O,x[2]=R,x[3]=P,this.instanceCount++,this.instanceCount>=this.maxInstances&&this.endBatch()}}}}},{key:"_isValidEdge",value:function(r){var a=r._private.rscratch;return!(a.badLine||a.allpts==null||isNaN(a.allpts[0]))}},{key:"_getEdgePoints",value:function(r){var a=r._private.rscratch;if(this._isValidEdge(r)){var n=a.allpts;if(n.length==4)return n;var i=this._getNumSegments(r);return this._getCurveSegmentPoints(n,i)}}},{key:"_getNumSegments",value:function(r){var a=15;return Math.min(Math.max(a,5),this.maxInstances)}},{key:"_getCurveSegmentPoints",value:function(r,a){if(r.length==4)return r;for(var n=Array((a+1)*2),i=0;i<=a;i++)if(i==0)n[0]=r[0],n[1]=r[1];else if(i==a)n[i*2]=r[r.length-2],n[i*2+1]=r[r.length-1];else{var o=i/a;this._setCurvePoint(r,o,n,i*2)}return n}},{key:"_setCurvePoint",value:function(r,a,n,i){if(r.length<=2)n[i]=r[0],n[i+1]=r[1];else{for(var o=Array(r.length-2),s=0;s<o.length;s+=2){var u=(1-a)*r[s]+a*r[s+2],l=(1-a)*r[s+1]+a*r[s+3];o[s]=u,o[s+1]=l}return this._setCurvePoint(o,a,n,i)}}},{key:"endBatch",value:function(){var r=this.gl,a=this.vao,n=this.vertexCount,i=this.instanceCount;if(i!==0){var o=this.renderTarget.picking?this.pickingProgram:this.program;r.useProgram(o),r.bindVertexArray(a);var s=zt(this.buffers),u;try{for(s.s();!(u=s.n()).done;){var l=u.value;l.bufferSubData(i)}}catch(d){s.e(d)}finally{s.f()}for(var f=this.batchManager.getAtlases(),v=0;v<f.length;v++)f[v].bufferIfNeeded(r);for(var c=0;c<f.length;c++)r.activeTexture(r.TEXTURE0+c),r.bindTexture(r.TEXTURE_2D,f[c].texture),r.uniform1i(o.uTextures[c],c);r.uniform1f(o.uZoom,e0(this.r)),r.uniformMatrix3fv(o.uPanZoomMatrix,!1,this.panZoomMatrix),r.uniform1i(o.uAtlasSize,this.batchManager.getAtlasSize());var h=zr(this.bgColor,1);r.uniform4fv(o.uBGColor,h),r.drawArraysInstanced(r.TRIANGLES,0,n,i),r.bindVertexArray(null),r.bindTexture(r.TEXTURE_2D,null),this.debug&&this.batchDebugInfo.push({count:i,atlasCount:f.length}),this.startBatch()}}},{key:"getDebugInfo",value:function(){var r=this.atlasManager.getDebugInfo(),a=r.reduce(function(o,s){return o+s.atlasCount},0),n=this.batchDebugInfo,i=n.reduce(function(o,s){return o+s.count},0);return{atlasInfo:r,totalAtlases:a,wrappedCount:this.wrappedCount,simpleCount:this.simpleCount,batchCount:n.length,batchInfo:n,totalInstances:i}}}])})(),Mc={};Mc.initWebgl=function(t,e){var r=this,a=r.data.contexts[r.WEBGL];t.bgColor=x0(r),t.webglTexSize=Math.min(t.webglTexSize,a.getParameter(a.MAX_TEXTURE_SIZE)),t.webglTexRows=Math.min(t.webglTexRows,54),t.webglTexRowsNodes=Math.min(t.webglTexRowsNodes,54),t.webglBatchSize=Math.min(t.webglBatchSize,16384),t.webglTexPerBatch=Math.min(t.webglTexPerBatch,a.getParameter(a.MAX_TEXTURE_IMAGE_UNITS)),r.webglDebug=t.webglDebug,r.webglDebugShowAtlases=t.webglDebugShowAtlases,r.pickingFrameBuffer=u0(a),r.pickingFrameBuffer.needsDraw=!0,r.drawing=new E0(r,a,t);var n=function(v){return function(c){return r.getTextAngle(c,v)}},i=function(v){return function(c){var h=c.pstyle(v);return h&&h.value}},o=function(v){return function(c){return c.pstyle("".concat(v,"-opacity")).value>0}},s=function(v){var c=v.pstyle("text-events").strValue==="yes";return c?oi.USE_BB:oi.IGNORE},u=function(v){var c=v.position(),h=c.x,d=c.y,g=v.outerWidth(),m=v.outerHeight();return{w:g,h:m,x1:h-g/2,y1:d-m/2}};r.drawing.addAtlasCollection("node",{texRows:t.webglTexRowsNodes}),r.drawing.addAtlasCollection("label",{texRows:t.webglTexRows}),r.drawing.addTextureAtlasRenderType("node-body",{collection:"node",getKey:e.getStyleKey,getBoundingBox:e.getElementBox,drawElement:e.drawElement}),r.drawing.addSimpleShapeRenderType("node-body",{getBoundingBox:u,isSimple:r0,shapeProps:{shape:"shape",color:"background-color",opacity:"background-opacity",radius:"corner-radius",border:!0}}),r.drawing.addSimpleShapeRenderType("node-overlay",{getBoundingBox:u,isVisible:o("overlay"),shapeProps:{shape:"overlay-shape",color:"overlay-color",opacity:"overlay-opacity",padding:"overlay-padding",radius:"overlay-corner-radius"}}),r.drawing.addSimpleShapeRenderType("node-underlay",{getBoundingBox:u,isVisible:o("underlay"),shapeProps:{shape:"underlay-shape",color:"underlay-color",opacity:"underlay-opacity",padding:"underlay-padding",radius:"underlay-corner-radius"}}),r.drawing.addTextureAtlasRenderType("label",{collection:"label",getTexPickingMode:s,getKey:ss(e.getLabelKey,null),getBoundingBox:ls(e.getLabelBox,null),drawClipped:!0,drawElement:e.drawLabel,getRotation:n(null),getRotationPoint:e.getLabelRotationPoint,getRotationOffset:e.getLabelRotationOffset,isVisible:i("label")}),r.drawing.addTextureAtlasRenderType("edge-source-label",{collection:"label",getTexPickingMode:s,getKey:ss(e.getSourceLabelKey,"source"),getBoundingBox:ls(e.getSourceLabelBox,"source"),drawClipped:!0,drawElement:e.drawSourceLabel,getRotation:n("source"),getRotationPoint:e.getSourceLabelRotationPoint,getRotationOffset:e.getSourceLabelRotationOffset,isVisible:i("source-label")}),r.drawing.addTextureAtlasRenderType("edge-target-label",{collection:"label",getTexPickingMode:s,getKey:ss(e.getTargetLabelKey,"target"),getBoundingBox:ls(e.getTargetLabelBox,"target"),drawClipped:!0,drawElement:e.drawTargetLabel,getRotation:n("target"),getRotationPoint:e.getTargetLabelRotationPoint,getRotationOffset:e.getTargetLabelRotationOffset,isVisible:i("target-label")});var l=un(function(){console.log("garbage collect flag set"),r.data.gc=!0},1e4);r.onUpdateEleCalcs(function(f,v){var c=!1;v&&v.length>0&&(c|=r.drawing.invalidate(v)),c&&l()}),T0(r)};function x0(t){var e=t.cy.container(),r=e&&e.style&&e.style.backgroundColor||"white";return tv(r)}function Lc(t,e){var r=t._private.rscratch;return It(r,"labelWrapCachedLines",e)||[]}var ss=function(e,r){return function(a){var n=e(a),i=Lc(a,r);return i.length>1?i.map(function(o,s){return"".concat(n,"_").concat(s)}):n}},ls=function(e,r){return function(a,n){var i=e(a);if(typeof n=="string"){var o=n.indexOf("_");if(o>0){var s=Number(n.substring(o+1)),u=Lc(a,r),l=i.h/u.length,f=l*s,v=i.y1+f;return{x1:i.x1,w:i.w,y1:v,h:l,yOffset:f}}}return i}};function T0(t){{var e=t.render;t.render=function(i){i=i||{};var o=t.cy;t.webgl&&(o.zoom()>Ec?(C0(t),e.call(t,i)):(S0(t),Rc(t,i,Xa.SCREEN)))}}{var r=t.matchCanvasSize;t.matchCanvasSize=function(i){r.call(t,i),t.pickingFrameBuffer.setFramebufferAttachmentSizes(t.canvasWidth,t.canvasHeight),t.pickingFrameBuffer.needsDraw=!0}}t.findNearestElements=function(i,o,s,u){return R0(t,i,o)};{var a=t.invalidateCachedZSortedEles;t.invalidateCachedZSortedEles=function(){a.call(t),t.pickingFrameBuffer.needsDraw=!0}}{var n=t.notify;t.notify=function(i,o){n.call(t,i,o),i==="viewport"||i==="bounds"?t.pickingFrameBuffer.needsDraw=!0:i==="background"&&t.drawing.invalidate(o,{type:"node-body"})}}}function C0(t){var e=t.data.contexts[t.WEBGL];e.clear(e.COLOR_BUFFER_BIT|e.DEPTH_BUFFER_BIT)}function S0(t){var e=function(a){a.save(),a.setTransform(1,0,0,1,0,0),a.clearRect(0,0,t.canvasWidth,t.canvasHeight),a.restore()};e(t.data.contexts[t.NODE]),e(t.data.contexts[t.DRAG])}function D0(t){var e=t.canvasWidth,r=t.canvasHeight,a=el(t),n=a.pan,i=a.zoom,o=ns();$n(o,o,[n.x,n.y]),Ds(o,o,[i,i]);var s=ns();v0(s,e,r);var u=ns();return f0(u,s,o),u}function Nc(t,e){var r=t.canvasWidth,a=t.canvasHeight,n=el(t),i=n.pan,o=n.zoom;e.setTransform(1,0,0,1,0,0),e.clearRect(0,0,r,a),e.translate(i.x,i.y),e.scale(o,o)}function A0(t,e){t.drawSelectionRectangle(e,function(r){return Nc(t,r)})}function M0(t){var e=t.data.contexts[t.NODE];e.save(),Nc(t,e),e.strokeStyle="rgba(0, 0, 0, 0.3)",e.beginPath(),e.moveTo(-1e3,0),e.lineTo(1e3,0),e.stroke(),e.beginPath(),e.moveTo(0,-1e3),e.lineTo(0,1e3),e.stroke(),e.restore()}function L0(t){var e=function(n,i,o){for(var s=n.atlasManager.getAtlasCollection(i),u=t.data.contexts[t.NODE],l=s.atlases,f=0;f<l.length;f++){var v=l[f],c=v.canvas;if(c){var h=c.width,d=c.height,g=h*f,m=c.height*o,p=.4;u.save(),u.scale(p,p),u.drawImage(c,g,m),u.strokeStyle="black",u.rect(g,m,h,d),u.stroke(),u.restore()}}},r=0;e(t.drawing,"node",r++),e(t.drawing,"label",r++)}function N0(t,e,r,a,n){var i,o,s,u,l=el(t),f=l.pan,v=l.zoom;{var c=t0(t,f,v,e,r),h=dt(c,2),d=h[0],g=h[1],m=6;i=d-m/2,o=g-m/2,s=m,u=m}if(s===0||u===0)return[];var p=t.data.contexts[t.WEBGL];p.bindFramebuffer(p.FRAMEBUFFER,t.pickingFrameBuffer),t.pickingFrameBuffer.needsDraw&&(p.viewport(0,0,p.canvas.width,p.canvas.height),Rc(t,null,Xa.PICKING),t.pickingFrameBuffer.needsDraw=!1);var y=s*u,b=new Uint8Array(y*4);p.readPixels(i,o,s,u,p.RGBA,p.UNSIGNED_BYTE,b),p.bindFramebuffer(p.FRAMEBUFFER,null);for(var E=new Set,C=0;C<y;C++){var A=b.slice(C*4,C*4+4),D=n0(A)-1;D>=0&&E.add(D)}return E}function R0(t,e,r){var a=N0(t,e,r),n=t.getCachedZSortedEles(),i,o,s=zt(a),u;try{for(s.s();!(u=s.n()).done;){var l=u.value,f=n[l];if(!i&&f.isNode()&&(i=f),!o&&f.isEdge()&&(o=f),i&&o)break}}catch(v){s.e(v)}finally{s.f()}return[i,o].filter(Boolean)}function us(t,e,r){var a=t.drawing;e+=1,r.isNode()?(a.drawNode(r,e,"node-underlay"),a.drawNode(r,e,"node-body"),a.drawTexture(r,e,"label"),a.drawNode(r,e,"node-overlay")):(a.drawEdgeLine(r,e),a.drawEdgeArrow(r,e,"source"),a.drawEdgeArrow(r,e,"target"),a.drawTexture(r,e,"label"),a.drawTexture(r,e,"edge-source-label"),a.drawTexture(r,e,"edge-target-label"))}function Rc(t,e,r){var a;t.webglDebug&&(a=performance.now());var n=t.drawing,i=0;if(r.screen&&t.data.canvasNeedsRedraw[t.SELECT_BOX]&&A0(t,e),t.data.canvasNeedsRedraw[t.NODE]||r.picking){var o=t.data.contexts[t.WEBGL];r.screen?(o.clearColor(0,0,0,0),o.enable(o.BLEND),o.blendFunc(o.ONE,o.ONE_MINUS_SRC_ALPHA)):o.disable(o.BLEND),o.clear(o.COLOR_BUFFER_BIT|o.DEPTH_BUFFER_BIT),o.viewport(0,0,o.canvas.width,o.canvas.height);var s=D0(t),u=t.getCachedZSortedEles();if(i=u.length,n.startFrame(s,r),r.screen){for(var l=0;l<u.nondrag.length;l++)us(t,l,u.nondrag[l]);for(var f=0;f<u.drag.length;f++)us(t,f,u.drag[f])}else if(r.picking)for(var v=0;v<u.length;v++)us(t,v,u[v]);n.endFrame(),r.screen&&t.webglDebugShowAtlases&&(M0(t),L0(t)),t.data.canvasNeedsRedraw[t.NODE]=!1,t.data.canvasNeedsRedraw[t.DRAG]=!1}if(t.webglDebug){var c=performance.now(),h=!1,d=Math.ceil(c-a),g=n.getDebugInfo(),m=["".concat(i," elements"),"".concat(g.totalInstances," instances"),"".concat(g.batchCount," batches"),"".concat(g.totalAtlases," atlases"),"".concat(g.wrappedCount," wrapped textures"),"".concat(g.simpleCount," simple shapes")].join(", ");if(h)console.log("WebGL (".concat(r.name,") - time ").concat(d,"ms, ").concat(m));else{console.log("WebGL (".concat(r.name,") - frame time ").concat(d,"ms")),console.log("Totals:"),console.log(" ".concat(m)),console.log("Texture Atlases Used:");var p=g.atlasInfo,y=zt(p),b;try{for(y.s();!(b=y.n()).done;){var E=b.value;console.log(" ".concat(E.type,": ").concat(E.keyCount," keys, ").concat(E.atlasCount," atlases"))}}catch(C){y.e(C)}finally{y.f()}console.log("")}}t.data.gc&&(console.log("Garbage Collect!"),t.data.gc=!1,n.gc())}var Pr={};Pr.drawPolygonPath=function(t,e,r,a,n,i){var o=a/2,s=n/2;t.beginPath&&t.beginPath(),t.moveTo(e+o*i[0],r+s*i[1]);for(var u=1;u<i.length/2;u++)t.lineTo(e+o*i[u*2],r+s*i[u*2+1]);t.closePath()};Pr.drawRoundPolygonPath=function(t,e,r,a,n,i,o){o.forEach(function(s){return vc(t,s)}),t.closePath()};Pr.drawRoundRectanglePath=function(t,e,r,a,n,i){var o=a/2,s=n/2,u=i==="auto"?Cr(a,n):Math.min(i,s,o);t.beginPath&&t.beginPath(),t.moveTo(e,r-s),t.arcTo(e+o,r-s,e+o,r,u),t.arcTo(e+o,r+s,e,r+s,u),t.arcTo(e-o,r+s,e-o,r,u),t.arcTo(e-o,r-s,e,r-s,u),t.lineTo(e,r-s),t.closePath()};Pr.drawBottomRoundRectanglePath=function(t,e,r,a,n,i){var o=a/2,s=n/2,u=i==="auto"?Cr(a,n):i;t.beginPath&&t.beginPath(),t.moveTo(e,r-s),t.lineTo(e+o,r-s),t.lineTo(e+o,r),t.arcTo(e+o,r+s,e,r+s,u),t.arcTo(e-o,r+s,e-o,r,u),t.lineTo(e-o,r-s),t.lineTo(e,r-s),t.closePath()};Pr.drawCutRectanglePath=function(t,e,r,a,n,i,o){var s=a/2,u=n/2,l=o==="auto"?Gs():o;t.beginPath&&t.beginPath(),t.moveTo(e-s+l,r-u),t.lineTo(e+s-l,r-u),t.lineTo(e+s,r-u+l),t.lineTo(e+s,r+u-l),t.lineTo(e+s-l,r+u),t.lineTo(e-s+l,r+u),t.lineTo(e-s,r+u-l),t.lineTo(e-s,r-u+l),t.closePath()};Pr.drawBarrelPath=function(t,e,r,a,n){var i=a/2,o=n/2,s=e-i,u=e+i,l=r-o,f=r+o,v=cs(a,n),c=v.widthOffset,h=v.heightOffset,d=v.ctrlPtOffsetPct*c;t.beginPath&&t.beginPath(),t.moveTo(s,l+h),t.lineTo(s,f-h),t.quadraticCurveTo(s+d,f,s+c,f),t.lineTo(u-c,f),t.quadraticCurveTo(u-d,f,u,f-h),t.lineTo(u,l+h),t.quadraticCurveTo(u-d,l,u-c,l),t.lineTo(s+c,l),t.quadraticCurveTo(s+d,l,s,l+h),t.closePath()};var Wf=Math.sin(0),Xf=Math.cos(0),As={},Ms={},Pc=Math.PI/40;for(Vr=0*Math.PI;Vr<2*Math.PI;Vr+=Pc)As[Vr]=Math.sin(Vr),Ms[Vr]=Math.cos(Vr);var Vr;Pr.drawEllipsePath=function(t,e,r,a,n){if(t.beginPath&&t.beginPath(),t.ellipse)t.ellipse(e,r,a/2,n/2,0,0,2*Math.PI);else for(var i,o,s=a/2,u=n/2,l=0*Math.PI;l<2*Math.PI;l+=Pc)i=e-s*As[l]*Wf+s*Ms[l]*Xf,o=r+u*Ms[l]*Wf+u*As[l]*Xf,l===0?t.moveTo(i,o):t.lineTo(i,o);t.closePath()};var gn={};gn.createBuffer=function(t,e){var r=document.createElement("canvas");return r.width=t,r.height=e,[r,r.getContext("2d")]};gn.bufferCanvasImage=function(t){var e=this.cy,r=e.mutableElements(),a=r.boundingBox(),n=this.findContainerClientCoords(),i=t.full?Math.ceil(a.w):n[2],o=t.full?Math.ceil(a.h):n[3],s=we(t.maxWidth)||we(t.maxHeight),u=this.getPixelRatio(),l=1;if(t.scale!==void 0)i*=t.scale,o*=t.scale,l=t.scale;else if(s){var f=1/0,v=1/0;we(t.maxWidth)&&(f=l*t.maxWidth/i),we(t.maxHeight)&&(v=l*t.maxHeight/o),l=Math.min(f,v),i*=l,o*=l}s||(i*=u,o*=u,l*=u);var c=document.createElement("canvas");c.width=i,c.height=o,c.style.width=i+"px",c.style.height=o+"px";var h=c.getContext("2d");if(i>0&&o>0){h.clearRect(0,0,i,o),h.globalCompositeOperation="source-over";var d=this.getCachedZSortedEles();if(t.full)h.translate(-a.x1*l,-a.y1*l),h.scale(l,l),this.drawElements(h,d),h.scale(1/l,1/l),h.translate(a.x1*l,a.y1*l);else{var g=e.pan(),m={x:g.x*l,y:g.y*l};l*=e.zoom(),h.translate(m.x,m.y),h.scale(l,l),this.drawElements(h,d),h.scale(1/l,1/l),h.translate(-m.x,-m.y)}t.bg&&(h.globalCompositeOperation="destination-over",h.fillStyle=t.bg,h.rect(0,0,i,o),h.fill())}return c};function P0(t,e){for(var r=atob(t),a=new ArrayBuffer(r.length),n=new Uint8Array(a),i=0;i<r.length;i++)n[i]=r.charCodeAt(i);return new Blob([a],{type:e})}function $f(t){var e=t.indexOf(",");return t.substr(e+1)}function Oc(t,e,r){var a=function(){return e.toDataURL(r,t.quality)};switch(t.output){case"blob-promise":return new Ta(function(n,i){try{e.toBlob(function(o){o!=null?n(o):i(new Error("`canvas.toBlob()` sent a null value in its callback"))},r,t.quality)}catch(o){i(o)}});case"blob":return P0($f(a()),r);case"base64":return $f(a());default:return a()}}gn.png=function(t){return Oc(t,this.bufferCanvasImage(t),"image/png")};gn.jpg=function(t){return Oc(t,this.bufferCanvasImage(t),"image/jpeg")};var Ic={};Ic.nodeShapeImpl=function(t,e,r,a,n,i,o,s){switch(t){case"ellipse":return this.drawEllipsePath(e,r,a,n,i);case"polygon":return this.drawPolygonPath(e,r,a,n,i,o);case"round-polygon":return this.drawRoundPolygonPath(e,r,a,n,i,o,s);case"roundrectangle":case"round-rectangle":return this.drawRoundRectanglePath(e,r,a,n,i,s);case"cutrectangle":case"cut-rectangle":return this.drawCutRectanglePath(e,r,a,n,i,o,s);case"bottomroundrectangle":case"bottom-round-rectangle":return this.drawBottomRoundRectanglePath(e,r,a,n,i,s);case"barrel":return this.drawBarrelPath(e,r,a,n,i)}};var O0=Bc,Ge=Bc.prototype;Ge.CANVAS_LAYERS=3;Ge.SELECT_BOX=0;Ge.DRAG=1;Ge.NODE=2;Ge.WEBGL=3;Ge.CANVAS_TYPES=["2d","2d","2d","webgl2"];Ge.BUFFER_COUNT=3;Ge.TEXTURE_BUFFER=0;Ge.MOTIONBLUR_BUFFER_NODE=1;Ge.MOTIONBLUR_BUFFER_DRAG=2;function Bc(t){var e=this,r=e.cy.window(),a=r.document;t.webgl&&(Ge.CANVAS_LAYERS=e.CANVAS_LAYERS=4,console.log("webgl rendering enabled")),e.data={canvases:new Array(Ge.CANVAS_LAYERS),contexts:new Array(Ge.CANVAS_LAYERS),canvasNeedsRedraw:new Array(Ge.CANVAS_LAYERS),bufferCanvases:new Array(Ge.BUFFER_COUNT),bufferContexts:new Array(Ge.CANVAS_LAYERS)};var n="-webkit-tap-highlight-color",i="rgba(0,0,0,0)";e.data.canvasContainer=a.createElement("div");var o=e.data.canvasContainer.style;e.data.canvasContainer.style[n]=i,o.position="relative",o.zIndex="0",o.overflow="hidden";var s=t.cy.container();s.appendChild(e.data.canvasContainer),s.style[n]=i;var u={"-webkit-user-select":"none","-moz-user-select":"-moz-none","user-select":"none","-webkit-tap-highlight-color":"rgba(0,0,0,0)","outline-style":"none"};Ch()&&(u["-ms-touch-action"]="none",u["touch-action"]="none");for(var l=0;l<Ge.CANVAS_LAYERS;l++){var f=e.data.canvases[l]=a.createElement("canvas"),v=Ge.CANVAS_TYPES[l];e.data.contexts[l]=f.getContext(v),e.data.contexts[l]||nt("Could not create canvas of type "+v),Object.keys(u).forEach(function($){f.style[$]=u[$]}),f.style.position="absolute",f.setAttribute("data-id","layer"+l),f.style.zIndex=String(Ge.CANVAS_LAYERS-l),e.data.canvasContainer.appendChild(f),e.data.canvasNeedsRedraw[l]=!1}e.data.topCanvas=e.data.canvases[0],e.data.canvases[Ge.NODE].setAttribute("data-id","layer"+Ge.NODE+"-node"),e.data.canvases[Ge.SELECT_BOX].setAttribute("data-id","layer"+Ge.SELECT_BOX+"-selectbox"),e.data.canvases[Ge.DRAG].setAttribute("data-id","layer"+Ge.DRAG+"-drag"),e.data.canvases[Ge.WEBGL]&&e.data.canvases[Ge.WEBGL].setAttribute("data-id","layer"+Ge.WEBGL+"-webgl");for(var l=0;l<Ge.BUFFER_COUNT;l++)e.data.bufferCanvases[l]=a.createElement("canvas"),e.data.bufferContexts[l]=e.data.bufferCanvases[l].getContext("2d"),e.data.bufferCanvases[l].style.position="absolute",e.data.bufferCanvases[l].setAttribute("data-id","buffer"+l),e.data.bufferCanvases[l].style.zIndex=String(-l-1),e.data.bufferCanvases[l].style.visibility="hidden";e.pathsEnabled=!0;var c=Bt(),h=function(q){return{x:(q.x1+q.x2)/2,y:(q.y1+q.y2)/2}},d=function(q){return{x:-q.w/2,y:-q.h/2}},g=function(q){var K=q[0]._private,ee=K.oldBackgroundTimestamp===K.backgroundTimestamp;return!ee},m=function(q){return q[0]._private.nodeKey},p=function(q){return q[0]._private.labelStyleKey},y=function(q){return q[0]._private.sourceLabelStyleKey},b=function(q){return q[0]._private.targetLabelStyleKey},E=function(q,K,ee,ne,te){return e.drawElement(q,K,ee,!1,!1,te)},C=function(q,K,ee,ne,te){return e.drawElementText(q,K,ee,ne,"main",te)},A=function(q,K,ee,ne,te){return e.drawElementText(q,K,ee,ne,"source",te)},D=function(q,K,ee,ne,te){return e.drawElementText(q,K,ee,ne,"target",te)},N=function(q){return q.boundingBox(),q[0]._private.bodyBounds},O=function(q){return q.boundingBox(),q[0]._private.labelBounds.main||c},R=function(q){return q.boundingBox(),q[0]._private.labelBounds.source||c},P=function(q){return q.boundingBox(),q[0]._private.labelBounds.target||c},w=function(q,K){return K},x=function(q){return h(N(q))},T=function(q,K,ee){var ne=q?q+"-":"";return{x:K.x+ee.pstyle(ne+"text-margin-x").pfValue,y:K.y+ee.pstyle(ne+"text-margin-y").pfValue}},M=function(q,K,ee){var ne=q[0]._private.rscratch;return{x:ne[K],y:ne[ee]}},S=function(q){return T("",M(q,"labelX","labelY"),q)},I=function(q){return T("source",M(q,"sourceLabelX","sourceLabelY"),q)},B=function(q){return T("target",M(q,"targetLabelX","targetLabelY"),q)},V=function(q){return d(N(q))},F=function(q){return d(R(q))},k=function(q){return d(P(q))},U=function(q){var K=O(q),ee=d(O(q));if(q.isNode()){switch(wa(q.pstyle("text-halign").value)){case"left":ee.x=-K.w-(K.leftPad||0);break;case"right":ee.x=-(K.rightPad||0);break}switch(Ea(q.pstyle("text-valign").value)){case"top":ee.y=-K.h-(K.topPad||0);break;case"bottom":ee.y=-(K.botPad||0);break}}return ee},J=e.data.eleTxrCache=new qa(e,{getKey:m,doesEleInvalidateKey:g,drawElement:E,getBoundingBox:N,getRotationPoint:x,getRotationOffset:V,allowEdgeTxrCaching:!1,allowParentTxrCaching:!1}),W=e.data.lblTxrCache=new qa(e,{getKey:p,drawElement:C,getBoundingBox:O,getRotationPoint:S,getRotationOffset:U,isVisible:w}),Q=e.data.slbTxrCache=new qa(e,{getKey:y,drawElement:A,getBoundingBox:R,getRotationPoint:I,getRotationOffset:F,isVisible:w}),Z=e.data.tlbTxrCache=new qa(e,{getKey:b,drawElement:D,getBoundingBox:P,getRotationPoint:B,getRotationOffset:k,isVisible:w}),H=e.data.lyrTxrCache=new xc(e);e.onUpdateEleCalcs(function(q,K){J.invalidateElements(K),W.invalidateElements(K),Q.invalidateElements(K),Z.invalidateElements(K),H.invalidateElements(K);for(var ee=0;ee<K.length;ee++){var ne=K[ee]._private;ne.oldBackgroundTimestamp=ne.backgroundTimestamp}});var j=function(q){for(var K=0;K<q.length;K++)H.enqueueElementRefinement(q[K].ele)};J.onDequeue(j),W.onDequeue(j),Q.onDequeue(j),Z.onDequeue(j),t.webgl&&e.initWebgl(t,{getStyleKey:m,getLabelKey:p,getSourceLabelKey:y,getTargetLabelKey:b,drawElement:E,drawLabel:C,drawSourceLabel:A,drawTargetLabel:D,getElementBox:N,getLabelBox:O,getSourceLabelBox:R,getTargetLabelBox:P,getElementRotationPoint:x,getElementRotationOffset:V,getLabelRotationPoint:S,getSourceLabelRotationPoint:I,getTargetLabelRotationPoint:B,getLabelRotationOffset:U,getSourceLabelRotationOffset:F,getTargetLabelRotationOffset:k})}Ge.redrawHint=function(t,e){var r=this;switch(t){case"eles":r.data.canvasNeedsRedraw[Ge.NODE]=e;break;case"drag":r.data.canvasNeedsRedraw[Ge.DRAG]=e;break;case"select":r.data.canvasNeedsRedraw[Ge.SELECT_BOX]=e;break;case"gc":r.data.gc=!0;break}};var I0=typeof Path2D<"u";Ge.path2dEnabled=function(t){if(t===void 0)return this.pathsEnabled;this.pathsEnabled=!!t};Ge.usePaths=function(){return I0&&this.pathsEnabled};Ge.setImgSmoothing=function(t,e){t.imageSmoothingEnabled!=null?t.imageSmoothingEnabled=e:(t.webkitImageSmoothingEnabled=e,t.mozImageSmoothingEnabled=e,t.msImageSmoothingEnabled=e)};Ge.getImgSmoothing=function(t){return t.imageSmoothingEnabled!=null?t.imageSmoothingEnabled:t.webkitImageSmoothingEnabled||t.mozImageSmoothingEnabled||t.msImageSmoothingEnabled};Ge.makeOffscreenCanvas=function(t,e){var r;if((typeof OffscreenCanvas>"u"?"undefined":mt(OffscreenCanvas))!=="undefined")r=new OffscreenCanvas(t,e);else{var a=this.cy.window(),n=a.document;r=n.createElement("canvas"),r.width=t,r.height=e}return r};[Tc,rr,fr,js,Qr,Rr,kt,Mc,Pr,gn,Ic].forEach(function(t){Re(Ge,t)});var B0=[{name:"null",impl:lc},{name:"base",impl:bc},{name:"canvas",impl:O0}],k0=[{type:"layout",extensions:im},{type:"renderer",extensions:B0}],kc={},Fc={};function zc(t,e,r){var a=r,n=function(N){Qe("Can not register `"+e+"` for `"+t+"` since `"+N+"` already exists in the prototype and can not be overridden")};if(t==="core"){if(tn.prototype[e])return n(e);tn.prototype[e]=r}else if(t==="collection"){if(St.prototype[e])return n(e);St.prototype[e]=r}else if(t==="layout"){for(var i=function(N){this.options=N,r.call(this,N),$e(this._private)||(this._private={}),this._private.cy=N.cy,this._private.listeners=[],this.createEmitter()},o=i.prototype=Object.create(r.prototype),s=[],u=0;u<s.length;u++){var l=s[u];o[l]=o[l]||function(){return this}}o.start&&!o.run?o.run=function(){return this.start(),this}:!o.start&&o.run&&(o.start=function(){return this.run(),this});var f=r.prototype.stop;o.stop=function(){var D=this.options;if(D&&D.animate){var N=this.animations;if(N)for(var O=0;O<N.length;O++)N[O].stop()}return f?f.call(this):this.emit("layoutstop"),this},o.destroy||(o.destroy=function(){return this}),o.cy=function(){return this._private.cy};var v=function(N){return N._private.cy},c={addEventFields:function(N,O){O.layout=N,O.cy=v(N),O.target=N},bubble:function(){return!0},parent:function(N){return v(N)}};Re(o,{createEmitter:function(){return this._private.emitter=new mi(c,this),this},emitter:function(){return this._private.emitter},on:function(N,O){return this.emitter().on(N,O),this},one:function(N,O){return this.emitter().one(N,O),this},once:function(N,O){return this.emitter().one(N,O),this},removeListener:function(N,O){return this.emitter().removeListener(N,O),this},removeAllListeners:function(){return this.emitter().removeAllListeners(),this},emit:function(N,O){return this.emitter().emit(N,O),this}}),Ze.eventAliasesOn(o),a=i}else if(t==="renderer"&&e!=="null"&&e!=="base"){var h=Vc("renderer","base"),d=h.prototype,g=r,m=r.prototype,p=function(){h.apply(this,arguments),g.apply(this,arguments)},y=p.prototype;for(var b in d){var E=d[b],C=m[b]!=null;if(C)return n(b);y[b]=E}for(var A in m)y[A]=m[A];d.clientFunctions.forEach(function(D){y[D]=y[D]||function(){nt("Renderer does not implement `renderer."+D+"()` on its prototype")}}),a=p}else if(t==="__proto__"||t==="constructor"||t==="prototype")return nt(t+" is an illegal type to be registered, possibly lead to prototype pollutions");return rv({map:kc,keys:[t,e],value:a})}function Vc(t,e){return av({map:kc,keys:[t,e]})}function F0(t,e,r,a,n){return rv({map:Fc,keys:[t,e,r,a],value:n})}function z0(t,e,r,a){return av({map:Fc,keys:[t,e,r,a]})}var Ls=function(){if(arguments.length===2)return Vc.apply(null,arguments);if(arguments.length===3)return zc.apply(null,arguments);if(arguments.length===4)return z0.apply(null,arguments);if(arguments.length===5)return F0.apply(null,arguments);nt("Invalid extension access syntax")};tn.prototype.extension=Ls;k0.forEach(function(t){t.extensions.forEach(function(e){zc(t.type,e.name,e.impl)})});var si=function(){if(!(this instanceof si))return new si;this.length=0},_r=si.prototype;_r.instanceString=function(){return"stylesheet"};_r.selector=function(t){var e=this.length++;return this[e]={selector:t,properties:[]},this};_r.css=function(t,e){var r=this.length-1;if(Le(t))this[r].properties.push({name:t,value:e});else if($e(t))for(var a=t,n=Object.keys(a),i=0;i<n.length;i++){var o=n[i],s=a[o];if(s!=null){var u=xt.properties[o]||xt.properties[li(o)];if(u!=null){var l=u.name,f=s;this[r].properties.push({name:l,value:f})}}}return this};_r.style=_r.css;_r.generateStyle=function(t){var e=new xt(t);return this.appendToStyle(e)};_r.appendToStyle=function(t){for(var e=0;e<this.length;e++){var r=this[e],a=r.selector,n=r.properties;t.selector(a);for(var i=0;i<n.length;i++){var o=n[i];t.css(o.name,o.value)}}return t};var V0="3.34.0",lr=function(e){if(e===void 0&&(e={}),$e(e))return new tn(e);if(Le(e))return Ls.apply(Ls,arguments)};lr.use=function(t){var e=Array.prototype.slice.call(arguments,1);return e.unshift(lr),t.apply(null,e),this};lr.warnings=function(t){return fv(t)};lr.version=V0;lr.stylesheet=lr.Stylesheet=si;var _c=oh(Gc(),1);var Ma={Entity:0,Service:1,Event:1,UseCase:2,Port:3,DTO:4,VO:4,Error:4,Shared:4,Adapter:5},qc={Entity:95,Service:72,Event:60,UseCase:48,Port:30,DTO:0,VO:0,Error:0,Shared:22,Adapter:18},Yc={Entity:"barrel",Service:"rectangle",UseCase:"round-rectangle",Port:"cut-rectangle",Event:"rhomboid",DTO:"round-rectangle",VO:"round-rectangle",Error:"round-rectangle",Shared:"round-rectangle",Adapter:"round-rectangle"},ol=["Entity","Service","UseCase","Port","Event"],sl=["DTO","VO","Error"],bn=42,Wc=338,G0=15;function Uc(t){let e=0;for(let a=0;a<t.length;a++)e=e*31+t.charCodeAt(a)|0;let r=Math.abs(e*.6180339887%1);return Math.round(bn+r*(Wc-bn))}var U0=(t,e)=>{let r=Math.abs(t-e)%360;return Math.min(r,360-r)};function Xc(t){let e=[...new Set(t)].filter(i=>!La(i)).sort(),r=[],a=new Map,n=Wc-bn;for(let i of e){let o=Uc(i),s=o;for(let u=0;u<n;u++){let l=bn+(o-bn+u)%n;if(r.every(f=>U0(f,l)>=G0)){s=l;break}}r.push(s),a.set(i,s)}return i=>La(i)?0:a.get(i)??Uc(i)}var La=t=>t==="common"||t==="shared",Di=190,H0=40,q0=230,Y0=268,W0=130,Hc=34,X0=30;function $0(t){let e=new Map;for(let o of t){let s=Ma[o.component];e.set(s,[...e.get(s)??[],o])}let r=new Map,a=0;for(let o of[...e.keys()].sort((s,u)=>s-u)){let s=e.get(o),u=s.length*Y0/(2*Math.PI),l=o===0&&s.length===1?0:Math.max(a+q0,u,170);s.forEach((f,v)=>{if(l===0)r.set(f.id,[0,0]);else{let c=2*Math.PI*v/s.length-Math.PI/2;r.set(f.id,[l*Math.cos(c),l*Math.sin(c)])}}),a=l}let n=0,i=0;for(let[o,s]of r.values())n=Math.max(n,Math.abs(o)),i=Math.max(i,Math.abs(s));return{pos:r,hw:n+Di/2+Hc,hh:i+H0/2+Hc+X0/2}}function K0(t,e,r=W0){let a=new Map(t.nodes.map(c=>[c.id,c])),n=new Map;for(let c of t.edges){let h=a.get(c.src)?.domain,d=a.get(c.dst)?.domain;if(!h||!d||h===d)continue;let g=h<d?`${h}|${d}`:`${d}|${h}`;n.set(g,(n.get(g)??0)+1)}let i=c=>e.get(c)??{hw:0,hh:0},o=c=>i(c).hw*i(c).hh,s=[...e.keys()].sort((c,h)=>o(h)-o(c)),u=new Map,l=0,f=0;s.forEach((c,h)=>{if(h===0){u.set(c,[0,0]);return}l+=Math.hypot(i(c).hw,i(c).hh)*.95,f+=2.399963,u.set(c,[l*Math.cos(f),l*Math.sin(f)])});let v=c=>{let h=0;for(let d=0;d<s.length;d++){let g=s[d];for(let m=d+1;m<s.length;m++){let p=s[m],y=u.get(g),b=u.get(p),E=b[0]-y[0],C=b[1]-y[1],A=i(g).hw+i(p).hw+r-Math.abs(E),D=i(g).hh+i(p).hh+r-Math.abs(C);if(A<=0||D<=0)continue;h=Math.max(h,Math.min(A,D));let N=Math.min(A,D)*c;if(A<D){let O=E>=0?1:-1;y[0]-=O*N,b[0]+=O*N}else{let O=C>=0?1:-1;y[1]-=O*N,b[1]+=O*N}}}return h};for(let c=0;c<400;c++){for(let h=0;h<s.length;h++){let d=s[h];for(let g=h+1;g<s.length;g++){let m=s[g],p=n.get(d<m?`${d}|${m}`:`${m}|${d}`)??0,y=u.get(d),b=u.get(m),E=b[0]-y[0],C=b[1]-y[1],A=Math.hypot(E,C)||1,D=i(d).hw+i(m).hw+r-Math.abs(E),N=i(d).hh+i(m).hh+r-Math.abs(C);if(D>0&&N>0)continue;let O=-Math.min(D,N),R=Math.min(O*(p?.06*Math.log1p(p):.006),90);u.set(d,[y[0]+E/A*R,y[1]+C/A*R]),u.set(m,[b[0]-E/A*R,b[1]-C/A*R])}}v(.5);for(let h of s){let d=u.get(h);d[0]-=d[0]*.004,d[1]-=d[1]*.004}}for(let c=0;c<600&&v(.5)>.5;c++);return u}function ll(t){let e=new Map;for(let o of t.nodes)e.set(o.domain,[...e.get(o.domain)??[],o]);let r=new Map,a=new Map;for(let[o,s]of e){let u=$0(s);r.set(o,u.pos),a.set(o,{hw:u.hw,hh:u.hh})}let n=K0(t,a),i=[];for(let[o,s]of r){let[u,l]=n.get(o)??[0,0];for(let[f,[v,c]]of s)i.push({id:f,x:Math.round(u+v),y:Math.round(l+c)})}return i}var _0=Di+54,Z0=74;function Q0(t,e){let r=[...e].sort((i,o)=>Ma[i.component]-Ma[o.component]||i.name.localeCompare(o.name)),a=Math.max(1,Math.min(5,Math.ceil(Math.sqrt(r.length/2.2)))),n=Math.ceil(r.length/a);return{d:t,items:r,cols:a,w:a*_0+80,h:n*Z0+92}}function $c(t,e=3e3){let r=new Map;for(let l of t.nodes)r.set(l.domain,[...r.get(l.domain)??[],l]);let a=[...r.entries()].map(([l,f])=>Q0(l,f)).sort((l,f)=>f.items.length-l.items.length),n=e,i=[],o=0,s=0,u=0;for(let l of a)s+l.w>n&&s>0&&(o+=u+90,s=0,u=0),l.items.forEach((f,v)=>{i.push({id:f.id,x:Math.round(s+40+v%l.cols*(Di+54)+Di/2),y:Math.round(o+52+Math.floor(v/l.cols)*74)})}),s+=l.w+70,u=Math.max(u,l.h);return i}lr.use(_c.default);var vr=(t,e,r)=>`hsl(${t},${e}%,${r}%)`,He=t=>document.getElementById(t),ea=t=>Array.from(document.querySelectorAll(t)),Ue,wt,pl,Li="hex",Or=!1,jr=!1,Ai,ta=null,Jr="both",Kc,Ni,wn=()=>0;async function J0(){wt=await(await fetch("/api/graph")).json();let t=[...new Set(wt.nodes.map(a=>a.domain))];wn=Xc(t);let e=[...new Set(wt.nodes.map(a=>a.component))].sort((a,n)=>Ma[a]-Ma[n]);pl={hex:new Map(ll(wt).map(a=>[a.id,{x:a.x,y:a.y}])),grid:new Map($c(wt).map(a=>[a.id,{x:a.x,y:a.y}]))},document.title=`${wt.project} \u2014 hexwright`,He("title").textContent=wt.project,He("ref").textContent=wt.ref;let r={added:wt.nodes.filter(a=>a.status==="added").length,modified:wt.nodes.filter(a=>a.status==="modified").length,addedEdges:wt.edges.filter(a=>a.status==="added").length};(r.added||r.modified)&&(He("delta").innerHTML=`<span class="k"></span>added ${r.added} nodes \xB7 ${r.addedEdges} edges<br><span class="k2"></span>modified ${r.modified} nodes`,He("deltaBox").style.display="block"),j0(t,e),tb(),cl("bhex"),gl("core")}function j0(t,e){let r=new Map;for(let a of wt.nodes)r.set(`c:${a.component}`,(r.get(`c:${a.component}`)??0)+1),r.set(`d:${a.domain}`,(r.get(`d:${a.domain}`)??0)+1);He("comps").innerHTML=e.map(a=>`<label><span class="sw" style="${eb(a)}"></span><input type=checkbox class=cf value="${a}" ${ol.includes(a)?"checked":""}>${a}<span class="n">${r.get(`c:${a}`)??0}</span></label>`).join(""),He("doms").innerHTML=t.sort((a,n)=>(r.get(`d:${n}`)??0)-(r.get(`d:${a}`)??0)).map(a=>{let n=wn(a);return`<label><span class="sw" style="background:${vr(n,La(a)?0:60,50)}"></span><input type=checkbox class=df value="${a}" checked>${a}<span class="n">${r.get(`d:${a}`)??0}</span></label>`}).join("");for(let a of ea(".cf,.df,.rf"))a.onchange=()=>Ir();He("showId").onchange=()=>Ir(),He("crossOnly").onchange=()=>Ir(),He("deltaOnly").onchange=()=>Ir()}function eb(t){let e="#8b949e";return sl.includes(t)?`border:1.4px dashed ${e};border-radius:5px`:`background:${e};${{Entity:"border-radius:6px/50%",Service:"border-radius:0",Port:"clip-path:polygon(22% 0,100% 0,100% 78%,78% 100%,0 100%,0 22%)",Event:"transform:skewX(-16deg)"}[t]??"border-radius:5px"}`}function tb(){let t=[...new Set(wt.nodes.map(n=>n.domain))].map(n=>({data:{id:`dom::${n}`,label:n,kind:"domain",hue:wn(n),sat:La(n)?0:26}})),e=wt.nodes.map(n=>({data:{...n,parent:`dom::${n.domain}`,kind:"type",hue:wn(n.domain),sat:La(n.domain)?0:qc[n.component],shape:Yc[n.component],outline:sl.includes(n.component),label:n.name},position:{...pl.hex.get(n.id)??{x:0,y:0}}})),r=wt.edges.map((n,i)=>({data:{...n,id:`e${i}`,source:n.src,target:n.dst,hue:wn(vl(n.src)?.domain??"")}}));Ue=lr({container:He("cy"),elements:[...t,...e,...r],layout:{name:"preset"},minZoom:.05,maxZoom:3,wheelSensitivity:.25,style:[{selector:'node[kind="domain"]',style:{"background-color":n=>vr(n.data("hue"),n.data("sat"),13),"background-opacity":.5,"border-width":1.5,"border-color":n=>vr(n.data("hue"),n.data("sat")+19,42),shape:"round-rectangle",label:"data(label)","text-valign":"top","font-size":21,"font-weight":"bold",color:n=>vr(n.data("hue"),n.data("sat")+29,62),"text-margin-y":-7,padding:"16px"}},{selector:'node[kind="type"]',style:{shape:"data(shape)",width:"182px",height:"32px","background-color":n=>vr(n.data("hue"),n.data("sat"),46-n.data("sat")*.07),"background-opacity":n=>n.data("outline")?0:1,label:"data(label)","font-size":11,"text-valign":"center","text-wrap":"ellipsis","text-max-width":"160px",color:n=>n.data("outline")?vr(n.data("hue"),n.data("hue")?52:0,72):"#fff","border-width":n=>n.data("outline")?1.4:1,"border-color":n=>vr(n.data("hue"),n.data("outline")?48:n.data("sat"),n.data("outline")?52:70),"border-style":n=>n.data("outline")?"dashed":"solid"}},{selector:'node[component="Entity"]',style:{"border-width":2.6,width:"190px",height:"36px","font-weight":"bold","font-size":12}},{selector:'node[component="Service"]',style:{"border-width":1.8}},{selector:"edge",style:{width:1.9,"line-color":n=>vr(n.data("hue"),n.data("crossDomain")?62:22,n.data("crossDomain")?58:46),opacity:n=>n.data("crossDomain")?.8:.62,"target-arrow-color":n=>vr(n.data("hue"),n.data("crossDomain")?62:22,n.data("crossDomain")?58:46)}},{selector:'edge[rel="DEPENDS_ON"]',style:{"line-style":"solid","curve-style":"straight","target-arrow-shape":"vee","arrow-scale":.95}},{selector:'edge[rel="IMPLEMENTS"]',style:{"line-style":"dashed","line-dash-pattern":[9,5],width:2.2,"curve-style":"unbundled-bezier","control-point-distances":[42],"control-point-weights":[.5],"target-arrow-shape":"triangle","target-arrow-fill":"hollow","arrow-scale":1.35}},{selector:'edge[rel="EXTENDS"]',style:{"line-style":"dashed","line-dash-pattern":[3,3],width:3.4,"curve-style":"unbundled-bezier","control-point-distances":[58],"control-point-weights":[.5],"target-arrow-shape":"triangle","target-arrow-fill":"hollow","arrow-scale":1.6}},{selector:"edge[?identifierOnly]",style:{"line-style":"dotted",opacity:.4}},{selector:'edge[violation != ""]',style:{"line-color":"#f85149","target-arrow-color":"#f85149",width:3.4,opacity:1,"z-index":90,label:"data(violation)","font-size":10,color:"#f85149","text-background-color":"#0e1116","text-background-opacity":.85,"text-background-padding":"3px"}},{selector:'edge[status="added"]',style:{opacity:1,"line-color":"#f0883e","target-arrow-color":"#f0883e","z-index":80}},{selector:".dim",style:{opacity:.035,"text-opacity":0}},{selector:".nb",style:{"border-width":2.4,"border-color":"#58a6ff","z-index":50}},{selector:".hi",style:{"border-width":5,"border-color":"#58a6ff","z-index":100}},{selector:"edge.sel",style:{width:5,opacity:1,"line-color":"#58a6ff","target-arrow-color":"#58a6ff","z-index":99}}]}),window.cy=Ue,new ResizeObserver(()=>{Ue.resize();let n=Ue.nodes('[kind="type"]').filter(i=>i.style("display")==="element");n.length&&Ue.fit(n,40)}).observe(He("cy")),Ue.on("tap",'node[kind="type"]',n=>dl(n.target)),Ue.on("tap","edge",n=>sb(n.target)),Ue.on("tap",n=>{let i=n.target;(n.target===Ue||i.data?.("kind")==="domain")&&hl()}),document.addEventListener("keydown",n=>{n.key==="Escape"&&hl()})}var vl=t=>wt.nodes.find(e=>e.id===t);function Ir(){let t=new Set(ea(".cf:checked").map(u=>u.value)),e=new Set(ea(".df:checked").map(u=>u.value)),r=new Set(ea(".rf:checked").map(u=>u.value)),a=He("showId").checked,n=He("crossOnly").checked,i=He("deltaOnly").checked,o=new Set;if(jr)for(let u of Ue.edges())u.data("violation")&&(o.add(u.data("source")),o.add(u.data("target")));Ue.batch(()=>{for(let l of Ue.nodes('[kind="type"]')){let f=l.data(),v=t.has(f.component)&&e.has(f.domain);v&&i&&f.status==="existing"&&(v=!1),v&&jr&&!o.has(f.id)&&(v=!1),l.style("display",v?"element":"none")}let u=l=>l.style("display")==="element";for(let l of Ue.nodes('[kind="domain"]'))l.style("display",l.children().filter(f=>u(f)).length?"element":"none");for(let l of Ue.edges()){let f=u(l.source())&&u(l.target())&&r.has(l.data("rel"));f&&!a&&l.data("identifierOnly")&&(f=!1),f&&n&&!l.data("crossDomain")&&(f=!1),f&&jr&&!l.data("violation")&&(f=!1),l.style("display",f?"element":"none")}}),rb(),Ue.nodes('[kind="type"]').filter(u=>u.style("display")==="element").length&&ab()}function rb(){let t=n=>n.style("display")==="element",e=Ue.nodes('[kind="type"]').filter(n=>t(n)).length,r=Ue.edges().filter(n=>t(n)).length,a=Ue.edges().filter(n=>t(n)&&n.data("violation")).length;He("stat").innerHTML=`Nodes <b>${e}</b>/${Ue.nodes('[kind="type"]').length} \xB7 Edges <b>${r}</b>/${Ue.edges().length}`,He("cviol").textContent=String(a);for(let n of["DEPENDS_ON","IMPLEMENTS","EXTENDS"]){let i=document.getElementById(`c${n}`);i&&(i.textContent=String(Ue.edges(`[rel="${n}"]`).filter(o=>t(o)).length))}}function ab(){clearTimeout(Kc),Kc=setTimeout(Mi,110)}function Mi(){Ni?.stop(),Ni=void 0,Or?Li==="hex"?nb():ob():ib()}var ul=t=>t.style("display")==="element";function nb(){let t=new Set(Ue.nodes('[kind="type"]').filter(i=>ul(i)).map(i=>i.id())),e=new Set(Ue.edges().filter(i=>ul(i)).map(i=>i.id())),r={...wt,nodes:wt.nodes.filter(i=>t.has(i.id)),edges:wt.edges.filter((i,o)=>e.has(`e${o}`))},a=new Map(ll(r).map(i=>[i.id,i]));Ue.batch(()=>{for(let i of Ue.nodes('[kind="type"]')){let o=a.get(i.id());o&&i.position({x:o.x,y:o.y})}});let n=Ue.nodes('[kind="type"]').filter(i=>ul(i));n.length&&Ue.fit(n,40)}function ib(){let t=pl[Li];Ue.batch(()=>{for(let r of Ue.nodes('[kind="type"]')){let a=t.get(r.id());a&&r.position({x:a.x,y:a.y})}});let e=Ue.nodes('[kind="type"]').filter(r=>r.style("display")==="element");e.length&&Ue.fit(e,40)}function ob(){let t=Ue.elements().filter(r=>r.style("display")==="element"),e=t.nodes().length;e&&(Ni=t.layout({name:"fcose",quality:e<=150?"proof":e<=400?"default":"draft",numIter:e<=150?1600:e<=400?900:500,randomize:e<=150,animate:e<=250,animationDuration:400,nodeSeparation:210,idealEdgeLength:r=>r.data("crossDomain")?300:130,nodeRepulsion:34e3,gravity:.12,gravityCompound:.9,gravityRangeCompound:2.2,packComponents:!0,tile:!0,nodeDimensionsIncludeLabels:!0,stop:()=>Ue.fit(t.nodes(),60)}),Ni.run())}var cl=t=>{for(let e of["bhex","bgrid"])He(e).classList.toggle("on",e===t)};function hl(){Ue.elements().removeClass("hi dim sel nb"),He("info").style.display="none",ta=null,Jr="both"}var Vt=(t,e)=>`<tr><td>${t}</td><td>${e}</td></tr>`,fl=t=>t?'<span style="color:#f0883e">yes</span>':"no",Zc=t=>t==="added"?'<span style="color:#f0883e">added</span>':t==="modified"?'<span style="color:#a371f7">modified</span>':"existing";function dl(t){ta=t.id();let e=t.data(),r=c=>c.style("display")==="element",a=t.connectedEdges().filter(c=>r(c)),n=a.filter(c=>c.target().id()===ta),i=a.filter(c=>c.source().id()===ta),o=Jr==="in"?n:Jr==="out"?i:a,s=o.connectedNodes().difference(t);Ue.elements().removeClass("hi dim sel nb").addClass("dim"),t.removeClass("dim").addClass("hi"),s.removeClass("dim").addClass("nb"),o.removeClass("dim").addClass("sel"),s.parent().removeClass("dim"),t.parent().removeClass("dim");let u=(c,h,d)=>`<button class="dirb ${Jr===c?"on":""}" data-dir="${c}">${h} ${d}</button>`,l=(c,h,d)=>{let g=d.data();return`<div class="lk" data-goto="${g.id}"><span class="ar">${h}</span>${g.name}<span class="mut"> ${g.domain}\xB7${g.component}</span><span class="rel">${c.data("rel")==="DEPENDS_ON"?"":c.data("rel")}</span></div>`},f="";if(Jr!=="out")for(let c of n)f+=l(c,"\u2190",c.source());if(Jr!=="in")for(let c of i)f+=l(c,"\u2192",c.target());let v=e.api.length||e.props.length?`<div class="dirbar" style="display:block"><b>Public contract</b><span class="mut"> ${e.api.length} fn${e.props.length?` \xB7 ${e.props.length} prop`:""}</span></div><div class="lks">${e.api.map(c=>{let h=c.indexOf("(");return`<div class="lk"><span class="sig"><b>${c.slice(0,h)}</b>${c.slice(h)}</span></div>`}).join("")}${e.props.map(c=>`<div class="lk"><span class="sig" style="color:#6e7681">${c}</span></div>`).join("")}</div>`:"";He("info").style.display="block",He("info").innerHTML=`<div class="ih">${e.name}<span class="x">\xD7</span></div><table>${Vt("Domain",e.domain)}${Vt("Component",`${e.component} <span class="mut">${e.layer}${e.sublayer?`/${e.sublayer}`:""}</span>`)}${Vt("Kind",e.kind)}${Vt("Status",Zc(e.status))}${Vt("File",`<span class="mut">${e.file}:${e.line}</span>`)}${Vt("Id",`<span class="mut" style="word-break:break-all">${e.id}</span>`)}</table>${v}<div class="dirbar">${u("both","Both",a.length)}${u("in","\u2190 In",n.length)}${u("out","Out \u2192",i.length)}</div><div class="lks">${f||'<span class="mut">No visible connections</span>'}</div><div class="hint">Click an item to focus it \xB7 Esc to clear</div>`,Qc()}function sb(t){ta=null;let e=t.data(),r=vl(e.src),a=vl(e.dst);Ue.elements().removeClass("hi dim sel nb").addClass("dim"),t.removeClass("dim").addClass("sel"),t.connectedNodes().removeClass("dim").addClass("nb").parent().removeClass("dim");let n=e.contracts.length?`<div class="dirbar" style="display:block"><b>Contracts used</b><span class="mut"> ${e.contracts.length}/${a?.api.length??0}</span></div><div class="lks">${e.contracts.map(i=>{let o=i.indexOf("(");return`<div class="lk"><span class="sig"><b>${o>0?i.slice(0,o):i}</b>${o>0?i.slice(o):""}</span></div>`}).join("")}</div>`:'<div class="hint">No method calls \u2014 type reference only</div>';He("info").style.display="block",He("info").innerHTML=`<div class="ih">${e.rel}<span class="x">\xD7</span></div><table>${Vt("Source",`${r?.name} <span class="mut">${r?.domain}\xB7${r?.component}</span>`)}${Vt("Target",`${a?.name} <span class="mut">${a?.domain}\xB7${a?.component}</span>`)}${e.rel==="DEPENDS_ON"?Vt("Weight",`${e.weight} <span class="mut">occurrences</span>`):""}${Vt("Cross-domain",fl(e.crossDomain))}${Vt("Identifier only",fl(e.identifierOnly))}${Vt("Via signature",fl(e.viaSignature))}${e.violation?Vt("Violation",`<span style="color:#f85149">${e.violation}</span>`):""}${Vt("Status",Zc(e.status))}</table>${n}`,Qc()}function Qc(){let t=He("info").querySelector(".x");t&&(t.onclick=()=>hl());for(let e of Array.from(He("info").querySelectorAll(".dirb")))e.onclick=()=>{Jr=e.dataset.dir,ta&&dl(Ue.getElementById(ta))};for(let e of Array.from(He("info").querySelectorAll("[data-goto]")))e.onclick=()=>dl(Ue.getElementById(e.dataset.goto))}function gl(t){for(let e of ea(".cf"))e.checked=t==="core"?ol.includes(e.value):!0;for(let e of["pcore","pall"])He(e).classList.toggle("on",e===`p${t}`);Ir()}function lb(){He("pcore").onclick=()=>gl("core"),He("pall").onclick=()=>gl("all"),He("bhex").onclick=()=>{Li="hex",cl("bhex"),Mi()},He("bgrid").onclick=()=>{Li="grid",cl("bgrid"),Mi()},He("borg").onclick=()=>{Or=!Or,He("borg").classList.toggle("on",Or),Mi()},He("bviol").onclick=()=>{jr=!jr,He("bviol").classList.toggle("on",jr),jr?(Ai=Or,Or=!0):Ai!==void 0&&(Or=Ai,Ai=void 0),He("borg").classList.toggle("on",Or),Ir()},He("allDomOn").onclick=()=>{for(let t of ea(".df"))t.checked=!0;Ir()},He("allDomOff").onclick=()=>{for(let t of ea(".df"))t.checked=!1;Ir()},J0()}lb();})();
321
+ `),s=Jm(a,n,o);s.aPosition=a.getAttribLocation(s,"aPosition"),s.aIndex=a.getAttribLocation(s,"aIndex"),s.aVertType=a.getAttribLocation(s,"aVertType"),s.aTransform=a.getAttribLocation(s,"aTransform"),s.aAtlasId=a.getAttribLocation(s,"aAtlasId"),s.aTex=a.getAttribLocation(s,"aTex"),s.aPointAPointB=a.getAttribLocation(s,"aPointAPointB"),s.aPointCPointD=a.getAttribLocation(s,"aPointCPointD"),s.aLineWidth=a.getAttribLocation(s,"aLineWidth"),s.aColor=a.getAttribLocation(s,"aColor"),s.aCornerRadius=a.getAttribLocation(s,"aCornerRadius"),s.aBorderColor=a.getAttribLocation(s,"aBorderColor"),s.uPanZoomMatrix=a.getUniformLocation(s,"uPanZoomMatrix"),s.uAtlasSize=a.getUniformLocation(s,"uAtlasSize"),s.uBGColor=a.getUniformLocation(s,"uBGColor"),s.uZoom=a.getUniformLocation(s,"uZoom"),s.uTextures=[];for(var u=0;u<this.batchManager.getMaxAtlasesPerBatch();u++)s.uTextures.push(a.getUniformLocation(s,"uTexture".concat(u)));return s}},{key:"_createVAO",value:function(){var r=[0,0,1,0,1,1,0,0,1,1,0,1];this.vertexCount=r.length/2;var a=this.maxInstances,n=this.gl,i=this.program,o=n.createVertexArray();return n.bindVertexArray(o),s0(n,"vec2",i.aPosition,r),this.transformBuffer=l0(n,a,i.aTransform),this.indexBuffer=Zt(n,a,"vec4",i.aIndex),this.vertTypeBuffer=Zt(n,a,"int",i.aVertType),this.atlasIdBuffer=Zt(n,a,"int",i.aAtlasId),this.texBuffer=Zt(n,a,"vec4",i.aTex),this.pointAPointBBuffer=Zt(n,a,"vec4",i.aPointAPointB),this.pointCPointDBuffer=Zt(n,a,"vec4",i.aPointCPointD),this.lineWidthBuffer=Zt(n,a,"vec2",i.aLineWidth),this.colorBuffer=Zt(n,a,"vec4",i.aColor),this.cornerRadiusBuffer=Zt(n,a,"vec4",i.aCornerRadius),this.borderColorBuffer=Zt(n,a,"vec4",i.aBorderColor),n.bindVertexArray(null),o}},{key:"buffers",get:function(){var r=this;return this._buffers||(this._buffers=Object.keys(this).filter(function(a){return yr(a,"Buffer")}).map(function(a){return r[a]})),this._buffers}},{key:"startFrame",value:function(r){var a=arguments.length>1&&arguments[1]!==void 0?arguments[1]:Xa.SCREEN;this.panZoomMatrix=r,this.renderTarget=a,this.batchDebugInfo=[],this.wrappedCount=0,this.simpleCount=0,this.startBatch()}},{key:"startBatch",value:function(){this.instanceCount=0,this.batchManager.startBatch()}},{key:"endFrame",value:function(){this.endBatch()}},{key:"_isVisible",value:function(r,a){return r.visible()?a&&a.isVisible?a.isVisible(r):!0:!1}},{key:"drawTexture",value:function(r,a,n){var i=this.atlasManager,o=this.batchManager,s=i.getRenderTypeOpts(n);if(this._isVisible(r,s)&&!(r.isEdge()&&!this._isValidEdge(r))){if(this.renderTarget.picking&&s.getTexPickingMode){var u=s.getTexPickingMode(r);if(u===oi.IGNORE)return;if(u==oi.USE_BB){this.drawPickingRectangle(r,a,n);return}}var l=i.getAtlasInfo(r,n),f=zt(l),v;try{for(f.s();!(v=f.n()).done;){var c=v.value,h=c.atlas,d=c.tex1,g=c.tex2;o.canAddToCurrentBatch(h)||this.endBatch();for(var m=o.getAtlasIndexForBatch(h),p=0,y=[[d,!0],[g,!1]];p<y.length;p++){var b=dt(y[p],2),E=b[0],C=b[1];if(E.w!=0){var A=this.instanceCount;this.vertTypeBuffer.getView(A)[0]=is;var D=this.indexBuffer.getView(A);sa(a,D);var N=this.atlasIdBuffer.getView(A);N[0]=m;var O=this.texBuffer.getView(A);O[0]=E.x,O[1]=E.y,O[2]=E.w,O[3]=E.h;var R=this.transformBuffer.getMatrixView(A);this.setTransformMatrix(r,R,s,c,C),this.instanceCount++,C||this.wrappedCount++,this.instanceCount>=this.maxInstances&&this.endBatch()}}}}catch(P){f.e(P)}finally{f.f()}}}},{key:"setTransformMatrix",value:function(r,a,n,i){var o=arguments.length>4&&arguments[4]!==void 0?arguments[4]:!0,s=0;if(n.shapeProps&&n.shapeProps.padding&&(s=r.pstyle(n.shapeProps.padding).pfValue),i){var u=i.bb,l=i.tex1,f=i.tex2,v=l.w/(l.w+f.w);o||(v=1-v);var c=this._getAdjustedBB(u,s,o,v);this._applyTransformMatrix(a,c,n,r)}else{var h=n.getBoundingBox(r),d=this._getAdjustedBB(h,s,!0,1);this._applyTransformMatrix(a,d,n,r)}}},{key:"_applyTransformMatrix",value:function(r,a,n,i){var o,s;Uf(r);var u=n.getRotation?n.getRotation(i):0;if(u!==0){var l=n.getRotationPoint(i),f=l.x,v=l.y;$n(r,r,[f,v]),Hf(r,r,u);var c=n.getRotationOffset(i);o=c.x+(a.xOffset||0),s=c.y+(a.yOffset||0)}else o=a.x1,s=a.y1;$n(r,r,[o,s]),Ds(r,r,[a.w,a.h])}},{key:"_getAdjustedBB",value:function(r,a,n,i){var o=r.x1,s=r.y1,u=r.w,l=r.h,f=r.yOffset;a&&(o-=a,s-=a,u+=2*a,l+=2*a);var v=0,c=u*i;return n&&i<1?u=c:!n&&i<1&&(v=u-c,o+=v,u=c),{x1:o,y1:s,w:u,h:l,xOffset:v,yOffset:f}}},{key:"drawPickingRectangle",value:function(r,a,n){var i=this.atlasManager.getRenderTypeOpts(n),o=this.instanceCount;this.vertTypeBuffer.getView(o)[0]=la;var s=this.indexBuffer.getView(o);sa(a,s);var u=this.colorBuffer.getView(o);zr([0,0,0],1,u);var l=this.transformBuffer.getMatrixView(o);this.setTransformMatrix(r,l,i),this.simpleCount++,this.instanceCount++,this.instanceCount>=this.maxInstances&&this.endBatch()}},{key:"drawNode",value:function(r,a,n){var i=this.simpleShapeOptions.get(n);if(this._isVisible(r,i)){var o=i.shapeProps,s=this._getVertTypeForShape(r,o.shape);if(s===void 0||i.isSimple&&!i.isSimple(r,this.renderTarget)){this.drawTexture(r,a,n);return}var u=this.instanceCount;if(this.vertTypeBuffer.getView(u)[0]=s,s===kn||s===Va){var l=i.getBoundingBox(r),f=this._getCornerRadius(r,o.radius,l),v=this.cornerRadiusBuffer.getView(u);v[0]=f,v[1]=f,v[2]=f,v[3]=f,s===Va&&(v[0]=0,v[2]=0)}var c=this.indexBuffer.getView(u);sa(a,c);var h=this.renderTarget.picking?1:n==="node-body"?r.effectiveOpacity():1,d=this.renderTarget.picking?1:r.pstyle(o.opacity).value*h,g=r.pstyle(o.color).value,m=this.colorBuffer.getView(u);zr(g,d,m);var p=this.lineWidthBuffer.getView(u);if(p[0]=0,p[1]=0,o.border){var y=r.pstyle("border-width").value;if(y>0){var b=r.pstyle("border-color").value,E=h*r.pstyle("border-opacity").value,C=this.borderColorBuffer.getView(u);zr(b,E,C);var A=r.pstyle("border-position").value;if(A==="inside")p[0]=0,p[1]=-y;else if(A==="outside")p[0]=y,p[1]=0;else{var D=y/2;p[0]=D,p[1]=-D}}}var N=this.transformBuffer.getMatrixView(u);this.setTransformMatrix(r,N,i),this.simpleCount++,this.instanceCount++,this.instanceCount>=this.maxInstances&&this.endBatch()}}},{key:"_getVertTypeForShape",value:function(r,a){var n=r.pstyle(a).value;switch(n){case"rectangle":return la;case"ellipse":return Ga;case"roundrectangle":case"round-rectangle":return kn;case"bottom-round-rectangle":return Va;default:return}}},{key:"_getCornerRadius",value:function(r,a,n){var i=n.w,o=n.h;if(r.pstyle(a).value==="auto")return Cr(i,o);var s=r.pstyle(a).pfValue,u=i/2,l=o/2;return Math.min(s,l,u)}},{key:"drawEdgeArrow",value:function(r,a,n){if(r.visible()){var i=r._private.rscratch,o,s,u;if(n==="source"?(o=i.arrowStartX,s=i.arrowStartY,u=i.srcArrowAngle):(o=i.arrowEndX,s=i.arrowEndY,u=i.tgtArrowAngle),!(isNaN(o)||o==null||isNaN(s)||s==null||isNaN(u)||u==null)){var l=r.pstyle(n+"-arrow-shape").value;if(l!=="none"){var f=r.pstyle(n+"-arrow-color").value,v=r.pstyle("opacity").value,c=r.pstyle("line-opacity").value,h=v*c,d=r.pstyle("width").pfValue,g=r.pstyle("arrow-scale").value,m=this.r.getArrowWidth(d,g),p=this.instanceCount,y=this.transformBuffer.getMatrixView(p);Uf(y),$n(y,y,[o,s]),Ds(y,y,[m,m]),Hf(y,y,u),this.vertTypeBuffer.getView(p)[0]=os;var b=this.indexBuffer.getView(p);sa(a,b);var E=this.colorBuffer.getView(p);zr(f,h,E),this.instanceCount++,this.instanceCount>=this.maxInstances&&this.endBatch()}}}}},{key:"drawEdgeLine",value:function(r,a){if(r.visible()){var n=this._getEdgePoints(r);if(n){var i=r.pstyle("opacity").value,o=r.pstyle("line-opacity").value,s=r.pstyle("width").pfValue,u=r.pstyle("line-color").value,l=i*o;if(n.length/2+this.instanceCount>this.maxInstances&&this.endBatch(),n.length==4){var f=this.instanceCount;this.vertTypeBuffer.getView(f)[0]=qf;var v=this.indexBuffer.getView(f);sa(a,v);var c=this.colorBuffer.getView(f);zr(u,l,c);var h=this.lineWidthBuffer.getView(f);h[0]=s;var d=this.pointAPointBBuffer.getView(f);d[0]=n[0],d[1]=n[1],d[2]=n[2],d[3]=n[3],this.instanceCount++,this.instanceCount>=this.maxInstances&&this.endBatch()}else for(var g=0;g<n.length-2;g+=2){var m=this.instanceCount;this.vertTypeBuffer.getView(m)[0]=Yf;var p=this.indexBuffer.getView(m);sa(a,p);var y=this.colorBuffer.getView(m);zr(u,l,y);var b=this.lineWidthBuffer.getView(m);b[0]=s;var E=n[g-2],C=n[g-1],A=n[g],D=n[g+1],N=n[g+2],O=n[g+3],R=n[g+4],P=n[g+5];g==0&&(E=2*A-N+.001,C=2*D-O+.001),g==n.length-4&&(R=2*N-A+.001,P=2*O-D+.001);var w=this.pointAPointBBuffer.getView(m);w[0]=E,w[1]=C,w[2]=A,w[3]=D;var x=this.pointCPointDBuffer.getView(m);x[0]=N,x[1]=O,x[2]=R,x[3]=P,this.instanceCount++,this.instanceCount>=this.maxInstances&&this.endBatch()}}}}},{key:"_isValidEdge",value:function(r){var a=r._private.rscratch;return!(a.badLine||a.allpts==null||isNaN(a.allpts[0]))}},{key:"_getEdgePoints",value:function(r){var a=r._private.rscratch;if(this._isValidEdge(r)){var n=a.allpts;if(n.length==4)return n;var i=this._getNumSegments(r);return this._getCurveSegmentPoints(n,i)}}},{key:"_getNumSegments",value:function(r){var a=15;return Math.min(Math.max(a,5),this.maxInstances)}},{key:"_getCurveSegmentPoints",value:function(r,a){if(r.length==4)return r;for(var n=Array((a+1)*2),i=0;i<=a;i++)if(i==0)n[0]=r[0],n[1]=r[1];else if(i==a)n[i*2]=r[r.length-2],n[i*2+1]=r[r.length-1];else{var o=i/a;this._setCurvePoint(r,o,n,i*2)}return n}},{key:"_setCurvePoint",value:function(r,a,n,i){if(r.length<=2)n[i]=r[0],n[i+1]=r[1];else{for(var o=Array(r.length-2),s=0;s<o.length;s+=2){var u=(1-a)*r[s]+a*r[s+2],l=(1-a)*r[s+1]+a*r[s+3];o[s]=u,o[s+1]=l}return this._setCurvePoint(o,a,n,i)}}},{key:"endBatch",value:function(){var r=this.gl,a=this.vao,n=this.vertexCount,i=this.instanceCount;if(i!==0){var o=this.renderTarget.picking?this.pickingProgram:this.program;r.useProgram(o),r.bindVertexArray(a);var s=zt(this.buffers),u;try{for(s.s();!(u=s.n()).done;){var l=u.value;l.bufferSubData(i)}}catch(d){s.e(d)}finally{s.f()}for(var f=this.batchManager.getAtlases(),v=0;v<f.length;v++)f[v].bufferIfNeeded(r);for(var c=0;c<f.length;c++)r.activeTexture(r.TEXTURE0+c),r.bindTexture(r.TEXTURE_2D,f[c].texture),r.uniform1i(o.uTextures[c],c);r.uniform1f(o.uZoom,e0(this.r)),r.uniformMatrix3fv(o.uPanZoomMatrix,!1,this.panZoomMatrix),r.uniform1i(o.uAtlasSize,this.batchManager.getAtlasSize());var h=zr(this.bgColor,1);r.uniform4fv(o.uBGColor,h),r.drawArraysInstanced(r.TRIANGLES,0,n,i),r.bindVertexArray(null),r.bindTexture(r.TEXTURE_2D,null),this.debug&&this.batchDebugInfo.push({count:i,atlasCount:f.length}),this.startBatch()}}},{key:"getDebugInfo",value:function(){var r=this.atlasManager.getDebugInfo(),a=r.reduce(function(o,s){return o+s.atlasCount},0),n=this.batchDebugInfo,i=n.reduce(function(o,s){return o+s.count},0);return{atlasInfo:r,totalAtlases:a,wrappedCount:this.wrappedCount,simpleCount:this.simpleCount,batchCount:n.length,batchInfo:n,totalInstances:i}}}])})(),Mc={};Mc.initWebgl=function(t,e){var r=this,a=r.data.contexts[r.WEBGL];t.bgColor=x0(r),t.webglTexSize=Math.min(t.webglTexSize,a.getParameter(a.MAX_TEXTURE_SIZE)),t.webglTexRows=Math.min(t.webglTexRows,54),t.webglTexRowsNodes=Math.min(t.webglTexRowsNodes,54),t.webglBatchSize=Math.min(t.webglBatchSize,16384),t.webglTexPerBatch=Math.min(t.webglTexPerBatch,a.getParameter(a.MAX_TEXTURE_IMAGE_UNITS)),r.webglDebug=t.webglDebug,r.webglDebugShowAtlases=t.webglDebugShowAtlases,r.pickingFrameBuffer=u0(a),r.pickingFrameBuffer.needsDraw=!0,r.drawing=new E0(r,a,t);var n=function(v){return function(c){return r.getTextAngle(c,v)}},i=function(v){return function(c){var h=c.pstyle(v);return h&&h.value}},o=function(v){return function(c){return c.pstyle("".concat(v,"-opacity")).value>0}},s=function(v){var c=v.pstyle("text-events").strValue==="yes";return c?oi.USE_BB:oi.IGNORE},u=function(v){var c=v.position(),h=c.x,d=c.y,g=v.outerWidth(),m=v.outerHeight();return{w:g,h:m,x1:h-g/2,y1:d-m/2}};r.drawing.addAtlasCollection("node",{texRows:t.webglTexRowsNodes}),r.drawing.addAtlasCollection("label",{texRows:t.webglTexRows}),r.drawing.addTextureAtlasRenderType("node-body",{collection:"node",getKey:e.getStyleKey,getBoundingBox:e.getElementBox,drawElement:e.drawElement}),r.drawing.addSimpleShapeRenderType("node-body",{getBoundingBox:u,isSimple:r0,shapeProps:{shape:"shape",color:"background-color",opacity:"background-opacity",radius:"corner-radius",border:!0}}),r.drawing.addSimpleShapeRenderType("node-overlay",{getBoundingBox:u,isVisible:o("overlay"),shapeProps:{shape:"overlay-shape",color:"overlay-color",opacity:"overlay-opacity",padding:"overlay-padding",radius:"overlay-corner-radius"}}),r.drawing.addSimpleShapeRenderType("node-underlay",{getBoundingBox:u,isVisible:o("underlay"),shapeProps:{shape:"underlay-shape",color:"underlay-color",opacity:"underlay-opacity",padding:"underlay-padding",radius:"underlay-corner-radius"}}),r.drawing.addTextureAtlasRenderType("label",{collection:"label",getTexPickingMode:s,getKey:ss(e.getLabelKey,null),getBoundingBox:ls(e.getLabelBox,null),drawClipped:!0,drawElement:e.drawLabel,getRotation:n(null),getRotationPoint:e.getLabelRotationPoint,getRotationOffset:e.getLabelRotationOffset,isVisible:i("label")}),r.drawing.addTextureAtlasRenderType("edge-source-label",{collection:"label",getTexPickingMode:s,getKey:ss(e.getSourceLabelKey,"source"),getBoundingBox:ls(e.getSourceLabelBox,"source"),drawClipped:!0,drawElement:e.drawSourceLabel,getRotation:n("source"),getRotationPoint:e.getSourceLabelRotationPoint,getRotationOffset:e.getSourceLabelRotationOffset,isVisible:i("source-label")}),r.drawing.addTextureAtlasRenderType("edge-target-label",{collection:"label",getTexPickingMode:s,getKey:ss(e.getTargetLabelKey,"target"),getBoundingBox:ls(e.getTargetLabelBox,"target"),drawClipped:!0,drawElement:e.drawTargetLabel,getRotation:n("target"),getRotationPoint:e.getTargetLabelRotationPoint,getRotationOffset:e.getTargetLabelRotationOffset,isVisible:i("target-label")});var l=un(function(){console.log("garbage collect flag set"),r.data.gc=!0},1e4);r.onUpdateEleCalcs(function(f,v){var c=!1;v&&v.length>0&&(c|=r.drawing.invalidate(v)),c&&l()}),T0(r)};function x0(t){var e=t.cy.container(),r=e&&e.style&&e.style.backgroundColor||"white";return tv(r)}function Lc(t,e){var r=t._private.rscratch;return It(r,"labelWrapCachedLines",e)||[]}var ss=function(e,r){return function(a){var n=e(a),i=Lc(a,r);return i.length>1?i.map(function(o,s){return"".concat(n,"_").concat(s)}):n}},ls=function(e,r){return function(a,n){var i=e(a);if(typeof n=="string"){var o=n.indexOf("_");if(o>0){var s=Number(n.substring(o+1)),u=Lc(a,r),l=i.h/u.length,f=l*s,v=i.y1+f;return{x1:i.x1,w:i.w,y1:v,h:l,yOffset:f}}}return i}};function T0(t){{var e=t.render;t.render=function(i){i=i||{};var o=t.cy;t.webgl&&(o.zoom()>Ec?(C0(t),e.call(t,i)):(S0(t),Rc(t,i,Xa.SCREEN)))}}{var r=t.matchCanvasSize;t.matchCanvasSize=function(i){r.call(t,i),t.pickingFrameBuffer.setFramebufferAttachmentSizes(t.canvasWidth,t.canvasHeight),t.pickingFrameBuffer.needsDraw=!0}}t.findNearestElements=function(i,o,s,u){return R0(t,i,o)};{var a=t.invalidateCachedZSortedEles;t.invalidateCachedZSortedEles=function(){a.call(t),t.pickingFrameBuffer.needsDraw=!0}}{var n=t.notify;t.notify=function(i,o){n.call(t,i,o),i==="viewport"||i==="bounds"?t.pickingFrameBuffer.needsDraw=!0:i==="background"&&t.drawing.invalidate(o,{type:"node-body"})}}}function C0(t){var e=t.data.contexts[t.WEBGL];e.clear(e.COLOR_BUFFER_BIT|e.DEPTH_BUFFER_BIT)}function S0(t){var e=function(a){a.save(),a.setTransform(1,0,0,1,0,0),a.clearRect(0,0,t.canvasWidth,t.canvasHeight),a.restore()};e(t.data.contexts[t.NODE]),e(t.data.contexts[t.DRAG])}function D0(t){var e=t.canvasWidth,r=t.canvasHeight,a=el(t),n=a.pan,i=a.zoom,o=ns();$n(o,o,[n.x,n.y]),Ds(o,o,[i,i]);var s=ns();v0(s,e,r);var u=ns();return f0(u,s,o),u}function Nc(t,e){var r=t.canvasWidth,a=t.canvasHeight,n=el(t),i=n.pan,o=n.zoom;e.setTransform(1,0,0,1,0,0),e.clearRect(0,0,r,a),e.translate(i.x,i.y),e.scale(o,o)}function A0(t,e){t.drawSelectionRectangle(e,function(r){return Nc(t,r)})}function M0(t){var e=t.data.contexts[t.NODE];e.save(),Nc(t,e),e.strokeStyle="rgba(0, 0, 0, 0.3)",e.beginPath(),e.moveTo(-1e3,0),e.lineTo(1e3,0),e.stroke(),e.beginPath(),e.moveTo(0,-1e3),e.lineTo(0,1e3),e.stroke(),e.restore()}function L0(t){var e=function(n,i,o){for(var s=n.atlasManager.getAtlasCollection(i),u=t.data.contexts[t.NODE],l=s.atlases,f=0;f<l.length;f++){var v=l[f],c=v.canvas;if(c){var h=c.width,d=c.height,g=h*f,m=c.height*o,p=.4;u.save(),u.scale(p,p),u.drawImage(c,g,m),u.strokeStyle="black",u.rect(g,m,h,d),u.stroke(),u.restore()}}},r=0;e(t.drawing,"node",r++),e(t.drawing,"label",r++)}function N0(t,e,r,a,n){var i,o,s,u,l=el(t),f=l.pan,v=l.zoom;{var c=t0(t,f,v,e,r),h=dt(c,2),d=h[0],g=h[1],m=6;i=d-m/2,o=g-m/2,s=m,u=m}if(s===0||u===0)return[];var p=t.data.contexts[t.WEBGL];p.bindFramebuffer(p.FRAMEBUFFER,t.pickingFrameBuffer),t.pickingFrameBuffer.needsDraw&&(p.viewport(0,0,p.canvas.width,p.canvas.height),Rc(t,null,Xa.PICKING),t.pickingFrameBuffer.needsDraw=!1);var y=s*u,b=new Uint8Array(y*4);p.readPixels(i,o,s,u,p.RGBA,p.UNSIGNED_BYTE,b),p.bindFramebuffer(p.FRAMEBUFFER,null);for(var E=new Set,C=0;C<y;C++){var A=b.slice(C*4,C*4+4),D=n0(A)-1;D>=0&&E.add(D)}return E}function R0(t,e,r){var a=N0(t,e,r),n=t.getCachedZSortedEles(),i,o,s=zt(a),u;try{for(s.s();!(u=s.n()).done;){var l=u.value,f=n[l];if(!i&&f.isNode()&&(i=f),!o&&f.isEdge()&&(o=f),i&&o)break}}catch(v){s.e(v)}finally{s.f()}return[i,o].filter(Boolean)}function us(t,e,r){var a=t.drawing;e+=1,r.isNode()?(a.drawNode(r,e,"node-underlay"),a.drawNode(r,e,"node-body"),a.drawTexture(r,e,"label"),a.drawNode(r,e,"node-overlay")):(a.drawEdgeLine(r,e),a.drawEdgeArrow(r,e,"source"),a.drawEdgeArrow(r,e,"target"),a.drawTexture(r,e,"label"),a.drawTexture(r,e,"edge-source-label"),a.drawTexture(r,e,"edge-target-label"))}function Rc(t,e,r){var a;t.webglDebug&&(a=performance.now());var n=t.drawing,i=0;if(r.screen&&t.data.canvasNeedsRedraw[t.SELECT_BOX]&&A0(t,e),t.data.canvasNeedsRedraw[t.NODE]||r.picking){var o=t.data.contexts[t.WEBGL];r.screen?(o.clearColor(0,0,0,0),o.enable(o.BLEND),o.blendFunc(o.ONE,o.ONE_MINUS_SRC_ALPHA)):o.disable(o.BLEND),o.clear(o.COLOR_BUFFER_BIT|o.DEPTH_BUFFER_BIT),o.viewport(0,0,o.canvas.width,o.canvas.height);var s=D0(t),u=t.getCachedZSortedEles();if(i=u.length,n.startFrame(s,r),r.screen){for(var l=0;l<u.nondrag.length;l++)us(t,l,u.nondrag[l]);for(var f=0;f<u.drag.length;f++)us(t,f,u.drag[f])}else if(r.picking)for(var v=0;v<u.length;v++)us(t,v,u[v]);n.endFrame(),r.screen&&t.webglDebugShowAtlases&&(M0(t),L0(t)),t.data.canvasNeedsRedraw[t.NODE]=!1,t.data.canvasNeedsRedraw[t.DRAG]=!1}if(t.webglDebug){var c=performance.now(),h=!1,d=Math.ceil(c-a),g=n.getDebugInfo(),m=["".concat(i," elements"),"".concat(g.totalInstances," instances"),"".concat(g.batchCount," batches"),"".concat(g.totalAtlases," atlases"),"".concat(g.wrappedCount," wrapped textures"),"".concat(g.simpleCount," simple shapes")].join(", ");if(h)console.log("WebGL (".concat(r.name,") - time ").concat(d,"ms, ").concat(m));else{console.log("WebGL (".concat(r.name,") - frame time ").concat(d,"ms")),console.log("Totals:"),console.log(" ".concat(m)),console.log("Texture Atlases Used:");var p=g.atlasInfo,y=zt(p),b;try{for(y.s();!(b=y.n()).done;){var E=b.value;console.log(" ".concat(E.type,": ").concat(E.keyCount," keys, ").concat(E.atlasCount," atlases"))}}catch(C){y.e(C)}finally{y.f()}console.log("")}}t.data.gc&&(console.log("Garbage Collect!"),t.data.gc=!1,n.gc())}var Pr={};Pr.drawPolygonPath=function(t,e,r,a,n,i){var o=a/2,s=n/2;t.beginPath&&t.beginPath(),t.moveTo(e+o*i[0],r+s*i[1]);for(var u=1;u<i.length/2;u++)t.lineTo(e+o*i[u*2],r+s*i[u*2+1]);t.closePath()};Pr.drawRoundPolygonPath=function(t,e,r,a,n,i,o){o.forEach(function(s){return vc(t,s)}),t.closePath()};Pr.drawRoundRectanglePath=function(t,e,r,a,n,i){var o=a/2,s=n/2,u=i==="auto"?Cr(a,n):Math.min(i,s,o);t.beginPath&&t.beginPath(),t.moveTo(e,r-s),t.arcTo(e+o,r-s,e+o,r,u),t.arcTo(e+o,r+s,e,r+s,u),t.arcTo(e-o,r+s,e-o,r,u),t.arcTo(e-o,r-s,e,r-s,u),t.lineTo(e,r-s),t.closePath()};Pr.drawBottomRoundRectanglePath=function(t,e,r,a,n,i){var o=a/2,s=n/2,u=i==="auto"?Cr(a,n):i;t.beginPath&&t.beginPath(),t.moveTo(e,r-s),t.lineTo(e+o,r-s),t.lineTo(e+o,r),t.arcTo(e+o,r+s,e,r+s,u),t.arcTo(e-o,r+s,e-o,r,u),t.lineTo(e-o,r-s),t.lineTo(e,r-s),t.closePath()};Pr.drawCutRectanglePath=function(t,e,r,a,n,i,o){var s=a/2,u=n/2,l=o==="auto"?Gs():o;t.beginPath&&t.beginPath(),t.moveTo(e-s+l,r-u),t.lineTo(e+s-l,r-u),t.lineTo(e+s,r-u+l),t.lineTo(e+s,r+u-l),t.lineTo(e+s-l,r+u),t.lineTo(e-s+l,r+u),t.lineTo(e-s,r+u-l),t.lineTo(e-s,r-u+l),t.closePath()};Pr.drawBarrelPath=function(t,e,r,a,n){var i=a/2,o=n/2,s=e-i,u=e+i,l=r-o,f=r+o,v=cs(a,n),c=v.widthOffset,h=v.heightOffset,d=v.ctrlPtOffsetPct*c;t.beginPath&&t.beginPath(),t.moveTo(s,l+h),t.lineTo(s,f-h),t.quadraticCurveTo(s+d,f,s+c,f),t.lineTo(u-c,f),t.quadraticCurveTo(u-d,f,u,f-h),t.lineTo(u,l+h),t.quadraticCurveTo(u-d,l,u-c,l),t.lineTo(s+c,l),t.quadraticCurveTo(s+d,l,s,l+h),t.closePath()};var Wf=Math.sin(0),Xf=Math.cos(0),As={},Ms={},Pc=Math.PI/40;for(Vr=0*Math.PI;Vr<2*Math.PI;Vr+=Pc)As[Vr]=Math.sin(Vr),Ms[Vr]=Math.cos(Vr);var Vr;Pr.drawEllipsePath=function(t,e,r,a,n){if(t.beginPath&&t.beginPath(),t.ellipse)t.ellipse(e,r,a/2,n/2,0,0,2*Math.PI);else for(var i,o,s=a/2,u=n/2,l=0*Math.PI;l<2*Math.PI;l+=Pc)i=e-s*As[l]*Wf+s*Ms[l]*Xf,o=r+u*Ms[l]*Wf+u*As[l]*Xf,l===0?t.moveTo(i,o):t.lineTo(i,o);t.closePath()};var gn={};gn.createBuffer=function(t,e){var r=document.createElement("canvas");return r.width=t,r.height=e,[r,r.getContext("2d")]};gn.bufferCanvasImage=function(t){var e=this.cy,r=e.mutableElements(),a=r.boundingBox(),n=this.findContainerClientCoords(),i=t.full?Math.ceil(a.w):n[2],o=t.full?Math.ceil(a.h):n[3],s=we(t.maxWidth)||we(t.maxHeight),u=this.getPixelRatio(),l=1;if(t.scale!==void 0)i*=t.scale,o*=t.scale,l=t.scale;else if(s){var f=1/0,v=1/0;we(t.maxWidth)&&(f=l*t.maxWidth/i),we(t.maxHeight)&&(v=l*t.maxHeight/o),l=Math.min(f,v),i*=l,o*=l}s||(i*=u,o*=u,l*=u);var c=document.createElement("canvas");c.width=i,c.height=o,c.style.width=i+"px",c.style.height=o+"px";var h=c.getContext("2d");if(i>0&&o>0){h.clearRect(0,0,i,o),h.globalCompositeOperation="source-over";var d=this.getCachedZSortedEles();if(t.full)h.translate(-a.x1*l,-a.y1*l),h.scale(l,l),this.drawElements(h,d),h.scale(1/l,1/l),h.translate(a.x1*l,a.y1*l);else{var g=e.pan(),m={x:g.x*l,y:g.y*l};l*=e.zoom(),h.translate(m.x,m.y),h.scale(l,l),this.drawElements(h,d),h.scale(1/l,1/l),h.translate(-m.x,-m.y)}t.bg&&(h.globalCompositeOperation="destination-over",h.fillStyle=t.bg,h.rect(0,0,i,o),h.fill())}return c};function P0(t,e){for(var r=atob(t),a=new ArrayBuffer(r.length),n=new Uint8Array(a),i=0;i<r.length;i++)n[i]=r.charCodeAt(i);return new Blob([a],{type:e})}function $f(t){var e=t.indexOf(",");return t.substr(e+1)}function Oc(t,e,r){var a=function(){return e.toDataURL(r,t.quality)};switch(t.output){case"blob-promise":return new Ta(function(n,i){try{e.toBlob(function(o){o!=null?n(o):i(new Error("`canvas.toBlob()` sent a null value in its callback"))},r,t.quality)}catch(o){i(o)}});case"blob":return P0($f(a()),r);case"base64":return $f(a());default:return a()}}gn.png=function(t){return Oc(t,this.bufferCanvasImage(t),"image/png")};gn.jpg=function(t){return Oc(t,this.bufferCanvasImage(t),"image/jpeg")};var Ic={};Ic.nodeShapeImpl=function(t,e,r,a,n,i,o,s){switch(t){case"ellipse":return this.drawEllipsePath(e,r,a,n,i);case"polygon":return this.drawPolygonPath(e,r,a,n,i,o);case"round-polygon":return this.drawRoundPolygonPath(e,r,a,n,i,o,s);case"roundrectangle":case"round-rectangle":return this.drawRoundRectanglePath(e,r,a,n,i,s);case"cutrectangle":case"cut-rectangle":return this.drawCutRectanglePath(e,r,a,n,i,o,s);case"bottomroundrectangle":case"bottom-round-rectangle":return this.drawBottomRoundRectanglePath(e,r,a,n,i,s);case"barrel":return this.drawBarrelPath(e,r,a,n,i)}};var O0=Bc,Ge=Bc.prototype;Ge.CANVAS_LAYERS=3;Ge.SELECT_BOX=0;Ge.DRAG=1;Ge.NODE=2;Ge.WEBGL=3;Ge.CANVAS_TYPES=["2d","2d","2d","webgl2"];Ge.BUFFER_COUNT=3;Ge.TEXTURE_BUFFER=0;Ge.MOTIONBLUR_BUFFER_NODE=1;Ge.MOTIONBLUR_BUFFER_DRAG=2;function Bc(t){var e=this,r=e.cy.window(),a=r.document;t.webgl&&(Ge.CANVAS_LAYERS=e.CANVAS_LAYERS=4,console.log("webgl rendering enabled")),e.data={canvases:new Array(Ge.CANVAS_LAYERS),contexts:new Array(Ge.CANVAS_LAYERS),canvasNeedsRedraw:new Array(Ge.CANVAS_LAYERS),bufferCanvases:new Array(Ge.BUFFER_COUNT),bufferContexts:new Array(Ge.CANVAS_LAYERS)};var n="-webkit-tap-highlight-color",i="rgba(0,0,0,0)";e.data.canvasContainer=a.createElement("div");var o=e.data.canvasContainer.style;e.data.canvasContainer.style[n]=i,o.position="relative",o.zIndex="0",o.overflow="hidden";var s=t.cy.container();s.appendChild(e.data.canvasContainer),s.style[n]=i;var u={"-webkit-user-select":"none","-moz-user-select":"-moz-none","user-select":"none","-webkit-tap-highlight-color":"rgba(0,0,0,0)","outline-style":"none"};Ch()&&(u["-ms-touch-action"]="none",u["touch-action"]="none");for(var l=0;l<Ge.CANVAS_LAYERS;l++){var f=e.data.canvases[l]=a.createElement("canvas"),v=Ge.CANVAS_TYPES[l];e.data.contexts[l]=f.getContext(v),e.data.contexts[l]||nt("Could not create canvas of type "+v),Object.keys(u).forEach(function($){f.style[$]=u[$]}),f.style.position="absolute",f.setAttribute("data-id","layer"+l),f.style.zIndex=String(Ge.CANVAS_LAYERS-l),e.data.canvasContainer.appendChild(f),e.data.canvasNeedsRedraw[l]=!1}e.data.topCanvas=e.data.canvases[0],e.data.canvases[Ge.NODE].setAttribute("data-id","layer"+Ge.NODE+"-node"),e.data.canvases[Ge.SELECT_BOX].setAttribute("data-id","layer"+Ge.SELECT_BOX+"-selectbox"),e.data.canvases[Ge.DRAG].setAttribute("data-id","layer"+Ge.DRAG+"-drag"),e.data.canvases[Ge.WEBGL]&&e.data.canvases[Ge.WEBGL].setAttribute("data-id","layer"+Ge.WEBGL+"-webgl");for(var l=0;l<Ge.BUFFER_COUNT;l++)e.data.bufferCanvases[l]=a.createElement("canvas"),e.data.bufferContexts[l]=e.data.bufferCanvases[l].getContext("2d"),e.data.bufferCanvases[l].style.position="absolute",e.data.bufferCanvases[l].setAttribute("data-id","buffer"+l),e.data.bufferCanvases[l].style.zIndex=String(-l-1),e.data.bufferCanvases[l].style.visibility="hidden";e.pathsEnabled=!0;var c=Bt(),h=function(q){return{x:(q.x1+q.x2)/2,y:(q.y1+q.y2)/2}},d=function(q){return{x:-q.w/2,y:-q.h/2}},g=function(q){var K=q[0]._private,ee=K.oldBackgroundTimestamp===K.backgroundTimestamp;return!ee},m=function(q){return q[0]._private.nodeKey},p=function(q){return q[0]._private.labelStyleKey},y=function(q){return q[0]._private.sourceLabelStyleKey},b=function(q){return q[0]._private.targetLabelStyleKey},E=function(q,K,ee,ne,te){return e.drawElement(q,K,ee,!1,!1,te)},C=function(q,K,ee,ne,te){return e.drawElementText(q,K,ee,ne,"main",te)},A=function(q,K,ee,ne,te){return e.drawElementText(q,K,ee,ne,"source",te)},D=function(q,K,ee,ne,te){return e.drawElementText(q,K,ee,ne,"target",te)},N=function(q){return q.boundingBox(),q[0]._private.bodyBounds},O=function(q){return q.boundingBox(),q[0]._private.labelBounds.main||c},R=function(q){return q.boundingBox(),q[0]._private.labelBounds.source||c},P=function(q){return q.boundingBox(),q[0]._private.labelBounds.target||c},w=function(q,K){return K},x=function(q){return h(N(q))},T=function(q,K,ee){var ne=q?q+"-":"";return{x:K.x+ee.pstyle(ne+"text-margin-x").pfValue,y:K.y+ee.pstyle(ne+"text-margin-y").pfValue}},M=function(q,K,ee){var ne=q[0]._private.rscratch;return{x:ne[K],y:ne[ee]}},S=function(q){return T("",M(q,"labelX","labelY"),q)},I=function(q){return T("source",M(q,"sourceLabelX","sourceLabelY"),q)},B=function(q){return T("target",M(q,"targetLabelX","targetLabelY"),q)},V=function(q){return d(N(q))},F=function(q){return d(R(q))},k=function(q){return d(P(q))},U=function(q){var K=O(q),ee=d(O(q));if(q.isNode()){switch(wa(q.pstyle("text-halign").value)){case"left":ee.x=-K.w-(K.leftPad||0);break;case"right":ee.x=-(K.rightPad||0);break}switch(Ea(q.pstyle("text-valign").value)){case"top":ee.y=-K.h-(K.topPad||0);break;case"bottom":ee.y=-(K.botPad||0);break}}return ee},J=e.data.eleTxrCache=new qa(e,{getKey:m,doesEleInvalidateKey:g,drawElement:E,getBoundingBox:N,getRotationPoint:x,getRotationOffset:V,allowEdgeTxrCaching:!1,allowParentTxrCaching:!1}),W=e.data.lblTxrCache=new qa(e,{getKey:p,drawElement:C,getBoundingBox:O,getRotationPoint:S,getRotationOffset:U,isVisible:w}),Q=e.data.slbTxrCache=new qa(e,{getKey:y,drawElement:A,getBoundingBox:R,getRotationPoint:I,getRotationOffset:F,isVisible:w}),Z=e.data.tlbTxrCache=new qa(e,{getKey:b,drawElement:D,getBoundingBox:P,getRotationPoint:B,getRotationOffset:k,isVisible:w}),H=e.data.lyrTxrCache=new xc(e);e.onUpdateEleCalcs(function(q,K){J.invalidateElements(K),W.invalidateElements(K),Q.invalidateElements(K),Z.invalidateElements(K),H.invalidateElements(K);for(var ee=0;ee<K.length;ee++){var ne=K[ee]._private;ne.oldBackgroundTimestamp=ne.backgroundTimestamp}});var j=function(q){for(var K=0;K<q.length;K++)H.enqueueElementRefinement(q[K].ele)};J.onDequeue(j),W.onDequeue(j),Q.onDequeue(j),Z.onDequeue(j),t.webgl&&e.initWebgl(t,{getStyleKey:m,getLabelKey:p,getSourceLabelKey:y,getTargetLabelKey:b,drawElement:E,drawLabel:C,drawSourceLabel:A,drawTargetLabel:D,getElementBox:N,getLabelBox:O,getSourceLabelBox:R,getTargetLabelBox:P,getElementRotationPoint:x,getElementRotationOffset:V,getLabelRotationPoint:S,getSourceLabelRotationPoint:I,getTargetLabelRotationPoint:B,getLabelRotationOffset:U,getSourceLabelRotationOffset:F,getTargetLabelRotationOffset:k})}Ge.redrawHint=function(t,e){var r=this;switch(t){case"eles":r.data.canvasNeedsRedraw[Ge.NODE]=e;break;case"drag":r.data.canvasNeedsRedraw[Ge.DRAG]=e;break;case"select":r.data.canvasNeedsRedraw[Ge.SELECT_BOX]=e;break;case"gc":r.data.gc=!0;break}};var I0=typeof Path2D<"u";Ge.path2dEnabled=function(t){if(t===void 0)return this.pathsEnabled;this.pathsEnabled=!!t};Ge.usePaths=function(){return I0&&this.pathsEnabled};Ge.setImgSmoothing=function(t,e){t.imageSmoothingEnabled!=null?t.imageSmoothingEnabled=e:(t.webkitImageSmoothingEnabled=e,t.mozImageSmoothingEnabled=e,t.msImageSmoothingEnabled=e)};Ge.getImgSmoothing=function(t){return t.imageSmoothingEnabled!=null?t.imageSmoothingEnabled:t.webkitImageSmoothingEnabled||t.mozImageSmoothingEnabled||t.msImageSmoothingEnabled};Ge.makeOffscreenCanvas=function(t,e){var r;if((typeof OffscreenCanvas>"u"?"undefined":mt(OffscreenCanvas))!=="undefined")r=new OffscreenCanvas(t,e);else{var a=this.cy.window(),n=a.document;r=n.createElement("canvas"),r.width=t,r.height=e}return r};[Tc,rr,fr,js,Qr,Rr,kt,Mc,Pr,gn,Ic].forEach(function(t){Re(Ge,t)});var B0=[{name:"null",impl:lc},{name:"base",impl:bc},{name:"canvas",impl:O0}],k0=[{type:"layout",extensions:im},{type:"renderer",extensions:B0}],kc={},Fc={};function zc(t,e,r){var a=r,n=function(N){Qe("Can not register `"+e+"` for `"+t+"` since `"+N+"` already exists in the prototype and can not be overridden")};if(t==="core"){if(tn.prototype[e])return n(e);tn.prototype[e]=r}else if(t==="collection"){if(St.prototype[e])return n(e);St.prototype[e]=r}else if(t==="layout"){for(var i=function(N){this.options=N,r.call(this,N),$e(this._private)||(this._private={}),this._private.cy=N.cy,this._private.listeners=[],this.createEmitter()},o=i.prototype=Object.create(r.prototype),s=[],u=0;u<s.length;u++){var l=s[u];o[l]=o[l]||function(){return this}}o.start&&!o.run?o.run=function(){return this.start(),this}:!o.start&&o.run&&(o.start=function(){return this.run(),this});var f=r.prototype.stop;o.stop=function(){var D=this.options;if(D&&D.animate){var N=this.animations;if(N)for(var O=0;O<N.length;O++)N[O].stop()}return f?f.call(this):this.emit("layoutstop"),this},o.destroy||(o.destroy=function(){return this}),o.cy=function(){return this._private.cy};var v=function(N){return N._private.cy},c={addEventFields:function(N,O){O.layout=N,O.cy=v(N),O.target=N},bubble:function(){return!0},parent:function(N){return v(N)}};Re(o,{createEmitter:function(){return this._private.emitter=new mi(c,this),this},emitter:function(){return this._private.emitter},on:function(N,O){return this.emitter().on(N,O),this},one:function(N,O){return this.emitter().one(N,O),this},once:function(N,O){return this.emitter().one(N,O),this},removeListener:function(N,O){return this.emitter().removeListener(N,O),this},removeAllListeners:function(){return this.emitter().removeAllListeners(),this},emit:function(N,O){return this.emitter().emit(N,O),this}}),Ze.eventAliasesOn(o),a=i}else if(t==="renderer"&&e!=="null"&&e!=="base"){var h=Vc("renderer","base"),d=h.prototype,g=r,m=r.prototype,p=function(){h.apply(this,arguments),g.apply(this,arguments)},y=p.prototype;for(var b in d){var E=d[b],C=m[b]!=null;if(C)return n(b);y[b]=E}for(var A in m)y[A]=m[A];d.clientFunctions.forEach(function(D){y[D]=y[D]||function(){nt("Renderer does not implement `renderer."+D+"()` on its prototype")}}),a=p}else if(t==="__proto__"||t==="constructor"||t==="prototype")return nt(t+" is an illegal type to be registered, possibly lead to prototype pollutions");return rv({map:kc,keys:[t,e],value:a})}function Vc(t,e){return av({map:kc,keys:[t,e]})}function F0(t,e,r,a,n){return rv({map:Fc,keys:[t,e,r,a],value:n})}function z0(t,e,r,a){return av({map:Fc,keys:[t,e,r,a]})}var Ls=function(){if(arguments.length===2)return Vc.apply(null,arguments);if(arguments.length===3)return zc.apply(null,arguments);if(arguments.length===4)return z0.apply(null,arguments);if(arguments.length===5)return F0.apply(null,arguments);nt("Invalid extension access syntax")};tn.prototype.extension=Ls;k0.forEach(function(t){t.extensions.forEach(function(e){zc(t.type,e.name,e.impl)})});var si=function(){if(!(this instanceof si))return new si;this.length=0},_r=si.prototype;_r.instanceString=function(){return"stylesheet"};_r.selector=function(t){var e=this.length++;return this[e]={selector:t,properties:[]},this};_r.css=function(t,e){var r=this.length-1;if(Le(t))this[r].properties.push({name:t,value:e});else if($e(t))for(var a=t,n=Object.keys(a),i=0;i<n.length;i++){var o=n[i],s=a[o];if(s!=null){var u=xt.properties[o]||xt.properties[li(o)];if(u!=null){var l=u.name,f=s;this[r].properties.push({name:l,value:f})}}}return this};_r.style=_r.css;_r.generateStyle=function(t){var e=new xt(t);return this.appendToStyle(e)};_r.appendToStyle=function(t){for(var e=0;e<this.length;e++){var r=this[e],a=r.selector,n=r.properties;t.selector(a);for(var i=0;i<n.length;i++){var o=n[i];t.css(o.name,o.value)}}return t};var V0="3.34.0",lr=function(e){if(e===void 0&&(e={}),$e(e))return new tn(e);if(Le(e))return Ls.apply(Ls,arguments)};lr.use=function(t){var e=Array.prototype.slice.call(arguments,1);return e.unshift(lr),t.apply(null,e),this};lr.warnings=function(t){return fv(t)};lr.version=V0;lr.stylesheet=lr.Stylesheet=si;var _c=oh(Gc(),1);var Ma={Entity:0,Service:1,Event:1,UseCase:2,Port:3,DTO:4,VO:4,Error:4,Shared:4,Adapter:5},qc={Entity:95,Service:72,Event:60,UseCase:48,Port:30,DTO:0,VO:0,Error:0,Shared:22,Adapter:18},Yc={Entity:"barrel",Service:"rectangle",UseCase:"round-rectangle",Port:"cut-rectangle",Event:"rhomboid",DTO:"round-rectangle",VO:"round-rectangle",Error:"round-rectangle",Shared:"round-rectangle",Adapter:"round-rectangle"},ol=["Entity","Service","UseCase","Port","Event"],sl=["DTO","VO","Error"],bn=42,Wc=338,G0=15;function Uc(t){let e=0;for(let a=0;a<t.length;a++)e=e*31+t.charCodeAt(a)|0;let r=Math.abs(e*.6180339887%1);return Math.round(bn+r*(Wc-bn))}var U0=(t,e)=>{let r=Math.abs(t-e)%360;return Math.min(r,360-r)};function Xc(t){let e=[...new Set(t)].filter(i=>!La(i)).sort(),r=[],a=new Map,n=Wc-bn;for(let i of e){let o=Uc(i),s=o;for(let u=0;u<n;u++){let l=bn+(o-bn+u)%n;if(r.every(f=>U0(f,l)>=G0)){s=l;break}}r.push(s),a.set(i,s)}return i=>La(i)?0:a.get(i)??Uc(i)}var La=t=>t==="common"||t==="shared",Di=190,H0=40,q0=230,Y0=268,W0=130,Hc=34,X0=30;function $0(t){let e=new Map;for(let o of t){let s=Ma[o.component];e.set(s,[...e.get(s)??[],o])}let r=new Map,a=0;for(let o of[...e.keys()].sort((s,u)=>s-u)){let s=e.get(o),u=s.length*Y0/(2*Math.PI),l=o===0&&s.length===1?0:Math.max(a+q0,u,170);s.forEach((f,v)=>{if(l===0)r.set(f.id,[0,0]);else{let c=2*Math.PI*v/s.length-Math.PI/2;r.set(f.id,[l*Math.cos(c),l*Math.sin(c)])}}),a=l}let n=0,i=0;for(let[o,s]of r.values())n=Math.max(n,Math.abs(o)),i=Math.max(i,Math.abs(s));return{pos:r,hw:n+Di/2+Hc,hh:i+H0/2+Hc+X0/2}}function K0(t,e,r=W0){let a=new Map(t.nodes.map(c=>[c.id,c])),n=new Map;for(let c of t.edges){let h=a.get(c.src)?.domain,d=a.get(c.dst)?.domain;if(!h||!d||h===d)continue;let g=h<d?`${h}|${d}`:`${d}|${h}`;n.set(g,(n.get(g)??0)+1)}let i=c=>e.get(c)??{hw:0,hh:0},o=c=>i(c).hw*i(c).hh,s=[...e.keys()].sort((c,h)=>o(h)-o(c)),u=new Map,l=0,f=0;s.forEach((c,h)=>{if(h===0){u.set(c,[0,0]);return}l+=Math.hypot(i(c).hw,i(c).hh)*.95,f+=2.399963,u.set(c,[l*Math.cos(f),l*Math.sin(f)])});let v=c=>{let h=0;for(let d=0;d<s.length;d++){let g=s[d];for(let m=d+1;m<s.length;m++){let p=s[m],y=u.get(g),b=u.get(p),E=b[0]-y[0],C=b[1]-y[1],A=i(g).hw+i(p).hw+r-Math.abs(E),D=i(g).hh+i(p).hh+r-Math.abs(C);if(A<=0||D<=0)continue;h=Math.max(h,Math.min(A,D));let N=Math.min(A,D)*c;if(A<D){let O=E>=0?1:-1;y[0]-=O*N,b[0]+=O*N}else{let O=C>=0?1:-1;y[1]-=O*N,b[1]+=O*N}}}return h};for(let c=0;c<400;c++){for(let h=0;h<s.length;h++){let d=s[h];for(let g=h+1;g<s.length;g++){let m=s[g],p=n.get(d<m?`${d}|${m}`:`${m}|${d}`)??0,y=u.get(d),b=u.get(m),E=b[0]-y[0],C=b[1]-y[1],A=Math.hypot(E,C)||1,D=i(d).hw+i(m).hw+r-Math.abs(E),N=i(d).hh+i(m).hh+r-Math.abs(C);if(D>0&&N>0)continue;let O=-Math.min(D,N),R=Math.min(O*(p?.06*Math.log1p(p):.006),90);u.set(d,[y[0]+E/A*R,y[1]+C/A*R]),u.set(m,[b[0]-E/A*R,b[1]-C/A*R])}}v(.5);for(let h of s){let d=u.get(h);d[0]-=d[0]*.004,d[1]-=d[1]*.004}}for(let c=0;c<600&&v(.5)>.5;c++);return u}function ll(t){let e=new Map;for(let o of t.nodes)e.set(o.domain,[...e.get(o.domain)??[],o]);let r=new Map,a=new Map;for(let[o,s]of e){let u=$0(s);r.set(o,u.pos),a.set(o,{hw:u.hw,hh:u.hh})}let n=K0(t,a),i=[];for(let[o,s]of r){let[u,l]=n.get(o)??[0,0];for(let[f,[v,c]]of s)i.push({id:f,x:Math.round(u+v),y:Math.round(l+c)})}return i}var _0=Di+54,Z0=74;function Q0(t,e){let r=[...e].sort((i,o)=>Ma[i.component]-Ma[o.component]||i.name.localeCompare(o.name)),a=Math.max(1,Math.min(5,Math.ceil(Math.sqrt(r.length/2.2)))),n=Math.ceil(r.length/a);return{d:t,items:r,cols:a,w:a*_0+80,h:n*Z0+92}}function $c(t,e=3e3){let r=new Map;for(let l of t.nodes)r.set(l.domain,[...r.get(l.domain)??[],l]);let a=[...r.entries()].map(([l,f])=>Q0(l,f)).sort((l,f)=>f.items.length-l.items.length),n=e,i=[],o=0,s=0,u=0;for(let l of a)s+l.w>n&&s>0&&(o+=u+90,s=0,u=0),l.items.forEach((f,v)=>{i.push({id:f.id,x:Math.round(s+40+v%l.cols*(Di+54)+Di/2),y:Math.round(o+52+Math.floor(v/l.cols)*74)})}),s+=l.w+70,u=Math.max(u,l.h);return i}lr.use(_c.default);var vr=(t,e,r)=>`hsl(${t},${e}%,${r}%)`,He=t=>document.getElementById(t),ea=t=>Array.from(document.querySelectorAll(t)),Ue,wt,pl,Li="hex",Or=!1,jr=!1,Ai,ta=null,Jr="both",Kc,Ni,wn=()=>0;async function J0(){wt=await(await fetch("/api/graph")).json();let t=[...new Set(wt.nodes.map(a=>a.domain))];wn=Xc(t);let e=[...new Set(wt.nodes.map(a=>a.component))].sort((a,n)=>Ma[a]-Ma[n]);pl={hex:new Map(ll(wt).map(a=>[a.id,{x:a.x,y:a.y}])),grid:new Map($c(wt).map(a=>[a.id,{x:a.x,y:a.y}]))},document.title=`${wt.project} \u2014 hexwright`,He("title").textContent=wt.project,He("ref").textContent=wt.ref;let r={added:wt.nodes.filter(a=>a.status==="added").length,modified:wt.nodes.filter(a=>a.status==="modified").length,addedEdges:wt.edges.filter(a=>a.status==="added").length};(r.added||r.modified)&&(He("delta").innerHTML=`<span class="k"></span>added ${r.added} nodes \xB7 ${r.addedEdges} edges<br><span class="k2"></span>modified ${r.modified} nodes`,He("deltaBox").style.display="block"),j0(t,e),tb(),cl("bhex"),gl("core")}function j0(t,e){let r=new Map;for(let a of wt.nodes)r.set(`c:${a.component}`,(r.get(`c:${a.component}`)??0)+1),r.set(`d:${a.domain}`,(r.get(`d:${a.domain}`)??0)+1);He("comps").innerHTML=e.map(a=>`<label><span class="sw" style="${eb(a)}"></span><input type=checkbox class=cf value="${a}" ${ol.includes(a)?"checked":""}>${a}<span class="n">${r.get(`c:${a}`)??0}</span></label>`).join(""),He("doms").innerHTML=t.sort((a,n)=>(r.get(`d:${n}`)??0)-(r.get(`d:${a}`)??0)).map(a=>{let n=wn(a);return`<label><span class="sw" style="background:${vr(n,La(a)?0:60,50)}"></span><input type=checkbox class=df value="${a}" checked>${a}<span class="n">${r.get(`d:${a}`)??0}</span></label>`}).join("");for(let a of ea(".cf,.df,.rf"))a.onchange=()=>Ir();He("showId").onchange=()=>Ir(),He("crossOnly").onchange=()=>Ir(),He("deltaOnly").onchange=()=>Ir()}function eb(t){let e="#8b949e";return sl.includes(t)?`border:1.4px dashed ${e};border-radius:5px`:`background:${e};${{Entity:"border-radius:6px/50%",Service:"border-radius:0",Port:"clip-path:polygon(22% 0,100% 0,100% 78%,78% 100%,0 100%,0 22%)",Event:"transform:skewX(-16deg)"}[t]??"border-radius:5px"}`}function tb(){let t=[...new Set(wt.nodes.map(n=>n.domain))].map(n=>({data:{id:`dom::${n}`,label:n,kind:"domain",hue:wn(n),sat:La(n)?0:26}})),e=wt.nodes.map(n=>({data:{...n,parent:`dom::${n.domain}`,kind:"type",hue:wn(n.domain),sat:La(n.domain)?0:qc[n.component],shape:Yc[n.component],outline:sl.includes(n.component),label:n.name},position:{...pl.hex.get(n.id)??{x:0,y:0}}})),r=wt.edges.map((n,i)=>({data:{...n,id:`e${i}`,source:n.src,target:n.dst,hue:wn(vl(n.src)?.domain??"")}}));Ue=lr({container:He("cy"),elements:[...t,...e,...r],layout:{name:"preset"},minZoom:.05,maxZoom:3,wheelSensitivity:.25,style:[{selector:'node[kind="domain"]',style:{"background-color":n=>vr(n.data("hue"),n.data("sat"),13),"background-opacity":.5,"border-width":1.5,"border-color":n=>vr(n.data("hue"),n.data("sat")+19,42),shape:"round-rectangle",label:"data(label)","text-valign":"top","font-size":21,"font-weight":"bold",color:n=>vr(n.data("hue"),n.data("sat")+29,62),"text-margin-y":-7,padding:"16px"}},{selector:'node[kind="type"]',style:{shape:"data(shape)",width:"182px",height:"32px","background-color":n=>vr(n.data("hue"),n.data("sat"),46-n.data("sat")*.07),"background-opacity":n=>n.data("outline")?0:1,label:"data(label)","font-size":11,"text-valign":"center","text-wrap":"ellipsis","text-max-width":"160px",color:n=>n.data("outline")?vr(n.data("hue"),n.data("hue")?52:0,72):"#fff","border-width":n=>n.data("outline")?1.4:1,"border-color":n=>vr(n.data("hue"),n.data("outline")?48:n.data("sat"),n.data("outline")?52:70),"border-style":n=>n.data("outline")?"dashed":"solid"}},{selector:'node[component="Entity"]',style:{"border-width":2.6,width:"190px",height:"36px","font-weight":"bold","font-size":12}},{selector:'node[component="Service"]',style:{"border-width":1.8}},{selector:"edge",style:{width:1.9,"line-color":n=>vr(n.data("hue"),n.data("crossDomain")?62:22,n.data("crossDomain")?58:46),opacity:n=>n.data("crossDomain")?.8:.62,"target-arrow-color":n=>vr(n.data("hue"),n.data("crossDomain")?62:22,n.data("crossDomain")?58:46)}},{selector:'edge[rel="DEPENDS_ON"]',style:{"line-style":"solid","curve-style":"straight","target-arrow-shape":"vee","arrow-scale":.95}},{selector:'edge[rel="REFERENCES"]',style:{"line-style":"dashed","line-dash-pattern":[2,4],width:1.4,"curve-style":"unbundled-bezier","control-point-distances":[24],"control-point-weights":[.5],"target-arrow-shape":"vee","arrow-scale":.9}},{selector:'edge[rel="IMPLEMENTS"]',style:{"line-style":"dashed","line-dash-pattern":[9,5],width:2.2,"curve-style":"unbundled-bezier","control-point-distances":[42],"control-point-weights":[.5],"target-arrow-shape":"triangle","target-arrow-fill":"hollow","arrow-scale":1.35}},{selector:'edge[rel="EXTENDS"]',style:{"line-style":"dashed","line-dash-pattern":[3,3],width:3.4,"curve-style":"unbundled-bezier","control-point-distances":[58],"control-point-weights":[.5],"target-arrow-shape":"triangle","target-arrow-fill":"hollow","arrow-scale":1.6}},{selector:"edge[?identifierOnly]",style:{"line-style":"dotted",opacity:.4}},{selector:'edge[violation != ""]',style:{"line-color":"#f85149","target-arrow-color":"#f85149",width:3.4,opacity:1,"z-index":90,label:"data(violation)","font-size":10,color:"#f85149","text-background-color":"#0e1116","text-background-opacity":.85,"text-background-padding":"3px"}},{selector:'edge[status="added"]',style:{opacity:1,"line-color":"#f0883e","target-arrow-color":"#f0883e","z-index":80}},{selector:".dim",style:{opacity:.035,"text-opacity":0}},{selector:".nb",style:{"border-width":2.4,"border-color":"#58a6ff","z-index":50}},{selector:".hi",style:{"border-width":5,"border-color":"#58a6ff","z-index":100}},{selector:"edge.sel",style:{width:5,opacity:1,"line-color":"#58a6ff","target-arrow-color":"#58a6ff","z-index":99}}]}),window.cy=Ue,new ResizeObserver(()=>{Ue.resize();let n=Ue.nodes('[kind="type"]').filter(i=>i.style("display")==="element");n.length&&Ue.fit(n,40)}).observe(He("cy")),Ue.on("tap",'node[kind="type"]',n=>dl(n.target)),Ue.on("tap","edge",n=>sb(n.target)),Ue.on("tap",n=>{let i=n.target;(n.target===Ue||i.data?.("kind")==="domain")&&hl()}),document.addEventListener("keydown",n=>{n.key==="Escape"&&hl()})}var vl=t=>wt.nodes.find(e=>e.id===t);function Ir(){let t=new Set(ea(".cf:checked").map(u=>u.value)),e=new Set(ea(".df:checked").map(u=>u.value)),r=new Set(ea(".rf:checked").map(u=>u.value)),a=He("showId").checked,n=He("crossOnly").checked,i=He("deltaOnly").checked,o=new Set;if(jr)for(let u of Ue.edges())u.data("violation")&&(o.add(u.data("source")),o.add(u.data("target")));Ue.batch(()=>{for(let l of Ue.nodes('[kind="type"]')){let f=l.data(),v=t.has(f.component)&&e.has(f.domain);v&&i&&f.status==="existing"&&(v=!1),v&&jr&&!o.has(f.id)&&(v=!1),l.style("display",v?"element":"none")}let u=l=>l.style("display")==="element";for(let l of Ue.nodes('[kind="domain"]'))l.style("display",l.children().filter(f=>u(f)).length?"element":"none");for(let l of Ue.edges()){let f=u(l.source())&&u(l.target())&&r.has(l.data("rel"));f&&!a&&l.data("identifierOnly")&&(f=!1),f&&n&&!l.data("crossDomain")&&(f=!1),f&&jr&&!l.data("violation")&&(f=!1),l.style("display",f?"element":"none")}}),rb(),Ue.nodes('[kind="type"]').filter(u=>u.style("display")==="element").length&&ab()}function rb(){let t=n=>n.style("display")==="element",e=Ue.nodes('[kind="type"]').filter(n=>t(n)).length,r=Ue.edges().filter(n=>t(n)).length,a=Ue.edges().filter(n=>t(n)&&n.data("violation")).length;He("stat").innerHTML=`Nodes <b>${e}</b>/${Ue.nodes('[kind="type"]').length} \xB7 Edges <b>${r}</b>/${Ue.edges().length}`,He("cviol").textContent=String(a);for(let n of["DEPENDS_ON","REFERENCES","IMPLEMENTS","EXTENDS"]){let i=document.getElementById(`c${n}`);i&&(i.textContent=String(Ue.edges(`[rel="${n}"]`).filter(o=>t(o)).length))}}function ab(){clearTimeout(Kc),Kc=setTimeout(Mi,110)}function Mi(){Ni?.stop(),Ni=void 0,Or?Li==="hex"?nb():ob():ib()}var ul=t=>t.style("display")==="element";function nb(){let t=new Set(Ue.nodes('[kind="type"]').filter(i=>ul(i)).map(i=>i.id())),e=new Set(Ue.edges().filter(i=>ul(i)).map(i=>i.id())),r={...wt,nodes:wt.nodes.filter(i=>t.has(i.id)),edges:wt.edges.filter((i,o)=>e.has(`e${o}`))},a=new Map(ll(r).map(i=>[i.id,i]));Ue.batch(()=>{for(let i of Ue.nodes('[kind="type"]')){let o=a.get(i.id());o&&i.position({x:o.x,y:o.y})}});let n=Ue.nodes('[kind="type"]').filter(i=>ul(i));n.length&&Ue.fit(n,40)}function ib(){let t=pl[Li];Ue.batch(()=>{for(let r of Ue.nodes('[kind="type"]')){let a=t.get(r.id());a&&r.position({x:a.x,y:a.y})}});let e=Ue.nodes('[kind="type"]').filter(r=>r.style("display")==="element");e.length&&Ue.fit(e,40)}function ob(){let t=Ue.elements().filter(r=>r.style("display")==="element"),e=t.nodes().length;e&&(Ni=t.layout({name:"fcose",quality:e<=150?"proof":e<=400?"default":"draft",numIter:e<=150?1600:e<=400?900:500,randomize:e<=150,animate:e<=250,animationDuration:400,nodeSeparation:210,idealEdgeLength:r=>r.data("crossDomain")?300:130,nodeRepulsion:34e3,gravity:.12,gravityCompound:.9,gravityRangeCompound:2.2,packComponents:!0,tile:!0,nodeDimensionsIncludeLabels:!0,stop:()=>Ue.fit(t.nodes(),60)}),Ni.run())}var cl=t=>{for(let e of["bhex","bgrid"])He(e).classList.toggle("on",e===t)};function hl(){Ue.elements().removeClass("hi dim sel nb"),He("info").style.display="none",ta=null,Jr="both"}var Vt=(t,e)=>`<tr><td>${t}</td><td>${e}</td></tr>`,fl=t=>t?'<span style="color:#f0883e">yes</span>':"no",Zc=t=>t==="added"?'<span style="color:#f0883e">added</span>':t==="modified"?'<span style="color:#a371f7">modified</span>':"existing";function dl(t){ta=t.id();let e=t.data(),r=c=>c.style("display")==="element",a=t.connectedEdges().filter(c=>r(c)),n=a.filter(c=>c.target().id()===ta),i=a.filter(c=>c.source().id()===ta),o=Jr==="in"?n:Jr==="out"?i:a,s=o.connectedNodes().difference(t);Ue.elements().removeClass("hi dim sel nb").addClass("dim"),t.removeClass("dim").addClass("hi"),s.removeClass("dim").addClass("nb"),o.removeClass("dim").addClass("sel"),s.parent().removeClass("dim"),t.parent().removeClass("dim");let u=(c,h,d)=>`<button class="dirb ${Jr===c?"on":""}" data-dir="${c}">${h} ${d}</button>`,l=(c,h,d)=>{let g=d.data();return`<div class="lk" data-goto="${g.id}"><span class="ar">${h}</span>${g.name}<span class="mut"> ${g.domain}\xB7${g.component}</span><span class="rel">${c.data("rel")==="DEPENDS_ON"?"":c.data("rel")}</span></div>`},f="";if(Jr!=="out")for(let c of n)f+=l(c,"\u2190",c.source());if(Jr!=="in")for(let c of i)f+=l(c,"\u2192",c.target());let v=e.api.length||e.props.length?`<div class="dirbar" style="display:block"><b>Public contract</b><span class="mut"> ${e.api.length} fn${e.props.length?` \xB7 ${e.props.length} prop`:""}</span></div><div class="lks">${e.api.map(c=>{let h=c.indexOf("(");return`<div class="lk"><span class="sig"><b>${c.slice(0,h)}</b>${c.slice(h)}</span></div>`}).join("")}${e.props.map(c=>`<div class="lk"><span class="sig" style="color:#6e7681">${c}</span></div>`).join("")}</div>`:"";He("info").style.display="block",He("info").innerHTML=`<div class="ih">${e.name}<span class="x">\xD7</span></div><table>${Vt("Domain",e.domain)}${Vt("Component",`${e.component} <span class="mut">${e.layer}${e.sublayer?`/${e.sublayer}`:""}</span>`)}${Vt("Kind",e.kind)}${Vt("Status",Zc(e.status))}${Vt("File",`<span class="mut">${e.file}:${e.line}</span>`)}${Vt("Id",`<span class="mut" style="word-break:break-all">${e.id}</span>`)}</table>${v}<div class="dirbar">${u("both","Both",a.length)}${u("in","\u2190 In",n.length)}${u("out","Out \u2192",i.length)}</div><div class="lks">${f||'<span class="mut">No visible connections</span>'}</div><div class="hint">Click an item to focus it \xB7 Esc to clear</div>`,Qc()}function sb(t){ta=null;let e=t.data(),r=vl(e.src),a=vl(e.dst);Ue.elements().removeClass("hi dim sel nb").addClass("dim"),t.removeClass("dim").addClass("sel"),t.connectedNodes().removeClass("dim").addClass("nb").parent().removeClass("dim");let n=e.contracts.length?`<div class="dirbar" style="display:block"><b>Contracts used</b><span class="mut"> ${e.contracts.length}/${a?.api.length??0}</span></div><div class="lks">${e.contracts.map(i=>{let o=i.indexOf("(");return`<div class="lk"><span class="sig"><b>${o>0?i.slice(0,o):i}</b>${o>0?i.slice(o):""}</span></div>`}).join("")}</div>`:'<div class="hint">No method calls \u2014 type reference only</div>';He("info").style.display="block",He("info").innerHTML=`<div class="ih">${e.rel}<span class="x">\xD7</span></div><table>${Vt("Source",`${r?.name} <span class="mut">${r?.domain}\xB7${r?.component}</span>`)}${Vt("Target",`${a?.name} <span class="mut">${a?.domain}\xB7${a?.component}</span>`)}${e.rel==="DEPENDS_ON"?Vt("Weight",`${e.weight} <span class="mut">occurrences</span>`):""}${Vt("Cross-domain",fl(e.crossDomain))}${Vt("Identifier only",fl(e.identifierOnly))}${Vt("Via signature",fl(e.viaSignature))}${e.violation?Vt("Violation",`<span style="color:#f85149">${e.violation}</span>`):""}${Vt("Status",Zc(e.status))}</table>${n}`,Qc()}function Qc(){let t=He("info").querySelector(".x");t&&(t.onclick=()=>hl());for(let e of Array.from(He("info").querySelectorAll(".dirb")))e.onclick=()=>{Jr=e.dataset.dir,ta&&dl(Ue.getElementById(ta))};for(let e of Array.from(He("info").querySelectorAll("[data-goto]")))e.onclick=()=>dl(Ue.getElementById(e.dataset.goto))}function gl(t){for(let e of ea(".cf"))e.checked=t==="core"?ol.includes(e.value):!0;for(let e of["pcore","pall"])He(e).classList.toggle("on",e===`p${t}`);Ir()}function lb(){He("pcore").onclick=()=>gl("core"),He("pall").onclick=()=>gl("all"),He("bhex").onclick=()=>{Li="hex",cl("bhex"),Mi()},He("bgrid").onclick=()=>{Li="grid",cl("bgrid"),Mi()},He("borg").onclick=()=>{Or=!Or,He("borg").classList.toggle("on",Or),Mi()},He("bviol").onclick=()=>{jr=!jr,He("bviol").classList.toggle("on",jr),jr?(Ai=Or,Or=!0):Ai!==void 0&&(Or=Ai,Ai=void 0),He("borg").classList.toggle("on",Or),Ir()},He("allDomOn").onclick=()=>{for(let t of ea(".df"))t.checked=!0;Ir()},He("allDomOff").onclick=()=>{for(let t of ea(".df"))t.checked=!1;Ir()},J0()}lb();})();
322
322
  /*! Bundled license information:
323
323
 
324
324
  cytoscape/dist/cytoscape.esm.mjs:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hexwright",
3
- "version": "0.1.0",
3
+ "version": "0.3.0",
4
4
  "description": "Design graph for hexagonal-architecture codebases. Renders what a branch changed as one picture a human can confirm at a glance, and gives a coding agent boundary verdicts it can run on itself before asking for review.",
5
5
  "keywords": [
6
6
  "hexagonal-architecture",
@@ -61,7 +61,7 @@
61
61
  "esbuild": "^0.28.1",
62
62
  "tsup": "^8.3.5",
63
63
  "typescript": "^5.7.2",
64
- "vitest": "^2.1.8"
64
+ "vitest": "^4.1.10"
65
65
  },
66
66
  "optionalDependencies": {
67
67
  "@resvg/resvg-js": "^2.6.2"
@@ -14,6 +14,18 @@ domain:
14
14
  # which segment is the domain (0-based, after the prefix is stripped)
15
15
  at: 0
16
16
 
17
+ # How an identifier is tied to the aggregate it identifies, so that a type holding
18
+ # another aggregate's id is drawn as REFERENCES rather than as a dependency on the
19
+ # id. Remove this block and no identifier is resolved.
20
+ identity:
21
+ # property = the type declaring this property owns the identifier. Structural, and
22
+ # it survives an aggregate whose name is not the identifier's stem — MediaId
23
+ # identifies MediaItem, not Media.
24
+ # suffix = strip the suffix from the identifier's name and look for that type.
25
+ # Simpler, but resolves nothing the moment the two names diverge.
26
+ from: property
27
+ property: id
28
+
17
29
  # Path fragments to exclude from analysis
18
30
  exclude:
19
31
  - /config/