@lunora/studio 0.0.0 → 1.0.0-alpha.2

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 (81) hide show
  1. package/LICENSE.md +105 -0
  2. package/README.md +123 -9
  3. package/__assets__/package-og.svg +14 -0
  4. package/dist/index.d.ts +1402 -0
  5. package/dist/index.js +41 -0
  6. package/dist/mount.d.ts +21 -0
  7. package/dist/mount.js +26 -0
  8. package/dist/packem_shared/ADMIN_FUNCTION_PREFIX-DmBqMZ-z.js +45 -0
  9. package/dist/packem_shared/ApiDocsPanel-DpRjJhG5.js +842 -0
  10. package/dist/packem_shared/ApiReferencePanel-DMIUp-kK.js +229 -0
  11. package/dist/packem_shared/ApiTab-DURGU15e.js +251 -0
  12. package/dist/packem_shared/AuditPanel-BC59Nhst.js +212 -0
  13. package/dist/packem_shared/CommandPalette-Dx_CoB9i.js +373 -0
  14. package/dist/packem_shared/ConfirmButton-WQVUoGFb.js +59 -0
  15. package/dist/packem_shared/ConnectionBadge-Bxagrip8.js +111 -0
  16. package/dist/packem_shared/DEFAULT_AUTO_REFRESH_MS-Vxwaxx51.js +50 -0
  17. package/dist/packem_shared/DEFAULT_INSIGHT_THRESHOLDS-DjF0h-gA.js +89 -0
  18. package/dist/packem_shared/DataBrowser-Coz6jJE6.js +4542 -0
  19. package/dist/packem_shared/DataFilters-FNquMaiu.js +249 -0
  20. package/dist/packem_shared/ErrorBoundary-BzAApI7J.js +66 -0
  21. package/dist/packem_shared/ExportImportPanel-WO34fJxy.js +193 -0
  22. package/dist/packem_shared/FileBrowser-Zcr-Qgxo.js +2932 -0
  23. package/dist/packem_shared/FunctionRunner-j0Rd5m9t.js +343 -0
  24. package/dist/packem_shared/FunctionStatsPanel-DboBl-XL.js +432 -0
  25. package/dist/packem_shared/GlobalDataBrowser-9MhPEfgN.js +318 -0
  26. package/dist/packem_shared/HealthPanel-DOIgbUtx.js +640 -0
  27. package/dist/packem_shared/HomePanel-bdOCNA-p.js +1273 -0
  28. package/dist/packem_shared/InsightsPanel-DaZPnSgt.js +423 -0
  29. package/dist/packem_shared/LogsPanel-CWdqAGpQ.js +839 -0
  30. package/dist/packem_shared/MailPanel-D_EGtDnS.js +447 -0
  31. package/dist/packem_shared/MetricsPanel-E4Gv6wTO.js +1625 -0
  32. package/dist/packem_shared/MigrationsPanel-DQdPY9io.js +246 -0
  33. package/dist/packem_shared/OpenRpcReferencePanel-j2p3HB0s.js +191 -0
  34. package/dist/packem_shared/PitrPanel-BbBkQR6t.js +252 -0
  35. package/dist/packem_shared/STUDIO_ROOT_CLASS-D12gX2dV.js +3 -0
  36. package/dist/packem_shared/ScheduledJobs-Ok1CYYwI.js +159 -0
  37. package/dist/packem_shared/SchemaViewer-D8XGnp-X.js +2512 -0
  38. package/dist/packem_shared/SecurityAdvisorPanel-Cdm2IxLW.js +79 -0
  39. package/dist/packem_shared/SettingsPanel-D3WF2mBU.js +176 -0
  40. package/dist/packem_shared/ShardInput-DNCsT1KW.js +107 -0
  41. package/dist/packem_shared/SqlEditorPanel-BuQ7f2Hs.js +13 -0
  42. package/dist/packem_shared/Studio-D36od9Oz.js +33 -0
  43. package/dist/packem_shared/StudioApp-dvywkJ8I.js +383 -0
  44. package/dist/packem_shared/StudioI18nProvider-Dcajsznk.js +48 -0
  45. package/dist/packem_shared/TableEditor-DIVDk3vT.js +371 -0
  46. package/dist/packem_shared/advisor-view-DBlzJi6C.js +159 -0
  47. package/dist/packem_shared/aggregateMetrics-D4nUHEKU.js +108 -0
  48. package/dist/packem_shared/app.d-CCmwDEVs.d.ts +300 -0
  49. package/dist/packem_shared/badge-B2PKA1-5.js +49 -0
  50. package/dist/packem_shared/bar-chart-CzJAgqkp.js +3245 -0
  51. package/dist/packem_shared/button-BhsN2uZH.js +49 -0
  52. package/dist/packem_shared/card-DURq3ElK.js +175 -0
  53. package/dist/packem_shared/cf-links-BZfRdxSE.js +8 -0
  54. package/dist/packem_shared/checkbox-UNkzAxl-.js +63 -0
  55. package/dist/packem_shared/createStudioI18n-CgvlmDkN.js +27 -0
  56. package/dist/packem_shared/data-grid-CCh2Couo.js +183 -0
  57. package/dist/packem_shared/dropdown-menu-WY4B_eJO.js +280 -0
  58. package/dist/packem_shared/empty-state-DY_oe0k6.js +98 -0
  59. package/dist/packem_shared/grid-features-DTjG6Sex.js +840 -0
  60. package/dist/packem_shared/input-XH4r1Pt1.js +53 -0
  61. package/dist/packem_shared/internal-BBZYexre.js +68 -0
  62. package/dist/packem_shared/label-D8ykjn5J.js +46 -0
  63. package/dist/packem_shared/live-status-bPff1O7Y.js +44 -0
  64. package/dist/packem_shared/reference-view-BCKIoai7.js +2180 -0
  65. package/dist/packem_shared/shard-history-DyebH1R5.js +38 -0
  66. package/dist/packem_shared/sparkline-10dG-_f0.js +93 -0
  67. package/dist/packem_shared/sql-editor-panel-CW2y2x9h.js +2562 -0
  68. package/dist/packem_shared/storage-tier-CL98eOvn.js +85 -0
  69. package/dist/packem_shared/studio-BDVd7rIV.js +10303 -0
  70. package/dist/packem_shared/table-_RzNvy3R.js +246 -0
  71. package/dist/packem_shared/table-list-sidebar-aZHLq70w.js +832 -0
  72. package/dist/packem_shared/textarea-D3gaCU_-.js +46 -0
  73. package/dist/packem_shared/use-live-admin-D1h1Fzsd.js +73 -0
  74. package/dist/packem_shared/use-live-shard-seed-B74RYcOy.js +76 -0
  75. package/dist/packem_shared/useDebounced-Dxncpg6z.js +32 -0
  76. package/dist/packem_shared/utils-B05Dmz_H.js +8 -0
  77. package/dist/packem_shared/virtual-rect-CVMUskSm.js +10 -0
  78. package/dist/standalone/studio.js +356 -0
  79. package/dist/styles.css +2 -0
  80. package/package.json +77 -17
  81. package/src/theme.css +59 -0
