@lunora/studio 1.0.0-alpha.4 → 1.0.0-alpha.40

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 (187) hide show
  1. package/LICENSE.md +6 -0
  2. package/__assets__/package-og.svg +1 -1
  3. package/dist/index.d.ts +33 -18
  4. package/dist/index.js +29 -29
  5. package/dist/mount.d.ts +1 -1
  6. package/dist/mount.js +3 -2
  7. package/dist/{packem_shared/ApiTab-W3no0KOj.js → packem_chunks/ApiTab.js} +5 -5
  8. package/dist/{packem_shared/AuditPanel-Bq4o_IqT.js → packem_chunks/AuditPanel.js} +29 -41
  9. package/dist/{packem_shared/ExportImportPanel-dxY56TDF.js → packem_chunks/ExportImportPanel.js} +16 -11
  10. package/dist/{packem_shared/FileBrowser-Dhy4zES8.js → packem_chunks/FileBrowser.js} +15 -15
  11. package/dist/{packem_shared/FunctionRunner--fQJRPAD.js → packem_chunks/FunctionRunner.js} +10 -10
  12. package/dist/{packem_shared/FunctionStatsPanel-BjRUA_G3.js → packem_chunks/FunctionStatsPanel.js} +153 -208
  13. package/dist/{packem_shared/HealthPanel-PxclMWmA.js → packem_chunks/HealthPanel.js} +37 -29
  14. package/dist/{packem_shared/InsightsPanel-CWS_C-xW.js → packem_chunks/InsightsPanel.js} +108 -69
  15. package/dist/{packem_shared/LogsPanel-CTW8CFcM.js → packem_chunks/LogsPanel.js} +46 -58
  16. package/dist/{packem_shared/MailPanel-BwkvfIHF.js → packem_chunks/MailPanel.js} +45 -139
  17. package/dist/{packem_shared/MetricsPanel-BLuOhZQ4.js → packem_chunks/MetricsPanel.js} +41 -322
  18. package/dist/{packem_shared/MigrationsPanel-DT3lnwHF.js → packem_chunks/MigrationsPanel.js} +44 -51
  19. package/dist/{packem_shared/PitrPanel-CdErL7EJ.js → packem_chunks/PitrPanel.js} +9 -9
  20. package/dist/{packem_shared/SchemaViewer-LJDcmNIO.js → packem_chunks/SchemaViewer.js} +17 -16
  21. package/dist/{packem_shared/SecurityAdvisorPanel-C_ETsPih.js → packem_chunks/SecurityAdvisorPanel.js} +47 -31
  22. package/dist/packem_chunks/SettingsPanel.js +391 -0
  23. package/dist/{packem_shared/sql-editor-panel-BFRpzj6r.js → packem_chunks/SqlEditorPanel.js} +158 -387
  24. package/dist/{packem_shared/TableEditor-ChfUOZec.js → packem_chunks/TableEditor.js} +10 -68
  25. package/dist/packem_chunks/analytics-panel.js +261 -0
  26. package/dist/packem_chunks/auth-config-panel.js +365 -0
  27. package/dist/packem_chunks/auth-sessions-panel.js +175 -0
  28. package/dist/packem_chunks/containers-panel.js +247 -0
  29. package/dist/packem_chunks/dashboards-panel.js +780 -0
  30. package/dist/packem_chunks/fanout-panel.js +482 -0
  31. package/dist/packem_chunks/flags-panel.js +176 -0
  32. package/dist/packem_chunks/kv-browser.js +1896 -0
  33. package/dist/packem_chunks/log-drains-panel.js +273 -0
  34. package/dist/packem_chunks/organizations-panel.js +3178 -0
  35. package/dist/packem_chunks/payments-panel.js +186 -0
  36. package/dist/packem_chunks/permissions-panel.js +805 -0
  37. package/dist/packem_chunks/queues-panel.js +1075 -0
  38. package/dist/packem_chunks/rls-panel.js +315 -0
  39. package/dist/packem_chunks/schedule-panel.js +831 -0
  40. package/dist/packem_chunks/sparkline.js +79 -0
  41. package/dist/packem_chunks/storage-rules-panel.js +140 -0
  42. package/dist/packem_chunks/subscriptions-panel.js +238 -0
  43. package/dist/packem_chunks/users-panel.js +1731 -0
  44. package/dist/packem_chunks/vector-browser.js +281 -0
  45. package/dist/packem_chunks/workflows-panel.js +562 -0
  46. package/dist/packem_shared/{ADMIN_FUNCTIONS-DmBqMZ-z.js → ADMIN_FUNCTIONS-BHHJi3Gb.js} +7 -0
  47. package/dist/packem_shared/{ApiDocsPanel-C5-yJ1p7.js → ApiDocsPanel-CBma-lnp.js} +2 -2
  48. package/dist/packem_shared/{ApiReferencePanel-1vubqG5s.js → ApiReferencePanel-CQM3pPN7.js} +2 -1
  49. package/dist/packem_shared/{CommandPalette-BtgkBzZI.js → CommandPalette-X2tkbyHk.js} +1 -1
  50. package/dist/packem_shared/{DataBrowser-CtBe1So9.js → DataBrowser-D2ywrdId.js} +198 -247
  51. package/dist/packem_shared/{GlobalDataBrowser-BTEmGrph.js → GlobalDataBrowser-BkTPLzAY.js} +37 -66
  52. package/dist/packem_shared/HomePanel-D1Q9LZgK.js +14 -0
  53. package/dist/packem_shared/{OpenRpcReferencePanel-vbcYbv3V.js → OpenRpcReferencePanel-Dno-hfDb.js} +2 -1
  54. package/dist/packem_shared/{ScheduledJobs-CabfKbyM.js → ScheduledJobs-Ctw4jYtU.js} +163 -60
  55. package/dist/packem_shared/Studio-lJhzDAze.js +16 -0
  56. package/dist/packem_shared/{StudioApp-CHOZA-z-.js → StudioApp-DiMkupvZ.js} +276 -11
  57. package/dist/packem_shared/{advisor-view-CGcfMiPq.js → advisor-view-BX8OhG0w.js} +6 -6
  58. package/dist/packem_shared/alert-CdAET2K_.js +68 -0
  59. package/dist/packem_shared/{app.d-CCmwDEVs.d.ts → app.d-CNLRTrWw.d.ts} +1 -1
  60. package/dist/packem_shared/{bar-chart-CzJAgqkp.js → bar-chart-DSwcWIRy.js} +5 -4
  61. package/dist/packem_shared/browser-storage-BTrX4y3B.js +215 -0
  62. package/dist/packem_shared/{cf-links-2cktDedA.js → cf-links-BZfRdxSE.js} +1 -1
  63. package/dist/packem_shared/{data-grid-B5CaV3wS.js → data-grid-CdXztApG.js} +1 -1
  64. package/dist/packem_shared/data-view-params-Cd6yRVbv.js +96 -0
  65. package/dist/packem_shared/error-alert-CXjqyGw9.js +114 -0
  66. package/dist/packem_shared/{grid-features-CzUfqgsM.js → grid-features-BF-KBDFz.js} +131 -163
  67. package/dist/packem_shared/home-panel-TFcRf9Ui.js +1889 -0
  68. package/dist/packem_shared/{internal-rXJEAhXS.js → internal-CYcbqMjX.js} +44 -3
  69. package/dist/packem_shared/modal-shell-hyaJvIJ6.js +100 -0
  70. package/dist/packem_shared/{reference-view-B4E49Lip.js → reference-view-DUiJcILV.js} +6 -45
  71. package/dist/packem_shared/scroll-area-DLhcy-ml.js +93 -0
  72. package/dist/packem_shared/select-UkNYCT3s.js +273 -0
  73. package/dist/packem_shared/skeleton-CGhL0p20.js +45 -0
  74. package/dist/packem_shared/{sparkline-10dG-_f0.js → sparkline-BnA1kC9X.js} +1 -1
  75. package/dist/packem_shared/studio-Dh9UlaF_.js +4015 -0
  76. package/dist/packem_shared/{table-_RzNvy3R.js → table-DsCa9Qp9.js} +1 -1
  77. package/dist/packem_shared/{table-list-sidebar-Bg7uzbvC.js → table-list-sidebar-UVIXQJdU.js} +1 -1
  78. package/dist/packem_shared/use-admin-query-CfHYWx5n.js +106 -0
  79. package/dist/packem_shared/use-async-submit-DJQiPc-_.js +91 -0
  80. package/dist/standalone/chunk-23C4TCRO.js +1 -0
  81. package/dist/standalone/chunk-2K47A3P6.js +1 -0
  82. package/dist/standalone/chunk-2NGUNNGW.js +1 -0
  83. package/dist/standalone/chunk-3CJW6NWG.js +4 -0
  84. package/dist/standalone/chunk-3OA7PECS.js +6 -0
  85. package/dist/standalone/chunk-4QHKBC77.js +1 -0
  86. package/dist/standalone/chunk-5OIBXYZM.js +1 -0
  87. package/dist/standalone/chunk-5ZAA2PVR.js +1 -0
  88. package/dist/standalone/chunk-676HEBIR.js +3 -0
  89. package/dist/standalone/chunk-6VO23MMW.js +4 -0
  90. package/dist/standalone/chunk-7RE5UW27.js +8 -0
  91. package/dist/standalone/chunk-7TJJXVSE.js +1 -0
  92. package/dist/standalone/chunk-7YXOPTWI.js +1 -0
  93. package/dist/standalone/chunk-AAVIFQ4Y.js +2 -0
  94. package/dist/standalone/chunk-AHILM3ZP.js +1 -0
  95. package/dist/standalone/chunk-AJFQ3LNM.js +1 -0
  96. package/dist/standalone/chunk-AJULNB46.js +4 -0
  97. package/dist/standalone/chunk-BGXOXASQ.js +1 -0
  98. package/dist/standalone/chunk-BJGBHGK3.js +1 -0
  99. package/dist/standalone/chunk-BKW7FFEO.js +1 -0
  100. package/dist/standalone/chunk-BOXSWNXZ.js +1 -0
  101. package/dist/standalone/chunk-BXOYVWJR.js +13 -0
  102. package/dist/standalone/chunk-C7WTJLC3.js +1 -0
  103. package/dist/standalone/chunk-CACB34RQ.js +1 -0
  104. package/dist/standalone/chunk-CICVBMEN.js +1 -0
  105. package/dist/standalone/chunk-CKSHCYGC.js +2 -0
  106. package/dist/standalone/chunk-CWEAJUHW.js +1 -0
  107. package/dist/standalone/chunk-DC72CQY4.js +76 -0
  108. package/dist/standalone/chunk-DECHEGIC.js +1 -0
  109. package/dist/standalone/chunk-DWDILV2E.js +1 -0
  110. package/dist/standalone/chunk-E75ANNWX.js +19 -0
  111. package/dist/standalone/chunk-ERJNDIXC.js +1 -0
  112. package/dist/standalone/chunk-FKACHRWO.js +1 -0
  113. package/dist/standalone/chunk-FSGCANAU.js +1 -0
  114. package/dist/standalone/chunk-GLUNBZRI.js +1 -0
  115. package/dist/standalone/chunk-GMSGZDDH.js +13 -0
  116. package/dist/standalone/chunk-GTM65MVX.js +1 -0
  117. package/dist/standalone/chunk-H6RKXQZU.js +1 -0
  118. package/dist/standalone/chunk-HV7G6DFP.js +5 -0
  119. package/dist/standalone/chunk-HZTGDL4L.js +1 -0
  120. package/dist/standalone/chunk-I7ZZRM7I.js +1 -0
  121. package/dist/standalone/chunk-IXDH4GL5.js +1 -0
  122. package/dist/standalone/chunk-J46WXQYL.js +1 -0
  123. package/dist/standalone/chunk-J6J54MBP.js +1 -0
  124. package/dist/standalone/chunk-JSEXCW5Q.js +1 -0
  125. package/dist/standalone/chunk-JVODY4EP.js +1 -0
  126. package/dist/standalone/chunk-KEGAWN6Y.js +1 -0
  127. package/dist/standalone/chunk-KJJ3WM6H.js +4 -0
  128. package/dist/standalone/chunk-KSKXW5PX.js +1 -0
  129. package/dist/standalone/chunk-KZ6INM5M.js +1 -0
  130. package/dist/standalone/chunk-L7SK4ZZD.js +1 -0
  131. package/dist/standalone/chunk-LAK5VSPI.js +1 -0
  132. package/dist/standalone/chunk-LNZIB2MD.js +1 -0
  133. package/dist/standalone/chunk-LYB5L53X.js +1 -0
  134. package/dist/standalone/chunk-MJWVMKQ4.js +6 -0
  135. package/dist/standalone/chunk-MT2J3H7O.js +3 -0
  136. package/dist/standalone/chunk-N746FOQP.js +1 -0
  137. package/dist/standalone/chunk-NC6MBMSI.js +1 -0
  138. package/dist/standalone/chunk-NN27EDQB.js +1 -0
  139. package/dist/standalone/chunk-NY6GDADQ.js +1 -0
  140. package/dist/standalone/chunk-O3NAGRTR.js +1 -0
  141. package/dist/standalone/chunk-OY3HD7BJ.js +4 -0
  142. package/dist/standalone/chunk-P5HJXCZS.js +1 -0
  143. package/dist/standalone/chunk-PTS5TW3J.js +1 -0
  144. package/dist/standalone/chunk-Q52CHOSY.js +1 -0
  145. package/dist/standalone/chunk-QAFAJBAW.js +1 -0
  146. package/dist/standalone/chunk-QBAT52GB.js +1 -0
  147. package/dist/standalone/chunk-QDBOPDJ7.js +1 -0
  148. package/dist/standalone/chunk-QHFTGJPS.js +4 -0
  149. package/dist/standalone/chunk-RRCPZMC2.js +22 -0
  150. package/dist/standalone/chunk-SEU5V7I6.js +1 -0
  151. package/dist/standalone/chunk-SG3ALJJU.js +1 -0
  152. package/dist/standalone/chunk-SSI4G2MY.js +1 -0
  153. package/dist/standalone/chunk-TAD43CG5.js +1 -0
  154. package/dist/standalone/chunk-TBMYIZIO.js +1 -0
  155. package/dist/standalone/chunk-TH45YG6Q.js +1 -0
  156. package/dist/standalone/chunk-TQ36RWOP.js +1 -0
  157. package/dist/standalone/chunk-UGUEC6BC.js +1 -0
  158. package/dist/standalone/chunk-UK64ZSUW.js +1 -0
  159. package/dist/standalone/chunk-UKDJ4H7I.js +1 -0
  160. package/dist/standalone/chunk-V6IWFYAQ.js +1 -0
  161. package/dist/standalone/chunk-V7SRH36W.js +1 -0
  162. package/dist/standalone/chunk-VLXV72QE.js +1 -0
  163. package/dist/standalone/chunk-VON7JUPG.js +1 -0
  164. package/dist/standalone/chunk-WI7GWFEG.js +1 -0
  165. package/dist/standalone/chunk-WPNXY7IS.js +1 -0
  166. package/dist/standalone/chunk-X33MSJPP.js +1 -0
  167. package/dist/standalone/chunk-XNJNSCLM.js +1 -0
  168. package/dist/standalone/chunk-XRNXOIVZ.js +1 -0
  169. package/dist/standalone/chunk-YAECF5LW.js +1 -0
  170. package/dist/standalone/chunk-YBGC4PPD.js +1 -0
  171. package/dist/standalone/chunk-YNZ7ARWW.js +1 -0
  172. package/dist/standalone/chunk-YTO65GHS.js +1 -0
  173. package/dist/standalone/chunk-ZE6FT5Z3.js +1 -0
  174. package/dist/standalone/chunk-ZHVTQ37P.js +1 -0
  175. package/dist/standalone/chunk-ZIGWVHCS.js +1 -0
  176. package/dist/standalone/chunk-ZPP2KOR4.js +1 -0
  177. package/dist/standalone/chunk-ZPUO7FNI.js +1 -0
  178. package/dist/standalone/studio.js +104 -246
  179. package/dist/styles.css +2 -2
  180. package/package.json +15 -13
  181. package/dist/packem_shared/HomePanel-Cw16stjq.js +0 -1273
  182. package/dist/packem_shared/SettingsPanel-C0uLRf5P.js +0 -176
  183. package/dist/packem_shared/SqlEditorPanel-CguV7otm.js +0 -13
  184. package/dist/packem_shared/Studio-DFWAlcuf.js +0 -33
  185. package/dist/packem_shared/studio-Bj8psK1c.js +0 -10303
  186. package/dist/packem_shared/use-live-admin-Dq6g3daN.js +0 -73
  187. package/dist/packem_shared/use-live-shard-seed-Cuk3dnH0.js +0 -76
