@aetherwing/fcp-drawio 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +119 -0
  3. package/dist/adapter.d.ts +38 -0
  4. package/dist/adapter.js +259 -0
  5. package/dist/adapter.js.map +1 -0
  6. package/dist/index.d.ts +1 -0
  7. package/dist/index.js +6 -0
  8. package/dist/index.js.map +1 -0
  9. package/dist/layout/elk-layout.d.ts +49 -0
  10. package/dist/layout/elk-layout.js +144 -0
  11. package/dist/layout/elk-layout.js.map +1 -0
  12. package/dist/lib/drawio-cli.d.ts +22 -0
  13. package/dist/lib/drawio-cli.js +88 -0
  14. package/dist/lib/drawio-cli.js.map +1 -0
  15. package/dist/lib/node-types.d.ts +22 -0
  16. package/dist/lib/node-types.js +174 -0
  17. package/dist/lib/node-types.js.map +1 -0
  18. package/dist/lib/stencils/aws.d.ts +2 -0
  19. package/dist/lib/stencils/aws.js +69 -0
  20. package/dist/lib/stencils/aws.js.map +1 -0
  21. package/dist/lib/stencils/azure.d.ts +2 -0
  22. package/dist/lib/stencils/azure.js +54 -0
  23. package/dist/lib/stencils/azure.js.map +1 -0
  24. package/dist/lib/stencils/cisco.d.ts +2 -0
  25. package/dist/lib/stencils/cisco.js +30 -0
  26. package/dist/lib/stencils/cisco.js.map +1 -0
  27. package/dist/lib/stencils/gcp.d.ts +2 -0
  28. package/dist/lib/stencils/gcp.js +38 -0
  29. package/dist/lib/stencils/gcp.js.map +1 -0
  30. package/dist/lib/stencils/ibm.d.ts +2 -0
  31. package/dist/lib/stencils/ibm.js +32 -0
  32. package/dist/lib/stencils/ibm.js.map +1 -0
  33. package/dist/lib/stencils/index.d.ts +10 -0
  34. package/dist/lib/stencils/index.js +33 -0
  35. package/dist/lib/stencils/index.js.map +1 -0
  36. package/dist/lib/stencils/k8s.d.ts +2 -0
  37. package/dist/lib/stencils/k8s.js +32 -0
  38. package/dist/lib/stencils/k8s.js.map +1 -0
  39. package/dist/lib/stencils/types.d.ts +14 -0
  40. package/dist/lib/stencils/types.js +2 -0
  41. package/dist/lib/stencils/types.js.map +1 -0
  42. package/dist/lib/themes.d.ts +8 -0
  43. package/dist/lib/themes.js +32 -0
  44. package/dist/lib/themes.js.map +1 -0
  45. package/dist/model/defaults.d.ts +3 -0
  46. package/dist/model/defaults.js +26 -0
  47. package/dist/model/defaults.js.map +1 -0
  48. package/dist/model/diagram-model.d.ts +110 -0
  49. package/dist/model/diagram-model.js +938 -0
  50. package/dist/model/diagram-model.js.map +1 -0
  51. package/dist/model/event-log.d.ts +30 -0
  52. package/dist/model/event-log.js +112 -0
  53. package/dist/model/event-log.js.map +1 -0
  54. package/dist/model/id.d.ts +9 -0
  55. package/dist/model/id.js +35 -0
  56. package/dist/model/id.js.map +1 -0
  57. package/dist/model/reference-registry.d.ts +33 -0
  58. package/dist/model/reference-registry.js +143 -0
  59. package/dist/model/reference-registry.js.map +1 -0
  60. package/dist/model/spatial.d.ts +20 -0
  61. package/dist/model/spatial.js +59 -0
  62. package/dist/model/spatial.js.map +1 -0
  63. package/dist/parser/parse-op.d.ts +18 -0
  64. package/dist/parser/parse-op.js +430 -0
  65. package/dist/parser/parse-op.js.map +1 -0
  66. package/dist/parser/resolve-ref.d.ts +27 -0
  67. package/dist/parser/resolve-ref.js +232 -0
  68. package/dist/parser/resolve-ref.js.map +1 -0
  69. package/dist/parser/tokenizer.d.ts +6 -0
  70. package/dist/parser/tokenizer.js +7 -0
  71. package/dist/parser/tokenizer.js.map +1 -0
  72. package/dist/serialization/connector-intelligence.d.ts +35 -0
  73. package/dist/serialization/connector-intelligence.js +336 -0
  74. package/dist/serialization/connector-intelligence.js.map +1 -0
  75. package/dist/serialization/deserialize.d.ts +6 -0
  76. package/dist/serialization/deserialize.js +511 -0
  77. package/dist/serialization/deserialize.js.map +1 -0
  78. package/dist/serialization/serialize.d.ts +15 -0
  79. package/dist/serialization/serialize.js +332 -0
  80. package/dist/serialization/serialize.js.map +1 -0
  81. package/dist/server/intent-layer.d.ts +48 -0
  82. package/dist/server/intent-layer.js +1322 -0
  83. package/dist/server/intent-layer.js.map +1 -0
  84. package/dist/server/mcp-server.d.ts +7 -0
  85. package/dist/server/mcp-server.js +26 -0
  86. package/dist/server/mcp-server.js.map +1 -0
  87. package/dist/server/model-map.d.ts +8 -0
  88. package/dist/server/model-map.js +240 -0
  89. package/dist/server/model-map.js.map +1 -0
  90. package/dist/server/query-handler.d.ts +19 -0
  91. package/dist/server/query-handler.js +148 -0
  92. package/dist/server/query-handler.js.map +1 -0
  93. package/dist/server/response-formatter.d.ts +56 -0
  94. package/dist/server/response-formatter.js +351 -0
  95. package/dist/server/response-formatter.js.map +1 -0
  96. package/dist/server/session-handler.d.ts +6 -0
  97. package/dist/server/session-handler.js +127 -0
  98. package/dist/server/session-handler.js.map +1 -0
  99. package/dist/types/index.d.ts +238 -0
  100. package/dist/types/index.js +3 -0
  101. package/dist/types/index.js.map +1 -0
  102. package/dist/verb-specs.d.ts +6 -0
  103. package/dist/verb-specs.js +144 -0
  104. package/dist/verb-specs.js.map +1 -0
  105. package/package.json +39 -0