@@ -0,0 +1,1273 @@
1
+ import { c } from 'react/compiler-runtime';
2
+ import { useLunora } from '@lunora/react';
3
+ import { useNavigate } from '@tanstack/react-router';
4
+ import { useState, useEffect } from 'react';
5
+ import { B as Bar, E as EvilBarChart } from './bar-chart-CzJAgqkp.js';
6
+ import { B as Badge } from './badge-B2PKA1-5.js';
7
+ import { C as Card, a as CardContent } from './card-DURq3ElK.js';
8
+ import { E as EmptyState } from './empty-state-DY_oe0k6.js';
9
+ import { useT } from './createStudioI18n-CgvlmDkN.js';
10
+ import { ADMIN_FUNCTIONS } from './ADMIN_FUNCTION_PREFIX-DmBqMZ-z.js';
11
+ import { g as formatBytes, f as fireAndForget, c as callOptions, a as adminRef } from './internal-BBZYexre.js';
12
+ import { c as cn } from './utils-B05Dmz_H.js';
13
+ import { deriveInsights } from './DEFAULT_INSIGHT_THRESHOLDS-DjF0h-gA.js';
14
+ import { jsxDEV } from 'react/jsx-dev-runtime';
15
+
16
+ const GET_METRICS = adminRef(ADMIN_FUNCTIONS.getMetrics);
17
+ const GET_FUNCTION_STATS = adminRef(ADMIN_FUNCTIONS.getFunctionStats);
18
+ const GET_SECURITY_AUDIT = adminRef(ADMIN_FUNCTIONS.getSecurityAudit);
19
+ const GET_AUDIT_LOG = adminRef(ADMIN_FUNCTIONS.getAuditLog);
20
+ const LIST_SUBSCRIPTIONS = adminRef(ADMIN_FUNCTIONS.listSubscriptions);
21
+ const formatMs = (ms) => {
22
+ if (ms < 1e3) {
23
+ return `${String(Math.round(ms))}ms`;
24
+ }
25
+ const digits = ms >= 1e4 ? 0 : 1;
26
+ return `${(ms / 1e3).toFixed(digits)}s`;
27
+ };
28
+ const relativeTime = (ts, now) => {
29
+ const seconds = Math.max(0, Math.round((now - ts) / 1e3));
30
+ if (seconds < 60) {
31
+ return `${String(seconds)}s ago`;
32
+ }
33
+ const minutes = Math.round(seconds / 60);
34
+ if (minutes < 60) {
35
+ return `${String(minutes)}m ago`;
36
+ }
37
+ const hours = Math.round(minutes / 60);
38
+ return hours < 24 ? `${String(hours)}h ago` : `${String(Math.round(hours / 24))}d ago`;
39
+ };
40
+ const SPARKLINE_CONFIG = {
41
+ value: {
42
+ colors: {
43
+ dark: ["var(--foreground)"],
44
+ light: ["var(--foreground)"]
45
+ },
46
+ label: ""
47
+ }
48
+ };
49
+ const Sparkline = (t0) => {
50
+ const $ = c(6);
51
+ const {
52
+ data
53
+ } = t0;
54
+ let t1;
55
+ let t2;
56
+ if ($[0] !== data) {
57
+ t2 = /* @__PURE__ */ Symbol.for("react.early_return_sentinel");
58
+ bb0: {
59
+ const bars = data.slice(-16);
60
+ if (bars.length < 3) {
61
+ t2 = null;
62
+ break bb0;
63
+ }
64
+ t1 = bars.map(_temp);
65
+ }
66
+ $[0] = data;
67
+ $[1] = t1;
68
+ $[2] = t2;
69
+ } else {
70
+ t1 = $[1];
71
+ t2 = $[2];
72
+ }
73
+ if (t2 !== /* @__PURE__ */ Symbol.for("react.early_return_sentinel")) {
74
+ return t2;
75
+ }
76
+ const rows = t1;
77
+ let t3;
78
+ if ($[3] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
79
+ t3 = /* @__PURE__ */ jsxDEV(Bar, {
80
+ dataKey: "value"
81
+ }, void 0, false);
82
+ $[3] = t3;
83
+ } else {
84
+ t3 = $[3];
85
+ }
86
+ let t4;
87
+ if ($[4] !== rows) {
88
+ t4 = /* @__PURE__ */ jsxDEV("div", {
89
+ "aria-hidden": "true",
90
+ className: "h-8 w-28",
91
+ children: /* @__PURE__ */ jsxDEV(EvilBarChart, {
92
+ animationType: "none",
93
+ barCategoryGap: 1,
94
+ className: "h-8 w-full",
95
+ config: SPARKLINE_CONFIG,
96
+ data: rows,
97
+ children: t3
98
+ }, void 0, false)
99
+ }, void 0, false);
100
+ $[4] = rows;
101
+ $[5] = t4;
102
+ } else {
103
+ t4 = $[5];
104
+ }
105
+ return t4;
106
+ };
107
+ const bucketSeries = (history, field) => {
108
+ if (history === void 0 || history.length === 0) {
109
+ return [];
110
+ }
111
+ const byBucket = /* @__PURE__ */ new Map();
112
+ for (const bucket of history) {
113
+ byBucket.set(bucket.bucketMs, (byBucket.get(bucket.bucketMs) ?? 0) + bucket[field]);
114
+ }
115
+ return [...byBucket.entries()].toSorted(([a], [b]) => a - b).map(([, total]) => total);
116
+ };
117
+ const seriesDelta = (series, higherIsBetter = true) => {
118
+ if (series.length < 4) {
119
+ return null;
120
+ }
121
+ const mid = Math.floor(series.length / 2);
122
+ const earlier = series.slice(0, mid).reduce((sum, value) => sum + value, 0);
123
+ const recent = series.slice(mid).reduce((sum, value) => sum + value, 0);
124
+ if (earlier === 0) {
125
+ return null;
126
+ }
127
+ const pct = (recent - earlier) / earlier * 100;
128
+ return {
129
+ positive: higherIsBetter ? pct >= 0 : pct <= 0,
130
+ text: `${pct >= 0 ? "+" : ""}${pct.toFixed(1)}%`
131
+ };
132
+ };
133
+ const StatCard = (t0) => {
134
+ const $ = c(24);
135
+ const {
136
+ delta,
137
+ footer,
138
+ label,
139
+ trend,
140
+ unit,
141
+ value
142
+ } = t0;
143
+ const t = useT();
144
+ let t1;
145
+ if ($[0] !== label) {
146
+ t1 = /* @__PURE__ */ jsxDEV("span", {
147
+ className: "font-mono text-[11px] tracking-wide text-muted-foreground uppercase",
148
+ children: label
149
+ }, void 0, false);
150
+ $[0] = label;
151
+ $[1] = t1;
152
+ } else {
153
+ t1 = $[1];
154
+ }
155
+ let t2;
156
+ if ($[2] !== value) {
157
+ t2 = /* @__PURE__ */ jsxDEV("span", {
158
+ className: "text-2xl font-semibold tabular-nums text-foreground",
159
+ children: value
160
+ }, void 0, false);
161
+ $[2] = value;
162
+ $[3] = t2;
163
+ } else {
164
+ t2 = $[3];
165
+ }
166
+ let t3;
167
+ if ($[4] !== unit) {
168
+ t3 = unit !== void 0 && /* @__PURE__ */ jsxDEV("span", {
169
+ className: "text-xs text-muted-foreground",
170
+ children: unit
171
+ }, void 0, false);
172
+ $[4] = unit;
173
+ $[5] = t3;
174
+ } else {
175
+ t3 = $[5];
176
+ }
177
+ let t4;
178
+ if ($[6] !== t2 || $[7] !== t3) {
179
+ t4 = /* @__PURE__ */ jsxDEV("span", {
180
+ className: "flex items-baseline gap-1.5",
181
+ children: [t2, t3]
182
+ }, void 0, true);
183
+ $[6] = t2;
184
+ $[7] = t3;
185
+ $[8] = t4;
186
+ } else {
187
+ t4 = $[8];
188
+ }
189
+ let t5;
190
+ if ($[9] !== trend) {
191
+ t5 = trend !== void 0 && /* @__PURE__ */ jsxDEV(Sparkline, {
192
+ data: trend
193
+ }, void 0, false);
194
+ $[9] = trend;
195
+ $[10] = t5;
196
+ } else {
197
+ t5 = $[10];
198
+ }
199
+ let t6;
200
+ if ($[11] !== t4 || $[12] !== t5) {
201
+ t6 = /* @__PURE__ */ jsxDEV("div", {
202
+ className: "flex items-center justify-between gap-3",
203
+ children: [t4, t5]
204
+ }, void 0, true);
205
+ $[11] = t4;
206
+ $[12] = t5;
207
+ $[13] = t6;
208
+ } else {
209
+ t6 = $[13];
210
+ }
211
+ let t7;
212
+ if ($[14] !== t1 || $[15] !== t6) {
213
+ t7 = /* @__PURE__ */ jsxDEV("div", {
214
+ className: "flex flex-col gap-2.5 p-4",
215
+ children: [t1, t6]
216
+ }, void 0, true);
217
+ $[14] = t1;
218
+ $[15] = t6;
219
+ $[16] = t7;
220
+ } else {
221
+ t7 = $[16];
222
+ }
223
+ let t8;
224
+ if ($[17] !== delta || $[18] !== footer || $[19] !== t) {
225
+ t8 = delta == null ? footer != null && /* @__PURE__ */ jsxDEV("div", {
226
+ className: "border-t border-border bg-muted/50 px-4 py-2.5 text-[11px] text-muted-foreground",
227
+ children: footer
228
+ }, void 0, false) : /* @__PURE__ */ jsxDEV("div", {
229
+ className: "border-t border-border bg-muted/50 px-4 py-2.5 text-[11px]",
230
+ children: [/* @__PURE__ */ jsxDEV("span", {
231
+ className: cn("font-semibold", delta.positive ? "text-success" : "text-destructive"),
232
+ children: delta.text
233
+ }, void 0, false), " ", /* @__PURE__ */ jsxDEV("span", {
234
+ className: "text-muted-foreground",
235
+ children: t("vs. prev.")
236
+ }, void 0, false)]
237
+ }, void 0, true);
238
+ $[17] = delta;
239
+ $[18] = footer;
240
+ $[19] = t;
241
+ $[20] = t8;
242
+ } else {
243
+ t8 = $[20];
244
+ }
245
+ let t9;
246
+ if ($[21] !== t7 || $[22] !== t8) {
247
+ t9 = /* @__PURE__ */ jsxDEV(Card, {
248
+ className: "justify-between gap-0 py-0",
249
+ children: [t7, t8]
250
+ }, void 0, true);
251
+ $[21] = t7;
252
+ $[22] = t8;
253
+ $[23] = t9;
254
+ } else {
255
+ t9 = $[23];
256
+ }
257
+ return t9;
258
+ };
259
+ const ChevronRight = () => {
260
+ const $ = c(1);
261
+ let t0;
262
+ if ($[0] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
263
+ t0 = /* @__PURE__ */ jsxDEV("svg", {
264
+ "aria-hidden": "true",
265
+ className: "size-3.5",
266
+ fill: "none",
267
+ stroke: "currentColor",
268
+ strokeLinecap: "round",
269
+ strokeLinejoin: "round",
270
+ strokeWidth: 1.8,
271
+ viewBox: "0 0 24 24",
272
+ children: /* @__PURE__ */ jsxDEV("path", {
273
+ d: "m9 6 6 6-6 6"
274
+ }, void 0, false)
275
+ }, void 0, false);
276
+ $[0] = t0;
277
+ } else {
278
+ t0 = $[0];
279
+ }
280
+ return t0;
281
+ };
282
+ const ConnectCard = (t0) => {
283
+ const $ = c(7);
284
+ const {
285
+ command,
286
+ label
287
+ } = t0;
288
+ let t1;
289
+ if ($[0] !== label) {
290
+ t1 = /* @__PURE__ */ jsxDEV("div", {
291
+ className: "p-4",
292
+ children: /* @__PURE__ */ jsxDEV("span", {
293
+ className: "text-sm font-medium text-foreground",
294
+ children: label
295
+ }, void 0, false)
296
+ }, void 0, false);
297
+ $[0] = label;
298
+ $[1] = t1;
299
+ } else {
300
+ t1 = $[1];
301
+ }
302
+ let t2;
303
+ if ($[2] !== command) {
304
+ t2 = /* @__PURE__ */ jsxDEV("div", {
305
+ className: "border-t border-border bg-muted/50 px-4 py-2.5",
306
+ children: /* @__PURE__ */ jsxDEV("code", {
307
+ className: "font-mono text-xs text-muted-foreground",
308
+ children: command
309
+ }, void 0, false)
310
+ }, void 0, false);
311
+ $[2] = command;
312
+ $[3] = t2;
313
+ } else {
314
+ t2 = $[3];
315
+ }
316
+ let t3;
317
+ if ($[4] !== t1 || $[5] !== t2) {
318
+ t3 = /* @__PURE__ */ jsxDEV(Card, {
319
+ className: "justify-between gap-0 py-0",
320
+ children: [t1, t2]
321
+ }, void 0, true);
322
+ $[4] = t1;
323
+ $[5] = t2;
324
+ $[6] = t3;
325
+ } else {
326
+ t3 = $[6];
327
+ }
328
+ return t3;
329
+ };
330
+ const AdvisorCard = (t0) => {
331
+ const $ = c(18);
332
+ const {
333
+ count,
334
+ onView,
335
+ testId,
336
+ title
337
+ } = t0;
338
+ const t = useT();
339
+ let t1;
340
+ if ($[0] !== title) {
341
+ t1 = /* @__PURE__ */ jsxDEV("span", {
342
+ className: "font-mono text-[11px] tracking-wide text-muted-foreground uppercase",
343
+ children: title
344
+ }, void 0, false);
345
+ $[0] = title;
346
+ $[1] = t1;
347
+ } else {
348
+ t1 = $[1];
349
+ }
350
+ let t2;
351
+ if ($[2] !== count || $[3] !== t) {
352
+ t2 = count === null ? /* @__PURE__ */ jsxDEV("span", {
353
+ className: "text-xs text-muted-foreground",
354
+ children: t("No data yet")
355
+ }, void 0, false) : /* @__PURE__ */ jsxDEV(Badge, {
356
+ variant: count > 0 ? "destructive" : "success",
357
+ children: count > 0 ? count : t("All clear")
358
+ }, void 0, false);
359
+ $[2] = count;
360
+ $[3] = t;
361
+ $[4] = t2;
362
+ } else {
363
+ t2 = $[4];
364
+ }
365
+ let t3;
366
+ if ($[5] !== t1 || $[6] !== t2) {
367
+ t3 = /* @__PURE__ */ jsxDEV("div", {
368
+ className: "flex items-start justify-between gap-2 p-4",
369
+ children: [t1, t2]
370
+ }, void 0, true);
371
+ $[5] = t1;
372
+ $[6] = t2;
373
+ $[7] = t3;
374
+ } else {
375
+ t3 = $[7];
376
+ }
377
+ let t4;
378
+ if ($[8] !== t) {
379
+ t4 = t("View");
380
+ $[8] = t;
381
+ $[9] = t4;
382
+ } else {
383
+ t4 = $[9];
384
+ }
385
+ let t5;
386
+ if ($[10] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
387
+ t5 = /* @__PURE__ */ jsxDEV(ChevronRight, {}, void 0, false);
388
+ $[10] = t5;
389
+ } else {
390
+ t5 = $[10];
391
+ }
392
+ let t6;
393
+ if ($[11] !== onView || $[12] !== t4) {
394
+ t6 = /* @__PURE__ */ jsxDEV("button", {
395
+ className: "flex items-center gap-1 border-t border-border bg-muted/50 px-4 py-2.5 text-[12px] font-medium text-foreground outline-none transition-colors hover:bg-muted focus-visible:bg-muted",
396
+ onClick: onView,
397
+ type: "button",
398
+ children: [t4, t5]
399
+ }, void 0, true);
400
+ $[11] = onView;
401
+ $[12] = t4;
402
+ $[13] = t6;
403
+ } else {
404
+ t6 = $[13];
405
+ }
406
+ let t7;
407
+ if ($[14] !== t3 || $[15] !== t6 || $[16] !== testId) {
408
+ t7 = /* @__PURE__ */ jsxDEV(Card, {
409
+ className: "justify-between gap-0 py-0",
410
+ "data-testid": testId,
411
+ children: [t3, t6]
412
+ }, void 0, true);
413
+ $[14] = t3;
414
+ $[15] = t6;
415
+ $[16] = testId;
416
+ $[17] = t7;
417
+ } else {
418
+ t7 = $[17];
419
+ }
420
+ return t7;
421
+ };
422
+ const TopFunctionsCard = (t0) => {
423
+ const $ = c(7);
424
+ const {
425
+ functions
426
+ } = t0;
427
+ const t = useT();
428
+ let t1;
429
+ if ($[0] !== functions || $[1] !== t) {
430
+ const top = [...functions].toSorted(_temp2).slice(0, 5);
431
+ let t2;
432
+ if ($[3] !== t) {
433
+ t2 = t("Top functions");
434
+ $[3] = t;
435
+ $[4] = t2;
436
+ } else {
437
+ t2 = $[4];
438
+ }
439
+ let t3;
440
+ if ($[5] !== t2) {
441
+ t3 = /* @__PURE__ */ jsxDEV("div", {
442
+ className: "border-b border-border px-4 py-3",
443
+ children: /* @__PURE__ */ jsxDEV("span", {
444
+ className: "font-mono text-[11px] tracking-wide text-muted-foreground uppercase",
445
+ children: t2
446
+ }, void 0, false)
447
+ }, void 0, false);
448
+ $[5] = t2;
449
+ $[6] = t3;
450
+ } else {
451
+ t3 = $[6];
452
+ }
453
+ t1 = /* @__PURE__ */ jsxDEV(Card, {
454
+ className: "gap-0 py-0",
455
+ "data-testid": "home-top-functions",
456
+ children: [t3, top.length === 0 ? /* @__PURE__ */ jsxDEV("p", {
457
+ className: "px-4 py-8 text-center text-xs text-muted-foreground",
458
+ children: t("No functions called yet.")
459
+ }, void 0, false) : /* @__PURE__ */ jsxDEV("div", {
460
+ className: "divide-y divide-border",
461
+ children: [/* @__PURE__ */ jsxDEV("div", {
462
+ className: "grid grid-cols-[1fr_auto_auto_auto] gap-4 px-4 py-1.5 font-mono text-[10px] tracking-wide text-muted-foreground uppercase",
463
+ children: [/* @__PURE__ */ jsxDEV("span", {
464
+ children: t("Function")
465
+ }, void 0, false), /* @__PURE__ */ jsxDEV("span", {
466
+ className: "text-end",
467
+ children: t("Calls")
468
+ }, void 0, false), /* @__PURE__ */ jsxDEV("span", {
469
+ className: "w-12 text-end",
470
+ children: t("Avg")
471
+ }, void 0, false), /* @__PURE__ */ jsxDEV("span", {
472
+ className: "w-8 text-end",
473
+ children: t("Err")
474
+ }, void 0, false)]
475
+ }, void 0, true), top.map(_temp3)]
476
+ }, void 0, true)]
477
+ }, void 0, true);
478
+ $[0] = functions;
479
+ $[1] = t;
480
+ $[2] = t1;
481
+ } else {
482
+ t1 = $[2];
483
+ }
484
+ return t1;
485
+ };
486
+ const LiveConnectionsCard = (t0) => {
487
+ const $ = c(26);
488
+ const {
489
+ subs
490
+ } = t0;
491
+ const t = useT();
492
+ let t1;
493
+ if ($[0] !== t) {
494
+ t1 = t("Live connections");
495
+ $[0] = t;
496
+ $[1] = t1;
497
+ } else {
498
+ t1 = $[1];
499
+ }
500
+ let t2;
501
+ if ($[2] !== t1) {
502
+ t2 = /* @__PURE__ */ jsxDEV("span", {
503
+ className: "font-mono text-[11px] tracking-wide text-muted-foreground uppercase",
504
+ children: t1
505
+ }, void 0, false);
506
+ $[2] = t1;
507
+ $[3] = t2;
508
+ } else {
509
+ t2 = $[3];
510
+ }
511
+ const t3 = subs?.totalConnections ?? 0;
512
+ let t4;
513
+ if ($[4] !== t3) {
514
+ t4 = t3.toLocaleString();
515
+ $[4] = t3;
516
+ $[5] = t4;
517
+ } else {
518
+ t4 = $[5];
519
+ }
520
+ let t5;
521
+ if ($[6] !== t4) {
522
+ t5 = /* @__PURE__ */ jsxDEV("span", {
523
+ className: "text-2xl font-semibold tabular-nums text-foreground",
524
+ children: t4
525
+ }, void 0, false);
526
+ $[6] = t4;
527
+ $[7] = t5;
528
+ } else {
529
+ t5 = $[7];
530
+ }
531
+ let t6;
532
+ if ($[8] !== t) {
533
+ t6 = t("sockets");
534
+ $[8] = t;
535
+ $[9] = t6;
536
+ } else {
537
+ t6 = $[9];
538
+ }
539
+ let t7;
540
+ if ($[10] !== t6) {
541
+ t7 = /* @__PURE__ */ jsxDEV("span", {
542
+ className: "text-xs text-muted-foreground",
543
+ children: t6
544
+ }, void 0, false);
545
+ $[10] = t6;
546
+ $[11] = t7;
547
+ } else {
548
+ t7 = $[11];
549
+ }
550
+ let t8;
551
+ if ($[12] !== t5 || $[13] !== t7) {
552
+ t8 = /* @__PURE__ */ jsxDEV("span", {
553
+ className: "flex items-baseline gap-1.5",
554
+ children: [t5, t7]
555
+ }, void 0, true);
556
+ $[12] = t5;
557
+ $[13] = t7;
558
+ $[14] = t8;
559
+ } else {
560
+ t8 = $[14];
561
+ }
562
+ const t9 = subs?.totalSubscriptions ?? 0;
563
+ let t10;
564
+ if ($[15] !== t9) {
565
+ t10 = t9.toLocaleString();
566
+ $[15] = t9;
567
+ $[16] = t10;
568
+ } else {
569
+ t10 = $[16];
570
+ }
571
+ let t11;
572
+ if ($[17] !== t) {
573
+ t11 = t("active subscriptions");
574
+ $[17] = t;
575
+ $[18] = t11;
576
+ } else {
577
+ t11 = $[18];
578
+ }
579
+ let t12;
580
+ if ($[19] !== t10 || $[20] !== t11) {
581
+ t12 = /* @__PURE__ */ jsxDEV("span", {
582
+ className: "text-[11px] text-muted-foreground",
583
+ children: [t10, " ", t11]
584
+ }, void 0, true);
585
+ $[19] = t10;
586
+ $[20] = t11;
587
+ $[21] = t12;
588
+ } else {
589
+ t12 = $[21];
590
+ }
591
+ let t13;
592
+ if ($[22] !== t12 || $[23] !== t2 || $[24] !== t8) {
593
+ t13 = /* @__PURE__ */ jsxDEV(Card, {
594
+ "data-testid": "home-live-connections",
595
+ children: /* @__PURE__ */ jsxDEV(CardContent, {
596
+ className: "flex flex-col gap-2.5 py-4",
597
+ children: [t2, t8, t12]
598
+ }, void 0, true)
599
+ }, void 0, false);
600
+ $[22] = t12;
601
+ $[23] = t2;
602
+ $[24] = t8;
603
+ $[25] = t13;
604
+ } else {
605
+ t13 = $[25];
606
+ }
607
+ return t13;
608
+ };
609
+ const RecentActivityCard = (t0) => {
610
+ const $ = c(7);
611
+ const {
612
+ entries
613
+ } = t0;
614
+ const t = useT();
615
+ let t1;
616
+ if ($[0] !== entries || $[1] !== t) {
617
+ const now = Date.now();
618
+ let t2;
619
+ if ($[3] !== t) {
620
+ t2 = t("Recent activity");
621
+ $[3] = t;
622
+ $[4] = t2;
623
+ } else {
624
+ t2 = $[4];
625
+ }
626
+ let t3;
627
+ if ($[5] !== t2) {
628
+ t3 = /* @__PURE__ */ jsxDEV("div", {
629
+ className: "border-b border-border px-4 py-3",
630
+ children: /* @__PURE__ */ jsxDEV("span", {
631
+ className: "font-mono text-[11px] tracking-wide text-muted-foreground uppercase",
632
+ children: t2
633
+ }, void 0, false)
634
+ }, void 0, false);
635
+ $[5] = t2;
636
+ $[6] = t3;
637
+ } else {
638
+ t3 = $[6];
639
+ }
640
+ t1 = /* @__PURE__ */ jsxDEV(Card, {
641
+ className: "gap-0 py-0",
642
+ "data-testid": "home-recent-activity",
643
+ children: [t3, entries.length === 0 ? /* @__PURE__ */ jsxDEV("p", {
644
+ className: "px-4 py-8 text-center text-xs text-muted-foreground",
645
+ children: t("No recent activity.")
646
+ }, void 0, false) : /* @__PURE__ */ jsxDEV("ul", {
647
+ className: "divide-y divide-border",
648
+ children: entries.slice(0, 5).map((entry) => /* @__PURE__ */ jsxDEV("li", {
649
+ className: "flex items-center justify-between gap-3 px-4 py-2 text-[13px]",
650
+ children: [/* @__PURE__ */ jsxDEV("span", {
651
+ className: "flex min-w-0 items-center gap-2",
652
+ children: [/* @__PURE__ */ jsxDEV("span", {
653
+ "aria-hidden": "true",
654
+ className: "size-1.5 shrink-0 rounded-full bg-muted-foreground/40"
655
+ }, void 0, false), /* @__PURE__ */ jsxDEV("span", {
656
+ className: "truncate text-foreground",
657
+ children: [entry.op, entry.table !== void 0 && /* @__PURE__ */ jsxDEV("span", {
658
+ className: "text-muted-foreground",
659
+ children: [" · ", entry.table, entry.id === void 0 ? "" : `#${entry.id}`]
660
+ }, void 0, true)]
661
+ }, void 0, true)]
662
+ }, void 0, true), /* @__PURE__ */ jsxDEV("span", {
663
+ className: "shrink-0 text-xs tabular-nums text-muted-foreground",
664
+ children: relativeTime(entry.ts, now)
665
+ }, void 0, false)]
666
+ }, entry.seq, true))
667
+ }, void 0, false)]
668
+ }, void 0, true);
669
+ $[0] = entries;
670
+ $[1] = t;
671
+ $[2] = t1;
672
+ } else {
673
+ t1 = $[2];
674
+ }
675
+ return t1;
676
+ };
677
+ const averageLatencyMs = (functions) => {
678
+ const calls = functions.reduce((sum, function_) => sum + function_.calls, 0);
679
+ if (calls === 0) {
680
+ return null;
681
+ }
682
+ return functions.reduce((sum, function_) => sum + function_.totalDurationMs, 0) / calls;
683
+ };
684
+ const HomePanel = (t0) => {
685
+ const $ = c(132);
686
+ const {
687
+ initialShardKey
688
+ } = t0;
689
+ const client = useLunora();
690
+ const t = useT();
691
+ const navigate = useNavigate();
692
+ const [metrics, setMetrics] = useState(null);
693
+ let t1;
694
+ if ($[0] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
695
+ t1 = [];
696
+ $[0] = t1;
697
+ } else {
698
+ t1 = $[0];
699
+ }
700
+ const [functions, setFunctions] = useState(t1);
701
+ const [performanceCount, setPerformanceCount] = useState(null);
702
+ const [securityCount, setSecurityCount] = useState(null);
703
+ const [subscriptions, setSubscriptions] = useState(null);
704
+ let t2;
705
+ if ($[1] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
706
+ t2 = [];
707
+ $[1] = t2;
708
+ } else {
709
+ t2 = $[1];
710
+ }
711
+ const [activity, setActivity] = useState(t2);
712
+ let t3;
713
+ let t4;
714
+ if ($[2] !== client || $[3] !== initialShardKey) {
715
+ t3 = () => {
716
+ const shard = initialShardKey ?? "";
717
+ const load = async () => {
718
+ const [snapshot, stats, audit, subs, recent] = await Promise.allSettled([client.query(GET_METRICS, {}, callOptions(shard)), client.query(GET_FUNCTION_STATS, {}, callOptions(shard)), client.query(GET_SECURITY_AUDIT, {}, callOptions("")), client.query(LIST_SUBSCRIPTIONS, {}, callOptions(shard)), client.query(GET_AUDIT_LOG, {}, callOptions(shard))]);
719
+ const snapshotValue = snapshot.status === "fulfilled" ? snapshot.value : null;
720
+ const statFns = stats.status === "fulfilled" && Array.isArray(stats.value.functions) ? stats.value.functions : [];
721
+ setMetrics(snapshotValue);
722
+ setFunctions(statFns);
723
+ setPerformanceCount(stats.status === "fulfilled" ? deriveInsights(snapshotValue, statFns).length : null);
724
+ setSecurityCount(audit.status === "fulfilled" && Array.isArray(audit.value.findings) ? audit.value.findings.length : null);
725
+ setSubscriptions(subs.status === "fulfilled" ? subs.value : null);
726
+ setActivity(recent.status === "fulfilled" && Array.isArray(recent.value.entries) ? recent.value.entries : []);
727
+ };
728
+ fireAndForget(load());
729
+ };
730
+ t4 = [client, initialShardKey];
731
+ $[2] = client;
732
+ $[3] = initialShardKey;
733
+ $[4] = t3;
734
+ $[5] = t4;
735
+ } else {
736
+ t3 = $[4];
737
+ t4 = $[5];
738
+ }
739
+ useEffect(t3, t4);
740
+ let t5;
741
+ if ($[6] !== navigate) {
742
+ t5 = () => {
743
+ fireAndForget(navigate({
744
+ to: "/security"
745
+ }));
746
+ };
747
+ $[6] = navigate;
748
+ $[7] = t5;
749
+ } else {
750
+ t5 = $[7];
751
+ }
752
+ const viewSecurity = t5;
753
+ let t6;
754
+ if ($[8] !== navigate) {
755
+ t6 = () => {
756
+ fireAndForget(navigate({
757
+ to: "/insights"
758
+ }));
759
+ };
760
+ $[8] = navigate;
761
+ $[9] = t6;
762
+ } else {
763
+ t6 = $[9];
764
+ }
765
+ const viewPerformance = t6;
766
+ let T0;
767
+ let cacheHitRate;
768
+ let t10;
769
+ let t11;
770
+ let t12;
771
+ let t13;
772
+ let t14;
773
+ let t15;
774
+ let t7;
775
+ let t8;
776
+ let t9;
777
+ if ($[10] !== functions || $[11] !== metrics?.cache || $[12] !== metrics?.errors || $[13] !== metrics?.history || $[14] !== metrics?.requests || $[15] !== t) {
778
+ const requestSeries = bucketSeries(metrics?.history, "calls");
779
+ const errorSeries = bucketSeries(metrics?.history, "errors");
780
+ const avgLatency = averageLatencyMs(functions);
781
+ let t162;
782
+ if ($[27] !== functions) {
783
+ t162 = Math.max(0, ...functions.map(_temp4));
784
+ $[27] = functions;
785
+ $[28] = t162;
786
+ } else {
787
+ t162 = $[28];
788
+ }
789
+ const maxLatency = t162;
790
+ const cache = metrics?.cache;
791
+ let t172;
792
+ if ($[29] !== cache) {
793
+ t172 = cache != null && cache.hits + cache.misses > 0 ? Math.round(cache.hits / (cache.hits + cache.misses) * 100) : null;
794
+ $[29] = cache;
795
+ $[30] = t172;
796
+ } else {
797
+ t172 = $[30];
798
+ }
799
+ cacheHitRate = t172;
800
+ t14 = "flex flex-col gap-6";
801
+ t15 = "lunora-home";
802
+ t10 = "grid gap-3 sm:grid-cols-2 xl:grid-cols-4";
803
+ t11 = "home-health";
804
+ const t182 = seriesDelta(requestSeries);
805
+ let t192;
806
+ if ($[31] !== t) {
807
+ t192 = t("Requests");
808
+ $[31] = t;
809
+ $[32] = t192;
810
+ } else {
811
+ t192 = $[32];
812
+ }
813
+ const t202 = metrics?.requests ?? 0;
814
+ let t212;
815
+ if ($[33] !== t202) {
816
+ t212 = t202.toLocaleString();
817
+ $[33] = t202;
818
+ $[34] = t212;
819
+ } else {
820
+ t212 = $[34];
821
+ }
822
+ if ($[35] !== requestSeries || $[36] !== t182 || $[37] !== t192 || $[38] !== t212) {
823
+ t12 = /* @__PURE__ */ jsxDEV(StatCard, {
824
+ delta: t182,
825
+ label: t192,
826
+ trend: requestSeries,
827
+ value: t212
828
+ }, void 0, false);
829
+ $[35] = requestSeries;
830
+ $[36] = t182;
831
+ $[37] = t192;
832
+ $[38] = t212;
833
+ $[39] = t12;
834
+ } else {
835
+ t12 = $[39];
836
+ }
837
+ const t222 = seriesDelta(errorSeries, false);
838
+ let t232;
839
+ if ($[40] !== t) {
840
+ t232 = t("Errors");
841
+ $[40] = t;
842
+ $[41] = t232;
843
+ } else {
844
+ t232 = $[41];
845
+ }
846
+ const t242 = metrics?.errors ?? 0;
847
+ let t252;
848
+ if ($[42] !== t242) {
849
+ t252 = t242.toLocaleString();
850
+ $[42] = t242;
851
+ $[43] = t252;
852
+ } else {
853
+ t252 = $[43];
854
+ }
855
+ if ($[44] !== errorSeries || $[45] !== t222 || $[46] !== t232 || $[47] !== t252) {
856
+ t13 = /* @__PURE__ */ jsxDEV(StatCard, {
857
+ delta: t222,
858
+ label: t232,
859
+ trend: errorSeries,
860
+ value: t252
861
+ }, void 0, false);
862
+ $[44] = errorSeries;
863
+ $[45] = t222;
864
+ $[46] = t232;
865
+ $[47] = t252;
866
+ $[48] = t13;
867
+ } else {
868
+ t13 = $[48];
869
+ }
870
+ T0 = StatCard;
871
+ if ($[49] !== maxLatency || $[50] !== t) {
872
+ t7 = maxLatency > 0 ? `${t("max")} ${formatMs(maxLatency)}` : void 0;
873
+ $[49] = maxLatency;
874
+ $[50] = t;
875
+ $[51] = t7;
876
+ } else {
877
+ t7 = $[51];
878
+ }
879
+ if ($[52] !== t) {
880
+ t8 = t("Avg latency");
881
+ $[52] = t;
882
+ $[53] = t8;
883
+ } else {
884
+ t8 = $[53];
885
+ }
886
+ t9 = avgLatency === null ? "—" : formatMs(avgLatency);
887
+ $[10] = functions;
888
+ $[11] = metrics?.cache;
889
+ $[12] = metrics?.errors;
890
+ $[13] = metrics?.history;
891
+ $[14] = metrics?.requests;
892
+ $[15] = t;
893
+ $[16] = T0;
894
+ $[17] = cacheHitRate;
895
+ $[18] = t10;
896
+ $[19] = t11;
897
+ $[20] = t12;
898
+ $[21] = t13;
899
+ $[22] = t14;
900
+ $[23] = t15;
901
+ $[24] = t7;
902
+ $[25] = t8;
903
+ $[26] = t9;
904
+ } else {
905
+ T0 = $[16];
906
+ cacheHitRate = $[17];
907
+ t10 = $[18];
908
+ t11 = $[19];
909
+ t12 = $[20];
910
+ t13 = $[21];
911
+ t14 = $[22];
912
+ t15 = $[23];
913
+ t7 = $[24];
914
+ t8 = $[25];
915
+ t9 = $[26];
916
+ }
917
+ let t16;
918
+ if ($[54] !== T0 || $[55] !== t7 || $[56] !== t8 || $[57] !== t9) {
919
+ t16 = /* @__PURE__ */ jsxDEV(T0, {
920
+ footer: t7,
921
+ label: t8,
922
+ value: t9
923
+ }, void 0, false);
924
+ $[54] = T0;
925
+ $[55] = t7;
926
+ $[56] = t8;
927
+ $[57] = t9;
928
+ $[58] = t16;
929
+ } else {
930
+ t16 = $[58];
931
+ }
932
+ let t17;
933
+ if ($[59] !== cacheHitRate || $[60] !== t) {
934
+ t17 = cacheHitRate === null ? void 0 : `${String(cacheHitRate)}% ${t("cache hit")}`;
935
+ $[59] = cacheHitRate;
936
+ $[60] = t;
937
+ $[61] = t17;
938
+ } else {
939
+ t17 = $[61];
940
+ }
941
+ let t18;
942
+ if ($[62] !== t) {
943
+ t18 = t("Database size");
944
+ $[62] = t;
945
+ $[63] = t18;
946
+ } else {
947
+ t18 = $[63];
948
+ }
949
+ const t19 = metrics?.databaseSize ?? null;
950
+ let t20;
951
+ if ($[64] !== t19) {
952
+ t20 = formatBytes(t19);
953
+ $[64] = t19;
954
+ $[65] = t20;
955
+ } else {
956
+ t20 = $[65];
957
+ }
958
+ let t21;
959
+ if ($[66] !== t17 || $[67] !== t18 || $[68] !== t20) {
960
+ t21 = /* @__PURE__ */ jsxDEV(StatCard, {
961
+ footer: t17,
962
+ label: t18,
963
+ value: t20
964
+ }, void 0, false);
965
+ $[66] = t17;
966
+ $[67] = t18;
967
+ $[68] = t20;
968
+ $[69] = t21;
969
+ } else {
970
+ t21 = $[69];
971
+ }
972
+ let t22;
973
+ if ($[70] !== t10 || $[71] !== t11 || $[72] !== t12 || $[73] !== t13 || $[74] !== t16 || $[75] !== t21) {
974
+ t22 = /* @__PURE__ */ jsxDEV("div", {
975
+ className: t10,
976
+ "data-testid": t11,
977
+ children: [t12, t13, t16, t21]
978
+ }, void 0, true);
979
+ $[70] = t10;
980
+ $[71] = t11;
981
+ $[72] = t12;
982
+ $[73] = t13;
983
+ $[74] = t16;
984
+ $[75] = t21;
985
+ $[76] = t22;
986
+ } else {
987
+ t22 = $[76];
988
+ }
989
+ let t23;
990
+ if ($[77] !== functions) {
991
+ t23 = /* @__PURE__ */ jsxDEV("div", {
992
+ className: "lg:col-span-2",
993
+ children: /* @__PURE__ */ jsxDEV(TopFunctionsCard, {
994
+ functions
995
+ }, void 0, false)
996
+ }, void 0, false);
997
+ $[77] = functions;
998
+ $[78] = t23;
999
+ } else {
1000
+ t23 = $[78];
1001
+ }
1002
+ let t24;
1003
+ if ($[79] !== subscriptions) {
1004
+ t24 = /* @__PURE__ */ jsxDEV(LiveConnectionsCard, {
1005
+ subs: subscriptions
1006
+ }, void 0, false);
1007
+ $[79] = subscriptions;
1008
+ $[80] = t24;
1009
+ } else {
1010
+ t24 = $[80];
1011
+ }
1012
+ let t25;
1013
+ if ($[81] !== activity) {
1014
+ t25 = /* @__PURE__ */ jsxDEV(RecentActivityCard, {
1015
+ entries: activity
1016
+ }, void 0, false);
1017
+ $[81] = activity;
1018
+ $[82] = t25;
1019
+ } else {
1020
+ t25 = $[82];
1021
+ }
1022
+ let t26;
1023
+ if ($[83] !== t24 || $[84] !== t25) {
1024
+ t26 = /* @__PURE__ */ jsxDEV("div", {
1025
+ className: "flex flex-col gap-3",
1026
+ children: [t24, t25]
1027
+ }, void 0, true);
1028
+ $[83] = t24;
1029
+ $[84] = t25;
1030
+ $[85] = t26;
1031
+ } else {
1032
+ t26 = $[85];
1033
+ }
1034
+ let t27;
1035
+ if ($[86] !== t23 || $[87] !== t26) {
1036
+ t27 = /* @__PURE__ */ jsxDEV("div", {
1037
+ className: "grid gap-3 lg:grid-cols-3",
1038
+ children: [t23, t26]
1039
+ }, void 0, true);
1040
+ $[86] = t23;
1041
+ $[87] = t26;
1042
+ $[88] = t27;
1043
+ } else {
1044
+ t27 = $[88];
1045
+ }
1046
+ let t28;
1047
+ if ($[89] !== t) {
1048
+ t28 = t("Advisors");
1049
+ $[89] = t;
1050
+ $[90] = t28;
1051
+ } else {
1052
+ t28 = $[90];
1053
+ }
1054
+ let t29;
1055
+ if ($[91] !== t28) {
1056
+ t29 = /* @__PURE__ */ jsxDEV("h2", {
1057
+ className: "text-sm font-semibold tracking-tight text-foreground",
1058
+ children: t28
1059
+ }, void 0, false);
1060
+ $[91] = t28;
1061
+ $[92] = t29;
1062
+ } else {
1063
+ t29 = $[92];
1064
+ }
1065
+ let t30;
1066
+ if ($[93] !== performanceCount || $[94] !== securityCount || $[95] !== t || $[96] !== viewPerformance || $[97] !== viewSecurity) {
1067
+ t30 = securityCount === 0 && performanceCount === 0 ? /* @__PURE__ */ jsxDEV(EmptyState, {
1068
+ description: t("No security or performance issues detected."),
1069
+ icon: /* @__PURE__ */ jsxDEV("svg", {
1070
+ "aria-hidden": "true",
1071
+ fill: "none",
1072
+ stroke: "currentColor",
1073
+ strokeLinecap: "round",
1074
+ strokeLinejoin: "round",
1075
+ strokeWidth: 1.6,
1076
+ viewBox: "0 0 24 24",
1077
+ children: [/* @__PURE__ */ jsxDEV("path", {
1078
+ d: "M12 3 4 6v5c0 5 3.4 8.5 8 10 4.6-1.5 8-5 8-10V6l-8-3Z"
1079
+ }, void 0, false), /* @__PURE__ */ jsxDEV("path", {
1080
+ d: "m9 12 2 2 4-4"
1081
+ }, void 0, false)]
1082
+ }, void 0, true),
1083
+ testId: "home-advisors-clear",
1084
+ title: t("No issues found")
1085
+ }, void 0, false) : /* @__PURE__ */ jsxDEV("div", {
1086
+ className: "grid gap-3 sm:grid-cols-2",
1087
+ children: [/* @__PURE__ */ jsxDEV(AdvisorCard, {
1088
+ count: securityCount,
1089
+ onView: viewSecurity,
1090
+ testId: "home-security",
1091
+ title: t("Security findings")
1092
+ }, void 0, false), /* @__PURE__ */ jsxDEV(AdvisorCard, {
1093
+ count: performanceCount,
1094
+ onView: viewPerformance,
1095
+ testId: "home-performance",
1096
+ title: t("Performance issues")
1097
+ }, void 0, false)]
1098
+ }, void 0, true);
1099
+ $[93] = performanceCount;
1100
+ $[94] = securityCount;
1101
+ $[95] = t;
1102
+ $[96] = viewPerformance;
1103
+ $[97] = viewSecurity;
1104
+ $[98] = t30;
1105
+ } else {
1106
+ t30 = $[98];
1107
+ }
1108
+ let t31;
1109
+ if ($[99] !== t29 || $[100] !== t30) {
1110
+ t31 = /* @__PURE__ */ jsxDEV("section", {
1111
+ className: "flex flex-col gap-3",
1112
+ "data-testid": "home-advisors",
1113
+ children: [t29, t30]
1114
+ }, void 0, true);
1115
+ $[99] = t29;
1116
+ $[100] = t30;
1117
+ $[101] = t31;
1118
+ } else {
1119
+ t31 = $[101];
1120
+ }
1121
+ let t32;
1122
+ if ($[102] !== t) {
1123
+ t32 = t("Get connected");
1124
+ $[102] = t;
1125
+ $[103] = t32;
1126
+ } else {
1127
+ t32 = $[103];
1128
+ }
1129
+ let t33;
1130
+ if ($[104] !== t32) {
1131
+ t33 = /* @__PURE__ */ jsxDEV("h2", {
1132
+ className: "text-sm font-semibold tracking-tight text-foreground",
1133
+ children: t32
1134
+ }, void 0, false);
1135
+ $[104] = t32;
1136
+ $[105] = t33;
1137
+ } else {
1138
+ t33 = $[105];
1139
+ }
1140
+ let t34;
1141
+ if ($[106] !== t) {
1142
+ t34 = t("Client SDK");
1143
+ $[106] = t;
1144
+ $[107] = t34;
1145
+ } else {
1146
+ t34 = $[107];
1147
+ }
1148
+ let t35;
1149
+ if ($[108] !== t34) {
1150
+ t35 = /* @__PURE__ */ jsxDEV(ConnectCard, {
1151
+ command: "npm i @lunora/client",
1152
+ label: t34
1153
+ }, void 0, false);
1154
+ $[108] = t34;
1155
+ $[109] = t35;
1156
+ } else {
1157
+ t35 = $[109];
1158
+ }
1159
+ let t36;
1160
+ if ($[110] !== t) {
1161
+ t36 = t("React");
1162
+ $[110] = t;
1163
+ $[111] = t36;
1164
+ } else {
1165
+ t36 = $[111];
1166
+ }
1167
+ let t37;
1168
+ if ($[112] !== t36) {
1169
+ t37 = /* @__PURE__ */ jsxDEV(ConnectCard, {
1170
+ command: "npm i @lunora/react",
1171
+ label: t36
1172
+ }, void 0, false);
1173
+ $[112] = t36;
1174
+ $[113] = t37;
1175
+ } else {
1176
+ t37 = $[113];
1177
+ }
1178
+ let t38;
1179
+ if ($[114] !== t) {
1180
+ t38 = t("CLI");
1181
+ $[114] = t;
1182
+ $[115] = t38;
1183
+ } else {
1184
+ t38 = $[115];
1185
+ }
1186
+ let t39;
1187
+ if ($[116] !== t38) {
1188
+ t39 = /* @__PURE__ */ jsxDEV(ConnectCard, {
1189
+ command: "lunora dev",
1190
+ label: t38
1191
+ }, void 0, false);
1192
+ $[116] = t38;
1193
+ $[117] = t39;
1194
+ } else {
1195
+ t39 = $[117];
1196
+ }
1197
+ let t40;
1198
+ if ($[118] !== t35 || $[119] !== t37 || $[120] !== t39) {
1199
+ t40 = /* @__PURE__ */ jsxDEV("div", {
1200
+ className: "grid gap-3 sm:grid-cols-3",
1201
+ children: [t35, t37, t39]
1202
+ }, void 0, true);
1203
+ $[118] = t35;
1204
+ $[119] = t37;
1205
+ $[120] = t39;
1206
+ $[121] = t40;
1207
+ } else {
1208
+ t40 = $[121];
1209
+ }
1210
+ let t41;
1211
+ if ($[122] !== t33 || $[123] !== t40) {
1212
+ t41 = /* @__PURE__ */ jsxDEV("section", {
1213
+ className: "flex flex-col gap-3",
1214
+ "data-testid": "home-get-connected",
1215
+ children: [t33, t40]
1216
+ }, void 0, true);
1217
+ $[122] = t33;
1218
+ $[123] = t40;
1219
+ $[124] = t41;
1220
+ } else {
1221
+ t41 = $[124];
1222
+ }
1223
+ let t42;
1224
+ if ($[125] !== t14 || $[126] !== t15 || $[127] !== t22 || $[128] !== t27 || $[129] !== t31 || $[130] !== t41) {
1225
+ t42 = /* @__PURE__ */ jsxDEV("div", {
1226
+ className: t14,
1227
+ "data-testid": t15,
1228
+ children: [t22, t27, t31, t41]
1229
+ }, void 0, true);
1230
+ $[125] = t14;
1231
+ $[126] = t15;
1232
+ $[127] = t22;
1233
+ $[128] = t27;
1234
+ $[129] = t31;
1235
+ $[130] = t41;
1236
+ $[131] = t42;
1237
+ } else {
1238
+ t42 = $[131];
1239
+ }
1240
+ return t42;
1241
+ };
1242
+ function _temp(value, index) {
1243
+ return {
1244
+ index,
1245
+ value
1246
+ };
1247
+ }
1248
+ function _temp2(a, b) {
1249
+ return b.calls - a.calls;
1250
+ }
1251
+ function _temp3(function_) {
1252
+ return /* @__PURE__ */ jsxDEV("div", {
1253
+ className: "grid grid-cols-[1fr_auto_auto_auto] items-center gap-4 px-4 py-2 text-[13px]",
1254
+ children: [/* @__PURE__ */ jsxDEV("span", {
1255
+ className: "truncate font-mono text-xs text-foreground",
1256
+ children: function_.path
1257
+ }, void 0, false), /* @__PURE__ */ jsxDEV("span", {
1258
+ className: "text-end tabular-nums",
1259
+ children: function_.calls.toLocaleString()
1260
+ }, void 0, false), /* @__PURE__ */ jsxDEV("span", {
1261
+ className: "w-12 text-end tabular-nums text-muted-foreground",
1262
+ children: formatMs(function_.calls > 0 ? function_.totalDurationMs / function_.calls : 0)
1263
+ }, void 0, false), /* @__PURE__ */ jsxDEV("span", {
1264
+ className: cn("w-8 text-end tabular-nums", function_.errors > 0 ? "text-destructive" : "text-muted-foreground"),
1265
+ children: function_.errors
1266
+ }, void 0, false)]
1267
+ }, function_.path, true);
1268
+ }
1269
+ function _temp4(function_) {
1270
+ return function_.maxDurationMs;
1271
+ }
1272
+
1273
+ export { HomePanel };