@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,842 @@
1
+ import { c } from 'react/compiler-runtime';
2
+ import { useLunora } from '@lunora/react';
3
+ import { useState, useEffect } from 'react';
4
+ import { B as Button } from './button-BhsN2uZH.js';
5
+ import { E as EmptyState } from './empty-state-DY_oe0k6.js';
6
+ import { useT } from './createStudioI18n-CgvlmDkN.js';
7
+ import { ADMIN_FUNCTIONS } from './ADMIN_FUNCTION_PREFIX-DmBqMZ-z.js';
8
+ import { c as callOptions, a as adminRef, b as copyToClipboard } from './internal-BBZYexre.js';
9
+ import { jsxDEV } from 'react/jsx-dev-runtime';
10
+
11
+ const LIST_TABLES = adminRef(ADMIN_FUNCTIONS.listTables);
12
+ const TAB_KEYS = ["react", "client", "cli"];
13
+ const REACT_HAS_ACTION_HOOK = false;
14
+ const CLIENT_METHOD = {
15
+ action: "action",
16
+ mutation: "mutation",
17
+ query: "query"
18
+ };
19
+ const splitPath = (path) => {
20
+ const index = path.indexOf(":");
21
+ if (index === -1) {
22
+ return {
23
+ file: "",
24
+ fn: path
25
+ };
26
+ }
27
+ return {
28
+ file: path.slice(0, index),
29
+ fn: path.slice(index + 1)
30
+ };
31
+ };
32
+ const buildClientSnippet = ({
33
+ file,
34
+ fn,
35
+ kind
36
+ }) => `await client.${CLIENT_METHOD[kind]}(api.${file}.${fn}, { /* args */ });`;
37
+ const buildReactSnippet = (input) => {
38
+ const reference = `api.${input.file}.${input.fn}`;
39
+ switch (input.kind) {
40
+ case "action": {
41
+ return buildClientSnippet(input);
42
+ }
43
+ case "mutation": {
44
+ return `const ${input.fn} = useMutation(${reference});`;
45
+ }
46
+ default: {
47
+ return `const data = useQuery(${reference}, { /* args */ });`;
48
+ }
49
+ }
50
+ };
51
+ const buildCliSnippet = ({
52
+ file,
53
+ fn
54
+ }) => `lunora run ${file}:${fn} --args '{ }'`;
55
+ const buildTableSnippet = (table) => [`// Read rows`, `const rows = await ctx.db.query("${table}").collect();`, ``, `// Insert a row`, `const id = await ctx.db.insert("${table}", { /* fields */ });`, ``, `// Generated types`, `type Row = Doc<"${table}">;`, `type RowId = Id<"${table}">;`].join("\n");
56
+ const snippetForTab = (tab, input) => {
57
+ switch (tab) {
58
+ case "cli": {
59
+ return buildCliSnippet(input);
60
+ }
61
+ case "client": {
62
+ return buildClientSnippet(input);
63
+ }
64
+ default: {
65
+ return buildReactSnippet(input);
66
+ }
67
+ }
68
+ };
69
+ const SnippetBlock = (t0) => {
70
+ const $ = c(19);
71
+ const {
72
+ code,
73
+ label,
74
+ testId
75
+ } = t0;
76
+ const t = useT();
77
+ let t1;
78
+ if ($[0] !== code) {
79
+ t1 = () => {
80
+ copyToClipboard(code);
81
+ };
82
+ $[0] = code;
83
+ $[1] = t1;
84
+ } else {
85
+ t1 = $[1];
86
+ }
87
+ const onCopy = t1;
88
+ let t2;
89
+ if ($[2] !== label) {
90
+ t2 = /* @__PURE__ */ jsxDEV("span", {
91
+ className: "text-xs font-medium text-muted-foreground",
92
+ children: label
93
+ }, void 0, false);
94
+ $[2] = label;
95
+ $[3] = t2;
96
+ } else {
97
+ t2 = $[3];
98
+ }
99
+ const t3 = `${testId}-copy`;
100
+ let t4;
101
+ if ($[4] !== t) {
102
+ t4 = t("Copy");
103
+ $[4] = t;
104
+ $[5] = t4;
105
+ } else {
106
+ t4 = $[5];
107
+ }
108
+ let t5;
109
+ if ($[6] !== onCopy || $[7] !== t3 || $[8] !== t4) {
110
+ t5 = /* @__PURE__ */ jsxDEV(Button, {
111
+ "data-testid": t3,
112
+ onClick: onCopy,
113
+ size: "xs",
114
+ type: "button",
115
+ variant: "ghost",
116
+ children: t4
117
+ }, void 0, false);
118
+ $[6] = onCopy;
119
+ $[7] = t3;
120
+ $[8] = t4;
121
+ $[9] = t5;
122
+ } else {
123
+ t5 = $[9];
124
+ }
125
+ let t6;
126
+ if ($[10] !== t2 || $[11] !== t5) {
127
+ t6 = /* @__PURE__ */ jsxDEV("div", {
128
+ className: "flex items-center justify-between gap-2",
129
+ children: [t2, t5]
130
+ }, void 0, true);
131
+ $[10] = t2;
132
+ $[11] = t5;
133
+ $[12] = t6;
134
+ } else {
135
+ t6 = $[12];
136
+ }
137
+ let t7;
138
+ if ($[13] !== code || $[14] !== testId) {
139
+ t7 = /* @__PURE__ */ jsxDEV("pre", {
140
+ className: "overflow-auto rounded-md border border-border bg-muted/50 p-3 font-mono text-xs",
141
+ "data-testid": testId,
142
+ children: code
143
+ }, void 0, false);
144
+ $[13] = code;
145
+ $[14] = testId;
146
+ $[15] = t7;
147
+ } else {
148
+ t7 = $[15];
149
+ }
150
+ let t8;
151
+ if ($[16] !== t6 || $[17] !== t7) {
152
+ t8 = /* @__PURE__ */ jsxDEV("div", {
153
+ className: "flex flex-col gap-1.5",
154
+ children: [t6, t7]
155
+ }, void 0, true);
156
+ $[16] = t6;
157
+ $[17] = t7;
158
+ $[18] = t8;
159
+ } else {
160
+ t8 = $[18];
161
+ }
162
+ return t8;
163
+ };
164
+ const FunctionDoc = (t0) => {
165
+ const $ = c(50);
166
+ const {
167
+ file,
168
+ fn,
169
+ kind
170
+ } = t0;
171
+ const t = useT();
172
+ const [tab, setTab] = useState("react");
173
+ let selectTab;
174
+ let t1;
175
+ let tabLabel;
176
+ if ($[0] !== file || $[1] !== fn || $[2] !== kind || $[3] !== t || $[4] !== tab) {
177
+ const input = {
178
+ file,
179
+ fn,
180
+ kind
181
+ };
182
+ let t22;
183
+ if ($[8] !== t) {
184
+ t22 = t("CLI");
185
+ $[8] = t;
186
+ $[9] = t22;
187
+ } else {
188
+ t22 = $[9];
189
+ }
190
+ let t32;
191
+ if ($[10] !== t) {
192
+ t32 = t("Client");
193
+ $[10] = t;
194
+ $[11] = t32;
195
+ } else {
196
+ t32 = $[11];
197
+ }
198
+ let t42;
199
+ if ($[12] !== t) {
200
+ t42 = t("React");
201
+ $[12] = t;
202
+ $[13] = t42;
203
+ } else {
204
+ t42 = $[13];
205
+ }
206
+ let t52;
207
+ if ($[14] !== t22 || $[15] !== t32 || $[16] !== t42) {
208
+ t52 = {
209
+ cli: t22,
210
+ client: t32,
211
+ react: t42
212
+ };
213
+ $[14] = t22;
214
+ $[15] = t32;
215
+ $[16] = t42;
216
+ $[17] = t52;
217
+ } else {
218
+ t52 = $[17];
219
+ }
220
+ tabLabel = t52;
221
+ let t62;
222
+ if ($[18] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
223
+ t62 = (event) => {
224
+ setTab(event.currentTarget.dataset.tab);
225
+ };
226
+ $[18] = t62;
227
+ } else {
228
+ t62 = $[18];
229
+ }
230
+ selectTab = t62;
231
+ t1 = snippetForTab(tab, input);
232
+ $[0] = file;
233
+ $[1] = fn;
234
+ $[2] = kind;
235
+ $[3] = t;
236
+ $[4] = tab;
237
+ $[5] = selectTab;
238
+ $[6] = t1;
239
+ $[7] = tabLabel;
240
+ } else {
241
+ selectTab = $[5];
242
+ t1 = $[6];
243
+ tabLabel = $[7];
244
+ }
245
+ const code = t1;
246
+ const actionFellBack = kind === "action" && tab === "react" && !REACT_HAS_ACTION_HOOK;
247
+ const t2 = `api.${file}.${fn}`;
248
+ let t3;
249
+ if ($[19] !== t2) {
250
+ t3 = /* @__PURE__ */ jsxDEV("h2", {
251
+ className: "font-mono text-sm font-semibold text-foreground",
252
+ "data-testid": "api-fn-title",
253
+ children: t2
254
+ }, void 0, false);
255
+ $[19] = t2;
256
+ $[20] = t3;
257
+ } else {
258
+ t3 = $[20];
259
+ }
260
+ let t4;
261
+ if ($[21] !== kind || $[22] !== t) {
262
+ t4 = t("Call this {kind} from your app.", {
263
+ kind
264
+ });
265
+ $[21] = kind;
266
+ $[22] = t;
267
+ $[23] = t4;
268
+ } else {
269
+ t4 = $[23];
270
+ }
271
+ let t5;
272
+ if ($[24] !== t4) {
273
+ t5 = /* @__PURE__ */ jsxDEV("p", {
274
+ className: "text-xs text-muted-foreground",
275
+ children: t4
276
+ }, void 0, false);
277
+ $[24] = t4;
278
+ $[25] = t5;
279
+ } else {
280
+ t5 = $[25];
281
+ }
282
+ let t6;
283
+ if ($[26] !== t3 || $[27] !== t5) {
284
+ t6 = /* @__PURE__ */ jsxDEV("div", {
285
+ children: [t3, t5]
286
+ }, void 0, true);
287
+ $[26] = t3;
288
+ $[27] = t5;
289
+ $[28] = t6;
290
+ } else {
291
+ t6 = $[28];
292
+ }
293
+ let t7;
294
+ if ($[29] !== t) {
295
+ t7 = t("Snippet flavour");
296
+ $[29] = t;
297
+ $[30] = t7;
298
+ } else {
299
+ t7 = $[30];
300
+ }
301
+ let t8;
302
+ if ($[31] !== selectTab || $[32] !== tab || $[33] !== tabLabel) {
303
+ t8 = TAB_KEYS.map((key) => /* @__PURE__ */ jsxDEV(Button, {
304
+ "aria-selected": tab === key,
305
+ "data-tab": key,
306
+ "data-testid": `api-tab-${key}`,
307
+ onClick: selectTab,
308
+ role: "tab",
309
+ size: "xs",
310
+ type: "button",
311
+ variant: tab === key ? "default" : "outline",
312
+ children: tabLabel[key]
313
+ }, key, false));
314
+ $[31] = selectTab;
315
+ $[32] = tab;
316
+ $[33] = tabLabel;
317
+ $[34] = t8;
318
+ } else {
319
+ t8 = $[34];
320
+ }
321
+ let t9;
322
+ if ($[35] !== t7 || $[36] !== t8) {
323
+ t9 = /* @__PURE__ */ jsxDEV("div", {
324
+ "aria-label": t7,
325
+ className: "flex gap-1.5",
326
+ "data-testid": "api-tabs",
327
+ role: "tablist",
328
+ children: t8
329
+ }, void 0, false);
330
+ $[35] = t7;
331
+ $[36] = t8;
332
+ $[37] = t9;
333
+ } else {
334
+ t9 = $[37];
335
+ }
336
+ const t10 = tabLabel[tab];
337
+ const t11 = `api-snippet-${tab}`;
338
+ let t12;
339
+ if ($[38] !== code || $[39] !== t10 || $[40] !== t11) {
340
+ t12 = /* @__PURE__ */ jsxDEV(SnippetBlock, {
341
+ code,
342
+ label: t10,
343
+ testId: t11
344
+ }, void 0, false);
345
+ $[38] = code;
346
+ $[39] = t10;
347
+ $[40] = t11;
348
+ $[41] = t12;
349
+ } else {
350
+ t12 = $[41];
351
+ }
352
+ let t13;
353
+ if ($[42] !== actionFellBack || $[43] !== t) {
354
+ t13 = actionFellBack && /* @__PURE__ */ jsxDEV("p", {
355
+ className: "text-xs text-muted-foreground",
356
+ "data-testid": "api-action-note",
357
+ children: t("Actions have no React hook — call them through the client.")
358
+ }, void 0, false);
359
+ $[42] = actionFellBack;
360
+ $[43] = t;
361
+ $[44] = t13;
362
+ } else {
363
+ t13 = $[44];
364
+ }
365
+ let t14;
366
+ if ($[45] !== t12 || $[46] !== t13 || $[47] !== t6 || $[48] !== t9) {
367
+ t14 = /* @__PURE__ */ jsxDEV("div", {
368
+ className: "flex flex-col gap-3",
369
+ "data-testid": "api-fn-doc",
370
+ children: [t6, t9, t12, t13]
371
+ }, void 0, true);
372
+ $[45] = t12;
373
+ $[46] = t13;
374
+ $[47] = t6;
375
+ $[48] = t9;
376
+ $[49] = t14;
377
+ } else {
378
+ t14 = $[49];
379
+ }
380
+ return t14;
381
+ };
382
+ const TableDoc = (t0) => {
383
+ const $ = c(19);
384
+ const {
385
+ name
386
+ } = t0;
387
+ const t = useT();
388
+ let t1;
389
+ if ($[0] !== name) {
390
+ t1 = buildTableSnippet(name);
391
+ $[0] = name;
392
+ $[1] = t1;
393
+ } else {
394
+ t1 = $[1];
395
+ }
396
+ const code = t1;
397
+ let t2;
398
+ if ($[2] !== name) {
399
+ t2 = /* @__PURE__ */ jsxDEV("h2", {
400
+ className: "font-mono text-sm font-semibold text-foreground",
401
+ "data-testid": "api-table-title",
402
+ children: name
403
+ }, void 0, false);
404
+ $[2] = name;
405
+ $[3] = t2;
406
+ } else {
407
+ t2 = $[3];
408
+ }
409
+ let t3;
410
+ if ($[4] !== t) {
411
+ t3 = t("Read and write this table through the typed data model.");
412
+ $[4] = t;
413
+ $[5] = t3;
414
+ } else {
415
+ t3 = $[5];
416
+ }
417
+ let t4;
418
+ if ($[6] !== t3) {
419
+ t4 = /* @__PURE__ */ jsxDEV("p", {
420
+ className: "text-xs text-muted-foreground",
421
+ children: t3
422
+ }, void 0, false);
423
+ $[6] = t3;
424
+ $[7] = t4;
425
+ } else {
426
+ t4 = $[7];
427
+ }
428
+ let t5;
429
+ if ($[8] !== t2 || $[9] !== t4) {
430
+ t5 = /* @__PURE__ */ jsxDEV("div", {
431
+ children: [t2, t4]
432
+ }, void 0, true);
433
+ $[8] = t2;
434
+ $[9] = t4;
435
+ $[10] = t5;
436
+ } else {
437
+ t5 = $[10];
438
+ }
439
+ let t6;
440
+ if ($[11] !== t) {
441
+ t6 = t("Data model");
442
+ $[11] = t;
443
+ $[12] = t6;
444
+ } else {
445
+ t6 = $[12];
446
+ }
447
+ let t7;
448
+ if ($[13] !== code || $[14] !== t6) {
449
+ t7 = /* @__PURE__ */ jsxDEV(SnippetBlock, {
450
+ code,
451
+ label: t6,
452
+ testId: "api-snippet-table"
453
+ }, void 0, false);
454
+ $[13] = code;
455
+ $[14] = t6;
456
+ $[15] = t7;
457
+ } else {
458
+ t7 = $[15];
459
+ }
460
+ let t8;
461
+ if ($[16] !== t5 || $[17] !== t7) {
462
+ t8 = /* @__PURE__ */ jsxDEV("div", {
463
+ className: "flex flex-col gap-3",
464
+ "data-testid": "api-table-doc",
465
+ children: [t5, t7]
466
+ }, void 0, true);
467
+ $[16] = t5;
468
+ $[17] = t7;
469
+ $[18] = t8;
470
+ } else {
471
+ t8 = $[18];
472
+ }
473
+ return t8;
474
+ };
475
+ const RailButton = (t0) => {
476
+ const $ = c(8);
477
+ const {
478
+ active,
479
+ label,
480
+ onSelect,
481
+ testId,
482
+ value
483
+ } = t0;
484
+ let t1;
485
+ if ($[0] !== onSelect || $[1] !== value) {
486
+ t1 = () => {
487
+ onSelect(value);
488
+ };
489
+ $[0] = onSelect;
490
+ $[1] = value;
491
+ $[2] = t1;
492
+ } else {
493
+ t1 = $[2];
494
+ }
495
+ const onClick = t1;
496
+ const t2 = active ? "page" : void 0;
497
+ let t3;
498
+ if ($[3] !== label || $[4] !== onClick || $[5] !== t2 || $[6] !== testId) {
499
+ t3 = /* @__PURE__ */ jsxDEV("button", {
500
+ "aria-current": t2,
501
+ className: "w-full truncate rounded-md px-2 py-1 text-start font-mono text-xs text-muted-foreground outline-none transition-colors hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:bg-sidebar-accent aria-[current=page]:bg-sidebar-accent aria-[current=page]:font-medium aria-[current=page]:text-foreground",
502
+ "data-testid": testId,
503
+ onClick,
504
+ type: "button",
505
+ children: label
506
+ }, void 0, false);
507
+ $[3] = label;
508
+ $[4] = onClick;
509
+ $[5] = t2;
510
+ $[6] = testId;
511
+ $[7] = t3;
512
+ } else {
513
+ t3 = $[7];
514
+ }
515
+ return t3;
516
+ };
517
+ const ApiDocsPanel = (t0) => {
518
+ const $ = c(67);
519
+ const {
520
+ functions,
521
+ initialShardKey
522
+ } = t0;
523
+ const t = useT();
524
+ const client = useLunora();
525
+ const [tables, setTables] = useState(null);
526
+ const [selected, setSelected] = useState(null);
527
+ let t1;
528
+ let t2;
529
+ if ($[0] !== client || $[1] !== initialShardKey) {
530
+ t1 = () => {
531
+ let cancelled = false;
532
+ client.query(LIST_TABLES, {}, callOptions(initialShardKey ?? "")).then((result) => {
533
+ if (!cancelled) {
534
+ setTables(result);
535
+ }
536
+ return result;
537
+ }).catch(() => {
538
+ if (!cancelled) {
539
+ setTables([]);
540
+ }
541
+ });
542
+ return () => {
543
+ cancelled = true;
544
+ };
545
+ };
546
+ t2 = [client, initialShardKey];
547
+ $[0] = client;
548
+ $[1] = initialShardKey;
549
+ $[2] = t1;
550
+ $[3] = t2;
551
+ } else {
552
+ t1 = $[2];
553
+ t2 = $[3];
554
+ }
555
+ useEffect(t1, t2);
556
+ let t3;
557
+ if ($[4] !== functions) {
558
+ t3 = functions ?? [];
559
+ $[4] = functions;
560
+ $[5] = t3;
561
+ } else {
562
+ t3 = $[5];
563
+ }
564
+ const functionList = t3;
565
+ let t4;
566
+ if ($[6] !== functionList) {
567
+ const byFile = /* @__PURE__ */ new Map();
568
+ for (const descriptor of functionList) {
569
+ const {
570
+ file,
571
+ fn
572
+ } = splitPath(descriptor.path);
573
+ const bucket = byFile.get(file) ?? [];
574
+ bucket.push({
575
+ fn,
576
+ kind: descriptor.kind,
577
+ path: descriptor.path
578
+ });
579
+ byFile.set(file, bucket);
580
+ }
581
+ t4 = [...byFile.entries()].map(_temp2).toSorted(_temp3);
582
+ $[6] = functionList;
583
+ $[7] = t4;
584
+ } else {
585
+ t4 = $[7];
586
+ }
587
+ const grouped = t4;
588
+ let hasResources;
589
+ let selectedFunction;
590
+ let selectedSplit;
591
+ let t10;
592
+ let t11;
593
+ let t5;
594
+ let t6;
595
+ let t7;
596
+ let t8;
597
+ let t9;
598
+ if ($[8] !== functionList || $[9] !== grouped || $[10] !== selected || $[11] !== t || $[12] !== tables) {
599
+ const tableNames = (tables ?? []).map(_temp4).toSorted(_temp5);
600
+ let t122;
601
+ if ($[23] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
602
+ t122 = (path) => {
603
+ setSelected({
604
+ kind: "fn",
605
+ path
606
+ });
607
+ };
608
+ $[23] = t122;
609
+ } else {
610
+ t122 = $[23];
611
+ }
612
+ const selectFunction = t122;
613
+ let t132;
614
+ if ($[24] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
615
+ t132 = (name) => {
616
+ setSelected({
617
+ kind: "table",
618
+ name
619
+ });
620
+ };
621
+ $[24] = t132;
622
+ } else {
623
+ t132 = $[24];
624
+ }
625
+ const selectTable = t132;
626
+ selectedFunction = selected?.kind === "fn" ? functionList.find((descriptor_0) => descriptor_0.path === selected.path) : void 0;
627
+ hasResources = functionList.length > 0 || tableNames.length > 0;
628
+ selectedSplit = selectedFunction === void 0 ? void 0 : splitPath(selectedFunction.path);
629
+ t10 = "grid min-h-0 gap-6 md:grid-cols-[16rem_minmax(0,1fr)]";
630
+ t11 = "lunora-api-docs";
631
+ if ($[25] !== t) {
632
+ t5 = t("API resources");
633
+ $[25] = t;
634
+ $[26] = t5;
635
+ } else {
636
+ t5 = $[26];
637
+ }
638
+ t6 = "flex flex-col gap-4 overflow-y-auto";
639
+ t7 = "api-rail";
640
+ if ($[27] !== grouped || $[28] !== selected || $[29] !== t) {
641
+ let t142;
642
+ if ($[31] !== selected || $[32] !== t) {
643
+ t142 = (group) => /* @__PURE__ */ jsxDEV("div", {
644
+ className: "flex flex-col gap-1",
645
+ children: [/* @__PURE__ */ jsxDEV("span", {
646
+ className: "px-2 font-mono text-[11px] tracking-wide text-muted-foreground uppercase",
647
+ children: group.file || t("(root)")
648
+ }, void 0, false), group.items.map((item) => /* @__PURE__ */ jsxDEV(RailButton, {
649
+ active: selected?.kind === "fn" && selected.path === item.path,
650
+ label: item.fn,
651
+ onSelect: selectFunction,
652
+ testId: `api-rail-fn-${item.path}`,
653
+ value: item.path
654
+ }, item.path, false))]
655
+ }, group.file, true);
656
+ $[31] = selected;
657
+ $[32] = t;
658
+ $[33] = t142;
659
+ } else {
660
+ t142 = $[33];
661
+ }
662
+ t8 = grouped.map(t142);
663
+ $[27] = grouped;
664
+ $[28] = selected;
665
+ $[29] = t;
666
+ $[30] = t8;
667
+ } else {
668
+ t8 = $[30];
669
+ }
670
+ t9 = tableNames.length > 0 && /* @__PURE__ */ jsxDEV("div", {
671
+ className: "flex flex-col gap-1",
672
+ children: [/* @__PURE__ */ jsxDEV("span", {
673
+ className: "px-2 font-mono text-[11px] tracking-wide text-muted-foreground uppercase",
674
+ children: t("Tables")
675
+ }, void 0, false), tableNames.map((name_0) => /* @__PURE__ */ jsxDEV(RailButton, {
676
+ active: selected?.kind === "table" && selected.name === name_0,
677
+ label: name_0,
678
+ onSelect: selectTable,
679
+ testId: `api-rail-table-${name_0}`,
680
+ value: name_0
681
+ }, name_0, false))]
682
+ }, void 0, true);
683
+ $[8] = functionList;
684
+ $[9] = grouped;
685
+ $[10] = selected;
686
+ $[11] = t;
687
+ $[12] = tables;
688
+ $[13] = hasResources;
689
+ $[14] = selectedFunction;
690
+ $[15] = selectedSplit;
691
+ $[16] = t10;
692
+ $[17] = t11;
693
+ $[18] = t5;
694
+ $[19] = t6;
695
+ $[20] = t7;
696
+ $[21] = t8;
697
+ $[22] = t9;
698
+ } else {
699
+ hasResources = $[13];
700
+ selectedFunction = $[14];
701
+ selectedSplit = $[15];
702
+ t10 = $[16];
703
+ t11 = $[17];
704
+ t5 = $[18];
705
+ t6 = $[19];
706
+ t7 = $[20];
707
+ t8 = $[21];
708
+ t9 = $[22];
709
+ }
710
+ let t12;
711
+ if ($[34] !== hasResources || $[35] !== t) {
712
+ t12 = !hasResources && /* @__PURE__ */ jsxDEV("p", {
713
+ className: "px-2 text-xs text-muted-foreground",
714
+ "data-testid": "api-rail-empty",
715
+ children: t("No functions or tables to document yet.")
716
+ }, void 0, false);
717
+ $[34] = hasResources;
718
+ $[35] = t;
719
+ $[36] = t12;
720
+ } else {
721
+ t12 = $[36];
722
+ }
723
+ let t13;
724
+ if ($[37] !== t12 || $[38] !== t5 || $[39] !== t6 || $[40] !== t7 || $[41] !== t8 || $[42] !== t9) {
725
+ t13 = /* @__PURE__ */ jsxDEV("nav", {
726
+ "aria-label": t5,
727
+ className: t6,
728
+ "data-testid": t7,
729
+ children: [t8, t9, t12]
730
+ }, void 0, true);
731
+ $[37] = t12;
732
+ $[38] = t5;
733
+ $[39] = t6;
734
+ $[40] = t7;
735
+ $[41] = t8;
736
+ $[42] = t9;
737
+ $[43] = t13;
738
+ } else {
739
+ t13 = $[43];
740
+ }
741
+ let t14;
742
+ if ($[44] !== selected || $[45] !== t) {
743
+ t14 = selected === null && /* @__PURE__ */ jsxDEV(EmptyState, {
744
+ description: t("Select a function or table to see how to call it from your app."),
745
+ testId: "api-empty",
746
+ title: t("API usage snippets")
747
+ }, void 0, false);
748
+ $[44] = selected;
749
+ $[45] = t;
750
+ $[46] = t14;
751
+ } else {
752
+ t14 = $[46];
753
+ }
754
+ let t15;
755
+ if ($[47] !== selected?.kind || $[48] !== selectedFunction || $[49] !== selectedSplit) {
756
+ t15 = selected?.kind === "fn" && selectedFunction !== void 0 && selectedSplit !== void 0 && /* @__PURE__ */ jsxDEV(FunctionDoc, {
757
+ file: selectedSplit.file,
758
+ fn: selectedSplit.fn,
759
+ kind: selectedFunction.kind
760
+ }, selectedFunction.path, false);
761
+ $[47] = selected?.kind;
762
+ $[48] = selectedFunction;
763
+ $[49] = selectedSplit;
764
+ $[50] = t15;
765
+ } else {
766
+ t15 = $[50];
767
+ }
768
+ let t16;
769
+ if ($[51] !== selected?.kind || $[52] !== selectedFunction || $[53] !== t) {
770
+ t16 = selected?.kind === "fn" && selectedFunction === void 0 && /* @__PURE__ */ jsxDEV(EmptyState, {
771
+ testId: "api-empty",
772
+ title: t("API usage snippets")
773
+ }, void 0, false);
774
+ $[51] = selected?.kind;
775
+ $[52] = selectedFunction;
776
+ $[53] = t;
777
+ $[54] = t16;
778
+ } else {
779
+ t16 = $[54];
780
+ }
781
+ let t17;
782
+ if ($[55] !== selected) {
783
+ t17 = selected?.kind === "table" && /* @__PURE__ */ jsxDEV(TableDoc, {
784
+ name: selected.name
785
+ }, void 0, false);
786
+ $[55] = selected;
787
+ $[56] = t17;
788
+ } else {
789
+ t17 = $[56];
790
+ }
791
+ let t18;
792
+ if ($[57] !== t14 || $[58] !== t15 || $[59] !== t16 || $[60] !== t17) {
793
+ t18 = /* @__PURE__ */ jsxDEV("div", {
794
+ className: "min-w-0",
795
+ children: [t14, t15, t16, t17]
796
+ }, void 0, true);
797
+ $[57] = t14;
798
+ $[58] = t15;
799
+ $[59] = t16;
800
+ $[60] = t17;
801
+ $[61] = t18;
802
+ } else {
803
+ t18 = $[61];
804
+ }
805
+ let t19;
806
+ if ($[62] !== t10 || $[63] !== t11 || $[64] !== t13 || $[65] !== t18) {
807
+ t19 = /* @__PURE__ */ jsxDEV("div", {
808
+ className: t10,
809
+ "data-testid": t11,
810
+ children: [t13, t18]
811
+ }, void 0, true);
812
+ $[62] = t10;
813
+ $[63] = t11;
814
+ $[64] = t13;
815
+ $[65] = t18;
816
+ $[66] = t19;
817
+ } else {
818
+ t19 = $[66];
819
+ }
820
+ return t19;
821
+ };
822
+ function _temp(a, b) {
823
+ return a.fn.localeCompare(b.fn);
824
+ }
825
+ function _temp2(t0) {
826
+ const [file_0, items] = t0;
827
+ return {
828
+ file: file_0,
829
+ items: items.toSorted(_temp)
830
+ };
831
+ }
832
+ function _temp3(a_0, b_0) {
833
+ return a_0.file.localeCompare(b_0.file);
834
+ }
835
+ function _temp4(table) {
836
+ return table.name;
837
+ }
838
+ function _temp5(a_1, b_1) {
839
+ return a_1.localeCompare(b_1);
840
+ }
841
+
842
+ export { REACT_HAS_ACTION_HOOK, buildCliSnippet, buildClientSnippet, buildReactSnippet, buildTableSnippet, ApiDocsPanel as default, splitPath };