@stacksjs/ts-cloud 0.7.105 → 0.7.108

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 (75) hide show
  1. package/dist/bin/cli.js +784 -785
  2. package/dist/bin/dashboard-server.js +292 -292
  3. package/dist/{chunk-dmzez5f8.js → chunk-33sy72r8.js} +52 -3
  4. package/dist/{chunk-vkd2y0fs.js → chunk-eg8ck25v.js} +858 -150
  5. package/dist/deploy/dashboard-bundle-encoding.test.d.ts +1 -0
  6. package/dist/deploy/dashboard-payload.d.ts +20 -0
  7. package/dist/deploy/dashboard-payload.test.d.ts +1 -0
  8. package/dist/deploy/dashboard-topology.d.ts +85 -0
  9. package/dist/deploy/dashboard-topology.test.d.ts +1 -0
  10. package/dist/deploy/egress-collection.d.ts +60 -0
  11. package/dist/deploy/index.d.ts +2 -0
  12. package/dist/deploy/index.js +14 -2
  13. package/dist/drivers/index.js +1 -1
  14. package/dist/index.js +2 -2
  15. package/dist/ui/404.html +1 -0
  16. package/dist/ui/access-denied.html +1 -1
  17. package/dist/ui/account/automation.html +4 -4
  18. package/dist/ui/account/security.html +2 -2
  19. package/dist/ui/applications/compose.html +4 -4
  20. package/dist/ui/applications/new.html +2 -2
  21. package/dist/ui/data/backups.html +22 -9
  22. package/dist/ui/data/services.html +22 -9
  23. package/dist/ui/data/volumes.html +22 -9
  24. package/dist/ui/index.html +22 -9
  25. package/dist/ui/infrastructure/topology.html +2223 -0
  26. package/dist/ui/integrations.html +2 -2
  27. package/dist/ui/operations/alerts.html +22 -9
  28. package/dist/ui/operations/configuration.html +4 -4
  29. package/dist/ui/operations/jobs.html +22 -9
  30. package/dist/ui/operations/maintenance.html +4 -4
  31. package/dist/ui/operations/observability.html +22 -9
  32. package/dist/ui/operations/previews.html +4 -4
  33. package/dist/ui/operations/queue.html +4 -4
  34. package/dist/ui/operations/regions.html +4 -4
  35. package/dist/ui/operations/releases.html +4 -4
  36. package/dist/ui/operations/workloads.html +22 -9
  37. package/dist/ui/security.html +2 -2
  38. package/dist/ui/server/actions.html +3 -3
  39. package/dist/ui/server/activity.html +1 -1
  40. package/dist/ui/server/capacity.html +4 -4
  41. package/dist/ui/server/database.html +4 -4
  42. package/dist/ui/server/deployments.html +4 -4
  43. package/dist/ui/server/diagnostics.html +2 -2
  44. package/dist/ui/server/firewall.html +4 -4
  45. package/dist/ui/server/fleet.html +22 -9
  46. package/dist/ui/server/logs.html +22 -9
  47. package/dist/ui/server/metrics.html +130 -14
  48. package/dist/ui/server/security.html +2 -2
  49. package/dist/ui/server/services.html +2 -2
  50. package/dist/ui/server/sites.html +22 -9
  51. package/dist/ui/server/ssh-keys.html +4 -4
  52. package/dist/ui/server/team.html +4 -4
  53. package/dist/ui/server/terminal.html +2 -2
  54. package/dist/ui/serverless/alarms.html +3 -3
  55. package/dist/ui/serverless/assets.html +2 -2
  56. package/dist/ui/serverless/cost.html +2 -2
  57. package/dist/ui/serverless/data.html +4 -4
  58. package/dist/ui/serverless/deployments.html +2 -2
  59. package/dist/ui/serverless/firewall.html +2 -2
  60. package/dist/ui/serverless/functions.html +4 -4
  61. package/dist/ui/serverless/logs.html +21 -8
  62. package/dist/ui/serverless/metrics.html +2 -2
  63. package/dist/ui/serverless/queues.html +4 -4
  64. package/dist/ui/serverless/secrets.html +4 -4
  65. package/dist/ui/serverless/traces.html +4 -4
  66. package/dist/ui/serverless.html +4 -4
  67. package/dist/ui-src/functions/requestJson.ts +41 -0
  68. package/dist/ui-src/functions/useOpConfirm.ts +132 -0
  69. package/dist/ui-src/functions/usePolling.ts +98 -0
  70. package/dist/ui-src/functions/useTerminal.ts +79 -0
  71. package/dist/ui-src/pages/infrastructure/topology.stx +517 -0
  72. package/dist/ui-src/pages/partials/nav.stx +2 -0
  73. package/dist/ui-src/pages/server/metrics.stx +140 -6
  74. package/dist/ui-src/src/topology.ts +485 -0
  75. package/package.json +3 -3