@@ -0,0 +1,1889 @@
1
+ import { c } from 'react/compiler-runtime';
2
+ import { useNavigate } from '@tanstack/react-router';
3
+ import { useState, useEffect, Suspense, lazy } from 'react';
4
+ import { B as Badge } from './badge-B2PKA1-5.js';
5
+ import { a as CardContent, C as Card } from './card-DURq3ElK.js';
6
+ import { E as EmptyState } from './empty-state-DY_oe0k6.js';
7
+ import { u as useAdminQuery } from './use-admin-query-CfHYWx5n.js';
8
+ import { useT } from './DEFAULT_LOCALE-CiX4W7Kr.js';
9
+ import { ADMIN_FUNCTIONS } from './ADMIN_FUNCTIONS-BHHJi3Gb.js';
10
+ import { f as fireAndForget, c as callOptions, a as adminRef, r as resolveOrigin, g as copyToClipboard, j as formatBytes } from './internal-CYcbqMjX.js';
11
+ import { c as cn } from './utils-B05Dmz_H.js';
12
+ import { deriveInsights } from './DEFAULT_INSIGHT_THRESHOLDS-DjF0h-gA.js';
13
+ import { useLunora } from '@lunora/react';
14
+ import { jsxDEV } from 'react/jsx-dev-runtime';
15
+ import { B as Button } from './button-BhsN2uZH.js';
16
+
17
+ const STUDIO_FEATURES = adminRef(ADMIN_FUNCTIONS.studioFeatures);
18
+ const DEFAULT_STUDIO_FEATURES = {
19
+ analytics: true,
20
+ auth: true,
21
+ containers: true,
22
+ flags: true,
23
+ kv: true,
24
+ mail: true,
25
+ payments: true,
26
+ queues: true,
27
+ scheduler: true,
28
+ storage: true,
29
+ vectors: true,
30
+ workflows: true
31
+ };
32
+ const coerceFeatures = (raw) => {
33
+ if (raw === null || typeof raw !== "object") {
34
+ return DEFAULT_STUDIO_FEATURES;
35
+ }
36
+ const record = raw;
37
+ const flag = (key) => typeof record[key] === "boolean" ? record[key] : true;
38
+ return {
39
+ analytics: flag("analytics"),
40
+ auth: flag("auth"),
41
+ containers: flag("containers"),
42
+ flags: flag("flags"),
43
+ kv: flag("kv"),
44
+ mail: flag("mail"),
45
+ payments: flag("payments"),
46
+ queues: flag("queues"),
47
+ scheduler: flag("scheduler"),
48
+ storage: flag("storage"),
49
+ vectors: flag("vectors"),
50
+ workflows: flag("workflows")
51
+ };
52
+ };
53
+ const useStudioFeatures = () => {
54
+ const $ = c(3);
55
+ const client = useLunora();
56
+ const [features, setFeatures] = useState(DEFAULT_STUDIO_FEATURES);
57
+ let t0;
58
+ let t1;
59
+ if ($[0] !== client) {
60
+ t0 = () => {
61
+ fireAndForget((async () => {
62
+ try {
63
+ setFeatures(coerceFeatures(await client.query(STUDIO_FEATURES, {}, callOptions(""))));
64
+ } catch {
65
+ }
66
+ })());
67
+ };
68
+ t1 = [client];
69
+ $[0] = client;
70
+ $[1] = t0;
71
+ $[2] = t1;
72
+ } else {
73
+ t0 = $[1];
74
+ t1 = $[2];
75
+ }
76
+ useEffect(t0, t1);
77
+ return features;
78
+ };
79
+
80
+ const ChevronRight$1 = () => {
81
+ const $ = c(1);
82
+ let t0;
83
+ if ($[0] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
84
+ t0 = /* @__PURE__ */ jsxDEV("svg", {
85
+ "aria-hidden": "true",
86
+ className: "size-4 text-muted-foreground",
87
+ fill: "none",
88
+ stroke: "currentColor",
89
+ strokeWidth: 1.6,
90
+ viewBox: "0 0 24 24",
91
+ children: /* @__PURE__ */ jsxDEV("path", {
92
+ d: "m9 6 6 6-6 6",
93
+ strokeLinecap: "round",
94
+ strokeLinejoin: "round"
95
+ }, void 0, false)
96
+ }, void 0, false);
97
+ $[0] = t0;
98
+ } else {
99
+ t0 = $[0];
100
+ }
101
+ return t0;
102
+ };
103
+ const BindingCard = (t0) => {
104
+ const $ = c(24);
105
+ const {
106
+ group
107
+ } = t0;
108
+ const t = useT();
109
+ const navigate = useNavigate();
110
+ let t1;
111
+ if ($[0] !== group.tab || $[1] !== navigate) {
112
+ t1 = () => {
113
+ fireAndForget(navigate({
114
+ to: `/${group.tab}`
115
+ }));
116
+ };
117
+ $[0] = group.tab;
118
+ $[1] = navigate;
119
+ $[2] = t1;
120
+ } else {
121
+ t1 = $[2];
122
+ }
123
+ const onOpen = t1;
124
+ const count = group.bindings.length;
125
+ let t2;
126
+ if ($[3] !== group.label) {
127
+ t2 = /* @__PURE__ */ jsxDEV("span", {
128
+ className: "text-sm font-medium text-foreground",
129
+ children: group.label
130
+ }, void 0, false);
131
+ $[3] = group.label;
132
+ $[4] = t2;
133
+ } else {
134
+ t2 = $[4];
135
+ }
136
+ let t3;
137
+ if ($[5] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
138
+ t3 = /* @__PURE__ */ jsxDEV(ChevronRight$1, {}, void 0, false);
139
+ $[5] = t3;
140
+ } else {
141
+ t3 = $[5];
142
+ }
143
+ let t4;
144
+ if ($[6] !== t2) {
145
+ t4 = /* @__PURE__ */ jsxDEV("div", {
146
+ className: "flex items-center justify-between",
147
+ children: [t2, t3]
148
+ }, void 0, true);
149
+ $[6] = t2;
150
+ $[7] = t4;
151
+ } else {
152
+ t4 = $[7];
153
+ }
154
+ let t5;
155
+ if ($[8] !== count || $[9] !== t) {
156
+ t5 = count === 1 ? t("1 binding") : t("{count} bindings", {
157
+ count
158
+ });
159
+ $[8] = count;
160
+ $[9] = t;
161
+ $[10] = t5;
162
+ } else {
163
+ t5 = $[10];
164
+ }
165
+ let t6;
166
+ if ($[11] !== t5) {
167
+ t6 = /* @__PURE__ */ jsxDEV("span", {
168
+ className: "text-xs text-muted-foreground",
169
+ children: t5
170
+ }, void 0, false);
171
+ $[11] = t5;
172
+ $[12] = t6;
173
+ } else {
174
+ t6 = $[12];
175
+ }
176
+ let t7;
177
+ if ($[13] !== count || $[14] !== group.bindings) {
178
+ t7 = count > 0 && /* @__PURE__ */ jsxDEV("div", {
179
+ className: "flex flex-wrap gap-1.5",
180
+ children: group.bindings.map(_temp$1)
181
+ }, void 0, false);
182
+ $[13] = count;
183
+ $[14] = group.bindings;
184
+ $[15] = t7;
185
+ } else {
186
+ t7 = $[15];
187
+ }
188
+ let t8;
189
+ if ($[16] !== t4 || $[17] !== t6 || $[18] !== t7) {
190
+ t8 = /* @__PURE__ */ jsxDEV(CardContent, {
191
+ className: "flex flex-col gap-2 py-4",
192
+ children: [t4, t6, t7]
193
+ }, void 0, true);
194
+ $[16] = t4;
195
+ $[17] = t6;
196
+ $[18] = t7;
197
+ $[19] = t8;
198
+ } else {
199
+ t8 = $[19];
200
+ }
201
+ let t9;
202
+ if ($[20] !== group.testId || $[21] !== onOpen || $[22] !== t8) {
203
+ t9 = /* @__PURE__ */ jsxDEV(Card, {
204
+ className: "cursor-pointer gap-0 py-0 transition-colors hover:bg-muted/40",
205
+ "data-testid": group.testId,
206
+ onClick: onOpen,
207
+ children: t8
208
+ }, void 0, false);
209
+ $[20] = group.testId;
210
+ $[21] = onOpen;
211
+ $[22] = t8;
212
+ $[23] = t9;
213
+ } else {
214
+ t9 = $[23];
215
+ }
216
+ return t9;
217
+ };
218
+ const TAB_ORDER = ["kv", "files", "vectors"];
219
+ const upsertCard = (current, card) => [...current.filter((group) => group.tab !== card.tab), card].toSorted((a, b) => TAB_ORDER.indexOf(a.tab) - TAB_ORDER.indexOf(b.tab));
220
+ const BindingsOverview = () => {
221
+ const $ = c(19);
222
+ const client = useLunora();
223
+ const features = useStudioFeatures();
224
+ const t = useT();
225
+ let t0;
226
+ if ($[0] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
227
+ t0 = [];
228
+ $[0] = t0;
229
+ } else {
230
+ t0 = $[0];
231
+ }
232
+ const [groups, setGroups] = useState(t0);
233
+ let t1;
234
+ let t2;
235
+ if ($[1] !== client || $[2] !== features.kv || $[3] !== features.storage || $[4] !== features.vectors || $[5] !== t) {
236
+ t1 = () => {
237
+ const token = {
238
+ cancelled: false
239
+ };
240
+ const sources = [{
241
+ enabled: features.kv,
242
+ label: t("KV Namespaces"),
243
+ load: async () => {
244
+ const namespaces = await client.listKvNamespaces();
245
+ return namespaces.map(_temp2$1);
246
+ },
247
+ tab: "kv",
248
+ testId: "home-binding-kv"
249
+ }, {
250
+ enabled: features.storage,
251
+ label: t("R2 Buckets"),
252
+ load: () => client.listStorageBuckets(),
253
+ tab: "files",
254
+ testId: "home-binding-r2"
255
+ }, {
256
+ enabled: features.vectors,
257
+ label: t("Vectorize Indexes"),
258
+ load: async () => {
259
+ const indexes = await client.listVectorIndexes();
260
+ return indexes.map(_temp3$1);
261
+ },
262
+ tab: "vectors",
263
+ testId: "home-binding-vectors"
264
+ }];
265
+ for (const source of sources) {
266
+ if (!source.enabled) {
267
+ continue;
268
+ }
269
+ fireAndForget((async () => {
270
+ try {
271
+ const bindings = await source.load();
272
+ if (!token.cancelled) {
273
+ const card = {
274
+ bindings,
275
+ label: source.label,
276
+ tab: source.tab,
277
+ testId: source.testId
278
+ };
279
+ setGroups((current) => upsertCard(current, card));
280
+ }
281
+ } catch {
282
+ }
283
+ })());
284
+ }
285
+ return () => {
286
+ token.cancelled = true;
287
+ };
288
+ };
289
+ t2 = [client, features.kv, features.storage, features.vectors, t];
290
+ $[1] = client;
291
+ $[2] = features.kv;
292
+ $[3] = features.storage;
293
+ $[4] = features.vectors;
294
+ $[5] = t;
295
+ $[6] = t1;
296
+ $[7] = t2;
297
+ } else {
298
+ t1 = $[6];
299
+ t2 = $[7];
300
+ }
301
+ useEffect(t1, t2);
302
+ if (groups.length === 0) {
303
+ return null;
304
+ }
305
+ let t3;
306
+ if ($[8] !== t) {
307
+ t3 = t("Bindings");
308
+ $[8] = t;
309
+ $[9] = t3;
310
+ } else {
311
+ t3 = $[9];
312
+ }
313
+ let t4;
314
+ if ($[10] !== t3) {
315
+ t4 = /* @__PURE__ */ jsxDEV("h2", {
316
+ className: "text-sm font-semibold tracking-tight text-foreground",
317
+ children: t3
318
+ }, void 0, false);
319
+ $[10] = t3;
320
+ $[11] = t4;
321
+ } else {
322
+ t4 = $[11];
323
+ }
324
+ let t5;
325
+ if ($[12] !== groups) {
326
+ t5 = groups.map(_temp4);
327
+ $[12] = groups;
328
+ $[13] = t5;
329
+ } else {
330
+ t5 = $[13];
331
+ }
332
+ let t6;
333
+ if ($[14] !== t5) {
334
+ t6 = /* @__PURE__ */ jsxDEV("div", {
335
+ className: "grid gap-3 sm:grid-cols-2 lg:grid-cols-3",
336
+ children: t5
337
+ }, void 0, false);
338
+ $[14] = t5;
339
+ $[15] = t6;
340
+ } else {
341
+ t6 = $[15];
342
+ }
343
+ let t7;
344
+ if ($[16] !== t4 || $[17] !== t6) {
345
+ t7 = /* @__PURE__ */ jsxDEV("section", {
346
+ className: "flex flex-col gap-3",
347
+ "data-testid": "home-bindings",
348
+ children: [t4, t6]
349
+ }, void 0, true);
350
+ $[16] = t4;
351
+ $[17] = t6;
352
+ $[18] = t7;
353
+ } else {
354
+ t7 = $[18];
355
+ }
356
+ return t7;
357
+ };
358
+ function _temp$1(binding) {
359
+ return /* @__PURE__ */ jsxDEV(Badge, {
360
+ variant: "secondary",
361
+ children: binding
362
+ }, binding, false);
363
+ }
364
+ function _temp2$1(ns) {
365
+ return ns.binding;
366
+ }
367
+ function _temp3$1(index) {
368
+ return index.name;
369
+ }
370
+ function _temp4(group) {
371
+ return /* @__PURE__ */ jsxDEV(BindingCard, {
372
+ group
373
+ }, group.tab, false);
374
+ }
375
+
376
+ const MCP_TOOLS = [{
377
+ name: "lunora_list_functions",
378
+ summary: "list every query, mutation, and action with its path"
379
+ }, {
380
+ name: "lunora_list_tables",
381
+ summary: "list the schema's tables"
382
+ }, {
383
+ name: "lunora_get_function_schema",
384
+ summary: "read a function's argument JSON Schema before calling it"
385
+ }, {
386
+ name: "lunora_run_query",
387
+ summary: "run a read-only query"
388
+ }, {
389
+ name: "lunora_run_mutation",
390
+ summary: "run a mutation — writes; only when LUNORA_MCP_ALLOW_WRITES is set"
391
+ }, {
392
+ name: "lunora_run_action",
393
+ summary: "run an action — writes/effects; only when LUNORA_MCP_ALLOW_WRITES is set"
394
+ }];
395
+ const buildMcpConfig = (origin) => JSON.stringify({
396
+ mcpServers: {
397
+ lunora: {
398
+ args: ["-y", "@lunora/mcp"],
399
+ command: "npx",
400
+ env: {
401
+ LUNORA_ADMIN_TOKEN: "<your-admin-token>",
402
+ LUNORA_URL: origin
403
+ }
404
+ }
405
+ }
406
+ }, null, 2);
407
+ const buildAgentPrompt = (origin) => {
408
+ const tools = MCP_TOOLS.map((tool) => `- ${tool.name} — ${tool.summary}`).join("\n");
409
+ return [`You have a Lunora MCP server connected to the deployment at ${origin}.`, "It exposes this backend's functions and schema so you can inspect and operate it:", tools, "", `Start by calling lunora_list_functions and lunora_list_tables to learn what exists, then lunora_get_function_schema before any run call. The full HTTP API is also documented at ${origin}/_lunora/admin/openapi (that endpoint needs the same admin token the MCP server is configured with).`].join("\n");
410
+ };
411
+ const COPIED_RESET_MS = 1500;
412
+ const ConnectAgentCard = () => {
413
+ const $ = c(35);
414
+ const t = useT();
415
+ let t0;
416
+ if ($[0] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
417
+ t0 = resolveOrigin();
418
+ $[0] = t0;
419
+ } else {
420
+ t0 = $[0];
421
+ }
422
+ const origin = t0;
423
+ const [copied, setCopied] = useState(null);
424
+ let t1;
425
+ let t2;
426
+ if ($[1] !== copied) {
427
+ t1 = () => {
428
+ if (copied === null) {
429
+ return;
430
+ }
431
+ const timer = globalThis.setTimeout(() => {
432
+ setCopied(null);
433
+ }, COPIED_RESET_MS);
434
+ return () => {
435
+ globalThis.clearTimeout(timer);
436
+ };
437
+ };
438
+ t2 = [copied];
439
+ $[1] = copied;
440
+ $[2] = t1;
441
+ $[3] = t2;
442
+ } else {
443
+ t1 = $[2];
444
+ t2 = $[3];
445
+ }
446
+ useEffect(t1, t2);
447
+ let t3;
448
+ if ($[4] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
449
+ t3 = (target, text) => {
450
+ if (!copyToClipboard(text)) {
451
+ return;
452
+ }
453
+ setCopied(target);
454
+ };
455
+ $[4] = t3;
456
+ } else {
457
+ t3 = $[4];
458
+ }
459
+ const copy = t3;
460
+ let t4;
461
+ if ($[5] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
462
+ t4 = () => {
463
+ copy("config", buildMcpConfig(origin));
464
+ };
465
+ $[5] = t4;
466
+ } else {
467
+ t4 = $[5];
468
+ }
469
+ const onCopyConfig = t4;
470
+ let t5;
471
+ if ($[6] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
472
+ t5 = () => {
473
+ copy("prompt", buildAgentPrompt(origin));
474
+ };
475
+ $[6] = t5;
476
+ } else {
477
+ t5 = $[6];
478
+ }
479
+ const onCopyPrompt = t5;
480
+ let t6;
481
+ if ($[7] !== t) {
482
+ t6 = t("Connect an AI agent");
483
+ $[7] = t;
484
+ $[8] = t6;
485
+ } else {
486
+ t6 = $[8];
487
+ }
488
+ let t7;
489
+ if ($[9] !== t6) {
490
+ t7 = /* @__PURE__ */ jsxDEV("span", {
491
+ className: "text-sm font-medium text-foreground",
492
+ children: t6
493
+ }, void 0, false);
494
+ $[9] = t6;
495
+ $[10] = t7;
496
+ } else {
497
+ t7 = $[10];
498
+ }
499
+ let t8;
500
+ if ($[11] !== t) {
501
+ t8 = t("Drive this deployment from an AI agent over the Model Context Protocol — it can list functions and tables, read schemas, and run read-only queries. Writes stay off unless you opt in.");
502
+ $[11] = t;
503
+ $[12] = t8;
504
+ } else {
505
+ t8 = $[12];
506
+ }
507
+ let t9;
508
+ if ($[13] !== t8) {
509
+ t9 = /* @__PURE__ */ jsxDEV("span", {
510
+ className: "text-xs text-muted-foreground",
511
+ children: t8
512
+ }, void 0, false);
513
+ $[13] = t8;
514
+ $[14] = t9;
515
+ } else {
516
+ t9 = $[14];
517
+ }
518
+ let t10;
519
+ if ($[15] !== t7 || $[16] !== t9) {
520
+ t10 = /* @__PURE__ */ jsxDEV("div", {
521
+ className: "flex flex-col gap-1.5 p-4",
522
+ children: [t7, t9]
523
+ }, void 0, true);
524
+ $[15] = t7;
525
+ $[16] = t9;
526
+ $[17] = t10;
527
+ } else {
528
+ t10 = $[17];
529
+ }
530
+ let t11;
531
+ if ($[18] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
532
+ t11 = /* @__PURE__ */ jsxDEV("code", {
533
+ className: "font-mono text-xs text-muted-foreground",
534
+ "data-testid": "home-connect-agent-command",
535
+ children: "npx -y @lunora/mcp"
536
+ }, void 0, false);
537
+ $[18] = t11;
538
+ } else {
539
+ t11 = $[18];
540
+ }
541
+ let t12;
542
+ if ($[19] !== copied || $[20] !== t) {
543
+ t12 = copied === "config" ? t("Copied") : t("Copy MCP config");
544
+ $[19] = copied;
545
+ $[20] = t;
546
+ $[21] = t12;
547
+ } else {
548
+ t12 = $[21];
549
+ }
550
+ let t13;
551
+ if ($[22] !== t12) {
552
+ t13 = /* @__PURE__ */ jsxDEV(Button, {
553
+ "data-testid": "home-connect-agent-copy-config",
554
+ onClick: onCopyConfig,
555
+ size: "xs",
556
+ variant: "outline",
557
+ children: t12
558
+ }, void 0, false);
559
+ $[22] = t12;
560
+ $[23] = t13;
561
+ } else {
562
+ t13 = $[23];
563
+ }
564
+ let t14;
565
+ if ($[24] !== copied || $[25] !== t) {
566
+ t14 = copied === "prompt" ? t("Copied") : t("Copy agent prompt");
567
+ $[24] = copied;
568
+ $[25] = t;
569
+ $[26] = t14;
570
+ } else {
571
+ t14 = $[26];
572
+ }
573
+ let t15;
574
+ if ($[27] !== t14) {
575
+ t15 = /* @__PURE__ */ jsxDEV(Button, {
576
+ "data-testid": "home-connect-agent-copy-prompt",
577
+ onClick: onCopyPrompt,
578
+ size: "xs",
579
+ variant: "outline",
580
+ children: t14
581
+ }, void 0, false);
582
+ $[27] = t14;
583
+ $[28] = t15;
584
+ } else {
585
+ t15 = $[28];
586
+ }
587
+ let t16;
588
+ if ($[29] !== t13 || $[30] !== t15) {
589
+ t16 = /* @__PURE__ */ jsxDEV("div", {
590
+ className: "flex flex-col gap-3 border-t border-border bg-muted/50 px-4 py-3",
591
+ children: [t11, /* @__PURE__ */ jsxDEV("div", {
592
+ className: "flex flex-wrap gap-2",
593
+ children: [t13, t15]
594
+ }, void 0, true)]
595
+ }, void 0, true);
596
+ $[29] = t13;
597
+ $[30] = t15;
598
+ $[31] = t16;
599
+ } else {
600
+ t16 = $[31];
601
+ }
602
+ let t17;
603
+ if ($[32] !== t10 || $[33] !== t16) {
604
+ t17 = /* @__PURE__ */ jsxDEV(Card, {
605
+ className: "gap-0 py-0",
606
+ "data-testid": "home-connect-agent",
607
+ children: [t10, t16]
608
+ }, void 0, true);
609
+ $[32] = t10;
610
+ $[33] = t16;
611
+ $[34] = t17;
612
+ } else {
613
+ t17 = $[34];
614
+ }
615
+ return t17;
616
+ };
617
+
618
+ const Sparkline = /* @__PURE__ */ lazy(() => import('../packem_chunks/sparkline.js').then((m) => {
619
+ return {
620
+ default: m.Sparkline
621
+ };
622
+ }));
623
+ const formatMs = (ms) => {
624
+ if (ms < 1e3) {
625
+ return `${String(Math.round(ms))}ms`;
626
+ }
627
+ const digits = ms >= 1e4 ? 0 : 1;
628
+ return `${(ms / 1e3).toFixed(digits)}s`;
629
+ };
630
+ const relativeTime = (ts, now) => {
631
+ const seconds = Math.max(0, Math.round((now - ts) / 1e3));
632
+ if (seconds < 60) {
633
+ return `${String(seconds)}s ago`;
634
+ }
635
+ const minutes = Math.round(seconds / 60);
636
+ if (minutes < 60) {
637
+ return `${String(minutes)}m ago`;
638
+ }
639
+ const hours = Math.round(minutes / 60);
640
+ return hours < 24 ? `${String(hours)}h ago` : `${String(Math.round(hours / 24))}d ago`;
641
+ };
642
+ const bucketSeries = (history, field) => {
643
+ if (history === void 0 || history.length === 0) {
644
+ return [];
645
+ }
646
+ const byBucket = /* @__PURE__ */ new Map();
647
+ for (const bucket of history) {
648
+ byBucket.set(bucket.bucketMs, (byBucket.get(bucket.bucketMs) ?? 0) + bucket[field]);
649
+ }
650
+ return [...byBucket.entries()].toSorted(([a], [b]) => a - b).map(([, total]) => total);
651
+ };
652
+ const seriesDelta = (series, higherIsBetter = true) => {
653
+ if (series.length < 4) {
654
+ return null;
655
+ }
656
+ const mid = Math.floor(series.length / 2);
657
+ const earlier = series.slice(0, mid).reduce((sum, value) => sum + value, 0);
658
+ const recent = series.slice(mid).reduce((sum, value) => sum + value, 0);
659
+ if (earlier === 0) {
660
+ return null;
661
+ }
662
+ const pct = (recent - earlier) / earlier * 100;
663
+ return {
664
+ positive: higherIsBetter ? pct >= 0 : pct <= 0,
665
+ text: `${pct >= 0 ? "+" : ""}${pct.toFixed(1)}%`
666
+ };
667
+ };
668
+ const StatCard = (t0) => {
669
+ const $ = c(24);
670
+ const {
671
+ delta,
672
+ footer,
673
+ label,
674
+ trend,
675
+ unit,
676
+ value
677
+ } = t0;
678
+ const t = useT();
679
+ let t1;
680
+ if ($[0] !== label) {
681
+ t1 = /* @__PURE__ */ jsxDEV("span", {
682
+ className: "font-mono text-[11px] tracking-wide text-muted-foreground uppercase",
683
+ children: label
684
+ }, void 0, false);
685
+ $[0] = label;
686
+ $[1] = t1;
687
+ } else {
688
+ t1 = $[1];
689
+ }
690
+ let t2;
691
+ if ($[2] !== value) {
692
+ t2 = /* @__PURE__ */ jsxDEV("span", {
693
+ className: "text-2xl font-semibold tabular-nums text-foreground",
694
+ children: value
695
+ }, void 0, false);
696
+ $[2] = value;
697
+ $[3] = t2;
698
+ } else {
699
+ t2 = $[3];
700
+ }
701
+ let t3;
702
+ if ($[4] !== unit) {
703
+ t3 = unit !== void 0 && /* @__PURE__ */ jsxDEV("span", {
704
+ className: "text-xs text-muted-foreground",
705
+ children: unit
706
+ }, void 0, false);
707
+ $[4] = unit;
708
+ $[5] = t3;
709
+ } else {
710
+ t3 = $[5];
711
+ }
712
+ let t4;
713
+ if ($[6] !== t2 || $[7] !== t3) {
714
+ t4 = /* @__PURE__ */ jsxDEV("span", {
715
+ className: "flex items-baseline gap-1.5",
716
+ children: [t2, t3]
717
+ }, void 0, true);
718
+ $[6] = t2;
719
+ $[7] = t3;
720
+ $[8] = t4;
721
+ } else {
722
+ t4 = $[8];
723
+ }
724
+ let t5;
725
+ if ($[9] !== trend) {
726
+ t5 = trend !== void 0 && /* @__PURE__ */ jsxDEV(Suspense, {
727
+ fallback: /* @__PURE__ */ jsxDEV("div", {
728
+ "aria-hidden": "true",
729
+ className: "h-8 w-28"
730
+ }, void 0, false),
731
+ children: /* @__PURE__ */ jsxDEV(Sparkline, {
732
+ data: trend
733
+ }, void 0, false)
734
+ }, void 0, false);
735
+ $[9] = trend;
736
+ $[10] = t5;
737
+ } else {
738
+ t5 = $[10];
739
+ }
740
+ let t6;
741
+ if ($[11] !== t4 || $[12] !== t5) {
742
+ t6 = /* @__PURE__ */ jsxDEV("div", {
743
+ className: "flex items-center justify-between gap-3",
744
+ children: [t4, t5]
745
+ }, void 0, true);
746
+ $[11] = t4;
747
+ $[12] = t5;
748
+ $[13] = t6;
749
+ } else {
750
+ t6 = $[13];
751
+ }
752
+ let t7;
753
+ if ($[14] !== t1 || $[15] !== t6) {
754
+ t7 = /* @__PURE__ */ jsxDEV("div", {
755
+ className: "flex flex-col gap-2.5 p-4",
756
+ children: [t1, t6]
757
+ }, void 0, true);
758
+ $[14] = t1;
759
+ $[15] = t6;
760
+ $[16] = t7;
761
+ } else {
762
+ t7 = $[16];
763
+ }
764
+ let t8;
765
+ if ($[17] !== delta || $[18] !== footer || $[19] !== t) {
766
+ t8 = delta == null ? footer != null && /* @__PURE__ */ jsxDEV("div", {
767
+ className: "border-t border-border bg-muted/50 px-4 py-2.5 text-[11px] text-muted-foreground",
768
+ children: footer
769
+ }, void 0, false) : /* @__PURE__ */ jsxDEV("div", {
770
+ className: "border-t border-border bg-muted/50 px-4 py-2.5 text-[11px]",
771
+ children: [/* @__PURE__ */ jsxDEV("span", {
772
+ className: cn("font-semibold", delta.positive ? "text-success" : "text-destructive"),
773
+ children: delta.text
774
+ }, void 0, false), " ", /* @__PURE__ */ jsxDEV("span", {
775
+ className: "text-muted-foreground",
776
+ children: t("vs. prev.")
777
+ }, void 0, false)]
778
+ }, void 0, true);
779
+ $[17] = delta;
780
+ $[18] = footer;
781
+ $[19] = t;
782
+ $[20] = t8;
783
+ } else {
784
+ t8 = $[20];
785
+ }
786
+ let t9;
787
+ if ($[21] !== t7 || $[22] !== t8) {
788
+ t9 = /* @__PURE__ */ jsxDEV(Card, {
789
+ className: "justify-between gap-0 py-0",
790
+ children: [t7, t8]
791
+ }, void 0, true);
792
+ $[21] = t7;
793
+ $[22] = t8;
794
+ $[23] = t9;
795
+ } else {
796
+ t9 = $[23];
797
+ }
798
+ return t9;
799
+ };
800
+ const ChevronRight = () => {
801
+ const $ = c(1);
802
+ let t0;
803
+ if ($[0] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
804
+ t0 = /* @__PURE__ */ jsxDEV("svg", {
805
+ "aria-hidden": "true",
806
+ className: "size-3.5",
807
+ fill: "none",
808
+ stroke: "currentColor",
809
+ strokeLinecap: "round",
810
+ strokeLinejoin: "round",
811
+ strokeWidth: 1.8,
812
+ viewBox: "0 0 24 24",
813
+ children: /* @__PURE__ */ jsxDEV("path", {
814
+ d: "m9 6 6 6-6 6"
815
+ }, void 0, false)
816
+ }, void 0, false);
817
+ $[0] = t0;
818
+ } else {
819
+ t0 = $[0];
820
+ }
821
+ return t0;
822
+ };
823
+ const ConnectCard = (t0) => {
824
+ const $ = c(7);
825
+ const {
826
+ command,
827
+ label
828
+ } = t0;
829
+ let t1;
830
+ if ($[0] !== label) {
831
+ t1 = /* @__PURE__ */ jsxDEV("div", {
832
+ className: "p-4",
833
+ children: /* @__PURE__ */ jsxDEV("span", {
834
+ className: "text-sm font-medium text-foreground",
835
+ children: label
836
+ }, void 0, false)
837
+ }, void 0, false);
838
+ $[0] = label;
839
+ $[1] = t1;
840
+ } else {
841
+ t1 = $[1];
842
+ }
843
+ let t2;
844
+ if ($[2] !== command) {
845
+ t2 = /* @__PURE__ */ jsxDEV("div", {
846
+ className: "border-t border-border bg-muted/50 px-4 py-2.5",
847
+ children: /* @__PURE__ */ jsxDEV("code", {
848
+ className: "font-mono text-xs text-muted-foreground",
849
+ children: command
850
+ }, void 0, false)
851
+ }, void 0, false);
852
+ $[2] = command;
853
+ $[3] = t2;
854
+ } else {
855
+ t2 = $[3];
856
+ }
857
+ let t3;
858
+ if ($[4] !== t1 || $[5] !== t2) {
859
+ t3 = /* @__PURE__ */ jsxDEV(Card, {
860
+ className: "justify-between gap-0 py-0",
861
+ children: [t1, t2]
862
+ }, void 0, true);
863
+ $[4] = t1;
864
+ $[5] = t2;
865
+ $[6] = t3;
866
+ } else {
867
+ t3 = $[6];
868
+ }
869
+ return t3;
870
+ };
871
+ const AdvisorCard = (t0) => {
872
+ const $ = c(18);
873
+ const {
874
+ count,
875
+ onView,
876
+ testId,
877
+ title
878
+ } = t0;
879
+ const t = useT();
880
+ let t1;
881
+ if ($[0] !== title) {
882
+ t1 = /* @__PURE__ */ jsxDEV("span", {
883
+ className: "font-mono text-[11px] tracking-wide text-muted-foreground uppercase",
884
+ children: title
885
+ }, void 0, false);
886
+ $[0] = title;
887
+ $[1] = t1;
888
+ } else {
889
+ t1 = $[1];
890
+ }
891
+ let t2;
892
+ if ($[2] !== count || $[3] !== t) {
893
+ t2 = count === null ? /* @__PURE__ */ jsxDEV("span", {
894
+ className: "text-xs text-muted-foreground",
895
+ children: t("No data yet")
896
+ }, void 0, false) : /* @__PURE__ */ jsxDEV(Badge, {
897
+ variant: count > 0 ? "destructive" : "success",
898
+ children: count > 0 ? count : t("All clear")
899
+ }, void 0, false);
900
+ $[2] = count;
901
+ $[3] = t;
902
+ $[4] = t2;
903
+ } else {
904
+ t2 = $[4];
905
+ }
906
+ let t3;
907
+ if ($[5] !== t1 || $[6] !== t2) {
908
+ t3 = /* @__PURE__ */ jsxDEV("div", {
909
+ className: "flex items-start justify-between gap-2 p-4",
910
+ children: [t1, t2]
911
+ }, void 0, true);
912
+ $[5] = t1;
913
+ $[6] = t2;
914
+ $[7] = t3;
915
+ } else {
916
+ t3 = $[7];
917
+ }
918
+ let t4;
919
+ if ($[8] !== t) {
920
+ t4 = t("View");
921
+ $[8] = t;
922
+ $[9] = t4;
923
+ } else {
924
+ t4 = $[9];
925
+ }
926
+ let t5;
927
+ if ($[10] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
928
+ t5 = /* @__PURE__ */ jsxDEV(ChevronRight, {}, void 0, false);
929
+ $[10] = t5;
930
+ } else {
931
+ t5 = $[10];
932
+ }
933
+ let t6;
934
+ if ($[11] !== onView || $[12] !== t4) {
935
+ t6 = /* @__PURE__ */ jsxDEV("button", {
936
+ 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",
937
+ onClick: onView,
938
+ type: "button",
939
+ children: [t4, t5]
940
+ }, void 0, true);
941
+ $[11] = onView;
942
+ $[12] = t4;
943
+ $[13] = t6;
944
+ } else {
945
+ t6 = $[13];
946
+ }
947
+ let t7;
948
+ if ($[14] !== t3 || $[15] !== t6 || $[16] !== testId) {
949
+ t7 = /* @__PURE__ */ jsxDEV(Card, {
950
+ className: "justify-between gap-0 py-0",
951
+ "data-testid": testId,
952
+ children: [t3, t6]
953
+ }, void 0, true);
954
+ $[14] = t3;
955
+ $[15] = t6;
956
+ $[16] = testId;
957
+ $[17] = t7;
958
+ } else {
959
+ t7 = $[17];
960
+ }
961
+ return t7;
962
+ };
963
+ const TopFunctionsCard = (t0) => {
964
+ const $ = c(7);
965
+ const {
966
+ functions
967
+ } = t0;
968
+ const t = useT();
969
+ let t1;
970
+ if ($[0] !== functions || $[1] !== t) {
971
+ const top = [...functions].toSorted(_temp).slice(0, 5);
972
+ let t2;
973
+ if ($[3] !== t) {
974
+ t2 = t("Top functions");
975
+ $[3] = t;
976
+ $[4] = t2;
977
+ } else {
978
+ t2 = $[4];
979
+ }
980
+ let t3;
981
+ if ($[5] !== t2) {
982
+ t3 = /* @__PURE__ */ jsxDEV("div", {
983
+ className: "border-b border-border px-4 py-3",
984
+ children: /* @__PURE__ */ jsxDEV("span", {
985
+ className: "font-mono text-[11px] tracking-wide text-muted-foreground uppercase",
986
+ children: t2
987
+ }, void 0, false)
988
+ }, void 0, false);
989
+ $[5] = t2;
990
+ $[6] = t3;
991
+ } else {
992
+ t3 = $[6];
993
+ }
994
+ t1 = /* @__PURE__ */ jsxDEV(Card, {
995
+ className: "gap-0 py-0",
996
+ "data-testid": "home-top-functions",
997
+ children: [t3, top.length === 0 ? /* @__PURE__ */ jsxDEV("p", {
998
+ className: "px-4 py-8 text-center text-xs text-muted-foreground",
999
+ children: t("No functions called yet.")
1000
+ }, void 0, false) : /* @__PURE__ */ jsxDEV("div", {
1001
+ className: "divide-y divide-border",
1002
+ children: [/* @__PURE__ */ jsxDEV("div", {
1003
+ 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",
1004
+ children: [/* @__PURE__ */ jsxDEV("span", {
1005
+ children: t("Function")
1006
+ }, void 0, false), /* @__PURE__ */ jsxDEV("span", {
1007
+ className: "text-end",
1008
+ children: t("Calls")
1009
+ }, void 0, false), /* @__PURE__ */ jsxDEV("span", {
1010
+ className: "w-12 text-end",
1011
+ children: t("Avg")
1012
+ }, void 0, false), /* @__PURE__ */ jsxDEV("span", {
1013
+ className: "w-8 text-end",
1014
+ children: t("Err")
1015
+ }, void 0, false)]
1016
+ }, void 0, true), top.map(_temp2)]
1017
+ }, void 0, true)]
1018
+ }, void 0, true);
1019
+ $[0] = functions;
1020
+ $[1] = t;
1021
+ $[2] = t1;
1022
+ } else {
1023
+ t1 = $[2];
1024
+ }
1025
+ return t1;
1026
+ };
1027
+ const LiveConnectionsCard = (t0) => {
1028
+ const $ = c(26);
1029
+ const {
1030
+ subs
1031
+ } = t0;
1032
+ const t = useT();
1033
+ let t1;
1034
+ if ($[0] !== t) {
1035
+ t1 = t("Live connections");
1036
+ $[0] = t;
1037
+ $[1] = t1;
1038
+ } else {
1039
+ t1 = $[1];
1040
+ }
1041
+ let t2;
1042
+ if ($[2] !== t1) {
1043
+ t2 = /* @__PURE__ */ jsxDEV("span", {
1044
+ className: "font-mono text-[11px] tracking-wide text-muted-foreground uppercase",
1045
+ children: t1
1046
+ }, void 0, false);
1047
+ $[2] = t1;
1048
+ $[3] = t2;
1049
+ } else {
1050
+ t2 = $[3];
1051
+ }
1052
+ const t3 = subs?.totalConnections ?? 0;
1053
+ let t4;
1054
+ if ($[4] !== t3) {
1055
+ t4 = t3.toLocaleString();
1056
+ $[4] = t3;
1057
+ $[5] = t4;
1058
+ } else {
1059
+ t4 = $[5];
1060
+ }
1061
+ let t5;
1062
+ if ($[6] !== t4) {
1063
+ t5 = /* @__PURE__ */ jsxDEV("span", {
1064
+ className: "text-2xl font-semibold tabular-nums text-foreground",
1065
+ children: t4
1066
+ }, void 0, false);
1067
+ $[6] = t4;
1068
+ $[7] = t5;
1069
+ } else {
1070
+ t5 = $[7];
1071
+ }
1072
+ let t6;
1073
+ if ($[8] !== t) {
1074
+ t6 = t("sockets");
1075
+ $[8] = t;
1076
+ $[9] = t6;
1077
+ } else {
1078
+ t6 = $[9];
1079
+ }
1080
+ let t7;
1081
+ if ($[10] !== t6) {
1082
+ t7 = /* @__PURE__ */ jsxDEV("span", {
1083
+ className: "text-xs text-muted-foreground",
1084
+ children: t6
1085
+ }, void 0, false);
1086
+ $[10] = t6;
1087
+ $[11] = t7;
1088
+ } else {
1089
+ t7 = $[11];
1090
+ }
1091
+ let t8;
1092
+ if ($[12] !== t5 || $[13] !== t7) {
1093
+ t8 = /* @__PURE__ */ jsxDEV("span", {
1094
+ className: "flex items-baseline gap-1.5",
1095
+ children: [t5, t7]
1096
+ }, void 0, true);
1097
+ $[12] = t5;
1098
+ $[13] = t7;
1099
+ $[14] = t8;
1100
+ } else {
1101
+ t8 = $[14];
1102
+ }
1103
+ const t9 = subs?.totalSubscriptions ?? 0;
1104
+ let t10;
1105
+ if ($[15] !== t9) {
1106
+ t10 = t9.toLocaleString();
1107
+ $[15] = t9;
1108
+ $[16] = t10;
1109
+ } else {
1110
+ t10 = $[16];
1111
+ }
1112
+ let t11;
1113
+ if ($[17] !== t) {
1114
+ t11 = t("active subscriptions");
1115
+ $[17] = t;
1116
+ $[18] = t11;
1117
+ } else {
1118
+ t11 = $[18];
1119
+ }
1120
+ let t12;
1121
+ if ($[19] !== t10 || $[20] !== t11) {
1122
+ t12 = /* @__PURE__ */ jsxDEV("span", {
1123
+ className: "text-[11px] text-muted-foreground",
1124
+ children: [t10, " ", t11]
1125
+ }, void 0, true);
1126
+ $[19] = t10;
1127
+ $[20] = t11;
1128
+ $[21] = t12;
1129
+ } else {
1130
+ t12 = $[21];
1131
+ }
1132
+ let t13;
1133
+ if ($[22] !== t12 || $[23] !== t2 || $[24] !== t8) {
1134
+ t13 = /* @__PURE__ */ jsxDEV(Card, {
1135
+ "data-testid": "home-live-connections",
1136
+ children: /* @__PURE__ */ jsxDEV(CardContent, {
1137
+ className: "flex flex-col gap-2.5 py-4",
1138
+ children: [t2, t8, t12]
1139
+ }, void 0, true)
1140
+ }, void 0, false);
1141
+ $[22] = t12;
1142
+ $[23] = t2;
1143
+ $[24] = t8;
1144
+ $[25] = t13;
1145
+ } else {
1146
+ t13 = $[25];
1147
+ }
1148
+ return t13;
1149
+ };
1150
+ const RecentActivityCard = (t0) => {
1151
+ const $ = c(7);
1152
+ const {
1153
+ entries
1154
+ } = t0;
1155
+ const t = useT();
1156
+ let t1;
1157
+ if ($[0] !== entries || $[1] !== t) {
1158
+ const now = Date.now();
1159
+ let t2;
1160
+ if ($[3] !== t) {
1161
+ t2 = t("Recent activity");
1162
+ $[3] = t;
1163
+ $[4] = t2;
1164
+ } else {
1165
+ t2 = $[4];
1166
+ }
1167
+ let t3;
1168
+ if ($[5] !== t2) {
1169
+ t3 = /* @__PURE__ */ jsxDEV("div", {
1170
+ className: "border-b border-border px-4 py-3",
1171
+ children: /* @__PURE__ */ jsxDEV("span", {
1172
+ className: "font-mono text-[11px] tracking-wide text-muted-foreground uppercase",
1173
+ children: t2
1174
+ }, void 0, false)
1175
+ }, void 0, false);
1176
+ $[5] = t2;
1177
+ $[6] = t3;
1178
+ } else {
1179
+ t3 = $[6];
1180
+ }
1181
+ t1 = /* @__PURE__ */ jsxDEV(Card, {
1182
+ className: "gap-0 py-0",
1183
+ "data-testid": "home-recent-activity",
1184
+ children: [t3, entries.length === 0 ? /* @__PURE__ */ jsxDEV("p", {
1185
+ className: "px-4 py-8 text-center text-xs text-muted-foreground",
1186
+ children: t("No recent activity.")
1187
+ }, void 0, false) : /* @__PURE__ */ jsxDEV("ul", {
1188
+ className: "divide-y divide-border",
1189
+ children: entries.slice(0, 5).map((entry) => /* @__PURE__ */ jsxDEV("li", {
1190
+ className: "flex items-center justify-between gap-3 px-4 py-2 text-[13px]",
1191
+ children: [/* @__PURE__ */ jsxDEV("span", {
1192
+ className: "flex min-w-0 items-center gap-2",
1193
+ children: [/* @__PURE__ */ jsxDEV("span", {
1194
+ "aria-hidden": "true",
1195
+ className: "size-1.5 shrink-0 rounded-full bg-muted-foreground/40"
1196
+ }, void 0, false), /* @__PURE__ */ jsxDEV("span", {
1197
+ className: "truncate text-foreground",
1198
+ children: [entry.op, entry.table !== void 0 && /* @__PURE__ */ jsxDEV("span", {
1199
+ className: "text-muted-foreground",
1200
+ children: [" · ", entry.table, entry.id === void 0 ? "" : `#${entry.id}`]
1201
+ }, void 0, true)]
1202
+ }, void 0, true)]
1203
+ }, void 0, true), /* @__PURE__ */ jsxDEV("span", {
1204
+ className: "shrink-0 text-xs tabular-nums text-muted-foreground",
1205
+ children: relativeTime(entry.ts, now)
1206
+ }, void 0, false)]
1207
+ }, entry.seq, true))
1208
+ }, void 0, false)]
1209
+ }, void 0, true);
1210
+ $[0] = entries;
1211
+ $[1] = t;
1212
+ $[2] = t1;
1213
+ } else {
1214
+ t1 = $[2];
1215
+ }
1216
+ return t1;
1217
+ };
1218
+ const averageLatencyMs = (functions) => {
1219
+ const calls = functions.reduce((sum, function_) => sum + function_.calls, 0);
1220
+ if (calls === 0) {
1221
+ return null;
1222
+ }
1223
+ return functions.reduce((sum, function_) => sum + function_.totalDurationMs, 0) / calls;
1224
+ };
1225
+ const HomePanel = (t0) => {
1226
+ const $ = c(151);
1227
+ const {
1228
+ initialShardKey
1229
+ } = t0;
1230
+ const t = useT();
1231
+ const navigate = useNavigate();
1232
+ const shard = initialShardKey ?? "";
1233
+ let t1;
1234
+ if ($[0] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
1235
+ t1 = {};
1236
+ $[0] = t1;
1237
+ } else {
1238
+ t1 = $[0];
1239
+ }
1240
+ let t2;
1241
+ if ($[1] !== shard) {
1242
+ t2 = {
1243
+ shardKey: shard
1244
+ };
1245
+ $[1] = shard;
1246
+ $[2] = t2;
1247
+ } else {
1248
+ t2 = $[2];
1249
+ }
1250
+ const metricsQuery = useAdminQuery(ADMIN_FUNCTIONS.getMetrics, t1, t2);
1251
+ let t3;
1252
+ if ($[3] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
1253
+ t3 = {};
1254
+ $[3] = t3;
1255
+ } else {
1256
+ t3 = $[3];
1257
+ }
1258
+ let t4;
1259
+ if ($[4] !== shard) {
1260
+ t4 = {
1261
+ shardKey: shard
1262
+ };
1263
+ $[4] = shard;
1264
+ $[5] = t4;
1265
+ } else {
1266
+ t4 = $[5];
1267
+ }
1268
+ const statsQuery = useAdminQuery(ADMIN_FUNCTIONS.getFunctionStats, t3, t4);
1269
+ let t5;
1270
+ let t6;
1271
+ if ($[6] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
1272
+ t5 = {};
1273
+ t6 = {
1274
+ shardKey: ""
1275
+ };
1276
+ $[6] = t5;
1277
+ $[7] = t6;
1278
+ } else {
1279
+ t5 = $[6];
1280
+ t6 = $[7];
1281
+ }
1282
+ const auditQuery = useAdminQuery(ADMIN_FUNCTIONS.getSecurityAudit, t5, t6);
1283
+ let t7;
1284
+ if ($[8] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
1285
+ t7 = {};
1286
+ $[8] = t7;
1287
+ } else {
1288
+ t7 = $[8];
1289
+ }
1290
+ let t8;
1291
+ if ($[9] !== shard) {
1292
+ t8 = {
1293
+ shardKey: shard
1294
+ };
1295
+ $[9] = shard;
1296
+ $[10] = t8;
1297
+ } else {
1298
+ t8 = $[10];
1299
+ }
1300
+ const subscriptionsQuery = useAdminQuery(ADMIN_FUNCTIONS.listSubscriptions, t7, t8);
1301
+ let t9;
1302
+ if ($[11] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
1303
+ t9 = {};
1304
+ $[11] = t9;
1305
+ } else {
1306
+ t9 = $[11];
1307
+ }
1308
+ let t10;
1309
+ if ($[12] !== shard) {
1310
+ t10 = {
1311
+ shardKey: shard
1312
+ };
1313
+ $[12] = shard;
1314
+ $[13] = t10;
1315
+ } else {
1316
+ t10 = $[13];
1317
+ }
1318
+ const auditLogQuery = useAdminQuery(ADMIN_FUNCTIONS.getAuditLog, t9, t10);
1319
+ const metrics = metricsQuery.data ?? null;
1320
+ let T0;
1321
+ let activity;
1322
+ let cacheHitRate;
1323
+ let functions;
1324
+ let performanceCount;
1325
+ let securityCount;
1326
+ let subscriptions;
1327
+ let t11;
1328
+ let t12;
1329
+ let t13;
1330
+ let t14;
1331
+ let t15;
1332
+ let t16;
1333
+ let t17;
1334
+ let t18;
1335
+ let t19;
1336
+ let viewPerformance;
1337
+ let viewSecurity;
1338
+ if ($[14] !== auditLogQuery.data || $[15] !== auditQuery.data || $[16] !== metrics || $[17] !== metricsQuery.data || $[18] !== navigate || $[19] !== statsQuery.data || $[20] !== subscriptionsQuery.data || $[21] !== t) {
1339
+ functions = Array.isArray(statsQuery.data?.functions) ? statsQuery.data.functions : [];
1340
+ subscriptions = subscriptionsQuery.data ?? null;
1341
+ let t202;
1342
+ if ($[40] !== auditLogQuery.data) {
1343
+ t202 = Array.isArray(auditLogQuery.data?.entries) ? auditLogQuery.data.entries : [];
1344
+ $[40] = auditLogQuery.data;
1345
+ $[41] = t202;
1346
+ } else {
1347
+ t202 = $[41];
1348
+ }
1349
+ activity = t202;
1350
+ performanceCount = metricsQuery.data === void 0 || statsQuery.data === void 0 ? null : deriveInsights(metrics, functions).length;
1351
+ securityCount = Array.isArray(auditQuery.data?.findings) ? auditQuery.data.findings.length : null;
1352
+ let t212;
1353
+ if ($[42] !== navigate) {
1354
+ t212 = () => {
1355
+ fireAndForget(navigate({
1356
+ to: "/security"
1357
+ }));
1358
+ };
1359
+ $[42] = navigate;
1360
+ $[43] = t212;
1361
+ } else {
1362
+ t212 = $[43];
1363
+ }
1364
+ viewSecurity = t212;
1365
+ let t222;
1366
+ if ($[44] !== navigate) {
1367
+ t222 = () => {
1368
+ fireAndForget(navigate({
1369
+ to: "/insights"
1370
+ }));
1371
+ };
1372
+ $[44] = navigate;
1373
+ $[45] = t222;
1374
+ } else {
1375
+ t222 = $[45];
1376
+ }
1377
+ viewPerformance = t222;
1378
+ const requestSeries = bucketSeries(metrics?.history, "calls");
1379
+ const errorSeries = bucketSeries(metrics?.history, "errors");
1380
+ const avgLatency = averageLatencyMs(functions);
1381
+ const maxLatency = Math.max(0, ...functions.map(_temp3));
1382
+ const cache = metrics?.cache;
1383
+ let t232;
1384
+ if ($[46] !== cache) {
1385
+ t232 = cache != null && cache.hits + cache.misses > 0 ? Math.round(cache.hits / (cache.hits + cache.misses) * 100) : null;
1386
+ $[46] = cache;
1387
+ $[47] = t232;
1388
+ } else {
1389
+ t232 = $[47];
1390
+ }
1391
+ cacheHitRate = t232;
1392
+ t18 = "flex flex-col gap-6";
1393
+ t19 = "lunora-home";
1394
+ t14 = "grid gap-3 sm:grid-cols-2 xl:grid-cols-4";
1395
+ t15 = "home-health";
1396
+ const t242 = seriesDelta(requestSeries);
1397
+ let t252;
1398
+ if ($[48] !== t) {
1399
+ t252 = t("Requests");
1400
+ $[48] = t;
1401
+ $[49] = t252;
1402
+ } else {
1403
+ t252 = $[49];
1404
+ }
1405
+ const t262 = metrics?.requests ?? 0;
1406
+ let t272;
1407
+ if ($[50] !== t262) {
1408
+ t272 = t262.toLocaleString();
1409
+ $[50] = t262;
1410
+ $[51] = t272;
1411
+ } else {
1412
+ t272 = $[51];
1413
+ }
1414
+ if ($[52] !== requestSeries || $[53] !== t242 || $[54] !== t252 || $[55] !== t272) {
1415
+ t16 = /* @__PURE__ */ jsxDEV(StatCard, {
1416
+ delta: t242,
1417
+ label: t252,
1418
+ trend: requestSeries,
1419
+ value: t272
1420
+ }, void 0, false);
1421
+ $[52] = requestSeries;
1422
+ $[53] = t242;
1423
+ $[54] = t252;
1424
+ $[55] = t272;
1425
+ $[56] = t16;
1426
+ } else {
1427
+ t16 = $[56];
1428
+ }
1429
+ const t282 = seriesDelta(errorSeries, false);
1430
+ let t292;
1431
+ if ($[57] !== t) {
1432
+ t292 = t("Errors");
1433
+ $[57] = t;
1434
+ $[58] = t292;
1435
+ } else {
1436
+ t292 = $[58];
1437
+ }
1438
+ const t302 = metrics?.errors ?? 0;
1439
+ let t312;
1440
+ if ($[59] !== t302) {
1441
+ t312 = t302.toLocaleString();
1442
+ $[59] = t302;
1443
+ $[60] = t312;
1444
+ } else {
1445
+ t312 = $[60];
1446
+ }
1447
+ if ($[61] !== errorSeries || $[62] !== t282 || $[63] !== t292 || $[64] !== t312) {
1448
+ t17 = /* @__PURE__ */ jsxDEV(StatCard, {
1449
+ delta: t282,
1450
+ label: t292,
1451
+ trend: errorSeries,
1452
+ value: t312
1453
+ }, void 0, false);
1454
+ $[61] = errorSeries;
1455
+ $[62] = t282;
1456
+ $[63] = t292;
1457
+ $[64] = t312;
1458
+ $[65] = t17;
1459
+ } else {
1460
+ t17 = $[65];
1461
+ }
1462
+ T0 = StatCard;
1463
+ if ($[66] !== maxLatency || $[67] !== t) {
1464
+ t11 = maxLatency > 0 ? `${t("max")} ${formatMs(maxLatency)}` : void 0;
1465
+ $[66] = maxLatency;
1466
+ $[67] = t;
1467
+ $[68] = t11;
1468
+ } else {
1469
+ t11 = $[68];
1470
+ }
1471
+ if ($[69] !== t) {
1472
+ t12 = t("Avg latency");
1473
+ $[69] = t;
1474
+ $[70] = t12;
1475
+ } else {
1476
+ t12 = $[70];
1477
+ }
1478
+ t13 = avgLatency === null ? "—" : formatMs(avgLatency);
1479
+ $[14] = auditLogQuery.data;
1480
+ $[15] = auditQuery.data;
1481
+ $[16] = metrics;
1482
+ $[17] = metricsQuery.data;
1483
+ $[18] = navigate;
1484
+ $[19] = statsQuery.data;
1485
+ $[20] = subscriptionsQuery.data;
1486
+ $[21] = t;
1487
+ $[22] = T0;
1488
+ $[23] = activity;
1489
+ $[24] = cacheHitRate;
1490
+ $[25] = functions;
1491
+ $[26] = performanceCount;
1492
+ $[27] = securityCount;
1493
+ $[28] = subscriptions;
1494
+ $[29] = t11;
1495
+ $[30] = t12;
1496
+ $[31] = t13;
1497
+ $[32] = t14;
1498
+ $[33] = t15;
1499
+ $[34] = t16;
1500
+ $[35] = t17;
1501
+ $[36] = t18;
1502
+ $[37] = t19;
1503
+ $[38] = viewPerformance;
1504
+ $[39] = viewSecurity;
1505
+ } else {
1506
+ T0 = $[22];
1507
+ activity = $[23];
1508
+ cacheHitRate = $[24];
1509
+ functions = $[25];
1510
+ performanceCount = $[26];
1511
+ securityCount = $[27];
1512
+ subscriptions = $[28];
1513
+ t11 = $[29];
1514
+ t12 = $[30];
1515
+ t13 = $[31];
1516
+ t14 = $[32];
1517
+ t15 = $[33];
1518
+ t16 = $[34];
1519
+ t17 = $[35];
1520
+ t18 = $[36];
1521
+ t19 = $[37];
1522
+ viewPerformance = $[38];
1523
+ viewSecurity = $[39];
1524
+ }
1525
+ let t20;
1526
+ if ($[71] !== T0 || $[72] !== t11 || $[73] !== t12 || $[74] !== t13) {
1527
+ t20 = /* @__PURE__ */ jsxDEV(T0, {
1528
+ footer: t11,
1529
+ label: t12,
1530
+ value: t13
1531
+ }, void 0, false);
1532
+ $[71] = T0;
1533
+ $[72] = t11;
1534
+ $[73] = t12;
1535
+ $[74] = t13;
1536
+ $[75] = t20;
1537
+ } else {
1538
+ t20 = $[75];
1539
+ }
1540
+ let t21;
1541
+ if ($[76] !== cacheHitRate || $[77] !== t) {
1542
+ t21 = cacheHitRate === null ? void 0 : `${String(cacheHitRate)}% ${t("cache hit")}`;
1543
+ $[76] = cacheHitRate;
1544
+ $[77] = t;
1545
+ $[78] = t21;
1546
+ } else {
1547
+ t21 = $[78];
1548
+ }
1549
+ let t22;
1550
+ if ($[79] !== t) {
1551
+ t22 = t("Database size");
1552
+ $[79] = t;
1553
+ $[80] = t22;
1554
+ } else {
1555
+ t22 = $[80];
1556
+ }
1557
+ const t23 = metrics?.databaseSize ?? null;
1558
+ let t24;
1559
+ if ($[81] !== t23) {
1560
+ t24 = formatBytes(t23);
1561
+ $[81] = t23;
1562
+ $[82] = t24;
1563
+ } else {
1564
+ t24 = $[82];
1565
+ }
1566
+ let t25;
1567
+ if ($[83] !== t21 || $[84] !== t22 || $[85] !== t24) {
1568
+ t25 = /* @__PURE__ */ jsxDEV(StatCard, {
1569
+ footer: t21,
1570
+ label: t22,
1571
+ value: t24
1572
+ }, void 0, false);
1573
+ $[83] = t21;
1574
+ $[84] = t22;
1575
+ $[85] = t24;
1576
+ $[86] = t25;
1577
+ } else {
1578
+ t25 = $[86];
1579
+ }
1580
+ let t26;
1581
+ if ($[87] !== t14 || $[88] !== t15 || $[89] !== t16 || $[90] !== t17 || $[91] !== t20 || $[92] !== t25) {
1582
+ t26 = /* @__PURE__ */ jsxDEV("div", {
1583
+ className: t14,
1584
+ "data-testid": t15,
1585
+ children: [t16, t17, t20, t25]
1586
+ }, void 0, true);
1587
+ $[87] = t14;
1588
+ $[88] = t15;
1589
+ $[89] = t16;
1590
+ $[90] = t17;
1591
+ $[91] = t20;
1592
+ $[92] = t25;
1593
+ $[93] = t26;
1594
+ } else {
1595
+ t26 = $[93];
1596
+ }
1597
+ let t27;
1598
+ if ($[94] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
1599
+ t27 = /* @__PURE__ */ jsxDEV(BindingsOverview, {}, void 0, false);
1600
+ $[94] = t27;
1601
+ } else {
1602
+ t27 = $[94];
1603
+ }
1604
+ let t28;
1605
+ if ($[95] !== functions) {
1606
+ t28 = /* @__PURE__ */ jsxDEV("div", {
1607
+ className: "lg:col-span-2",
1608
+ children: /* @__PURE__ */ jsxDEV(TopFunctionsCard, {
1609
+ functions
1610
+ }, void 0, false)
1611
+ }, void 0, false);
1612
+ $[95] = functions;
1613
+ $[96] = t28;
1614
+ } else {
1615
+ t28 = $[96];
1616
+ }
1617
+ let t29;
1618
+ if ($[97] !== subscriptions) {
1619
+ t29 = /* @__PURE__ */ jsxDEV(LiveConnectionsCard, {
1620
+ subs: subscriptions
1621
+ }, void 0, false);
1622
+ $[97] = subscriptions;
1623
+ $[98] = t29;
1624
+ } else {
1625
+ t29 = $[98];
1626
+ }
1627
+ let t30;
1628
+ if ($[99] !== activity) {
1629
+ t30 = /* @__PURE__ */ jsxDEV(RecentActivityCard, {
1630
+ entries: activity
1631
+ }, void 0, false);
1632
+ $[99] = activity;
1633
+ $[100] = t30;
1634
+ } else {
1635
+ t30 = $[100];
1636
+ }
1637
+ let t31;
1638
+ if ($[101] !== t29 || $[102] !== t30) {
1639
+ t31 = /* @__PURE__ */ jsxDEV("div", {
1640
+ className: "flex flex-col gap-3",
1641
+ children: [t29, t30]
1642
+ }, void 0, true);
1643
+ $[101] = t29;
1644
+ $[102] = t30;
1645
+ $[103] = t31;
1646
+ } else {
1647
+ t31 = $[103];
1648
+ }
1649
+ let t32;
1650
+ if ($[104] !== t28 || $[105] !== t31) {
1651
+ t32 = /* @__PURE__ */ jsxDEV("div", {
1652
+ className: "grid gap-3 lg:grid-cols-3",
1653
+ children: [t28, t31]
1654
+ }, void 0, true);
1655
+ $[104] = t28;
1656
+ $[105] = t31;
1657
+ $[106] = t32;
1658
+ } else {
1659
+ t32 = $[106];
1660
+ }
1661
+ let t33;
1662
+ if ($[107] !== t) {
1663
+ t33 = t("Advisors");
1664
+ $[107] = t;
1665
+ $[108] = t33;
1666
+ } else {
1667
+ t33 = $[108];
1668
+ }
1669
+ let t34;
1670
+ if ($[109] !== t33) {
1671
+ t34 = /* @__PURE__ */ jsxDEV("h2", {
1672
+ className: "text-sm font-semibold tracking-tight text-foreground",
1673
+ children: t33
1674
+ }, void 0, false);
1675
+ $[109] = t33;
1676
+ $[110] = t34;
1677
+ } else {
1678
+ t34 = $[110];
1679
+ }
1680
+ let t35;
1681
+ if ($[111] !== performanceCount || $[112] !== securityCount || $[113] !== t || $[114] !== viewPerformance || $[115] !== viewSecurity) {
1682
+ t35 = securityCount === 0 && performanceCount === 0 ? /* @__PURE__ */ jsxDEV(EmptyState, {
1683
+ description: t("No security or performance issues detected."),
1684
+ icon: /* @__PURE__ */ jsxDEV("svg", {
1685
+ "aria-hidden": "true",
1686
+ fill: "none",
1687
+ stroke: "currentColor",
1688
+ strokeLinecap: "round",
1689
+ strokeLinejoin: "round",
1690
+ strokeWidth: 1.6,
1691
+ viewBox: "0 0 24 24",
1692
+ children: [/* @__PURE__ */ jsxDEV("path", {
1693
+ d: "M12 3 4 6v5c0 5 3.4 8.5 8 10 4.6-1.5 8-5 8-10V6l-8-3Z"
1694
+ }, void 0, false), /* @__PURE__ */ jsxDEV("path", {
1695
+ d: "m9 12 2 2 4-4"
1696
+ }, void 0, false)]
1697
+ }, void 0, true),
1698
+ testId: "home-advisors-clear",
1699
+ title: t("No issues found")
1700
+ }, void 0, false) : /* @__PURE__ */ jsxDEV("div", {
1701
+ className: "grid gap-3 sm:grid-cols-2",
1702
+ children: [/* @__PURE__ */ jsxDEV(AdvisorCard, {
1703
+ count: securityCount,
1704
+ onView: viewSecurity,
1705
+ testId: "home-security",
1706
+ title: t("Security findings")
1707
+ }, void 0, false), /* @__PURE__ */ jsxDEV(AdvisorCard, {
1708
+ count: performanceCount,
1709
+ onView: viewPerformance,
1710
+ testId: "home-performance",
1711
+ title: t("Performance issues")
1712
+ }, void 0, false)]
1713
+ }, void 0, true);
1714
+ $[111] = performanceCount;
1715
+ $[112] = securityCount;
1716
+ $[113] = t;
1717
+ $[114] = viewPerformance;
1718
+ $[115] = viewSecurity;
1719
+ $[116] = t35;
1720
+ } else {
1721
+ t35 = $[116];
1722
+ }
1723
+ let t36;
1724
+ if ($[117] !== t34 || $[118] !== t35) {
1725
+ t36 = /* @__PURE__ */ jsxDEV("section", {
1726
+ className: "flex flex-col gap-3",
1727
+ "data-testid": "home-advisors",
1728
+ children: [t34, t35]
1729
+ }, void 0, true);
1730
+ $[117] = t34;
1731
+ $[118] = t35;
1732
+ $[119] = t36;
1733
+ } else {
1734
+ t36 = $[119];
1735
+ }
1736
+ let t37;
1737
+ if ($[120] !== t) {
1738
+ t37 = t("Get connected");
1739
+ $[120] = t;
1740
+ $[121] = t37;
1741
+ } else {
1742
+ t37 = $[121];
1743
+ }
1744
+ let t38;
1745
+ if ($[122] !== t37) {
1746
+ t38 = /* @__PURE__ */ jsxDEV("h2", {
1747
+ className: "text-sm font-semibold tracking-tight text-foreground",
1748
+ children: t37
1749
+ }, void 0, false);
1750
+ $[122] = t37;
1751
+ $[123] = t38;
1752
+ } else {
1753
+ t38 = $[123];
1754
+ }
1755
+ let t39;
1756
+ if ($[124] !== t) {
1757
+ t39 = t("Client SDK");
1758
+ $[124] = t;
1759
+ $[125] = t39;
1760
+ } else {
1761
+ t39 = $[125];
1762
+ }
1763
+ let t40;
1764
+ if ($[126] !== t39) {
1765
+ t40 = /* @__PURE__ */ jsxDEV(ConnectCard, {
1766
+ command: "npm i @lunora/client",
1767
+ label: t39
1768
+ }, void 0, false);
1769
+ $[126] = t39;
1770
+ $[127] = t40;
1771
+ } else {
1772
+ t40 = $[127];
1773
+ }
1774
+ let t41;
1775
+ if ($[128] !== t) {
1776
+ t41 = t("React");
1777
+ $[128] = t;
1778
+ $[129] = t41;
1779
+ } else {
1780
+ t41 = $[129];
1781
+ }
1782
+ let t42;
1783
+ if ($[130] !== t41) {
1784
+ t42 = /* @__PURE__ */ jsxDEV(ConnectCard, {
1785
+ command: "npm i @lunora/react",
1786
+ label: t41
1787
+ }, void 0, false);
1788
+ $[130] = t41;
1789
+ $[131] = t42;
1790
+ } else {
1791
+ t42 = $[131];
1792
+ }
1793
+ let t43;
1794
+ if ($[132] !== t) {
1795
+ t43 = t("CLI");
1796
+ $[132] = t;
1797
+ $[133] = t43;
1798
+ } else {
1799
+ t43 = $[133];
1800
+ }
1801
+ let t44;
1802
+ if ($[134] !== t43) {
1803
+ t44 = /* @__PURE__ */ jsxDEV(ConnectCard, {
1804
+ command: "lunora dev",
1805
+ label: t43
1806
+ }, void 0, false);
1807
+ $[134] = t43;
1808
+ $[135] = t44;
1809
+ } else {
1810
+ t44 = $[135];
1811
+ }
1812
+ let t45;
1813
+ if ($[136] !== t40 || $[137] !== t42 || $[138] !== t44) {
1814
+ t45 = /* @__PURE__ */ jsxDEV("div", {
1815
+ className: "grid gap-3 sm:grid-cols-3",
1816
+ children: [t40, t42, t44]
1817
+ }, void 0, true);
1818
+ $[136] = t40;
1819
+ $[137] = t42;
1820
+ $[138] = t44;
1821
+ $[139] = t45;
1822
+ } else {
1823
+ t45 = $[139];
1824
+ }
1825
+ let t46;
1826
+ if ($[140] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
1827
+ t46 = /* @__PURE__ */ jsxDEV(ConnectAgentCard, {}, void 0, false);
1828
+ $[140] = t46;
1829
+ } else {
1830
+ t46 = $[140];
1831
+ }
1832
+ let t47;
1833
+ if ($[141] !== t38 || $[142] !== t45) {
1834
+ t47 = /* @__PURE__ */ jsxDEV("section", {
1835
+ className: "flex flex-col gap-3",
1836
+ "data-testid": "home-get-connected",
1837
+ children: [t38, t45, t46]
1838
+ }, void 0, true);
1839
+ $[141] = t38;
1840
+ $[142] = t45;
1841
+ $[143] = t47;
1842
+ } else {
1843
+ t47 = $[143];
1844
+ }
1845
+ let t48;
1846
+ if ($[144] !== t18 || $[145] !== t19 || $[146] !== t26 || $[147] !== t32 || $[148] !== t36 || $[149] !== t47) {
1847
+ t48 = /* @__PURE__ */ jsxDEV("div", {
1848
+ className: t18,
1849
+ "data-testid": t19,
1850
+ children: [t26, t27, t32, t36, t47]
1851
+ }, void 0, true);
1852
+ $[144] = t18;
1853
+ $[145] = t19;
1854
+ $[146] = t26;
1855
+ $[147] = t32;
1856
+ $[148] = t36;
1857
+ $[149] = t47;
1858
+ $[150] = t48;
1859
+ } else {
1860
+ t48 = $[150];
1861
+ }
1862
+ return t48;
1863
+ };
1864
+ function _temp(a, b) {
1865
+ return b.calls - a.calls;
1866
+ }
1867
+ function _temp2(function_) {
1868
+ return /* @__PURE__ */ jsxDEV("div", {
1869
+ className: "grid grid-cols-[1fr_auto_auto_auto] items-center gap-4 px-4 py-2 text-[13px]",
1870
+ children: [/* @__PURE__ */ jsxDEV("span", {
1871
+ className: "truncate font-mono text-xs text-foreground",
1872
+ children: function_.path
1873
+ }, void 0, false), /* @__PURE__ */ jsxDEV("span", {
1874
+ className: "text-end tabular-nums",
1875
+ children: function_.calls.toLocaleString()
1876
+ }, void 0, false), /* @__PURE__ */ jsxDEV("span", {
1877
+ className: "w-12 text-end tabular-nums text-muted-foreground",
1878
+ children: formatMs(function_.calls > 0 ? function_.totalDurationMs / function_.calls : 0)
1879
+ }, void 0, false), /* @__PURE__ */ jsxDEV("span", {
1880
+ className: cn("w-8 text-end tabular-nums", function_.errors > 0 ? "text-destructive" : "text-muted-foreground"),
1881
+ children: function_.errors
1882
+ }, void 0, false)]
1883
+ }, function_.path, true);
1884
+ }
1885
+ function _temp3(function_) {
1886
+ return function_.maxDurationMs;
1887
+ }
1888
+
1889
+ export { HomePanel as H, useStudioFeatures as u };