@@ -0,0 +1,232 @@
1
+ /**
2
+ * 5-level reference resolution cascade.
3
+ *
4
+ * 1. Exact label match (case-sensitive)
5
+ * 2. Case-insensitive match
6
+ * 3. Normalized match (strip hyphens, underscores, spaces)
7
+ * 4. Prefix match
8
+ * 5. Recency match (@recent)
9
+ *
10
+ * Short-circuits at the first level producing exactly one result.
11
+ */
12
+ export function resolveRef(ref, registry, model) {
13
+ // Handle selectors
14
+ if (ref.startsWith("@")) {
15
+ return resolveSelector(ref, registry, model);
16
+ }
17
+ // Handle type-qualified references: db:UserDB
18
+ if (ref.includes(":") && !ref.startsWith("#")) {
19
+ const [typeHint, label] = ref.split(":", 2);
20
+ const byType = registry.getByType(typeHint);
21
+ const match = byType.filter((s) => s.label === label);
22
+ if (match.length === 1)
23
+ return { kind: "single", shape: match[0] };
24
+ if (match.length > 1) {
25
+ return { kind: "multiple", shapes: match, message: `"${ref}" matches ${match.length} shapes` };
26
+ }
27
+ // Fall through to normal resolution with just the label part
28
+ return resolveRef(label, registry, model);
29
+ }
30
+ // Handle group-qualified references: Backend/AuthService
31
+ if (ref.includes("/")) {
32
+ const [groupName, label] = ref.split("/", 2);
33
+ const group = model.getGroupByName(groupName);
34
+ if (group) {
35
+ const page = model.getActivePage();
36
+ for (const memberId of group.memberIds) {
37
+ const shape = page.shapes.get(memberId);
38
+ if (shape && shape.label === label) {
39
+ return { kind: "single", shape };
40
+ }
41
+ }
42
+ }
43
+ }
44
+ // Level 1: Exact label match
45
+ const exact = registry.getByExactLabel(ref);
46
+ if (exact.length === 1)
47
+ return { kind: "single", shape: exact[0] };
48
+ if (exact.length > 1) {
49
+ return {
50
+ kind: "multiple",
51
+ shapes: exact,
52
+ message: `"${ref}" matches ${exact.length}: ${exact.map(s => `${s.label}(${s.type})`).join(", ")}. Qualify with type (e.g., db:${ref}) or group (e.g., Backend/${ref})`,
53
+ };
54
+ }
55
+ // Level 2: Case-insensitive match
56
+ const ci = registry.getByCaseInsensitiveLabel(ref);
57
+ if (ci.length === 1)
58
+ return { kind: "single", shape: ci[0] };
59
+ if (ci.length > 1) {
60
+ return {
61
+ kind: "multiple",
62
+ shapes: ci,
63
+ message: `"${ref}" matches ${ci.length}: ${ci.map(s => s.label).join(", ")}`,
64
+ };
65
+ }
66
+ // Level 3: Normalized match
67
+ const norm = registry.getByNormalizedLabel(ref);
68
+ if (norm.length === 1)
69
+ return { kind: "single", shape: norm[0] };
70
+ if (norm.length > 1) {
71
+ return {
72
+ kind: "multiple",
73
+ shapes: norm,
74
+ message: `"${ref}" matches ${norm.length}: ${norm.map(s => s.label).join(", ")}`,
75
+ };
76
+ }
77
+ // Level 4: Prefix match
78
+ const prefix = registry.getByPrefixLabel(ref);
79
+ if (prefix.length === 1)
80
+ return { kind: "single", shape: prefix[0] };
81
+ if (prefix.length > 1) {
82
+ return {
83
+ kind: "multiple",
84
+ shapes: prefix,
85
+ message: `"${ref}" matches ${prefix.length}: ${prefix.map(s => s.label).join(", ")}`,
86
+ };
87
+ }
88
+ // Level 5: Nothing found — suggest similar labels
89
+ const all = registry.getAllShapes();
90
+ const suggestions = findSimilar(ref, all.map((s) => s.label));
91
+ if (suggestions.length > 0) {
92
+ return {
93
+ kind: "none",
94
+ message: `unknown ref "${ref}". Did you mean "${suggestions[0]}"?`,
95
+ suggestedLabel: suggestions[0],
96
+ };
97
+ }
98
+ return {
99
+ kind: "none",
100
+ message: `unknown ref "${ref}". No shapes on this page.`,
101
+ };
102
+ }
103
+ /**
104
+ * Resolve a selector to matching shapes.
105
+ */
106
+ function resolveSelector(selector, registry, model) {
107
+ const page = model.getActivePage();
108
+ if (selector === "@all") {
109
+ const shapes = registry.getAllShapes();
110
+ if (shapes.length === 0)
111
+ return { kind: "none", message: "@all matched 0 shapes" };
112
+ return { kind: "multiple", shapes, message: `@all: ${shapes.length} shapes` };
113
+ }
114
+ if (selector === "@recent") {
115
+ const recent = registry.getMostRecent(1);
116
+ if (recent.length === 0)
117
+ return { kind: "none", message: "no recent shapes" };
118
+ return { kind: "single", shape: recent[0] };
119
+ }
120
+ if (selector.startsWith("@recent:")) {
121
+ const count = parseInt(selector.slice(8), 10);
122
+ if (isNaN(count) || count <= 0)
123
+ return { kind: "none", message: `invalid count in "${selector}"` };
124
+ const recent = registry.getMostRecent(count);
125
+ if (recent.length === 0)
126
+ return { kind: "none", message: "no recent shapes" };
127
+ return { kind: "multiple", shapes: recent, message: `@recent:${count}: ${recent.length} shapes` };
128
+ }
129
+ if (selector === "@orphan") {
130
+ const orphans = registry.getOrphans(page);
131
+ if (orphans.length === 0)
132
+ return { kind: "none", message: "@orphan matched 0 shapes" };
133
+ return { kind: "multiple", shapes: orphans, message: `@orphan: ${orphans.length} shapes` };
134
+ }
135
+ if (selector.startsWith("@type:")) {
136
+ const type = selector.slice(6);
137
+ const shapes = registry.getByType(type);
138
+ if (shapes.length === 0) {
139
+ const allTypes = new Map();
140
+ for (const s of registry.getAllShapes()) {
141
+ allTypes.set(s.type, (allTypes.get(s.type) ?? 0) + 1);
142
+ }
143
+ const available = [...allTypes.entries()].map(([t, c]) => `${c} ${t}`).join(", ");
144
+ return { kind: "none", message: `@type:${type} matched 0 shapes (page has: ${available || "no shapes"})` };
145
+ }
146
+ return { kind: "multiple", shapes, message: `@type:${type}: ${shapes.length} shapes` };
147
+ }
148
+ if (selector.startsWith("@group:")) {
149
+ const groupName = selector.slice(7);
150
+ const group = model.getGroupByName(groupName);
151
+ if (!group)
152
+ return { kind: "none", message: `unknown group "${groupName}"` };
153
+ const shapes = [];
154
+ for (const id of group.memberIds) {
155
+ const shape = page.shapes.get(id);
156
+ if (shape)
157
+ shapes.push(shape);
158
+ }
159
+ if (shapes.length === 0)
160
+ return { kind: "none", message: `@group:${groupName} has 0 members` };
161
+ return { kind: "multiple", shapes, message: `@group:${groupName}: ${shapes.length} shapes` };
162
+ }
163
+ if (selector.startsWith("@page:")) {
164
+ const pageName = selector.slice(6);
165
+ const targetPage = model.getPageByName(pageName);
166
+ if (!targetPage)
167
+ return { kind: "none", message: `unknown page "${pageName}"` };
168
+ const shapes = [...targetPage.shapes.values()];
169
+ if (shapes.length === 0)
170
+ return { kind: "none", message: `@page:${pageName} has 0 shapes` };
171
+ return { kind: "multiple", shapes, message: `@page:${pageName}: ${shapes.length} shapes` };
172
+ }
173
+ if (selector.startsWith("@layer:")) {
174
+ const layerName = selector.slice(7);
175
+ const shapes = registry.getAllShapes().filter((s) => {
176
+ const layer = page.layers.find((l) => l.id === s.layer);
177
+ return layer && layer.name === layerName;
178
+ });
179
+ if (shapes.length === 0)
180
+ return { kind: "none", message: `@layer:${layerName} matched 0 shapes` };
181
+ return { kind: "multiple", shapes, message: `@layer:${layerName}: ${shapes.length} shapes` };
182
+ }
183
+ if (selector.startsWith("@connected:")) {
184
+ const innerRef = selector.slice(11);
185
+ // Resolve the inner reference to find the anchor shape
186
+ const innerResult = resolveRef(innerRef, registry, model);
187
+ if (innerResult.kind === "none") {
188
+ return { kind: "none", message: `@connected:${innerRef} — ${innerResult.message}` };
189
+ }
190
+ if (innerResult.kind === "multiple") {
191
+ return { kind: "none", message: `@connected:${innerRef} — ambiguous: ${innerResult.message}` };
192
+ }
193
+ // innerResult.kind === "single" at this point
194
+ if (innerResult.kind !== "single") {
195
+ return { kind: "none", message: `@connected:${innerRef} — cannot use group as anchor` };
196
+ }
197
+ const connected = registry.getConnectedShapes(innerResult.shape.id, page);
198
+ if (connected.length === 0)
199
+ return { kind: "none", message: `@connected:${innerRef} matched 0 shapes` };
200
+ return { kind: "multiple", shapes: connected, message: `@connected:${innerRef}: ${connected.length} shapes` };
201
+ }
202
+ return { kind: "none", message: `unknown selector "${selector}"` };
203
+ }
204
+ /**
205
+ * Find similar labels using simple edit distance.
206
+ * Returns up to 3 suggestions sorted by similarity.
207
+ */
208
+ function findSimilar(target, candidates) {
209
+ const lower = target.toLowerCase();
210
+ const scored = candidates
211
+ .map((c) => ({ label: c, distance: levenshtein(lower, c.toLowerCase()) }))
212
+ .filter((s) => s.distance <= Math.max(3, Math.floor(target.length / 2)))
213
+ .sort((a, b) => a.distance - b.distance);
214
+ return scored.slice(0, 3).map((s) => s.label);
215
+ }
216
+ function levenshtein(a, b) {
217
+ const m = a.length, n = b.length;
218
+ const dp = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0));
219
+ for (let i = 0; i <= m; i++)
220
+ dp[i][0] = i;
221
+ for (let j = 0; j <= n; j++)
222
+ dp[0][j] = j;
223
+ for (let i = 1; i <= m; i++) {
224
+ for (let j = 1; j <= n; j++) {
225
+ dp[i][j] = a[i - 1] === b[j - 1]
226
+ ? dp[i - 1][j - 1]
227
+ : 1 + Math.min(dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1]);
228
+ }
229
+ }
230
+ return dp[m][n];
231
+ }
232
+ //# sourceMappingURL=resolve-ref.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-ref.js","sourceRoot":"","sources":["../../src/parser/resolve-ref.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Re-export tokenizer functions from @aetherwing/fcp-core.
3
+ * This file previously contained a local implementation that is now
4
+ * provided by the framework.
5
+ */
6
+ export { tokenize, isKeyValue, parseKeyValue, isArrow, isSelector, } from "@aetherwing/fcp-core";
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Re-export tokenizer functions from @aetherwing/fcp-core.
3
+ * This file previously contained a local implementation that is now
4
+ * provided by the framework.
5
+ */
6
+ export { tokenize, isKeyValue, parseKeyValue, isArrow, isSelector, } from "@aetherwing/fcp-core";
7
+ //# sourceMappingURL=tokenizer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokenizer.js","sourceRoot":"","sources":["../../src/parser/tokenizer.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EACL,QAAQ,EACR,UAAU,EACV,aAAa,EACb,OAAO,EACP,UAAU,GACX,MAAM,sBAAsB,CAAC"}
@@ -0,0 +1,35 @@
1
+ import type { Edge, Page, Shape } from "../types/index.js";
2
+ export interface PortAssignment {
3
+ exitX: number;
4
+ exitY: number;
5
+ entryX: number;
6
+ entryY: number;
7
+ }
8
+ export type Face = "right" | "bottom" | "left" | "top";
9
+ export interface EdgeRenderInfo {
10
+ ports: PortAssignment | null;
11
+ exitFace: Face | null;
12
+ entryFace: Face | null;
13
+ labelOffsetX: number;
14
+ labelOffsetY: number;
15
+ }
16
+ /**
17
+ * Pre-compute render info (port assignments and label offsets) for all edges on a page.
18
+ * Returns a Map keyed by edge ID.
19
+ */
20
+ export declare function computeAllEdgeRenderInfo(page: Page): Map<string, EdgeRenderInfo>;
21
+ /**
22
+ * Compute render info for a single edge.
23
+ */
24
+ export declare function computeEdgeRenderInfo(edge: Edge, page: Page): EdgeRenderInfo;
25
+ /**
26
+ * Map an angle to the dominant exit face.
27
+ * Right: [-45, 45), Bottom: [45, 135), Left: [135, 180] or [-180, -135), Top: [-135, -45)
28
+ */
29
+ export declare function angleFace(angleDeg: number): Face;
30
+ /**
31
+ * Given source and target shapes, compute smart port assignments.
32
+ * The exit point is on the face of the source closest to the target,
33
+ * with slight variation based on the angle offset from face center.
34
+ */
35
+ export declare function computeSmartPorts(source: Shape, target: Shape): PortAssignment;
@@ -0,0 +1,336 @@
1
+ // ── Main entry point ─────────────────────────────────────────
2
+ /**
3
+ * Pre-compute render info (port assignments and label offsets) for all edges on a page.
4
+ * Returns a Map keyed by edge ID.
5
+ */
6
+ export function computeAllEdgeRenderInfo(page) {
7
+ const result = new Map();
8
+ const edges = [...page.edges.values()];
9
+ // Phase 1: Compute smart ports for each edge individually
10
+ for (const edge of edges) {
11
+ result.set(edge.id, computeEdgeRenderInfo(edge, page));
12
+ }
13
+ // Phase 2: Fan-out spreading — distribute ports when multiple edges share same source+face
14
+ applyFanOutSpreading(result, edges, page);
15
+ // Phase 3: Label x-offset spreading — spread labeled edges so labels don't cluster at midpoints
16
+ applyLabelOffsetSpreading(result, edges);
17
+ return result;
18
+ }
19
+ /**
20
+ * Compute render info for a single edge.
21
+ */
22
+ export function computeEdgeRenderInfo(edge, page) {
23
+ const source = page.shapes.get(edge.sourceId);
24
+ const target = page.shapes.get(edge.targetId);
25
+ if (!source || !target) {
26
+ return { ports: null, exitFace: null, entryFace: null, labelOffsetX: 0, labelOffsetY: 0 };
27
+ }
28
+ // Check if edge has explicitly set ports (from deserialization) — preserve them
29
+ const style = edge.style;
30
+ if (style["exitX"] !== undefined && style["exitX"] !== "") {
31
+ return {
32
+ ports: {
33
+ exitX: parseFloat(String(style["exitX"])),
34
+ exitY: parseFloat(String(style["exitY"] ?? "0.5")),
35
+ entryX: parseFloat(String(style["entryX"] ?? "0.5")),
36
+ entryY: parseFloat(String(style["entryY"] ?? "0.5")),
37
+ },
38
+ exitFace: null,
39
+ entryFace: null,
40
+ labelOffsetX: 0,
41
+ labelOffsetY: 0,
42
+ };
43
+ }
44
+ // Compute smart ports — use cross-group hint if shapes are in different groups
45
+ const crossGroup = source.parentGroup !== target.parentGroup;
46
+ const ports = crossGroup
47
+ ? computeCrossGroupPorts(source, target, page)
48
+ : computeSmartPorts(source, target);
49
+ const exitFace = angleFace(computeAngle(source.bounds, target.bounds));
50
+ return {
51
+ ports,
52
+ exitFace,
53
+ entryFace: mirrorFace(exitFace),
54
+ labelOffsetX: 0,
55
+ labelOffsetY: 0,
56
+ };
57
+ }
58
+ // ── Smart port computation ───────────────────────────────────
59
+ /**
60
+ * Compute angle (in degrees) from source center to target center.
61
+ * Returns angle in range [-180, 180] where 0 = right, 90 = down, -90 = up.
62
+ */
63
+ function computeAngle(source, target) {
64
+ const sx = source.x + source.width / 2;
65
+ const sy = source.y + source.height / 2;
66
+ const tx = target.x + target.width / 2;
67
+ const ty = target.y + target.height / 2;
68
+ return Math.atan2(ty - sy, tx - sx) * (180 / Math.PI);
69
+ }
70
+ /**
71
+ * Map an angle to the dominant exit face.
72
+ * Right: [-45, 45), Bottom: [45, 135), Left: [135, 180] or [-180, -135), Top: [-135, -45)
73
+ */
74
+ export function angleFace(angleDeg) {
75
+ if (angleDeg >= -45 && angleDeg < 45)
76
+ return "right";
77
+ if (angleDeg >= 45 && angleDeg < 135)
78
+ return "bottom";
79
+ if (angleDeg >= -135 && angleDeg < -45)
80
+ return "top";
81
+ return "left"; // [135, 180] or [-180, -135)
82
+ }
83
+ /**
84
+ * Mirror a face: source exits right → target enters left, etc.
85
+ */
86
+ function mirrorFace(face) {
87
+ switch (face) {
88
+ case "right": return "left";
89
+ case "left": return "right";
90
+ case "top": return "bottom";
91
+ case "bottom": return "top";
92
+ }
93
+ }
94
+ /**
95
+ * Given source and target shapes, compute smart port assignments.
96
+ * The exit point is on the face of the source closest to the target,
97
+ * with slight variation based on the angle offset from face center.
98
+ */
99
+ export function computeSmartPorts(source, target) {
100
+ const angleDeg = computeAngle(source.bounds, target.bounds);
101
+ const face = angleFace(angleDeg);
102
+ // Compute fine-tuned position within the face based on angle offset.
103
+ // This gives slight variation so edges don't all leave from dead center.
104
+ const fineOffset = computeFineOffset(angleDeg, face);
105
+ const exit = faceToPort(face, fineOffset);
106
+ const entryFace = mirrorFace(face);
107
+ const entry = faceToPort(entryFace, fineOffset);
108
+ return {
109
+ exitX: exit.x,
110
+ exitY: exit.y,
111
+ entryX: entry.x,
112
+ entryY: entry.y,
113
+ };
114
+ }
115
+ /**
116
+ * Compute port assignments for edges crossing group boundaries.
117
+ * When source and target are in different groups (or one is ungrouped),
118
+ * compute the angle toward the target's group bounding box edge (not target center directly).
119
+ * This biases the exit port toward the group boundary.
120
+ */
121
+ function computeCrossGroupPorts(source, target, page) {
122
+ // If target is in a group, use the nearest edge of the group bounding box
123
+ // as the angle target instead of the target shape center directly
124
+ let targetBounds = target.bounds;
125
+ if (target.parentGroup) {
126
+ const group = page.groups.get(target.parentGroup);
127
+ if (group) {
128
+ targetBounds = group.bounds;
129
+ }
130
+ }
131
+ // Compute angle from source center to target group boundary
132
+ const angleDeg = computeAngle(source.bounds, targetBounds);
133
+ const face = angleFace(angleDeg);
134
+ const fineOffset = computeFineOffset(angleDeg, face);
135
+ const exit = faceToPort(face, fineOffset);
136
+ // For entry, compute from target's perspective toward source (or source's group)
137
+ let sourceBounds = source.bounds;
138
+ if (source.parentGroup) {
139
+ const group = page.groups.get(source.parentGroup);
140
+ if (group) {
141
+ sourceBounds = group.bounds;
142
+ }
143
+ }
144
+ const entryAngleDeg = computeAngle(target.bounds, sourceBounds);
145
+ const entryFace = angleFace(entryAngleDeg);
146
+ const entryFineOffset = computeFineOffset(entryAngleDeg, entryFace);
147
+ const entry = faceToPort(entryFace, entryFineOffset);
148
+ return {
149
+ exitX: exit.x,
150
+ exitY: exit.y,
151
+ entryX: entry.x,
152
+ entryY: entry.y,
153
+ };
154
+ }
155
+ /**
156
+ * Compute a fine offset within a face [-0.25, 0.25] based on angle deviation from face center.
157
+ */
158
+ function computeFineOffset(angleDeg, face) {
159
+ // Face center angles: right=0, bottom=90, left=180/-180, top=-90
160
+ let faceCenter;
161
+ switch (face) {
162
+ case "right":
163
+ faceCenter = 0;
164
+ break;
165
+ case "bottom":
166
+ faceCenter = 90;
167
+ break;
168
+ case "left":
169
+ faceCenter = angleDeg >= 0 ? 180 : -180;
170
+ break;
171
+ case "top":
172
+ faceCenter = -90;
173
+ break;
174
+ }
175
+ // Deviation from face center, normalized to [-0.25, 0.25]
176
+ const deviation = angleDeg - faceCenter;
177
+ return clamp(deviation / 180, -0.25, 0.25);
178
+ }
179
+ /**
180
+ * Convert a face + fine offset to exit/entry port coordinates.
181
+ * The offset shifts position along the face axis.
182
+ */
183
+ function faceToPort(face, fineOffset) {
184
+ switch (face) {
185
+ case "right": return { x: 1.0, y: clamp(0.5 + fineOffset, 0.1, 0.9) };
186
+ case "left": return { x: 0.0, y: clamp(0.5 + fineOffset, 0.1, 0.9) };
187
+ case "bottom": return { x: clamp(0.5 + fineOffset, 0.1, 0.9), y: 1.0 };
188
+ case "top": return { x: clamp(0.5 + fineOffset, 0.1, 0.9), y: 0.0 };
189
+ }
190
+ }
191
+ function clamp(v, min, max) {
192
+ return Math.max(min, Math.min(max, v));
193
+ }
194
+ // ── Fan-out spreading ────────────────────────────────────────
195
+ /**
196
+ * Post-process edge render infos to spread port positions when multiple edges
197
+ * exit from the same face of the same source shape (or enter the same face of the same target).
198
+ */
199
+ function applyFanOutSpreading(infos, edges, page) {
200
+ // Group edges by (sourceId, exitFace)
201
+ const exitGroups = new Map();
202
+ // Group edges by (targetId, entryFace)
203
+ const entryGroups = new Map();
204
+ for (const edge of edges) {
205
+ const info = infos.get(edge.id);
206
+ if (!info?.ports || !info.exitFace)
207
+ continue;
208
+ const exitKey = `${edge.sourceId}:${info.exitFace}`;
209
+ if (!exitGroups.has(exitKey))
210
+ exitGroups.set(exitKey, []);
211
+ exitGroups.get(exitKey).push({ edge, info });
212
+ const entryKey = `${edge.targetId}:${info.entryFace}`;
213
+ if (!entryGroups.has(entryKey))
214
+ entryGroups.set(entryKey, []);
215
+ entryGroups.get(entryKey).push({ edge, info });
216
+ }
217
+ // Spread exit ports for groups with N > 1
218
+ for (const [key, group] of exitGroups) {
219
+ if (group.length <= 1)
220
+ continue;
221
+ const face = key.split(":")[1];
222
+ spreadExitPorts(group, face, page);
223
+ }
224
+ // Spread entry ports for groups with N > 1
225
+ for (const [key, group] of entryGroups) {
226
+ if (group.length <= 1)
227
+ continue;
228
+ const face = key.split(":")[1];
229
+ spreadEntryPorts(group, face, page);
230
+ }
231
+ }
232
+ /**
233
+ * Spread exit port positions across a face when N edges leave from the same source face.
234
+ * Sort by target position along the face axis, then distribute evenly.
235
+ */
236
+ function spreadExitPorts(group, face, page) {
237
+ const n = group.length;
238
+ // Sort by target position along the face's variable axis
239
+ group.sort((a, b) => {
240
+ const ta = page.shapes.get(a.edge.targetId);
241
+ const tb = page.shapes.get(b.edge.targetId);
242
+ if (!ta || !tb)
243
+ return 0;
244
+ const taCx = ta.bounds.x + ta.bounds.width / 2;
245
+ const taCy = ta.bounds.y + ta.bounds.height / 2;
246
+ const tbCx = tb.bounds.x + tb.bounds.width / 2;
247
+ const tbCy = tb.bounds.y + tb.bounds.height / 2;
248
+ // For top/bottom faces, sort by target X; for left/right, sort by target Y
249
+ if (face === "top" || face === "bottom")
250
+ return taCx - tbCx;
251
+ return taCy - tbCy;
252
+ });
253
+ // Spread positions: (i + 1) / (N + 1) for i in [0, N-1]
254
+ for (let i = 0; i < n; i++) {
255
+ const pos = (i + 1) / (n + 1);
256
+ const info = group[i].info;
257
+ if (!info.ports)
258
+ continue;
259
+ if (face === "top" || face === "bottom") {
260
+ info.ports.exitX = pos;
261
+ }
262
+ else {
263
+ info.ports.exitY = pos;
264
+ }
265
+ }
266
+ }
267
+ /**
268
+ * Spread entry port positions across a face when N edges enter the same target face.
269
+ */
270
+ function spreadEntryPorts(group, face, page) {
271
+ const n = group.length;
272
+ // Sort by source position along the face's variable axis
273
+ group.sort((a, b) => {
274
+ const sa = page.shapes.get(a.edge.sourceId);
275
+ const sb = page.shapes.get(b.edge.sourceId);
276
+ if (!sa || !sb)
277
+ return 0;
278
+ const saCx = sa.bounds.x + sa.bounds.width / 2;
279
+ const saCy = sa.bounds.y + sa.bounds.height / 2;
280
+ const sbCx = sb.bounds.x + sb.bounds.width / 2;
281
+ const sbCy = sb.bounds.y + sb.bounds.height / 2;
282
+ if (face === "top" || face === "bottom")
283
+ return saCx - sbCx;
284
+ return saCy - sbCy;
285
+ });
286
+ for (let i = 0; i < n; i++) {
287
+ const pos = (i + 1) / (n + 1);
288
+ const info = group[i].info;
289
+ if (!info.ports)
290
+ continue;
291
+ if (face === "top" || face === "bottom") {
292
+ info.ports.entryX = pos;
293
+ }
294
+ else {
295
+ info.ports.entryY = pos;
296
+ }
297
+ }
298
+ }
299
+ // ── Label x-offset spreading ─────────────────────────────────
300
+ /**
301
+ * Spread label x-offsets for labeled edges sharing the same source shape,
302
+ * so labels don't all cluster at the midpoint.
303
+ *
304
+ * For N labeled edges from same source:
305
+ * N=1 → x=0 (centered)
306
+ * N=2 → x at -0.15, +0.15
307
+ * N=3 → x at -0.3, 0, +0.3
308
+ * General: x = -0.3 + (i * 0.6) / (N - 1)
309
+ */
310
+ function applyLabelOffsetSpreading(infos, edges) {
311
+ // Group labeled edges by source shape
312
+ const labelGroups = new Map();
313
+ for (const edge of edges) {
314
+ if (!edge.label)
315
+ continue;
316
+ const info = infos.get(edge.id);
317
+ if (!info)
318
+ continue;
319
+ const key = edge.sourceId;
320
+ if (!labelGroups.has(key))
321
+ labelGroups.set(key, []);
322
+ labelGroups.get(key).push({ edge, info });
323
+ }
324
+ for (const [, group] of labelGroups) {
325
+ const n = group.length;
326
+ if (n <= 1)
327
+ continue;
328
+ // Sort by target ID for deterministic ordering
329
+ group.sort((a, b) => a.edge.targetId.localeCompare(b.edge.targetId));
330
+ for (let i = 0; i < n; i++) {
331
+ const x = -0.3 + (i * 0.6) / (n - 1);
332
+ group[i].info.labelOffsetX = Math.round(x * 100) / 100;
333
+ }
334
+ }
335
+ }
336
+ //# sourceMappingURL=connector-intelligence.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connector-intelligence.js","sourceRoot":"","sources":["../../src/serialization/connector-intelligence.ts"],"names":[],"mappings":"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"}