@@ -0,0 +1,485 @@
1
+ // ../../node_modules/@ts-charts/graph/dist/layered.js
2
+ var Mj = { direction: "down", nodeWidth: 160, nodeHeight: 56, layerGap: 80, nodeGap: 28, padding: 24, iterations: 8, straightenPasses: 6 };
3
+ function Nj(Q, W) {
4
+ let J = [], _ = new Map;
5
+ for (let H of Q)
6
+ _.set(H, []);
7
+ for (let H of W)
8
+ _.get(H.source)?.push(H);
9
+ let V = new Set, Z = new Set, G = new Set, T = (H) => {
10
+ V.add(H), Z.add(H);
11
+ for (let I of _.get(H) ?? [])
12
+ if (Z.has(I.target))
13
+ G.add(I);
14
+ else if (!V.has(I.target))
15
+ T(I.target);
16
+ Z.delete(H);
17
+ };
18
+ for (let H of Q)
19
+ if (!V.has(H))
20
+ T(H);
21
+ for (let H of W) {
22
+ let I = H.weight ?? 1;
23
+ if (G.has(H))
24
+ J.push({ source: H.target, target: H.source, weight: I, reversed: true });
25
+ else
26
+ J.push({ source: H.source, target: H.target, weight: I, reversed: false });
27
+ }
28
+ return J;
29
+ }
30
+ function Qj(Q, W) {
31
+ let J = new Map, _ = new Map, V = new Map, Z = new Map;
32
+ for (let H of Q)
33
+ _.set(H.id, []), V.set(H.id, []), Z.set(H.id, 0);
34
+ for (let H of W) {
35
+ if (H.source === H.target)
36
+ continue;
37
+ _.get(H.target)?.push(H.source), V.get(H.source)?.push(H.target), Z.set(H.target, (Z.get(H.target) ?? 0) + 1);
38
+ }
39
+ let G = [];
40
+ for (let H of Q)
41
+ if ((Z.get(H.id) ?? 0) === 0)
42
+ J.set(H.id, 0), G.push(H.id);
43
+ for (let H = 0;H < G.length; H++) {
44
+ let I = G[H];
45
+ for (let U of V.get(I) ?? []) {
46
+ J.set(U, Math.max(J.get(U) ?? 0, (J.get(I) ?? 0) + 1));
47
+ let L = (Z.get(U) ?? 0) - 1;
48
+ if (Z.set(U, L), L === 0)
49
+ G.push(U);
50
+ }
51
+ }
52
+ for (let H of Q)
53
+ if (!J.has(H.id))
54
+ J.set(H.id, 0);
55
+ for (let H of Q)
56
+ if (H.layer != null && Number.isFinite(H.layer))
57
+ J.set(H.id, H.layer);
58
+ let T = Math.min(...J.values());
59
+ if (T !== 0)
60
+ for (let [H, I] of J)
61
+ J.set(H, I - T);
62
+ return J;
63
+ }
64
+ function b(Q, W) {
65
+ let J = 0;
66
+ for (let _ = 0;_ + 1 < Q.length; _++) {
67
+ let V = new Map;
68
+ Q[_ + 1].forEach((G, T) => V.set(G, T));
69
+ let Z = [];
70
+ for (let G of Q[_])
71
+ for (let T of W.get(G) ?? []) {
72
+ let H = V.get(T);
73
+ if (H != null)
74
+ Z.push(H);
75
+ }
76
+ for (let G = 0;G < Z.length; G++)
77
+ for (let T = G + 1;T < Z.length; T++)
78
+ if (Z[G] > Z[T])
79
+ J++;
80
+ }
81
+ return J;
82
+ }
83
+ function s(Q) {
84
+ if (!Q.length)
85
+ return -1;
86
+ let W = [...Q].sort((Z, G) => Z - G), J = W.length >> 1;
87
+ if (W.length % 2 === 1)
88
+ return W[J];
89
+ if (W.length === 2)
90
+ return (W[0] + W[1]) / 2;
91
+ let _ = W[J - 1] - W[0], V = W[W.length - 1] - W[J];
92
+ return (W[J - 1] * V + W[J] * _) / (_ + V || 1);
93
+ }
94
+ function Tj(Q, W = {}) {
95
+ let J = { ...Mj, ...W }, _ = J.direction === "right" || J.direction === "left", V = new Map;
96
+ for (let j of Q.nodes)
97
+ V.set(j.id, j);
98
+ let Z = [...V.keys()], G = Q.edges.filter((j) => V.has(j.source) && V.has(j.target));
99
+ if (!Z.length)
100
+ return { nodes: [], edges: [], layers: [], width: J.padding * 2, height: J.padding * 2, crossings: 0 };
101
+ let T = Nj(Z, G), H = Qj(Q.nodes, T), I = new Map, U = (j) => _ ? j.width ?? J.nodeWidth : j.height ?? J.nodeHeight, L = (j) => _ ? j.height ?? J.nodeHeight : j.width ?? J.nodeWidth;
102
+ for (let j of Q.nodes)
103
+ I.set(j.id, { id: j.id, layer: H.get(j.id) ?? 0, order: 0, depth: U(j), breadth: L(j), pos: 0, dummy: false });
104
+ let A = [], P = [], z = "__bend";
105
+ while (Z.some((j) => j.startsWith(z)))
106
+ z = `_${z}`;
107
+ let d = 0;
108
+ for (let j of T) {
109
+ if (j.source === j.target)
110
+ continue;
111
+ let E = I.get(j.source), F = I.get(j.target), N = { source: j.source, target: j.target, weight: j.weight, reversed: j.reversed, bends: [] };
112
+ if (A.push(N), F.layer <= E.layer) {
113
+ P.push({ from: j.source, to: j.target, weight: j.weight });
114
+ continue;
115
+ }
116
+ let R = j.source;
117
+ for (let K = E.layer + 1;K < F.layer; K++) {
118
+ let X = `${z}${d++}`;
119
+ I.set(X, { id: X, layer: K, order: 0, depth: 0, breadth: 0, pos: 0, dummy: true }), N.bends.push(X), P.push({ from: R, to: X, weight: j.weight }), R = X;
120
+ }
121
+ P.push({ from: R, to: j.target, weight: j.weight });
122
+ }
123
+ let n = Math.max(...[...I.values()].map((j) => j.layer)) + 1, B = Array.from({ length: n }, () => []);
124
+ for (let j of I.values())
125
+ B[j.layer].push(j.id);
126
+ let q = new Map, O = new Map;
127
+ for (let j of I.keys())
128
+ q.set(j, []), O.set(j, []);
129
+ for (let j of P) {
130
+ let E = I.get(j.from);
131
+ if (I.get(j.to).layer === E.layer + 1)
132
+ q.get(j.from).push(j.to), O.get(j.to).push(j.from);
133
+ }
134
+ let t = (j) => {
135
+ let E = new Map;
136
+ return j.forEach((F, N) => E.set(F, N)), E;
137
+ }, o = (j, E) => {
138
+ let F = j.map((R) => [...R]), N = E ? [...F.keys()].slice(1) : [...F.keys()].slice(0, -1).reverse();
139
+ for (let R of N) {
140
+ let K = t(F[E ? R - 1 : R + 1]), X = E ? O : q, Y = new Map;
141
+ F[R].forEach(($, C) => {
142
+ let Jj = (X.get($) ?? []).map((x) => K.get(x)).filter((x) => x != null), a = s(Jj);
143
+ Y.set($, a < 0 ? C : a);
144
+ }), F[R].sort(($, C) => (Y.get($) ?? 0) - (Y.get(C) ?? 0));
145
+ }
146
+ return F;
147
+ }, r = (j) => {
148
+ let E = j.map((R) => [...R]), F = true, N = 0;
149
+ while (F && N++ < 8) {
150
+ F = false;
151
+ for (let R = 0;R < E.length; R++)
152
+ for (let K = 0;K + 1 < E[R].length; K++) {
153
+ let X = b(E, q), Y = E[R], $ = () => {
154
+ let C = Y[K];
155
+ Y[K] = Y[K + 1], Y[K + 1] = C;
156
+ };
157
+ if ($(), b(E, q) < X)
158
+ F = true;
159
+ else
160
+ $();
161
+ }
162
+ }
163
+ return E;
164
+ }, v = B.map((j) => [...j]), f = b(v, q);
165
+ for (let j = 0;j < J.iterations; j++) {
166
+ B = r(o(B, j % 2 === 0));
167
+ let E = b(B, q);
168
+ if (E <= f)
169
+ f = E, v = B.map((F) => [...F]);
170
+ }
171
+ B = v, B.forEach((j, E) => {
172
+ j.forEach((F, N) => {
173
+ let R = I.get(F);
174
+ R.layer = E, R.order = N;
175
+ });
176
+ });
177
+ let e = (j) => {
178
+ let E = 0;
179
+ for (let F of j) {
180
+ let N = I.get(F);
181
+ N.pos = E + N.breadth / 2, E += N.breadth + J.nodeGap;
182
+ }
183
+ };
184
+ for (let j of B)
185
+ e(j);
186
+ let jj = (j) => {
187
+ for (let E = 1;E < j.length; E++) {
188
+ let F = I.get(j[E - 1]), N = I.get(j[E]), R = F.pos + F.breadth / 2 + J.nodeGap + N.breadth / 2;
189
+ if (N.pos < R)
190
+ N.pos = R;
191
+ }
192
+ for (let E = j.length - 2;E >= 0; E--) {
193
+ let F = I.get(j[E + 1]), N = I.get(j[E]), R = F.pos - F.breadth / 2 - J.nodeGap - N.breadth / 2;
194
+ if (N.pos > R)
195
+ N.pos = R;
196
+ }
197
+ };
198
+ for (let j = 0;j < J.straightenPasses; j++) {
199
+ let E = j % 2 === 0, F = E ? [...B.keys()] : [...B.keys()].reverse();
200
+ for (let N of F) {
201
+ let R = E ? O : q;
202
+ for (let K of B[N]) {
203
+ let X = I.get(K), Y = (R.get(K) ?? []).map(($) => I.get($).pos);
204
+ if (Y.length)
205
+ X.pos = X.dummy ? Rj(Y) : s(Y);
206
+ }
207
+ jj(B[N]);
208
+ }
209
+ }
210
+ let Ej = (j) => {
211
+ let E = 1 / 0, F = -1 / 0;
212
+ for (let N of j) {
213
+ let R = I.get(N);
214
+ E = Math.min(E, R.pos - R.breadth / 2), F = Math.max(F, R.pos + R.breadth / 2);
215
+ }
216
+ return j.length ? { min: E, max: F } : { min: 0, max: 0 };
217
+ }, k = B.map(Ej), m = Math.max(0, ...k.map((j) => j.max - j.min));
218
+ B.forEach((j, E) => {
219
+ let F = (m - (k[E].max - k[E].min)) / 2 - k[E].min;
220
+ for (let N of j)
221
+ I.get(N).pos += F;
222
+ });
223
+ let S = B.map((j) => Math.max(0, ...j.map((E) => I.get(E).depth))), g = [], h = J.padding;
224
+ for (let j = 0;j < B.length; j++)
225
+ g.push(h), h += S[j] + J.layerGap;
226
+ let y = h - J.layerGap + J.padding, u = m + J.padding * 2, p = J.direction === "up" || J.direction === "left", c = (j, E) => {
227
+ let F = g[j] + (S[j] - E) / 2;
228
+ return p ? y - F - E : F;
229
+ }, D = (j) => {
230
+ let E = c(j.layer, j.depth), F = j.pos + J.padding - j.breadth / 2;
231
+ return _ ? { x: E, y: F, width: j.depth, height: j.breadth } : { x: F, y: E, width: j.breadth, height: j.depth };
232
+ }, l = [];
233
+ for (let j of Q.nodes) {
234
+ let E = I.get(j.id), F = D(E);
235
+ l.push({ id: j.id, layer: E.layer, order: E.order, ...F });
236
+ }
237
+ let Fj = (j) => {
238
+ let E = D(j);
239
+ return { x: E.x + E.width / 2, y: E.y + E.height / 2 };
240
+ }, w = (j, E) => {
241
+ let F = D(j), N = E !== p;
242
+ if (_)
243
+ return { x: N ? F.x + F.width : F.x, y: F.y + F.height / 2 };
244
+ return { x: F.x + F.width / 2, y: N ? F.y + F.height : F.y };
245
+ }, i = (j, E) => {
246
+ let F = D(j), N = E.pos >= j.pos;
247
+ if (_)
248
+ return { x: F.x + F.width / 2, y: N ? F.y + F.height : F.y };
249
+ return { x: N ? F.x + F.width : F.x, y: F.y + F.height / 2 };
250
+ }, Hj = A.map((j) => {
251
+ let E = I.get(j.source), F = I.get(j.target), N = F.layer === E.layer, R = F.layer < E.layer, K = N ? [i(E, F), i(F, E)] : R ? [w(E, false), w(F, true)] : [w(E, true), ...j.bends.map((X) => Fj(I.get(X))), w(F, false)];
252
+ return j.reversed ? { source: j.target, target: j.source, points: [...K].reverse(), reversed: true, flat: N } : { source: j.source, target: j.target, points: K, reversed: false, flat: N };
253
+ }), Ij = B.map((j, E) => {
254
+ let F = j.filter(($) => !I.get($).dummy).map(($) => D(I.get($))), N = c(E, S[E]);
255
+ if (!F.length)
256
+ return _ ? { index: E, nodes: [], x: N, y: J.padding, width: S[E], height: 0 } : { index: E, nodes: [], x: J.padding, y: N, width: 0, height: S[E] };
257
+ let R = Math.min(...F.map(($) => $.x)), K = Math.min(...F.map(($) => $.y)), X = Math.max(...F.map(($) => $.x + $.width)), Y = Math.max(...F.map(($) => $.y + $.height));
258
+ return { index: E, nodes: j.filter(($) => !I.get($).dummy), x: R, y: K, width: X - R, height: Y - K };
259
+ });
260
+ return { nodes: l, edges: Hj, layers: Ij, width: _ ? y : u, height: _ ? u : y, crossings: f };
261
+ }
262
+ function Rj(Q) {
263
+ let W = 0;
264
+ for (let J of Q)
265
+ W += J;
266
+ return W / Q.length;
267
+ }
268
+ function Uj(Q, W = {}) {
269
+ if (Q.length < 2)
270
+ return "";
271
+ let { curve: J = "smooth", direction: _ = "down", radius: V = 10 } = W, Z = _ === "right" || _ === "left";
272
+ if (J === "linear")
273
+ return `M${M(Q[0].x)},${M(Q[0].y)}${Q.slice(1).map((T) => `L${M(T.x)},${M(T.y)}`).join("")}`;
274
+ if (J === "orthogonal") {
275
+ let T = `M${M(Q[0].x)},${M(Q[0].y)}`;
276
+ for (let H = 1;H < Q.length; H++) {
277
+ let I = Q[H - 1], U = Q[H], L = Z ? (I.x + U.x) / 2 : (I.y + U.y) / 2, A = Math.min(V, Math.abs(Z ? U.y - I.y : U.x - I.x) / 2);
278
+ if (A < 0.5) {
279
+ T += `L${M(U.x)},${M(U.y)}`;
280
+ continue;
281
+ }
282
+ if (Z) {
283
+ let P = U.y > I.y ? 1 : -1;
284
+ T += `L${M(L - A)},${M(I.y)}Q${M(L)},${M(I.y)} ${M(L)},${M(I.y + A * P)}`, T += `L${M(L)},${M(U.y - A * P)}Q${M(L)},${M(U.y)} ${M(L + A)},${M(U.y)}`, T += `L${M(U.x)},${M(U.y)}`;
285
+ } else {
286
+ let P = U.x > I.x ? 1 : -1;
287
+ T += `L${M(I.x)},${M(L - A)}Q${M(I.x)},${M(L)} ${M(I.x + A * P)},${M(L)}`, T += `L${M(U.x - A * P)},${M(L)}Q${M(U.x)},${M(L)} ${M(U.x)},${M(L + A)}`, T += `L${M(U.x)},${M(U.y)}`;
288
+ }
289
+ }
290
+ return T;
291
+ }
292
+ let G = `M${M(Q[0].x)},${M(Q[0].y)}`;
293
+ for (let T = 1;T < Q.length; T++) {
294
+ let H = Q[T - 1], I = Q[T];
295
+ if (Z) {
296
+ let U = (H.x + I.x) / 2;
297
+ G += `C${M(U)},${M(H.y)} ${M(U)},${M(I.y)} ${M(I.x)},${M(I.y)}`;
298
+ } else {
299
+ let U = (H.y + I.y) / 2;
300
+ G += `C${M(H.x)},${M(U)} ${M(I.x)},${M(U)} ${M(I.x)},${M(I.y)}`;
301
+ }
302
+ }
303
+ return G;
304
+ }
305
+ function M(Q) {
306
+ return Math.round(Q * 100) / 100;
307
+ }
308
+
309
+ // ../ui/src/topology.ts
310
+ var NODE_HEIGHT = 64;
311
+ var LANE_GUTTER = 78;
312
+ var GROUP_PADDING = 22;
313
+ function midpoint(a, b2) {
314
+ return { x: (a.x + b2.x) / 2, y: (a.y + b2.y) / 2 };
315
+ }
316
+ var ICONS = {
317
+ internet: "M12 3a9 9 0 100 18 9 9 0 000-18zM3 12h18M12 3c2.5 2.4 3.8 5.5 3.8 9S14.5 21.6 12 21c-2.5-2.4-3.8-5.5-3.8-9S9.5 3 12 3z",
318
+ dns: "M4 7h16M4 12h16M4 17h10M7 4v16",
319
+ waf: "M12 3l7 3v5c0 4.4-2.9 8.2-7 10-4.1-1.8-7-5.6-7-10V6l7-3z",
320
+ firewall: "M3 6h18M3 12h18M3 18h18M8 6v6M16 6v6M12 12v6",
321
+ cdn: "M6 17a4 4 0 010-8 5.5 5.5 0 0110.6-1.3A4.2 4.2 0 0118 17H6z",
322
+ gateway: "M4 8h16M4 16h16M8 4v16M16 4v16",
323
+ proxy: "M4 6h7l3 3h6M4 18h7l3-3h6M17 6l3 3-3 3M17 12l3 3-3 3",
324
+ site: "M4 5h16v14H4zM4 9h16M7 7h.01M10 7h.01",
325
+ function: "M8 5c-2 0-2 3-2 5s-1 2-2 2 1 0 2 2 0 5 2 5M16 5c2 0 2 3 2 5s1 2 2 2-1 0-2 2 0 5-2 5",
326
+ worker: "M12 9a3 3 0 100 6 3 3 0 000-6zM12 3v3M12 18v3M4.9 4.9l2.1 2.1M17 17l2.1 2.1M3 12h3M18 12h3M4.9 19.1L7 17M17 7l2.1-2.1",
327
+ scheduler: "M12 3a9 9 0 100 18 9 9 0 000-18zM12 7v5l3 2",
328
+ queue: "M4 7h16v4H4zM4 13h16v4H4z",
329
+ cache: "M12 4c4.4 0 8 1.3 8 3s-3.6 3-8 3-8-1.3-8-3 3.6-3 8-3zM4 7v10c0 1.7 3.6 3 8 3s8-1.3 8-3V7",
330
+ database: "M12 3c4.4 0 8 1.3 8 3s-3.6 3-8 3-8-1.3-8-3 3.6-3 8-3zM4 6v12c0 1.7 3.6 3 8 3s8-1.3 8-3V6M4 12c0 1.7 3.6 3 8 3s8-1.3 8-3",
331
+ storage: "M4 6h16v12H4zM4 10h16M8 14h4",
332
+ filesystem: "M4 7a2 2 0 012-2h4l2 2h6a2 2 0 012 2v8a2 2 0 01-2 2H6a2 2 0 01-2-2V7z",
333
+ backup: "M12 5a7 7 0 107 7M12 5V2M12 5l3 3M5 12a7 7 0 002 5"
334
+ };
335
+ var FALLBACK_ICON = "M5 5h14v14H5z";
336
+ function iconFor(kind) {
337
+ return ICONS[kind] ?? FALLBACK_ICON;
338
+ }
339
+ function widthFor(node) {
340
+ const label = (node.label ?? "").length;
341
+ const sub = (node.sub ?? "").length;
342
+ const longest = Math.max(label * 8.4, sub * 6.4);
343
+ return Math.round(Math.min(288, Math.max(168, longest + 78)));
344
+ }
345
+ function topologyGeometry(model, options = {}) {
346
+ const laneGutter = options.laneGutter ?? LANE_GUTTER;
347
+ const nodeHeight = options.nodeHeight ?? NODE_HEIGHT;
348
+ const nodes = Array.isArray(model?.nodes) ? model.nodes : [];
349
+ const links = Array.isArray(model?.links) ? model.links : [];
350
+ if (!nodes.length)
351
+ return { width: 400, height: laneGutter + 200, nodes: [], links: [], lanes: [], groups: [], crossings: 0 };
352
+ const used = [...new Set(nodes.map((node) => node.layer))].sort((a, b2) => a - b2);
353
+ const rankOf = new Map(used.map((layer, rank) => [layer, rank]));
354
+ const layout = Tj({
355
+ nodes: nodes.map((node) => ({
356
+ id: node.id,
357
+ layer: rankOf.get(node.layer) ?? 0,
358
+ width: widthFor(node),
359
+ height: nodeHeight
360
+ })),
361
+ edges: links.map((link) => ({ source: link.source, target: link.target }))
362
+ }, {
363
+ direction: "right",
364
+ layerGap: options.layerGap ?? 96,
365
+ nodeGap: options.nodeGap ?? 30,
366
+ padding: 28
367
+ });
368
+ const placed = new Map(layout.nodes.map((node) => [node.id, node]));
369
+ const neighbours = new Map;
370
+ for (const node of nodes)
371
+ neighbours.set(node.id, new Set);
372
+ for (const link of links) {
373
+ neighbours.get(link.source)?.add(link.target);
374
+ neighbours.get(link.target)?.add(link.source);
375
+ }
376
+ const shift = laneGutter;
377
+ const geometryNodes = nodes.flatMap((node) => {
378
+ const box = placed.get(node.id);
379
+ if (!box)
380
+ return [];
381
+ const y = box.y + shift;
382
+ return [{
383
+ ...node,
384
+ x: box.x,
385
+ y,
386
+ width: box.width,
387
+ height: box.height,
388
+ cx: box.x + box.width / 2,
389
+ cy: y + box.height / 2,
390
+ icon: iconFor(node.kind),
391
+ neighbours: [...neighbours.get(node.id) ?? []]
392
+ }];
393
+ });
394
+ const pending = new Map;
395
+ for (const link of links) {
396
+ const key = `${link.source}->${link.target}`;
397
+ if (!pending.has(key))
398
+ pending.set(key, []);
399
+ pending.get(key).push(link);
400
+ }
401
+ const geometryLinks = layout.edges.map((edge) => {
402
+ const source = pending.get(`${edge.source}->${edge.target}`)?.shift();
403
+ const points = edge.points.map((point) => ({ x: point.x, y: point.y + shift }));
404
+ const middle = points.length % 2 ? points[Math.floor(points.length / 2)] : midpoint(points[points.length / 2 - 1], points[points.length / 2]);
405
+ return {
406
+ source: edge.source,
407
+ target: edge.target,
408
+ flow: source?.flow ?? "request",
409
+ label: source?.label,
410
+ status: source?.status,
411
+ id: `${edge.source}->${edge.target}`,
412
+ d: Uj(points, { curve: "smooth", direction: "right" }),
413
+ labelX: middle.x,
414
+ labelY: middle.y - 7
415
+ };
416
+ });
417
+ const width = layout.width;
418
+ const height = layout.height + shift;
419
+ const labelOf = new Map((model.layers ?? []).map((layer) => [layer.index, layer.label]));
420
+ const lanes = used.flatMap((layer) => {
421
+ const members = geometryNodes.filter((node) => node.layer === layer);
422
+ if (!members.length)
423
+ return [];
424
+ const left = Math.min(...members.map((node) => node.x));
425
+ const right = Math.max(...members.map((node) => node.x + node.width));
426
+ return [{
427
+ id: `lane-${layer}`,
428
+ label: labelOf.get(layer) ?? `Layer ${layer}`,
429
+ x: left - 16,
430
+ y: shift - 34,
431
+ width: right - left + 32,
432
+ height: height - shift + 46,
433
+ count: members.length
434
+ }];
435
+ });
436
+ const groups = (model.groups ?? []).flatMap((group) => {
437
+ const members = geometryNodes.filter((node) => node.group === group.id);
438
+ if (!members.length)
439
+ return [];
440
+ const x = Math.min(...members.map((node) => node.x)) - GROUP_PADDING;
441
+ const y = Math.min(...members.map((node) => node.y)) - GROUP_PADDING - 12;
442
+ const right = Math.max(...members.map((node) => node.x + node.width)) + GROUP_PADDING;
443
+ const bottom = Math.max(...members.map((node) => node.y + node.height)) + GROUP_PADDING;
444
+ return [{ ...group, x, y, width: right - x, height: bottom - y }];
445
+ });
446
+ return { width, height, nodes: geometryNodes, links: geometryLinks, lanes, groups, crossings: layout.crossings };
447
+ }
448
+ function matchTopology(nodes, query) {
449
+ const needle = query.trim().toLowerCase();
450
+ if (!needle)
451
+ return new Set(nodes.map((node) => node.id));
452
+ return new Set(nodes.filter((node) => `${node.label} ${node.kind} ${node.sub ?? ""} ${node.facts.map((fact) => fact.value).join(" ")}`.toLowerCase().includes(needle)).map((node) => node.id));
453
+ }
454
+ function highlightFor(geometry, id) {
455
+ if (!id)
456
+ return null;
457
+ const keep = new Set([id]);
458
+ const incoming = new Map;
459
+ for (const link of geometry.links) {
460
+ if (!incoming.has(link.target))
461
+ incoming.set(link.target, []);
462
+ incoming.get(link.target).push(link.source);
463
+ }
464
+ const node = geometry.nodes.find((candidate) => candidate.id === id);
465
+ for (const neighbour of node?.neighbours ?? [])
466
+ keep.add(neighbour);
467
+ const seen = new Set([id]);
468
+ const queue = [id];
469
+ while (queue.length) {
470
+ const current = queue.shift();
471
+ for (const parent of incoming.get(current) ?? []) {
472
+ keep.add(parent);
473
+ if (seen.has(parent))
474
+ continue;
475
+ seen.add(parent);
476
+ queue.push(parent);
477
+ }
478
+ }
479
+ return keep;
480
+ }
481
+ export {
482
+ topologyGeometry,
483
+ matchTopology,
484
+ highlightFor
485
+ };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@stacksjs/ts-cloud",
3
3
  "type": "module",
4
- "version": "0.7.105",
4
+ "version": "0.7.108",
5
5
  "description": "A lightweight, performant infrastructure-as-code library and CLI for deploying both server-based (EC2) and serverless applications.",
6
6
  "author": "Chris Breuer <chris@stacksjs.com>",
7
7
  "license": "MIT",
@@ -90,8 +90,8 @@
90
90
  },
91
91
  "dependencies": {
92
92
  "@stacksjs/ts-xml": "^0.1.0",
93
- "@ts-cloud/aws-types": "0.7.105",
94
- "@ts-cloud/core": "0.7.105"
93
+ "@ts-cloud/aws-types": "0.7.108",
94
+ "@ts-cloud/core": "0.7.108"
95
95
  },
96
96
  "devDependencies": {
97
97
  "better-dx": "^0.2.16",