@rebasepro/studio 0.24.0 → 0.24.1-canary.gcb918fc

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 (48) hide show
  1. package/dist/{ApiExplorer-CCtczj3F.js → ApiExplorer-Bzt7Ye49.js} +5 -3
  2. package/dist/ApiExplorer-Bzt7Ye49.js.map +1 -0
  3. package/dist/{ApiKeysView-B66TdzhH.js → ApiKeysView-Bqf6XYR1.js} +2 -1
  4. package/dist/{ApiKeysView-B66TdzhH.js.map → ApiKeysView-Bqf6XYR1.js.map} +1 -1
  5. package/dist/{BackupsView-DmSMzAbT.js → BackupsView-BhOHB6iP.js} +6 -20
  6. package/dist/BackupsView-BhOHB6iP.js.map +1 -0
  7. package/dist/{BranchesView-DP1a87E-.js → BranchesView-BHfwGTYc.js} +5 -3
  8. package/dist/BranchesView-BHfwGTYc.js.map +1 -0
  9. package/dist/{CronJobsView-TDErHTuK.js → CronJobsView-CMNK7eWO.js} +52 -59
  10. package/dist/CronJobsView-CMNK7eWO.js.map +1 -0
  11. package/dist/{JSEditor-B59pwg4c.js → JSEditor-DIO2Mw8q.js} +115 -96
  12. package/dist/JSEditor-DIO2Mw8q.js.map +1 -0
  13. package/dist/{LogsExplorer-BKM4yfP8.js → LogsExplorer-C-bwDFIl.js} +19 -23
  14. package/dist/LogsExplorer-C-bwDFIl.js.map +1 -0
  15. package/dist/{RLSEditor-BlLLV6xs.js → RLSEditor-jFD_d06f.js} +10 -8
  16. package/dist/RLSEditor-jFD_d06f.js.map +1 -0
  17. package/dist/{SQLEditor-1An7w0j6.js → SQLEditor-D5Ci4pyW.js} +372 -545
  18. package/dist/SQLEditor-D5Ci4pyW.js.map +1 -0
  19. package/dist/{SchemaVisualizer-DCLVfA5t.js → SchemaVisualizer-D-rAqwul.js} +479 -206
  20. package/dist/SchemaVisualizer-D-rAqwul.js.map +1 -0
  21. package/dist/{StorageView-CbsHuCBf.js → StorageView-CPkDKbsX.js} +498 -241
  22. package/dist/StorageView-CPkDKbsX.js.map +1 -0
  23. package/dist/assets/dagre-layout.worker-BFnhAzuR.js.map +1 -0
  24. package/dist/components/SQLEditor/SQLEditor.d.ts +11 -0
  25. package/dist/components/SchemaVisualizer/dagre-layout.d.ts +32 -0
  26. package/dist/components/SchemaVisualizer/dagre-layout.worker.d.ts +13 -0
  27. package/dist/components/SchemaVisualizer/layout-runner.d.ts +23 -0
  28. package/dist/components/SchemaVisualizer/schema-visualizer.utils.d.ts +21 -10
  29. package/dist/components/SchemaVisualizer/useSchemaGraph.d.ts +38 -1
  30. package/dist/components/StorageView/useVisibleFileMetadata.d.ts +46 -0
  31. package/dist/dagre-layout.worker-j9NbH9Gb.js +27 -0
  32. package/dist/dagre-layout.worker-j9NbH9Gb.js.map +1 -0
  33. package/dist/index.es.js +16 -14
  34. package/dist/index.es.js.map +1 -1
  35. package/dist/sql_utils-BZD31xE3.js +478 -0
  36. package/dist/sql_utils-BZD31xE3.js.map +1 -0
  37. package/dist/utils/sql_utils.d.ts +60 -0
  38. package/package.json +9 -9
  39. package/dist/ApiExplorer-CCtczj3F.js.map +0 -1
  40. package/dist/BackupsView-DmSMzAbT.js.map +0 -1
  41. package/dist/BranchesView-DP1a87E-.js.map +0 -1
  42. package/dist/CronJobsView-TDErHTuK.js.map +0 -1
  43. package/dist/JSEditor-B59pwg4c.js.map +0 -1
  44. package/dist/LogsExplorer-BKM4yfP8.js.map +0 -1
  45. package/dist/RLSEditor-BlLLV6xs.js.map +0 -1
  46. package/dist/SQLEditor-1An7w0j6.js.map +0 -1
  47. package/dist/SchemaVisualizer-DCLVfA5t.js.map +0 -1
  48. package/dist/StorageView-CbsHuCBf.js.map +0 -1
@@ -1,6 +1,7 @@
1
1
  import { n as AuthSimulationSelector, t as useRunAsUsers } from "./useRunAsUsers-CLaAtXt6.js";
2
+ import { f as toCsv } from "./sql_utils-BZD31xE3.js";
2
3
  import { ErrorView, IconForView, useApiConfig, useModeController, useRebaseClient, useRebaseContext, useSnackbarController, useStudioCollectionRegistry, useStudioSidePanelController, useTranslation } from "@rebasepro/app";
3
- import { useCallback, useEffect, useMemo, useRef, useState } from "react";
4
+ import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
4
5
  import { Button, Chip, CircularProgress, Dialog, DialogActions, DialogContent, DialogTitle, DownloadIcon, IconButton, Menu, MenuItem, MoreVerticalIcon, PencilIcon, PlayIcon, PlusIcon, ResizablePanels, SaveIcon, Tab, Tabs, TerminalIcon, TextField, Tooltip, Trash2Icon, Typography, VirtualTable, XIcon, cls, defaultBorderMixin, iconSize } from "@rebasepro/ui";
5
6
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
6
7
  import { ALL_WHERE_FILTER_OPS } from "@rebasepro/types";
@@ -160,7 +161,7 @@ interface RebaseCMS {
160
161
  listUsers(options?: ListUsersOptions): Promise<UsersPage>;
161
162
  listUsersPaginated(options?: ListUsersOptions): Promise<UsersPage>;
162
163
  getUser(userId: string): Promise<{ user: AdminUser }>;
163
- createUser(data: { email: string; displayName?: string; password?: string; roles?: string[] }): Promise<{ user: AdminUser }>;
164
+ createUser(data: { email: string; displayName?: string; password?: string; roles?: string[]; skipPasswordPolicy?: boolean }): Promise<{ user: AdminUser }>;
164
165
  updateUser(userId: string, data: { email?: string; displayName?: string; password?: string; roles?: string[] }): Promise<{ user: AdminUser }>;
165
166
  deleteUser(userId: string): Promise<{ success: boolean }>;
166
167
  bootstrap(): Promise<{ success: boolean; message: string; user: { uid: string; roles: string[] } }>;
@@ -404,6 +405,7 @@ var QUICK_REFERENCE = [
404
405
  }
405
406
  ];
406
407
  var JSEditorSidebar = ({ collections, snippets, history, onSelectSnippet, onDeleteSnippet, onInsertCode }) => {
408
+ const { t } = useTranslation();
407
409
  const [activeTab, setActiveTab] = useState("collections");
408
410
  return /* @__PURE__ */ jsxs("div", {
409
411
  className: cls("flex flex-col h-full w-full bg-surface-card border-r", defaultBorderMixin),
@@ -419,7 +421,7 @@ var JSEditorSidebar = ({ collections, snippets, history, onSelectSnippet, onDele
419
421
  title: "Browse collections",
420
422
  children: /* @__PURE__ */ jsx("span", {
421
423
  className: "text-xs",
422
- children: "Collections"
424
+ children: t("studio_js_collections_tab")
423
425
  })
424
426
  })
425
427
  }),
@@ -458,7 +460,7 @@ var JSEditorSidebar = ({ collections, snippets, history, onSelectSnippet, onDele
458
460
  children: /* @__PURE__ */ jsx(Typography, {
459
461
  variant: "caption",
460
462
  className: "font-semibold uppercase tracking-wider text-text-disabled dark:text-text-disabled-dark",
461
- children: "Collections"
463
+ children: t("studio_js_collections_tab")
462
464
  })
463
465
  }), /* @__PURE__ */ jsx("div", {
464
466
  className: "flex-grow overflow-y-auto p-1 space-y-1 no-scrollbar",
@@ -682,6 +684,7 @@ function CollectionItem({ collection, onInsertCode }) {
682
684
  })] });
683
685
  }
684
686
  function SnippetItem({ snippet, onSelect, onDelete }) {
687
+ const { t } = useTranslation();
685
688
  return /* @__PURE__ */ jsxs("div", {
686
689
  className: cls("group p-2 rounded border hover:border-hairline-strong bg-surface-card transition-all cursor-pointer relative", defaultBorderMixin),
687
690
  onClick: () => onSelect(snippet.code),
@@ -697,6 +700,7 @@ function SnippetItem({ snippet, onSelect, onDelete }) {
697
700
  children: snippet.code
698
701
  }),
699
702
  /* @__PURE__ */ jsx(IconButton, {
703
+ "aria-label": t("delete"),
700
704
  size: "smallest",
701
705
  className: "absolute right-1 top-1 opacity-0 group-hover:opacity-100 text-text-disabled hover:text-red-500 transition-opacity",
702
706
  onClick: (e) => {
@@ -1144,13 +1148,97 @@ function JSEditor() {
1144
1148
  entityId: rowData[mc.pkColumn]
1145
1149
  }));
1146
1150
  }, [matchedCollections]);
1151
+ const resultColumns = useMemo(() => matchedCollections.length > 0 ? [{
1152
+ key: "__entity_action__",
1153
+ title: "",
1154
+ width: 36,
1155
+ sortable: false,
1156
+ resizable: false
1157
+ }, ...tableData.columns] : tableData.columns, [matchedCollections.length, tableData.columns]);
1158
+ const renderResultCell = useCallback(({ rowData, column }) => {
1159
+ if (column.key === "__entity_action__") {
1160
+ const rowActions = getRowEntityActions(rowData ?? {});
1161
+ if (rowActions.length === 0) return /* @__PURE__ */ jsx("div", { className: "h-full w-full" });
1162
+ if (rowActions.length === 1) {
1163
+ const ra = rowActions[0];
1164
+ return /* @__PURE__ */ jsx("div", {
1165
+ className: "h-full flex items-center justify-center",
1166
+ children: /* @__PURE__ */ jsx(Tooltip, {
1167
+ title: t("studio_sql_edit_entity", {
1168
+ name: ra.collection.collection.name,
1169
+ id: String(ra.entityId)
1170
+ }),
1171
+ children: /* @__PURE__ */ jsx(IconButton, {
1172
+ "aria-label": t("studio_sql_edit_entity", {
1173
+ name: ra.collection.collection.name,
1174
+ id: String(ra.entityId)
1175
+ }),
1176
+ size: "small",
1177
+ className: "text-surface-400 dark:text-surface-500 hover:text-surface-600 dark:hover:text-surface-300",
1178
+ onClick: (e) => {
1179
+ e.stopPropagation();
1180
+ sidePanelController.open({
1181
+ path: ra.collection.collectionSlug,
1182
+ entityId: ra.entityId,
1183
+ collection: ra.collection.collection,
1184
+ updateUrl: false
1185
+ });
1186
+ },
1187
+ children: /* @__PURE__ */ jsx(PencilIcon, { size: iconSize.smallest })
1188
+ })
1189
+ })
1190
+ });
1191
+ }
1192
+ return /* @__PURE__ */ jsx("div", {
1193
+ className: "h-full flex items-center justify-center",
1194
+ children: /* @__PURE__ */ jsx(Menu, {
1195
+ trigger: /* @__PURE__ */ jsx(IconButton, {
1196
+ "aria-label": t("more_actions"),
1197
+ size: "small",
1198
+ className: "text-surface-400 dark:text-surface-500 hover:text-surface-600 dark:hover:text-surface-300",
1199
+ onClick: (e) => e.stopPropagation(),
1200
+ children: /* @__PURE__ */ jsx(MoreVerticalIcon, { size: iconSize.smallest })
1201
+ }),
1202
+ children: rowActions.map((ra) => /* @__PURE__ */ jsx(MenuItem, {
1203
+ dense: true,
1204
+ onClick: () => {
1205
+ sidePanelController.open({
1206
+ path: ra.collection.collectionSlug,
1207
+ entityId: ra.entityId,
1208
+ collection: ra.collection.collection,
1209
+ updateUrl: false
1210
+ });
1211
+ },
1212
+ children: t("studio_sql_edit_entity", {
1213
+ name: ra.collection.collection.name,
1214
+ id: String(ra.entityId)
1215
+ })
1216
+ }, ra.collection.collectionSlug))
1217
+ })
1218
+ });
1219
+ }
1220
+ if (!rowData) return null;
1221
+ const val = rowData[column.key];
1222
+ const displayValue = typeof val === "object" && val !== null ? JSON.stringify(val) : String(val ?? "");
1223
+ return /* @__PURE__ */ jsx("div", {
1224
+ className: "px-4 py-1.5 h-full flex items-center whitespace-nowrap text-[13px] text-text-primary dark:text-text-primary-dark font-mono",
1225
+ children: /* @__PURE__ */ jsx("div", {
1226
+ className: "truncate flex-grow",
1227
+ title: displayValue,
1228
+ children: displayValue === "" ? /* @__PURE__ */ jsx("span", {
1229
+ className: "text-text-disabled dark:text-text-disabled-dark italic text-[11px]",
1230
+ children: "NULL"
1231
+ }) : displayValue
1232
+ })
1233
+ });
1234
+ }, [
1235
+ getRowEntityActions,
1236
+ sidePanelController,
1237
+ t
1238
+ ]);
1147
1239
  const handleExportCSV = useCallback(() => {
1148
1240
  if (tableData.data.length === 0) return;
1149
- const csv = [tableData.columns.map((c) => c.key).join(","), ...tableData.data.map((row) => tableData.columns.map((c) => {
1150
- const val = row[c.key];
1151
- const str = val === null || val === void 0 ? "" : String(val);
1152
- return str.includes(",") ? `"${str}"` : str;
1153
- }).join(","))].join("\n");
1241
+ const csv = toCsv(tableData.columns.map((c) => c.key), tableData.data);
1154
1242
  const blob = new Blob([csv], { type: "text/csv" });
1155
1243
  const url = URL.createObjectURL(blob);
1156
1244
  const a = document.createElement("a");
@@ -1192,6 +1280,7 @@ function JSEditor() {
1192
1280
  children: [/* @__PURE__ */ jsx("div", {
1193
1281
  className: "flex-grow overflow-hidden",
1194
1282
  children: /* @__PURE__ */ jsx(ResizablePanels, {
1283
+ dividerAriaLabel: t("resize_sidebar"),
1195
1284
  orientation: "horizontal",
1196
1285
  panelSizePercent: sidebarSize,
1197
1286
  onPanelSizeChange: setSidebarSize,
@@ -1231,6 +1320,7 @@ function JSEditor() {
1231
1320
  children: tab.name
1232
1321
  }),
1233
1322
  tabs.length > 1 && /* @__PURE__ */ jsx(IconButton, {
1323
+ "aria-label": t("close_tab"),
1234
1324
  size: "smallest",
1235
1325
  onClick: (e) => {
1236
1326
  e.stopPropagation();
@@ -1242,6 +1332,7 @@ function JSEditor() {
1242
1332
  ]
1243
1333
  }, tab.id))
1244
1334
  }), /* @__PURE__ */ jsx(IconButton, {
1335
+ "aria-label": t("new_tab"),
1245
1336
  size: "small",
1246
1337
  onClick: addTab,
1247
1338
  className: "ml-2 flex-shrink-0",
@@ -1291,6 +1382,7 @@ function JSEditor() {
1291
1382
  }), /* @__PURE__ */ jsx("div", {
1292
1383
  className: "flex-grow overflow-hidden",
1293
1384
  children: /* @__PURE__ */ jsx(ResizablePanels, {
1385
+ dividerAriaLabel: t("resize_editor"),
1294
1386
  orientation: "vertical",
1295
1387
  panelSizePercent: editorHeight,
1296
1388
  onPanelSizeChange: setEditorHeight,
@@ -1448,91 +1540,10 @@ function JSEditor() {
1448
1540
  className: "flex-grow relative h-full min-h-0 min-w-0",
1449
1541
  children: /* @__PURE__ */ jsx(VirtualTable, {
1450
1542
  data: tableData.data,
1451
- columns: matchedCollections.length > 0 ? [{
1452
- key: "__entity_action__",
1453
- title: "",
1454
- width: 36,
1455
- sortable: false,
1456
- resizable: false
1457
- }, ...tableData.columns] : tableData.columns,
1543
+ columns: resultColumns,
1458
1544
  rowHeight: 32,
1459
1545
  headerHeight: 32,
1460
- cellRenderer: ({ rowData, column, rowIndex }) => {
1461
- if (column.key === "__entity_action__") {
1462
- const rowActions = getRowEntityActions(rowData ?? {});
1463
- if (rowActions.length === 0) return /* @__PURE__ */ jsx("div", { className: "h-full w-full" });
1464
- if (rowActions.length === 1) {
1465
- const ra = rowActions[0];
1466
- return /* @__PURE__ */ jsx("div", {
1467
- className: "h-full flex items-center justify-center",
1468
- children: /* @__PURE__ */ jsx(Tooltip, {
1469
- title: t("studio_sql_edit_entity", {
1470
- name: ra.collection.collection.name,
1471
- id: String(ra.entityId)
1472
- }),
1473
- children: /* @__PURE__ */ jsx(IconButton, {
1474
- "aria-label": t("studio_sql_edit_entity", {
1475
- name: ra.collection.collection.name,
1476
- id: String(ra.entityId)
1477
- }),
1478
- size: "small",
1479
- className: "text-surface-400 dark:text-surface-500 hover:text-surface-600 dark:hover:text-surface-300",
1480
- onClick: (e) => {
1481
- e.stopPropagation();
1482
- sidePanelController.open({
1483
- path: ra.collection.collectionSlug,
1484
- entityId: ra.entityId,
1485
- collection: ra.collection.collection,
1486
- updateUrl: false
1487
- });
1488
- },
1489
- children: /* @__PURE__ */ jsx(PencilIcon, { size: iconSize.smallest })
1490
- })
1491
- })
1492
- });
1493
- }
1494
- return /* @__PURE__ */ jsx("div", {
1495
- className: "h-full flex items-center justify-center",
1496
- children: /* @__PURE__ */ jsx(Menu, {
1497
- trigger: /* @__PURE__ */ jsx(IconButton, {
1498
- size: "small",
1499
- className: "text-surface-400 dark:text-surface-500 hover:text-surface-600 dark:hover:text-surface-300",
1500
- onClick: (e) => e.stopPropagation(),
1501
- children: /* @__PURE__ */ jsx(MoreVerticalIcon, { size: iconSize.smallest })
1502
- }),
1503
- children: rowActions.map((ra) => /* @__PURE__ */ jsx(MenuItem, {
1504
- dense: true,
1505
- onClick: () => {
1506
- sidePanelController.open({
1507
- path: ra.collection.collectionSlug,
1508
- entityId: ra.entityId,
1509
- collection: ra.collection.collection,
1510
- updateUrl: false
1511
- });
1512
- },
1513
- children: t("studio_sql_edit_entity", {
1514
- name: ra.collection.collection.name,
1515
- id: String(ra.entityId)
1516
- })
1517
- }, ra.collection.collectionSlug))
1518
- })
1519
- });
1520
- }
1521
- if (!rowData) return null;
1522
- const val = rowData[column.key];
1523
- const displayValue = typeof val === "object" && val !== null ? JSON.stringify(val) : String(val ?? "");
1524
- return /* @__PURE__ */ jsx("div", {
1525
- className: "px-4 py-1.5 h-full flex items-center whitespace-nowrap text-[13px] text-text-primary dark:text-text-primary-dark font-mono",
1526
- children: /* @__PURE__ */ jsx("div", {
1527
- className: "truncate flex-grow",
1528
- title: displayValue,
1529
- children: displayValue === "" ? /* @__PURE__ */ jsx("span", {
1530
- className: "text-text-disabled dark:text-text-disabled-dark italic text-[11px]",
1531
- children: "NULL"
1532
- }) : displayValue
1533
- })
1534
- });
1535
- }
1546
+ cellRenderer: renderResultCell
1536
1547
  })
1537
1548
  })]
1538
1549
  }),
@@ -1559,7 +1570,7 @@ function JSEditor() {
1559
1570
  children: "Return Value"
1560
1571
  }), /* @__PURE__ */ jsx("pre", {
1561
1572
  className: "text-text-primary dark:text-text-primary-dark whitespace-pre-wrap break-words text-[12px]",
1562
- children: formatJSON(result.value)
1573
+ children: /* @__PURE__ */ jsx(FormattedJSON, { value: result.value })
1563
1574
  })]
1564
1575
  })]
1565
1576
  })
@@ -1651,7 +1662,11 @@ function JSEditor() {
1651
1662
  })]
1652
1663
  });
1653
1664
  }
1654
- function JSONHighlight({ value }) {
1665
+ /**
1666
+ * Memoised on the value: tokenising a large result is the costliest thing
1667
+ * this pane draws, and it used to run again for every keystroke in the editor.
1668
+ */
1669
+ var JSONHighlight = React.memo(function JSONHighlight({ value }) {
1655
1670
  const json = formatJSON(value);
1656
1671
  const { mode } = useModeController();
1657
1672
  return /* @__PURE__ */ jsx(Highlight, {
@@ -1669,8 +1684,12 @@ function JSONHighlight({ value }) {
1669
1684
  }, i))
1670
1685
  })
1671
1686
  });
1672
- }
1687
+ });
1688
+ /** A value as indented JSON, formatted again only when the value changes. */
1689
+ var FormattedJSON = React.memo(function FormattedJSON({ value }) {
1690
+ return /* @__PURE__ */ jsx(Fragment, { children: formatJSON(value) });
1691
+ });
1673
1692
  //#endregion
1674
1693
  export { JSEditor };
1675
1694
 
1676
- //# sourceMappingURL=JSEditor-B59pwg4c.js.map
1695
+ //# sourceMappingURL=JSEditor-DIO2Mw8q.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"JSEditor-DIO2Mw8q.js","names":[],"sources":["../src/components/JSEditor/JSMonacoEditor.tsx","../src/components/JSEditor/JSEditorSidebar.tsx","../src/components/JSEditor/JSEditor.tsx"],"sourcesContent":["\nimport React, { useRef, useEffect } from \"react\";\nimport Editor, { Monaco, OnMount } from \"@monaco-editor/react\";\nimport type { editor } from \"monaco-editor\";\nimport { cls, defaultBorderMixin, FileIcon } from \"@rebasepro/ui\";\nimport { useModeController } from \"@rebasepro/app\";\nimport { ALL_WHERE_FILTER_OPS } from \"@rebasepro/types\";\n\n/**\n * Shape of `monaco.languages.typescript` at runtime.\n * The bundled type stubs mark this API as deprecated, but it is fully functional.\n */\ninterface MonacoTypeScriptApi {\n typescriptDefaults: {\n setCompilerOptions(options: Record<string, unknown>): void;\n setDiagnosticsOptions(options: Record<string, unknown>): void;\n addExtraLib(content: string, filePath: string): void;\n };\n ScriptTarget: Record<string, number>;\n ModuleKind: Record<string, number>;\n}\n\n/**\n * Ambient type definitions for the Rebase client SDK injected into Monaco.\n *\n * Hand-mirrored from `@rebasepro/client`, so it drifts: this block spent long\n * enough declaring the ten Firestore-era filter operators and a\n * `where?: Record<string, string>` that the editor was autocompleting a query\n * shape the server rejects. The operator union is interpolated from\n * {@link ALL_WHERE_FILTER_OPS} for that reason — it is the one part that cannot\n * fall behind. The rest still has to be kept in step by hand.\n */\nconst REBASE_CLIENT_TYPES = `\n// ─── Rebase Client SDK Type Definitions ─────────────────────────────\n\n/** A flat database row with the id merged at the top level. */\n\ninterface FindParams {\n limit?: number;\n offset?: number;\n page?: number;\n /** \\`{ status: [\"==\", \"active\"] }\\` — a tuple per field, or an array of tuples. */\n where?: Record<string, [WhereFilterOp, any] | [WhereFilterOp, any][]>;\n logical?: LogicalCondition;\n /** \\`[\"created_at\", \"desc\"]\\` */\n orderBy?: [string, \"asc\" | \"desc\"];\n include?: string[];\n searchString?: string;\n}\n\ninterface FindResult<M extends Record<string, any> = any> {\n data: M[];\n meta: {\n total: number;\n limit: number;\n offset: number;\n hasMore: boolean;\n };\n}\n\ntype WhereFilterOp = ${ALL_WHERE_FILTER_OPS.map(op => `\"${op}\"`).join(\" | \")};\n\ninterface FilterCondition {\n column: string;\n operator: WhereFilterOp;\n value: any;\n}\n\ninterface LogicalCondition {\n type: \"and\" | \"or\";\n conditions: (FilterCondition | LogicalCondition)[];\n}\n\ninterface QueryBuilder<M extends Record<string, any> = any> {\n where(column: keyof M & string, operator: WhereFilterOp, value: any): QueryBuilder<M>;\n orderBy(column: keyof M & string, direction?: \"asc\" | \"desc\"): QueryBuilder<M>;\n limit(count: number): QueryBuilder<M>;\n offset(count: number): QueryBuilder<M>;\n search(searchString: string): QueryBuilder<M>;\n find(): Promise<FindResult<M>>;\n count(): Promise<number>;\n}\n\ninterface CollectionClient<M extends Record<string, any> = any> {\n find(params?: FindParams): Promise<FindResult<M>>;\n findById(id: string | number): Promise<M | undefined>;\n create(data: Partial<M>, id?: string | number): Promise<M>;\n update(id: string | number, data: Partial<M>): Promise<M>;\n delete(id: string | number): Promise<void>;\n where(column: keyof M & string, operator: WhereFilterOp, value: any): QueryBuilder<M>;\n orderBy(column: keyof M & string, direction?: \"asc\" | \"desc\"): QueryBuilder<M>;\n limit(count: number): QueryBuilder<M>;\n offset(count: number): QueryBuilder<M>;\n search(searchString: string): QueryBuilder<M>;\n listen?(params: FindParams | undefined, onUpdate: (response: FindResult<M>) => void, onError?: (error: Error) => void): () => void;\n listenById?(id: string | number, onUpdate: (row: M | undefined) => void, onError?: (error: Error) => void): () => void;\n count?(params?: FindParams): Promise<number>;\n}\n\ninterface User {\n uid: string;\n email: string | null;\n displayName: string | null;\n photoURL: string | null;\n providerId: string;\n isAnonymous: boolean;\n emailVerified?: boolean;\n roles?: string[];\n metadata?: Record<string, unknown>;\n}\n\ninterface RebaseSession {\n accessToken: string;\n refreshToken: string;\n expiresAt: number;\n user: User;\n}\n\ntype AuthChangeEvent = 'SIGNED_IN' | 'SIGNED_OUT' | 'TOKEN_REFRESHED' | 'USER_UPDATED';\n\ninterface RebaseAuth {\n signInWithEmail(email: string, password: string): Promise<{ user: User; accessToken: string; refreshToken: string }>;\n signUp(email: string, password: string, displayName?: string): Promise<{ user: User; accessToken: string; refreshToken: string }>;\n signInWithGoogle(idToken: string): Promise<{ user: User; accessToken: string; refreshToken: string }>;\n signOut(): Promise<void>;\n refreshSession(): Promise<RebaseSession>;\n getUser(): Promise<User>;\n updateUser(updates: { displayName?: string; photoURL?: string }): Promise<User>;\n resetPasswordForEmail(email: string): Promise<{ success: boolean; message: string }>;\n resetPassword(token: string, password: string): Promise<{ success: boolean; message: string }>;\n changePassword(oldPassword: string, newPassword: string): Promise<{ success: boolean; message: string }>;\n sendVerificationEmail(): Promise<{ success: boolean; message: string }>;\n verifyEmail(token: string): Promise<{ success: boolean; message: string }>;\n getSessions(): Promise<RebaseSession[]>;\n revokeSession(sessionId: string): Promise<{ success: boolean }>;\n revokeAllSessions(): Promise<{ success: boolean }>;\n getSession(): RebaseSession | null;\n onAuthStateChange(callback: (event: AuthChangeEvent, session: RebaseSession | null) => void): () => void;\n}\n\ninterface AdminUser {\n uid: string;\n email: string;\n displayName: string | null;\n photoURL: string | null;\n provider: string;\n roles: string[];\n createdAt: string;\n updatedAt: string;\n}\n\ninterface ListUsersOptions {\n search?: string;\n /** Page size. The server's default is 25. */\n limit?: number;\n offset?: number;\n orderBy?: string;\n orderDir?: \"asc\" | \"desc\";\n}\n\n/** One page of users, and \\`total\\`: how many match in all. */\ninterface UsersPage {\n users: AdminUser[];\n total: number;\n limit: number;\n offset: number;\n}\n\ninterface RebaseCMS {\n /** One page of users (25 unless \\`limit\\` says otherwise) and the total. */\n listUsers(options?: ListUsersOptions): Promise<UsersPage>;\n listUsersPaginated(options?: ListUsersOptions): Promise<UsersPage>;\n getUser(userId: string): Promise<{ user: AdminUser }>;\n createUser(data: { email: string; displayName?: string; password?: string; roles?: string[]; skipPasswordPolicy?: boolean }): Promise<{ user: AdminUser }>;\n updateUser(userId: string, data: { email?: string; displayName?: string; password?: string; roles?: string[] }): Promise<{ user: AdminUser }>;\n deleteUser(userId: string): Promise<{ success: boolean }>;\n bootstrap(): Promise<{ success: boolean; message: string; user: { uid: string; roles: string[] } }>;\n}\n\ninterface UploadFileProps {\n file: FileIcon;\n fileName?: string;\n path?: string;\n metadata?: Record<string, unknown>;\n bucket?: string;\n}\n\ninterface UploadFileResult {\n path: string;\n bucket?: string;\n downloadUrl?: string;\n}\n\ninterface DownloadConfig {\n url: string | null;\n fileNotFound?: boolean;\n metadata?: Record<string, unknown>;\n}\n\ninterface StorageSource {\n putObject(props: UploadFileProps): Promise<UploadFileResult>;\n getSignedUrl(pathOrUrl: string, bucket?: string): Promise<DownloadConfig>;\n getObject(path: string, bucket?: string): Promise<FileIcon | null>;\n deleteObject(path: string, bucket?: string): Promise<void>;\n listObjects(path: string, options?: { bucket?: string; maxResults?: number; pageToken?: string }): Promise<unknown>;\n}\n\ntype RebaseData = {\n /** Look up a collection by slug. */\n collection(slug: string): CollectionClient;\n} & {\n /** Dynamic collection access — e.g. client.data.authors */\n [collectionSlug: string]: CollectionClient;\n};\n\n/**\n * The Rebase client instance. Use \\`client.data\\`, \\`client.auth\\`, \\`client.admin\\`,\n * \\`client.storage\\`, and \\`client.call()\\` to interact with your Rebase backend.\n *\n * @example\n * // Query a collection\n * const result = await client.data.products.find({ limit: 10 });\n *\n * // Create a record\n * await client.data.products.create({ name: \"Camera\", price: 299 });\n *\n * // Fluent query\n * const expensive = await client.data.products.where(\"price\", \">\", 100).orderBy(\"price\", \"desc\").limit(5).find();\n *\n * // Auth\n * const session = client.auth.getSession();\n *\n * // Admin: one page of users, and how many there are\n * const { users, total } = await client.admin.listUsers({ limit: 50 });\n *\n * // Custom endpoint\n * const result = await client.call(\"/my-endpoint\", { myData: 123 });\n */\ninterface RebaseClient {\n /** Data access — dynamic collection accessors */\n data: RebaseData;\n /** Authentication methods */\n auth: RebaseAuth;\n /** User/role admin methods */\n admin: RebaseCMS;\n /** Storage operations */\n storage?: StorageSource;\n /** Call a custom server-side endpoint */\n call<T = unknown>(endpoint: string, payload?: unknown): Promise<T>;\n /** Direct collection access (shorthand) */\n [collectionSlug: string]: unknown;\n}\n\n/**\n * The client for this run: your own, one that runs every request as the user\n * picked in \"Run as\" (it holds no session, so \\`client.auth.getSession()\\` is null),\n * or an unauthenticated one under \"No Auth\".\n */\ndeclare const client: RebaseClient;\n\n/** Execution context with user and collection information. */\ninterface JSEditorContext {\n /** The user the script runs as: the one picked in \"Run as\", or you. \\`null\\` under \"No Auth\". */\n user: {\n uid: string;\n displayName: string | null;\n email: string | null;\n roles?: string[];\n } | null;\n /** Registered collections with their property names. */\n collections: Array<{\n slug: string;\n name: string;\n properties: string[];\n }>;\n}\n\n/** Execution context — contains info about the selected user and registered collections. */\ndeclare const context: JSEditorContext;\n`;\n\nexport type CollectionInfo = {\n slug: string;\n name: string;\n properties: string[];\n};\n\nexport type JSMonacoEditorProps = {\n value: string;\n onChange: (value: string | undefined) => void;\n onRun?: (selectedText?: string) => void;\n className?: string;\n readOnly?: boolean;\n autoFocus?: boolean;\n /** Collection slugs for basic autocomplete */\n collectionSlugs?: string[];\n /** Full collection info with property names for richer type generation */\n collections?: CollectionInfo[];\n};\n\nexport const JSMonacoEditor = ({\n value,\n onChange,\n onRun,\n className,\n readOnly = false,\n autoFocus = true,\n collectionSlugs = [],\n collections = []\n}: JSMonacoEditorProps) => {\n const { mode } = useModeController();\n const editorRef = useRef<editor.IStandaloneCodeEditor | null>(null);\n const monacoRef = useRef<Monaco | null>(null);\n const onRunRef = useRef(onRun);\n onRunRef.current = onRun;\n const typesRegisteredRef = useRef(false);\n\n const handleEditorOnMount: OnMount = (editorInstance, monaco) => {\n editorRef.current = editorInstance;\n monacoRef.current = monaco;\n\n // Register Cmd/Ctrl+Enter to run\n editorInstance.addAction({\n id: \"run-script\",\n label: \"Run Script\",\n keybindings: [monaco.KeyMod.CtrlCmd | monaco.KeyCode.Enter],\n contextMenuGroupId: \"operation\",\n contextMenuOrder: 0,\n run: () => {\n if (onRunRef.current) {\n const selection = editorInstance.getSelection();\n let selectedText: string | undefined;\n if (selection && !selection.isEmpty()) {\n selectedText = editorInstance.getModel()?.getValueInRange(selection)?.trim();\n }\n onRunRef.current(selectedText || undefined);\n }\n }\n });\n\n // Configure TypeScript/JavaScript defaults for richer completion\n if (!typesRegisteredRef.current) {\n typesRegisteredRef.current = true;\n\n // Configure TS compiler for modern JS with top-level await\n // Note: cast through `any` because the bundled type stubs mark\n // `monaco.languages.typescript` as deprecated while the runtime\n // API is fully functional.\n const ts = (monaco.languages as unknown as { typescript: MonacoTypeScriptApi }).typescript;\n ts.typescriptDefaults.setCompilerOptions({\n target: ts.ScriptTarget.ESNext,\n module: ts.ModuleKind.ESNext,\n allowJs: true,\n checkJs: false,\n strict: false,\n noEmit: true,\n allowNonTsExtensions: true\n });\n\n // Suppress diagnostics that don't apply to our script context.\n // Scripts are executed inside `new AsyncFunction(...)` at runtime,\n // so top-level `await` (1375) and `return` (1108) are valid.\n ts.typescriptDefaults.setDiagnosticsOptions({\n diagnosticCodesToIgnore: [1375, 1108]\n });\n\n // Inject the Rebase Client SDK type definitions\n ts.typescriptDefaults.addExtraLib(\n REBASE_CLIENT_TYPES,\n \"ts:rebase-client.d.ts\"\n );\n\n // Generate collection-specific types from registered collections\n if (collections.length > 0) {\n const lines: string[] = [];\n for (const col of collections) {\n // Generate a typed interface for each collection\n const ifaceName = col.slug.replace(/[^a-zA-Z0-9_]/g, \"_\");\n const propsType = col.properties.length > 0\n ? `{ ${col.properties.map(p => `${p}: any`).join(\"; \")} }`\n : \"Record<string, any>\";\n lines.push(`/** Collection: ${col.name} (${col.slug}) */`);\n lines.push(`interface ${ifaceName}_Row ${propsType}`);\n lines.push(`declare namespace client.data { const ${col.slug}: CollectionClient<${ifaceName}_Row>; }`);\n }\n ts.typescriptDefaults.addExtraLib(\n lines.join(\"\\n\"),\n \"ts:rebase-collections.d.ts\"\n );\n } else if (collectionSlugs.length > 0) {\n // Fallback: just slug names without property info\n const collectionHints = collectionSlugs.map(slug =>\n `/** Collection: ${slug} */\\ndeclare namespace client.data { const ${slug}: CollectionClient; }`\n ).join(\"\\n\");\n ts.typescriptDefaults.addExtraLib(\n collectionHints,\n \"ts:rebase-collections.d.ts\"\n );\n }\n }\n\n if (autoFocus) {\n editorInstance.focus();\n }\n };\n\n return (\n <div className={cls(\"relative w-full h-full overflow-hidden\", className)}>\n <Editor\n height=\"100%\"\n defaultLanguage=\"typescript\"\n path=\"rebase-script.ts\"\n value={value}\n onChange={onChange}\n onMount={handleEditorOnMount}\n theme={mode === \"dark\" ? \"vs-dark\" : \"vs\"}\n options={{\n minimap: { enabled: false },\n fontSize: 14,\n lineNumbers: \"on\",\n scrollBeyondLastLine: false,\n automaticLayout: true,\n readOnly,\n tabSize: 2,\n wordWrap: \"on\",\n suggestOnTriggerCharacters: true,\n quickSuggestions: true,\n parameterHints: { enabled: true }\n }}\n />\n </div>\n );\n};\n","\nimport React, { useState } from \"react\";\nimport { useTranslation } from \"@rebasepro/app\";\nimport {\n cls,\n defaultBorderMixin,\n IconButton,\n iconSize,\n PlusIcon,\n Tab,\n Tabs,\n Tooltip,\n Trash2Icon,\n Typography\n} from \"@rebasepro/ui\";\n\nexport interface JSSnippet {\n id: string;\n name: string;\n code: string;\n createdAt: number;\n isFavorite?: boolean;\n}\n\ninterface CollectionInfo {\n slug: string;\n properties: string[];\n}\n\ninterface JSEditorSidebarProps {\n collections: CollectionInfo[];\n snippets: JSSnippet[];\n history: string[];\n onSelectSnippet: (code: string) => void;\n onDeleteSnippet: (id: string) => void;\n onInsertCode: (code: string) => void;\n}\n\nconst QUICK_REFERENCE: { label: string; code: string; description: string }[] = [\n {\n label: \"Find all\",\n code: \"const result = await client.data.collection(\\\"COLLECTION\\\").find({ limit: 20 });\\nreturn result;\",\n description: \"Fetch records with pagination\"\n },\n {\n label: \"Find by ID\",\n code: \"const item = await client.data.collection(\\\"COLLECTION\\\").findById(\\\"ID\\\");\\nreturn item;\",\n description: \"Fetch a single record\"\n },\n {\n label: \"Create\",\n code: \"const created = await client.data.collection(\\\"COLLECTION\\\").create({\\n // your fields here\\n});\\nreturn created;\",\n description: \"Insert a new record\"\n },\n {\n label: \"Update\",\n code: \"const updated = await client.data.collection(\\\"COLLECTION\\\").update(\\\"ID\\\", {\\n // fields to update\\n});\\nreturn updated;\",\n description: \"Update an existing record\"\n },\n {\n label: \"Delete\",\n code: \"await client.data.collection(\\\"COLLECTION\\\").delete(\\\"ID\\\");\\nreturn { success: true };\",\n description: \"Delete a record\"\n },\n {\n label: \"Fluent query\",\n code: \"const result = await client.data.collection(\\\"COLLECTION\\\")\\n .where(\\\"field\\\", \\\">\\\", value)\\n .orderBy(\\\"field\\\", \\\"desc\\\")\\n .limit(10)\\n .find();\\nreturn result;\",\n description: \"Chained query builder\"\n },\n {\n label: \"Who am I\",\n code: \"return context.user;\",\n description: \"The user this script runs as, or null under No Auth\"\n },\n {\n label: \"Auth: Current session\",\n code: \"const session = client.auth.getSession();\\nreturn session;\",\n description: \"The session this client holds: yours, or none under Run as and No Auth\"\n },\n {\n label: \"Admin: List users\",\n code: \"// One page: raise limit or page with offset while users.length < total\\nconst { users, total } = await client.admin.listUsers({ limit: 50, offset: 0 });\\nreturn { users, total };\",\n description: \"A page of users, and how many there are in all\"\n },\n {\n label: \"Custom endpoint\",\n code: \"const result = await client.call(\\\"/my-endpoint\\\", { key: \\\"value\\\" });\\nreturn result;\",\n description: \"Call a custom API endpoint\"\n }\n];\n\nexport const JSEditorSidebar = ({\n collections,\n snippets,\n history,\n onSelectSnippet,\n onDeleteSnippet,\n onInsertCode\n}: JSEditorSidebarProps) => {\n const { t } = useTranslation();\n const [activeTab, setActiveTab] = useState<\"collections\" | \"snippets\" | \"history\" | \"reference\">(\"collections\");\n\n return (\n <div className={cls(\"flex flex-col h-full w-full bg-surface-card border-r\", defaultBorderMixin)}>\n <Tabs value={activeTab} onValueChange={(v) => setActiveTab(v as \"collections\" | \"snippets\" | \"history\" | \"reference\")} variant=\"boxy\" className=\"border-b border-hairline\">\n <Tab value=\"collections\">\n <Tooltip title=\"Browse collections\">\n <span className=\"text-xs\">{t(\"studio_js_collections_tab\")}</span>\n </Tooltip>\n </Tab>\n <Tab value=\"reference\">\n <Tooltip title=\"SDK quick reference\">\n <span className=\"text-xs\">Reference</span>\n </Tooltip>\n </Tab>\n <Tab value=\"snippets\">\n <span className=\"text-xs\">Snippets</span>\n </Tab>\n <Tab value=\"history\">\n <span className=\"text-xs\">History</span>\n </Tab>\n </Tabs>\n\n <div className=\"flex-grow overflow-hidden relative\">\n {/* Collections browser */}\n {activeTab === \"collections\" && (\n <div className=\"flex flex-col h-full\">\n <div className={cls(\"flex items-center justify-between px-3 py-2 border-b bg-surface-sheet min-h-[48px]\", defaultBorderMixin)}>\n <Typography variant=\"caption\" className=\"font-semibold uppercase tracking-wider text-text-disabled dark:text-text-disabled-dark\">\n {t(\"studio_js_collections_tab\")}\n </Typography>\n </div>\n <div className=\"flex-grow overflow-y-auto p-1 space-y-1 no-scrollbar\">\n {collections.length === 0 ? (\n <div className=\"p-4 text-center\">\n <Typography variant=\"caption\" className=\"text-text-disabled dark:text-text-disabled-dark\">\n No collections found\n </Typography>\n </div>\n ) : (\n collections.map(col => (\n <CollectionItem\n key={col.slug}\n collection={col}\n onInsertCode={onInsertCode}\n />\n ))\n )}\n </div>\n </div>\n )}\n\n {/* Quick reference */}\n {activeTab === \"reference\" && (\n <div className=\"flex flex-col h-full\">\n <div className={cls(\"flex items-center justify-between px-3 py-2 border-b bg-surface-sheet min-h-[48px]\", defaultBorderMixin)}>\n <Typography variant=\"caption\" className=\"font-semibold uppercase tracking-wider text-text-disabled dark:text-text-disabled-dark\">\n SDK Reference\n </Typography>\n </div>\n <div className=\"flex-grow overflow-y-auto p-2 space-y-2 no-scrollbar\">\n {QUICK_REFERENCE.map((ref, i) => (\n <div\n key={i}\n className={cls(\n \"group p-2.5 rounded-lg border hover:border-primary/40 dark:hover:border-primary/40\",\n \"bg-surface-card transition-all cursor-pointer\",\n defaultBorderMixin\n )}\n onClick={() => onInsertCode(ref.code)}\n >\n <div className=\"flex items-center justify-between mb-1\">\n <Typography variant=\"body2\" className=\"text-text-primary dark:text-text-primary-dark font-semibold text-[13px]\">\n {ref.label}\n </Typography>\n <svg className=\"w-3.5 h-3.5 text-text-disabled group-hover:text-primary transition-colors\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z\"/>\n </svg>\n </div>\n <Typography variant=\"caption\" className=\"text-text-disabled dark:text-text-disabled-dark text-[10px] leading-tight\">\n {ref.description}\n </Typography>\n </div>\n ))}\n </div>\n </div>\n )}\n\n {/* Snippets */}\n {activeTab === \"snippets\" && (() => {\n const favorites = snippets.filter(s => s.isFavorite);\n const others = snippets.filter(s => !s.isFavorite);\n\n return (\n <div className=\"flex flex-col h-full\">\n <div className={cls(\"flex items-center justify-between px-3 py-2 border-b bg-surface-sheet min-h-[48px]\", defaultBorderMixin)}>\n <Typography variant=\"caption\" className=\"font-semibold uppercase tracking-wider text-text-disabled dark:text-text-disabled-dark\">Snippets</Typography>\n </div>\n <div className=\"flex-grow overflow-y-auto p-2 space-y-2 no-scrollbar\">\n {snippets.length === 0 ? (\n <div className=\"p-4 text-center\">\n <Typography variant=\"caption\" className=\"text-text-disabled dark:text-text-disabled-dark\">\n No saved snippets yet. Use the save button to store reusable code.\n </Typography>\n </div>\n ) : (\n <>\n {favorites.length > 0 && (\n <div className=\"mb-3\">\n <Typography variant=\"caption\" className=\"text-[10px] font-semibold uppercase tracking-wider text-text-disabled dark:text-text-disabled-dark mb-2 px-1 flex items-center\">\n <svg className=\"w-3 h-3 mr-1 text-amber-500\" fill=\"currentColor\" viewBox=\"0 0 20 20\"><path d=\"M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z\"/></svg>\n Favorites\n </Typography>\n <div className=\"space-y-2\">\n {favorites.map(snippet => (\n <SnippetItem key={snippet.id} snippet={snippet} onSelect={onSelectSnippet} onDelete={onDeleteSnippet}/>\n ))}\n </div>\n </div>\n )}\n {others.length > 0 && (\n <div>\n {favorites.length > 0 && (\n <Typography variant=\"caption\" className=\"text-[10px] font-semibold uppercase tracking-wider text-text-disabled dark:text-text-disabled-dark mb-2 px-1\">\n Others\n </Typography>\n )}\n <div className=\"space-y-2\">\n {others.map(snippet => (\n <SnippetItem key={snippet.id} snippet={snippet} onSelect={onSelectSnippet} onDelete={onDeleteSnippet}/>\n ))}\n </div>\n </div>\n )}\n </>\n )}\n </div>\n </div>\n );\n })()}\n\n {/* History */}\n {activeTab === \"history\" && (\n <div className=\"flex flex-col h-full\">\n <div className={cls(\"flex items-center justify-between px-3 py-2 border-b bg-surface-sheet min-h-[48px]\", defaultBorderMixin)}>\n <Typography variant=\"caption\" className=\"font-semibold uppercase tracking-wider text-text-disabled dark:text-text-disabled-dark\">History</Typography>\n </div>\n <div className=\"flex-grow overflow-y-auto p-1 space-y-1 no-scrollbar\">\n {history.length === 0 ? (\n <div className=\"p-4 text-center\">\n <Typography variant=\"caption\" className=\"text-text-disabled dark:text-text-disabled-dark\">\n No execution history yet\n </Typography>\n </div>\n ) : (\n [...history].reverse().map((code, i) => (\n <div\n key={i}\n className=\"p-2 py-1.5 rounded hover:bg-surface-hover cursor-pointer group transition-colors flex items-start\"\n onClick={() => onSelectSnippet(code)}\n >\n <svg className=\"w-3 h-3 mt-1 mr-2 text-text-disabled dark:text-text-disabled-dark group-hover:text-primary transition-colors flex-shrink-0\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z\"/>\n </svg>\n <Typography variant=\"caption\" className=\"text-text-secondary dark:text-text-secondary-dark group-hover:text-text-primary dark:group-hover:text-text-primary-dark text-[11px] line-clamp-2 leading-tight flex-grow font-mono\">\n {code.length > 120 ? code.substring(0, 120) + \"…\" : code}\n </Typography>\n </div>\n ))\n )}\n </div>\n </div>\n )}\n </div>\n </div>\n );\n};\n\n// ─── Sub-components ──────────────────────────────────────────────────\n\nfunction CollectionItem({ collection, onInsertCode }: { collection: CollectionInfo; onInsertCode: (code: string) => void }) {\n const [expanded, setExpanded] = useState(false);\n\n return (\n <div>\n <div\n className=\"flex items-center p-1 cursor-pointer hover:bg-surface-hover rounded transition-colors group relative\"\n onClick={() => setExpanded(!expanded)}\n >\n <svg\n className={cls(\"w-3 h-3 mr-1 transition-transform\", expanded && \"rotate-90\")}\n fill=\"currentColor\" viewBox=\"0 0 20 20\"\n >\n <path d=\"M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z\"/>\n </svg>\n <svg className=\"w-3.5 h-3.5 mr-1 shrink-0 text-text-disabled dark:text-text-disabled-dark\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M4 7v10c0 2.21 3.582 4 8 4s8-1.79 8-4V7M4 7c0 2.21 3.582 4 8 4s8-1.79 8-4M4 7c0-2.21 3.582-4 8-4s8 1.79 8 4\"/>\n </svg>\n <Typography variant=\"body2\" className=\"text-text-secondary dark:text-text-secondary-dark text-xs truncate flex-1 min-w-0\">\n {collection.slug}\n </Typography>\n <Tooltip title=\"Insert find() snippet\">\n <IconButton aria-label=\"Insert find() snippet\"\n size=\"smallest\"\n className=\"opacity-0 group-hover:opacity-100 text-text-disabled hover:text-primary transition-all\"\n onClick={(e) => {\n e.stopPropagation();\n onInsertCode(`const result = await client.data.${collection.slug}.find({ limit: 20 });\\nreturn result;`);\n }}\n >\n <PlusIcon size={iconSize.smallest}/>\n </IconButton>\n </Tooltip>\n </div>\n {expanded && collection.properties.length > 0 && (\n <div className={cls(\"ml-5 mt-1 space-y-0.5 border-l\", defaultBorderMixin)}>\n {collection.properties.map(prop => (\n <div\n key={prop}\n className=\"flex items-center p-1 pl-2 hover:bg-surface-hover rounded-r cursor-pointer transition-colors group/prop relative min-h-[28px]\"\n onClick={() => onInsertCode(`\"${prop}\"`)}\n >\n <svg className=\"w-3 h-3 mr-1.5 text-text-disabled dark:text-text-disabled-dark shrink-0\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\"><path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={1.5} d=\"M9 4.5v15m6-15v15m-10.5-1.5h15c.621 0 1.125-.504 1.125-1.125V5.625c0-.621-.504-1.125-1.125-1.125h-15c-.621 0-1.125.504-1.125 1.125v12.75c0 .621.504 1.125 1.125 1.125Z\"/></svg>\n <Typography variant=\"caption\" className=\"text-text-primary dark:text-text-primary-dark text-[11px] truncate flex-grow font-mono\">{prop}</Typography>\n </div>\n ))}\n </div>\n )}\n </div>\n );\n}\n\nfunction SnippetItem({ snippet, onSelect, onDelete }: { snippet: JSSnippet; onSelect: (code: string) => void; onDelete: (id: string) => void }) {\n const { t } = useTranslation();\n return (\n <div\n className={cls(\"group p-2 rounded border hover:border-hairline-strong bg-surface-card transition-all cursor-pointer relative\", defaultBorderMixin)}\n onClick={() => onSelect(snippet.code)}\n >\n <Typography variant=\"body2\" className=\"text-text-primary dark:text-text-primary-dark font-medium text-[13px] truncate pr-6\">\n {snippet.name}\n </Typography>\n <Typography variant=\"caption\" className=\"text-text-secondary dark:text-text-secondary-dark text-[10px] block mt-1 truncate font-mono\">\n {snippet.code}\n </Typography>\n <IconButton aria-label={t(\"delete\")}\n size=\"smallest\"\n className=\"absolute right-1 top-1 opacity-0 group-hover:opacity-100 text-text-disabled hover:text-red-500 transition-opacity\"\n onClick={(e) => {\n e.stopPropagation();\n onDelete(snippet.id);\n }}\n >\n <Trash2Icon size={iconSize.smallest}/>\n </IconButton>\n </div>\n );\n}\n","\nimport React, { useState, useEffect, useCallback, useRef, useMemo } from \"react\";\nimport { Highlight, themes } from \"prism-react-renderer\";\nimport { toSnakeCase } from \"@rebasepro/utils\";\nimport {\n Button,\n CellRendererParams,\n Chip,\n CircularProgress,\n cls,\n defaultBorderMixin,\n Dialog,\n DialogActions,\n DialogContent,\n DialogTitle,\n DownloadIcon,\n IconButton,\n iconSize,\n Menu,\n MenuIcon,\n MenuItem,\n MoreVerticalIcon,\n PencilIcon,\n PlayIcon,\n PlusIcon,\n ResizablePanels,\n SaveIcon,\n Tab,\n Tabs,\n TerminalIcon,\n TextField,\n Tooltip,\n Typography,\n VirtualTable,\n VirtualTableColumn,\n XIcon\n} from \"@rebasepro/ui\";\nimport { useStudioUrlController, useStudioCollectionRegistry, useStudioSidePanelController } from \"@rebasepro/app\";\nimport { useRebaseContext, useRebaseClient, useSnackbarController, useApiConfig, useTranslation, useModeController, ErrorView, SelectableUser, IconForView } from \"@rebasepro/app\";\n\nimport { createMemoryStorage, createRebaseClient, type CreateAuthOptions } from \"@rebasepro/client\";\nimport { JSMonacoEditor } from \"./JSMonacoEditor\";\nimport { JSEditorSidebar, JSSnippet } from \"./JSEditorSidebar\";\nimport { AuthSimulationSelector } from \"../AuthSimulationSelector\";\nimport { useRunAsUsers } from \"../useRunAsUsers\";\nimport { toCsv } from \"../../utils/sql_utils\";\nimport type { AdminCollection } from \"@rebasepro/cms-types\";\n\n// ─── Types ───────────────────────────────────────────────────────────\n\ninterface ConsoleEntry {\n type: \"log\" | \"warn\" | \"error\" | \"info\";\n args: unknown[];\n timestamp: number;\n}\n\ninterface ExecutionResult {\n value: unknown;\n console: ConsoleEntry[];\n duration: number;\n error?: string;\n timestamp: number;\n /** The code that ran: the tab's, or the selection. */\n code: string;\n /**\n * Whether the run read as the signed-in user — not as someone picked in\n * \"Run as\", and not under \"No Auth\". A row it returned is then one the\n * entity editor, which works as the signed-in user, opens as the same row.\n */\n ranAsSignedInUser: boolean;\n}\n\ninterface EditorTab {\n id: string;\n name: string;\n code: string;\n}\n\n// SelectedUser is now SelectableUser from @rebasepro/app\n\n// ─── Constants ───────────────────────────────────────────────────────\n\nconst STORAGE_PREFIX = \"rebase_js_\";\nconst MAX_HISTORY = 50;\n\n/**\n * The starter script.\n *\n * It runs. That is the point: the console opens with the Run button armed, and\n * a starter that reads `collection(\"your_collection\")` made the first thing a\n * new user did be a 404 — a placeholder presented as working code. `slug` is\n * the project's first collection when one is known.\n */\nconst makeDefaultCode = (slug?: string) => `// Available: client (RebaseClient), context\n// Press Cmd+Enter (Ctrl+Enter) to run\n//\n// Examples:\n// const { users, total } = await client.admin.listUsers({ limit: 50, offset: 0 }); // one page of total\n// const me = context.user; // who this script runs as (\"Run as\"), null under No Auth\n${slug\n ? `\nconst result = await client.data.collection(${JSON.stringify(slug)}).find({ limit: 10 });\nreturn result;\n`\n : `\n// Name one of your collections to query it:\n// const result = await client.data.collection(\"posts\").find({ limit: 10 });\n// return result;\n\nreturn context.user;\n`}`;\n\nconst DEFAULT_CODE = makeDefaultCode();\n\n/**\n * The auth of a client built for one run: its own, in memory, and empty.\n *\n * The SDK's default auth restores the session the app saved in `localStorage`,\n * sends its token on every request and keeps refreshing it. A run under \"No\n * Auth\" or as another user must do none of that: it would go out as the\n * signed-in user, and `client.auth` would describe the wrong person.\n */\nfunction runOnlyAuth(): CreateAuthOptions {\n return { storage: createMemoryStorage(), persistSession: false, autoRefresh: false };\n}\n\n// ─── Helpers ─────────────────────────────────────────────────────────\n\nfunction loadFromStorage<T>(key: string, fallback: T): T {\n try {\n const raw = localStorage.getItem(STORAGE_PREFIX + key);\n return raw ? JSON.parse(raw) : fallback;\n } catch {\n return fallback;\n }\n}\n\nfunction saveToStorage<T>(key: string, value: T) {\n try {\n localStorage.setItem(STORAGE_PREFIX + key, JSON.stringify(value));\n } catch { /* quota */ }\n}\n\nfunction formatJSON(value: unknown): string {\n try {\n return JSON.stringify(value, null, 2);\n } catch {\n return String(value);\n }\n}\n\n// ─── Helpers: Collection matching for JS results ────────────────────\n\ninterface MatchedJSCollection {\n collectionSlug: string;\n collection: AdminCollection;\n pkColumn: string;\n}\n\n/** The script without its comments: a collection named in one is not where rows came from. */\nfunction withoutComments(code: string): string {\n return code.replace(/\\/\\*[\\s\\S]*?\\*\\//g, \"\").replace(/\\/\\/[^\\n]*/g, \"\");\n}\n\n/**\n * Given the raw SDK result, try to detect which collection its rows belong to.\n * JS SDK results typically come back as `{ data: [{ id, values }] }` or plain arrays.\n * The heuristic: the executed code, outside its comments, names exactly one\n * collection — `collection(\"<slug>\")` or `client.data.<slug>` — and the result has\n * rows with an \"id\" column. A script naming two could have returned either's\n * rows, and an action on a row would open the other collection's row with the\n * same id, so it gets none.\n */\nfunction detectCollectionsInResult(\n executedCode: string,\n resultValue: unknown,\n collections: AdminCollection[]\n): MatchedJSCollection[] {\n if (!resultValue || !collections?.length) return [];\n const code = withoutComments(executedCode);\n\n // Extract collection slugs mentioned in the code\n const mentionedSlugs = new Set<string>();\n\n // Match: collection(\"slug\") or collection('slug')\n const collectionCallRegex = /\\.collection\\([\"']([^\"']+)[\"']\\)/g;\n let m: RegExpExecArray | null;\n while ((m = collectionCallRegex.exec(code)) !== null) {\n mentionedSlugs.add(m[1]);\n }\n\n // Match: client.data.<slug>. (dot-access pattern)\n const dotAccessRegex = /client\\.data\\.([a-zA-Z_][a-zA-Z0-9_]*)\\./g;\n while ((m = dotAccessRegex.exec(code)) !== null) {\n if (![\"collection\", \"find\", \"findById\", \"create\", \"update\", \"delete\"].includes(m[1])) {\n mentionedSlugs.add(m[1]);\n }\n }\n\n if (mentionedSlugs.size !== 1) return [];\n\n // Check if result has rows with an \"id\" field\n let rows: Record<string, unknown>[] = [];\n const rv = resultValue as Record<string, unknown>;\n if (rv?.data && Array.isArray(rv.data)) {\n rows = rv.data;\n } else if (Array.isArray(resultValue)) {\n rows = resultValue;\n }\n\n const hasId = rows.length > 0 && rows.some(r => r?.id != null);\n if (!hasId) return [];\n\n const matched: MatchedJSCollection[] = [];\n for (const slug of mentionedSlugs) {\n const normalised = toSnakeCase(slug);\n const col = collections.find(c => {\n const tableName = (\"table\" in c ? c.table : undefined) || toSnakeCase(c.slug);\n return c.slug === slug || tableName === normalised || toSnakeCase(c.slug) === normalised;\n });\n if (col) {\n matched.push({\n collectionSlug: col.slug,\n collection: col,\n pkColumn: \"id\"\n });\n }\n }\n\n return matched;\n}\n\n// ─── Main Component ─────────────────────────────────────────────────\n\nexport function JSEditor() {\n // Contexts\n const rebaseContext = useRebaseContext();\n const rebaseClient = useRebaseClient();\n const apiConfig = useApiConfig();\n const snackbar = useSnackbarController();\n const collectionRegistry = useStudioCollectionRegistry();\n const sidePanelController = useStudioSidePanelController();\n const { t } = useTranslation();\n\n // User management for the \"Run as\" picker\n const currentUser = rebaseContext.authController?.user;\n\n // State\n const [tabs, setTabs] = useState<EditorTab[]>(() =>\n loadFromStorage(\"tabs\", [{ id: \"1\",\nname: \"Script 1\",\ncode: DEFAULT_CODE }])\n );\n const [activeTabId, setActiveTabId] = useState<string>(() =>\n loadFromStorage(\"activeTab\", \"1\")\n );\n const [result, setResult] = useState<ExecutionResult | null>(null);\n const [isRunning, setIsRunning] = useState(false);\n const [snippets, setSnippets] = useState<JSSnippet[]>(() =>\n loadFromStorage(\"snippets\", [])\n );\n const [history, setHistory] = useState<string[]>(() =>\n loadFromStorage(\"history\", [])\n );\n const [showSaveDialog, setShowSaveDialog] = useState(false);\n const [snippetName, setSnippetName] = useState(\"\");\n const [resultView, setResultView] = useState<\"json\" | \"table\" | \"console\">(\"json\");\n\n // \"Run as\" user state — null means \"self\" (current admin)\n const [selectedUser, setSelectedUser] = useState<SelectableUser | null>(null);\n const [authMode, setAuthMode] = useState<\"jwt\" | \"none\">(\"jwt\");\n\n const [sidebarSize, setSidebarSize] = useState<number>(() => {\n try {\n const stored = localStorage.getItem(STORAGE_PREFIX + \"sidebar_size\");\n return stored ? Number(stored) : 18;\n } catch { return 18; }\n });\n const [editorHeight, setEditorHeight] = useState<number>(() => {\n try {\n const stored = localStorage.getItem(STORAGE_PREFIX + \"editor_height\");\n return stored ? Number(stored) : 55;\n } catch { return 55; }\n });\n\n // Derived\n const activeTab = tabs.find(t => t.id === activeTabId) ?? tabs[0];\n\n // Collection info for the sidebar and Monaco\n const collectionInfos = useMemo(() => {\n const collections = collectionRegistry?.collections ?? [];\n return collections.map(col => ({\n slug: col.slug,\n name: col.name,\n properties: Object.keys(col.properties ?? {})\n }));\n }, [collectionRegistry?.collections]);\n\n const collectionSlugs = useMemo(() => collectionInfos.map(c => c.slug), [collectionInfos]);\n\n /**\n * Name a real collection in the starter script once the registry knows one.\n *\n * The registry is empty on first paint — in the hosted console it arrives\n * over the network — so the placeholder-free default cannot be built in the\n * `useState` initialiser. Rewriting only a tab whose content is still\n * *exactly* the untouched default means this can never overwrite anything\n * anyone typed, and never fires twice.\n */\n const firstSlug = collectionSlugs[0];\n useEffect(() => {\n if (!firstSlug) return;\n setTabs(prev => {\n if (!prev.some(tab => tab.code === DEFAULT_CODE)) return prev;\n const seeded = makeDefaultCode(firstSlug);\n return prev.map(tab => (tab.code === DEFAULT_CODE ? { ...tab,\ncode: seeded } : tab));\n });\n }, [firstSlug]);\n\n // The \"Run as\" picker: the project's users for an administrator, only\n // themselves for anyone else.\n const { users, currentUser: currentSelectableUser, loading: usersLoading, onSearchTextChange: onUserSearchTextChange, totalCount: userTotalCount } = useRunAsUsers();\n\n // ─── Persistence ─────────────────────────────────────────────\n\n useEffect(() => { saveToStorage(\"tabs\", tabs); }, [tabs]);\n useEffect(() => { saveToStorage(\"activeTab\", activeTabId); }, [activeTabId]);\n useEffect(() => { saveToStorage(\"snippets\", snippets); }, [snippets]);\n useEffect(() => { saveToStorage(\"history\", history); }, [history]);\n\n useEffect(() => {\n try { localStorage.setItem(STORAGE_PREFIX + \"sidebar_size\", sidebarSize.toString()); } catch { /* ignore */ }\n }, [sidebarSize]);\n\n useEffect(() => {\n try { localStorage.setItem(STORAGE_PREFIX + \"editor_height\", editorHeight.toString()); } catch { /* ignore */ }\n }, [editorHeight]);\n\n // ─── Tab management ──────────────────────────────────────────\n\n const updateActiveCode = useCallback((code: string | undefined) => {\n setTabs(prev => prev.map(t => t.id === activeTabId ? { ...t,\ncode: code ?? \"\" } : t));\n }, [activeTabId]);\n\n const addTab = useCallback(() => {\n const id = String(Date.now());\n const newTab: EditorTab = { id,\nname: `Script ${tabs.length + 1}`,\ncode: DEFAULT_CODE };\n setTabs(prev => [...prev, newTab]);\n setActiveTabId(id);\n }, [tabs.length]);\n\n const closeTab = useCallback((tabId: string) => {\n setTabs(prev => {\n const filtered = prev.filter(t => t.id !== tabId);\n if (filtered.length === 0) {\n const fresh = { id: String(Date.now()),\nname: \"Script 1\",\ncode: DEFAULT_CODE };\n setActiveTabId(fresh.id);\n return [fresh];\n }\n if (activeTabId === tabId) {\n setActiveTabId(filtered[filtered.length - 1].id);\n }\n return filtered;\n });\n }, [activeTabId]);\n\n // ─── Create an authenticated client for execution ────────────\n\n const buildClient = useCallback(async () => {\n const apiUrl = apiConfig?.apiUrl;\n const getAuthToken = apiConfig?.getAuthToken;\n\n if (!apiUrl) {\n throw new Error(\"API URL not configured. Make sure apiUrl is set.\");\n }\n\n if (authMode === \"none\") {\n // No credential at all, and no session to find one in.\n const client = createRebaseClient({\n baseUrl: apiUrl,\n auth: runOnlyAuth()\n });\n return { client,\nrelease: () => client.close() };\n }\n\n // If not running as another user safely reuse the application's global client.\n if (!selectedUser || (currentUser && selectedUser.uid === currentUser.uid)) {\n if (!rebaseClient) {\n throw new Error(\"Application client is not initialized.\");\n }\n return { client: rebaseClient };\n }\n\n // Get the current auth token\n const token = getAuthToken ? (await getAuthToken()) ?? undefined : undefined;\n if (!getAuthToken || !token) {\n throw new Error(\"No auth token available. Please sign in first.\");\n }\n\n // A fresh client that runs every request as the selected user: the\n // administrator's own token, and `impersonate` naming who to run as.\n // The server runs data, functions and realtime as that user, and\n // refuses every other route rather than answer as the administrator.\n // It holds no session: the token is asked of the app for each request,\n // so the app's own session is the one that gets refreshed.\n const client = createRebaseClient({\n baseUrl: apiUrl,\n token,\n impersonate: selectedUser.uid,\n auth: runOnlyAuth()\n });\n client.setAuthTokenGetter(getAuthToken);\n\n return { client,\nrelease: () => client.close() };\n }, [apiConfig, rebaseClient, selectedUser, currentUser, authMode]);\n\n // ─── Execution engine ────────────────────────────────────────\n\n const executeCode = useCallback(async (codeOverride?: string) => {\n const code = codeOverride ?? activeTab?.code ?? \"\";\n if (!code.trim()) return;\n\n setIsRunning(true);\n setResult(null);\n\n // Add to history\n setHistory(prev => {\n const deduped = prev.filter(h => h !== code);\n return [...deduped, code].slice(-MAX_HISTORY);\n });\n\n const consoleEntries: ConsoleEntry[] = [];\n const startTime = performance.now();\n let release: (() => void) | undefined;\n // The same choice `buildClient` makes: the app's own client, as the\n // signed-in user, unless \"No Auth\" or someone else is picked.\n const ranAsSignedInUser = authMode !== \"none\" && (!selectedUser || selectedUser.uid === currentUser?.uid);\n\n // Capture console methods\n const originalConsole = {\n log: console.log,\n warn: console.warn,\n error: console.error,\n info: console.info\n };\n\n const captureConsole = (type: ConsoleEntry[\"type\"]) => (...args: unknown[]) => {\n consoleEntries.push({ type,\nargs,\ntimestamp: Date.now() });\n originalConsole[type](...args);\n };\n\n try {\n console.log = captureConsole(\"log\");\n console.warn = captureConsole(\"warn\");\n console.error = captureConsole(\"error\");\n console.info = captureConsole(\"info\");\n\n // Build an authenticated client\n const built = await buildClient();\n release = built.release;\n const client = built.client;\n\n // The user the requests run as: nobody under \"No Auth\", the chosen\n // user when running as someone else, the signed-in user otherwise.\n const context = {\n user: authMode === \"none\"\n ? null\n : selectedUser ?? (currentUser ? {\n uid: currentUser.uid,\n displayName: currentUser.displayName,\n email: currentUser.email,\n roles: currentUser.roles\n } : null),\n collections: collectionInfos\n };\n\n // Create async function with `client` and `context` injected\n\n const AsyncFunction = Object.getPrototypeOf(async function () { }).constructor;\n const fn = new AsyncFunction(\"client\", \"context\", code);\n\n const value = await fn(client, context);\n const duration = performance.now() - startTime;\n\n setResult({\n value,\n console: consoleEntries,\n duration,\n timestamp: Date.now(),\n code,\n ranAsSignedInUser\n });\n\n // Auto-detect best view\n const resultObj = value as Record<string, unknown> | undefined;\n if (resultObj?.data && Array.isArray(resultObj.data)) {\n setResultView(\"table\");\n } else if (consoleEntries.length > 0 && value === undefined) {\n setResultView(\"console\");\n } else {\n setResultView(\"json\");\n }\n } catch (err: unknown) {\n const duration = performance.now() - startTime;\n setResult({\n value: undefined,\n console: consoleEntries,\n duration,\n error: err instanceof Error ? err.message : String(err),\n timestamp: Date.now(),\n code,\n ranAsSignedInUser\n });\n setResultView(\"json\");\n } finally {\n console.log = originalConsole.log;\n console.warn = originalConsole.warn;\n console.error = originalConsole.error;\n console.info = originalConsole.info;\n setIsRunning(false);\n\n // A client built for this run holds a socket and timers; release\n // them. The app's own client is left alone.\n release?.();\n }\n }, [activeTab?.code, buildClient, authMode, selectedUser, currentUser, collectionInfos]);\n\n // ─── Snippet management ──────────────────────────────────────\n\n const saveSnippet = useCallback(() => {\n if (!snippetName.trim() || !activeTab?.code.trim()) return;\n const snippet: JSSnippet = {\n id: String(Date.now()),\n name: snippetName.trim(),\n code: activeTab.code,\n createdAt: Date.now()\n };\n setSnippets(prev => [snippet, ...prev]);\n setShowSaveDialog(false);\n setSnippetName(\"\");\n snackbar.open({ type: \"success\",\nmessage: \"Snippet saved\" });\n }, [snippetName, activeTab?.code, snackbar]);\n\n const deleteSnippet = useCallback((id: string) => {\n setSnippets(prev => prev.filter(s => s.id !== id));\n }, []);\n\n // ─── Export ──────────────────────────────────────────────────\n\n const exportResult = useCallback(() => {\n if (!result?.value) return;\n const blob = new Blob([formatJSON(result.value)], { type: \"application/json\" });\n const url = URL.createObjectURL(blob);\n const a = document.createElement(\"a\");\n a.href = url;\n a.download = `rebase-result-${Date.now()}.json`;\n a.click();\n URL.revokeObjectURL(url);\n }, [result]);\n\n // ─── Table columns for array data ────────────────────────────\n\n const tableData = useMemo(() => {\n if (!result?.value) return { columns: [] as VirtualTableColumn[],\ndata: [] as Record<string, unknown>[] };\n\n let rows: Record<string, unknown>[] = [];\n const val = result.value as Record<string, unknown>;\n if (val?.data && Array.isArray(val.data)) {\n rows = (val.data as Record<string, unknown>[]).map((entity) => ({\n id: entity.id,\n ...(entity.values as Record<string, unknown> ?? {}),\n ...(entity.values ? {} : entity)\n }));\n } else if (Array.isArray(result.value)) {\n rows = result.value;\n }\n\n if (rows.length === 0) return { columns: [] as VirtualTableColumn[],\ndata: [] as Record<string, unknown>[] };\n\n const keys = new Set<string>();\n rows.slice(0, 20).forEach(row => {\n if (row && typeof row === \"object\") {\n Object.keys(row).forEach(k => keys.add(k));\n }\n });\n\n const columns: VirtualTableColumn[] = Array.from(keys).map(key => ({\n key,\n title: key,\n width: key === \"id\" ? 100 : 200\n }));\n\n return { columns,\ndata: rows };\n }, [result]);\n\n // ─── Matched collections for entity actions ──────────────────\n\n // Rows read as someone else are not offered to the entity editor, which\n // opens and saves them as the signed-in user.\n const matchedCollections = useMemo(() => {\n if (!result?.value || result.error || !result.ranAsSignedInUser) return [];\n return detectCollectionsInResult(\n result.code,\n result.value,\n collectionRegistry?.collections ?? []\n );\n }, [result, collectionRegistry?.collections]);\n\n const getRowEntityActions = useCallback((rowData: Record<string, unknown>): { collection: MatchedJSCollection; entityId: string | number }[] => {\n if (!rowData || matchedCollections.length === 0) return [];\n return matchedCollections\n .filter(mc => rowData[mc.pkColumn] != null)\n .map(mc => ({\n collection: mc,\n entityId: rowData[mc.pkColumn] as string | number\n }));\n }, [matchedCollections]);\n\n // What the result table is handed, kept the same object while only the\n // script's text changes: `VirtualTable` compares its props, and a new\n // column list or cell renderer per keystroke redrew every visible cell.\n const resultColumns = useMemo((): VirtualTableColumn[] => matchedCollections.length > 0\n ? [{ key: \"__entity_action__\",\ntitle: \"\",\nwidth: 36,\nsortable: false,\nresizable: false }, ...tableData.columns]\n : tableData.columns, [matchedCollections.length, tableData.columns]);\n\n const renderResultCell = useCallback(({ rowData, column }: CellRendererParams<Record<string, unknown>>) => {\n // Entity action column\n if (column.key === \"__entity_action__\") {\n const rowActions = getRowEntityActions(rowData ?? {});\n if (rowActions.length === 0) return <div className=\"h-full w-full\"/>;\n if (rowActions.length === 1) {\n const ra = rowActions[0];\n return (\n <div className=\"h-full flex items-center justify-center\">\n <Tooltip title={t(\"studio_sql_edit_entity\", { name: ra.collection.collection.name,\nid: String(ra.entityId) })}>\n <IconButton aria-label={t(\"studio_sql_edit_entity\", { name: ra.collection.collection.name, id: String(ra.entityId) })}\n size=\"small\"\n className=\"text-surface-400 dark:text-surface-500 hover:text-surface-600 dark:hover:text-surface-300\"\n onClick={(e) => {\n e.stopPropagation();\n sidePanelController.open({\n path: ra.collection.collectionSlug,\n entityId: ra.entityId,\n collection: ra.collection.collection,\n updateUrl: false\n });\n }}\n >\n <PencilIcon size={iconSize.smallest}/>\n </IconButton>\n </Tooltip>\n </div>\n );\n }\n // Multiple matched collections\n return (\n <div className=\"h-full flex items-center justify-center\">\n <Menu\n trigger={\n <IconButton aria-label={t(\"more_actions\")}\n size={\"small\"}\n className=\"text-surface-400 dark:text-surface-500 hover:text-surface-600 dark:hover:text-surface-300\"\n onClick={(e) => e.stopPropagation()}\n >\n <MoreVerticalIcon size={iconSize.smallest}/>\n </IconButton>\n }\n >\n {rowActions.map(ra => (\n <MenuItem\n key={ra.collection.collectionSlug}\n dense\n onClick={() => {\n sidePanelController.open({\n path: ra.collection.collectionSlug,\n entityId: ra.entityId,\n collection: ra.collection.collection,\n updateUrl: false\n });\n }}\n >\n {t(\"studio_sql_edit_entity\", { name: ra.collection.collection.name,\nid: String(ra.entityId) })}\n </MenuItem>\n ))}\n </Menu>\n </div>\n );\n }\n\n // Regular data cell\n if (!rowData) return null;\n const val = rowData[column.key];\n const displayValue = typeof val === \"object\" && val !== null ? JSON.stringify(val) : String(val ?? \"\");\n return (\n <div className=\"px-4 py-1.5 h-full flex items-center whitespace-nowrap text-[13px] text-text-primary dark:text-text-primary-dark font-mono\">\n <div className=\"truncate flex-grow\" title={displayValue}>\n {displayValue === \"\" ? <span className=\"text-text-disabled dark:text-text-disabled-dark italic text-[11px]\">NULL</span> : displayValue}\n </div>\n </div>\n );\n }, [getRowEntityActions, sidePanelController, t]);\n\n // ─── Export handlers ─────────────────────────────────────────\n\n const handleExportCSV = useCallback(() => {\n if (tableData.data.length === 0) return;\n // The SQL console's format. This one quoted a value only when it held\n // a comma — never doubling a quote or quoting a line break, so\n // `say \"hi\"` or a two-line string broke its row — and wrote an object\n // as `[object Object]`.\n const csv = toCsv(tableData.columns.map(c => c.key), tableData.data);\n const blob = new Blob([csv], { type: \"text/csv\" });\n const url = URL.createObjectURL(blob);\n const a = document.createElement(\"a\");\n a.href = url;\n a.download = `js_results_${new Date().toISOString().slice(0, 19)}.csv`;\n a.click();\n URL.revokeObjectURL(url);\n }, [tableData]);\n\n const handleExportMarkdown = useCallback(() => {\n if (tableData.data.length === 0) return;\n const headers = tableData.columns.map(c => c.key);\n const headerRow = `| ${headers.join(\" | \")} |`;\n const dividerRow = `| ${headers.map(() => \"---\").join(\" | \")} |`;\n const dataRows = tableData.data.map(row =>\n `| ${headers.map(h => {\n const val = row[h];\n if (val === null || val === undefined) return \"\";\n return String(val).replace(/\\|/g, \"\\\\|\").replace(/\\n/g, \" \");\n }).join(\" | \")} |`\n );\n const markdown = [headerRow, dividerRow, ...dataRows].join(\"\\n\");\n navigator.clipboard.writeText(markdown).then(() => {\n snackbar.open({ type: \"success\",\nmessage: t(\"studio_sql_markdown_copied\") });\n }).catch(() => {\n snackbar.open({ type: \"error\",\nmessage: t(\"studio_sql_markdown_copy_failed\") });\n });\n }, [tableData, snackbar, t]);\n\n // ─── Render ──────────────────────────────────────────────────\n\n return (\n <div className=\"flex flex-col h-full w-full\">\n {/* Main content */}\n <div className=\"flex-grow overflow-hidden\">\n <ResizablePanels\n dividerAriaLabel={t(\"resize_sidebar\")}\n orientation=\"horizontal\"\n panelSizePercent={sidebarSize}\n onPanelSizeChange={setSidebarSize}\n minPanelSizePx={200}\n firstPanel={\n <JSEditorSidebar\n collections={collectionInfos}\n snippets={snippets}\n history={history}\n onSelectSnippet={(code) => updateActiveCode(code)}\n onDeleteSnippet={deleteSnippet}\n onInsertCode={(code) => updateActiveCode(code)}\n />\n }\n secondPanel={\n <div className=\"flex flex-col h-full overflow-hidden\">\n {/* Toolbar: matching SQL Editor layout */}\n <div className={cls(\"flex items-center justify-between pr-2 border-b bg-surface-card\", defaultBorderMixin)}>\n <div className=\"flex items-center flex-grow overflow-hidden mr-4\">\n <div className=\"flex items-center no-scrollbar overflow-x-auto min-w-0\">\n <Tabs value={activeTabId} onValueChange={setActiveTabId} variant=\"boxy\" className=\"w-[unset] flex-shrink-0\" innerClassName=\"bg-surface-card\">\n {tabs.map(tab => (\n <Tab key={tab.id} value={tab.id} className=\"flex items-center justify-between group max-w-[200px]\">\n <TerminalIcon size={iconSize.smallest} className=\"text-amber-500 mr-1.5 flex-shrink-0\"/>\n <span className=\"truncate\">{tab.name}</span>\n {tabs.length > 1 && (\n <IconButton aria-label={t(\"close_tab\")}\n size=\"smallest\"\n onClick={(e) => { e.stopPropagation(); closeTab(tab.id); }}\n className=\"ml-1 !p-0.5 opacity-0 group-hover:opacity-100 hover:text-red-500 transition-opacity\"\n >\n <XIcon size={iconSize.smallest}/>\n </IconButton>\n )}\n </Tab>\n ))}\n </Tabs>\n <IconButton aria-label={t(\"new_tab\")}\n size=\"small\"\n onClick={addTab}\n className=\"ml-2 flex-shrink-0\"\n >\n <PlusIcon size={iconSize.smallest}/>\n </IconButton>\n </div>\n </div>\n <div className=\"flex shrink-0 items-center justify-end gap-1.5\">\n <Tooltip title=\"Save as snippet\">\n <IconButton aria-label=\"Save as snippet\"\n size=\"small\"\n onClick={() => {\n setSnippetName(\"\");\n setShowSaveDialog(true);\n }}\n disabled={!activeTab?.code.trim()}\n >\n <SaveIcon size={iconSize.smallest}/>\n </IconButton>\n </Tooltip>\n\n {result?.value != null && (\n <Tooltip title=\"Export result as JSON\">\n <IconButton aria-label=\"Export result as JSON\" size=\"small\" onClick={exportResult}>\n <DownloadIcon size={iconSize.smallest}/>\n </IconButton>\n </Tooltip>\n )}\n\n <Button\n size=\"small\"\n color=\"primary\"\n disabled={isRunning || !activeTab?.code.trim()}\n onClick={() => executeCode()}\n >\n {isRunning ? <CircularProgress size=\"smallest\" className=\"mr-2\"/> : <PlayIcon size={iconSize.smallest} className=\"mr-2\"/>}\n Run\n </Button>\n </div>\n </div>\n\n {/* Editor + Results split */}\n <div className=\"flex-grow overflow-hidden\">\n <ResizablePanels\n dividerAriaLabel={t(\"resize_editor\")}\n orientation=\"vertical\"\n panelSizePercent={editorHeight}\n onPanelSizeChange={setEditorHeight}\n minPanelSizePx={100}\n firstPanel={\n <div className=\"h-full w-full overflow-hidden flex flex-col\">\n {/* Auth Simulation UI */}\n <div className=\"p-2 px-3 border-b border-hairline bg-surface-sheet flex items-center shrink-0\">\n <AuthSimulationSelector\n authMode={authMode}\n setAuthMode={setAuthMode}\n selectedUser={selectedUser}\n setSelectedUser={setSelectedUser}\n users={users}\n loading={usersLoading}\n onUserSearchTextChange={onUserSearchTextChange}\n userTotalCount={userTotalCount}\n currentUser={currentSelectableUser}\n />\n </div>\n <div className=\"flex-1 min-h-0\">\n <JSMonacoEditor\n value={activeTab?.code ?? \"\"}\n onChange={updateActiveCode}\n onRun={(selectedText) => executeCode(selectedText)}\n collectionSlugs={collectionSlugs}\n collections={collectionInfos}\n autoFocus\n />\n </div>\n </div>\n }\n secondPanel={\n <div className=\"h-full w-full flex flex-col bg-surface-well overflow-hidden min-h-0\">\n {/* Result header — matches SQL editor */}\n <div className={cls(\"p-2 px-4 bg-surface-raised border-b shrink-0 flex items-center\", defaultBorderMixin)}>\n <Typography variant=\"caption\" className=\"font-semibold text-text-disabled dark:text-text-disabled-dark uppercase tracking-widest text-[10px]\">\n {t(\"studio_sql_query_results\")}\n </Typography>\n\n {result && (\n <>\n <div className=\"flex-grow\"/>\n\n <Tabs value={resultView} onValueChange={(val) => setResultView(val as \"json\" | \"table\" | \"console\")} variant=\"pill\" className=\"w-[unset] mr-2\">\n <Tab value=\"json\">JSON</Tab>\n {tableData.data.length > 0 && <Tab value=\"table\">Table</Tab>}\n {result.console.length > 0 && <Tab value=\"console\">Console ({result.console.length})</Tab>}\n </Tabs>\n\n <Chip size=\"smallest\" colorScheme={result.error ? \"redDarker\" : \"greenDarker\"}>\n {result.error ? \"Error\" : `${result.duration.toFixed(0)}ms`}\n </Chip>\n </>\n )}\n </div>\n\n {/* Result content */}\n <div className=\"flex-grow flex flex-col min-h-0 overflow-hidden\">\n {isRunning && (\n <div className=\"flex-grow flex items-center justify-center\">\n <div className=\"text-center\">\n <CircularProgress size=\"medium\"/>\n <Typography variant=\"body2\" className=\"mt-4 text-text-secondary dark:text-text-secondary-dark font-mono tracking-tight animate-pulse\">\n EXECUTING SCRIPT...\n </Typography>\n </div>\n </div>\n )}\n\n {!isRunning && !result && (\n <div className=\"flex-grow flex items-center justify-center text-text-disabled dark:text-text-disabled-dark\">\n <div className=\"text-center\">\n <svg className=\"w-12 h-12 mx-auto mb-4 opacity-50\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\"><path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={1} d=\"M8 9l3 3-3 3m5 0h3M5 20h14a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z\"/></svg>\n <Typography variant=\"body2\">Write JavaScript and press <kbd className=\"px-1.5 py-0.5 rounded bg-surface-raised text-[11px] font-mono\">⌘ Enter</kbd> to run</Typography>\n </div>\n </div>\n )}\n\n {!isRunning && result?.error && (\n <div className=\"flex-grow flex items-center justify-center p-6 overflow-auto\">\n <ErrorView\n title=\"Execution Error\"\n error={result.error}\n />\n </div>\n )}\n\n {!isRunning && result && !result.error && resultView === \"json\" && (\n <pre className=\"flex-grow overflow-auto p-4 text-[13px] font-mono leading-relaxed text-text-primary dark:text-text-primary-dark whitespace-pre-wrap break-words\">\n {result.value === undefined ? (\n <span className=\"text-text-disabled italic\">undefined (no return value)</span>\n ) : (\n <JSONHighlight value={result.value}/>\n )}\n </pre>\n )}\n\n {!isRunning && result && !result.error && resultView === \"table\" && tableData.data.length > 0 && (\n <div className=\"flex-grow flex flex-col overflow-hidden min-h-0\">\n {/* Collection badges bar — matching SQL editor */}\n {matchedCollections.length > 0 && (\n <div className={cls(\"px-4 py-1.5 border-b flex items-center gap-2 shrink-0 bg-surface-sheet\", defaultBorderMixin)}>\n <Tooltip title={t(\"studio_sql_admin_collections_tooltip\")}>\n <Typography variant=\"caption\" className=\"text-[10px] font-semibold uppercase tracking-widest text-text-disabled dark:text-text-disabled-dark mr-1 shrink-0 cursor-help\">{t(\"studio_sql_collections_label\")}</Typography>\n </Tooltip>\n <div className=\"flex items-center gap-1.5 overflow-x-auto no-scrollbar\">\n {matchedCollections.map(mc => (\n <Tooltip key={mc.collectionSlug} title={`${mc.collection.name} (${mc.collectionSlug})`}>\n <span className=\"inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-[11px] font-medium bg-primary/10 dark:bg-primary-dark/15 text-primary dark:text-primary-dark whitespace-nowrap border border-primary/20 dark:border-primary-dark/20\">\n {typeof mc.collection.icon === \"string\" && (\n <IconForView collectionOrView={{ icon: mc.collection.icon } as never} className=\"text-[12px]\"/>\n )}\n {mc.collection.name}\n </span>\n </Tooltip>\n ))}\n </div>\n </div>\n )}\n <div className=\"flex-grow relative h-full min-h-0 min-w-0\">\n <VirtualTable\n data={tableData.data}\n columns={resultColumns}\n rowHeight={32}\n headerHeight={32}\n cellRenderer={renderResultCell}\n />\n </div>\n </div>\n )}\n\n {!isRunning && result && resultView === \"console\" && (\n <div className=\"flex-grow overflow-auto p-2 space-y-1 font-mono text-[12px]\">\n {result.console.length === 0 ? (\n <Typography variant=\"caption\" className=\"text-text-disabled p-2\">No console output</Typography>\n ) : (\n result.console.map((entry, i) => (\n <div\n key={i}\n className={cls(\n \"px-2 py-1 rounded flex items-start gap-2\",\n entry.type === \"error\" && \"bg-red-50 dark:bg-red-950/30 text-red-700 dark:text-red-400\",\n entry.type === \"warn\" && \"bg-amber-50 dark:bg-amber-950/30 text-amber-700 dark:text-amber-400\",\n entry.type === \"log\" && \"text-text-primary dark:text-text-primary-dark\",\n entry.type === \"info\" && \"text-blue-700 dark:text-blue-400\"\n )}\n >\n <span className=\"text-[10px] opacity-50 flex-shrink-0 mt-0.5\">\n {entry.type === \"error\" ? \"❌\" : entry.type === \"warn\" ? \"⚠️\" : entry.type === \"info\" ? \"ℹ️\" : \"›\"}\n </span>\n <span className=\"whitespace-pre-wrap break-words\">\n {entry.args.map(a => typeof a === \"object\" ? JSON.stringify(a, null, 2) : String(a)).join(\" \")}\n </span>\n </div>\n ))\n )}\n\n {result.value !== undefined && (\n <div className={cls(\"px-2 py-1 mt-2 border-t pt-2\", defaultBorderMixin)}>\n <Typography variant=\"caption\" className=\"text-text-disabled text-[10px] uppercase tracking-wider mb-1 block\">Return Value</Typography>\n <pre className=\"text-text-primary dark:text-text-primary-dark whitespace-pre-wrap break-words text-[12px]\">\n <FormattedJSON value={result.value}/>\n </pre>\n </div>\n )}\n </div>\n )}\n </div>\n\n {/* Footer bar — matching SQL editor */}\n {!isRunning && result && !result.error && resultView === \"table\" && tableData.data.length > 0 && (\n <div className={cls(\"p-2 px-4 border-t bg-surface-sheet flex justify-between items-center shrink-0\", defaultBorderMixin)}>\n <div className=\"flex space-x-4\">\n <div className=\"flex items-center text-[11px]\">\n <span className=\"font-semibold text-text-disabled dark:text-text-disabled-dark mr-2 uppercase tracking-tighter\">{t(\"studio_sql_rows\")}</span>\n <span className=\"font-mono text-text-secondary dark:text-text-secondary-dark\">{tableData.data.length}</span>\n </div>\n <div className=\"flex items-center text-[11px]\">\n <span className=\"font-semibold text-text-disabled dark:text-text-disabled-dark mr-2 uppercase tracking-tighter\">{t(\"studio_sql_time\")}</span>\n <span className=\"font-mono text-text-secondary dark:text-text-secondary-dark\">{result.duration.toFixed(0)}ms</span>\n </div>\n </div>\n <div className=\"flex gap-2 overflow-x-auto no-scrollbar items-center px-2\">\n <Button\n size=\"small\"\n variant=\"text\"\n className=\"text-[10px] uppercase font-semibold text-text-secondary dark:text-text-secondary-dark whitespace-nowrap\"\n onClick={handleExportMarkdown}\n >\n {t(\"studio_sql_copy_markdown\")}\n </Button>\n <Button\n size=\"small\"\n variant=\"text\"\n className=\"text-[10px] uppercase font-semibold text-text-secondary dark:text-text-secondary-dark whitespace-nowrap\"\n onClick={exportResult}\n >\n {t(\"studio_sql_export_json\")}\n </Button>\n <Button\n size=\"small\"\n variant=\"text\"\n className=\"text-[10px] uppercase font-semibold text-text-secondary dark:text-text-secondary-dark whitespace-nowrap\"\n onClick={handleExportCSV}\n >\n {t(\"studio_sql_export_csv\")}\n </Button>\n </div>\n </div>\n )}\n </div>\n }\n />\n </div>\n </div>\n }\n />\n </div>\n\n {/* Save snippet dialog */}\n <Dialog open={showSaveDialog} onOpenChange={setShowSaveDialog}>\n <DialogTitle>Save Snippet</DialogTitle>\n <DialogContent>\n <TextField\n label=\"Snippet name\"\n value={snippetName}\n onChange={(e) => setSnippetName(e.target.value)}\n placeholder=\"e.g. List all products\"\n autoFocus\n onKeyDown={(e) => {\n if (e.key === \"Enter\") saveSnippet();\n }}\n />\n </DialogContent>\n <DialogActions>\n <Button variant=\"text\" onClick={() => setShowSaveDialog(false)}>Cancel</Button>\n <Button variant=\"filled\" color=\"primary\" onClick={saveSnippet} disabled={!snippetName.trim()}>Save</Button>\n </DialogActions>\n </Dialog>\n </div>\n );\n}\n\n// ─── JSON Syntax Highlighting ────────────────────────────────────────\n\n/**\n * Memoised on the value: tokenising a large result is the costliest thing\n * this pane draws, and it used to run again for every keystroke in the editor.\n */\nconst JSONHighlight = React.memo(function JSONHighlight({ value }: { value: unknown }) {\n const json = formatJSON(value);\n const { mode } = useModeController();\n\n return (\n <Highlight\n theme={mode === \"dark\" ? themes.vsDark : themes.github}\n code={json}\n language=\"json\"\n >\n {({ style, tokens, getLineProps, getTokenProps }) => (\n <span style={{ ...style,\nbackgroundColor: \"transparent\" }}>\n {tokens.map((line, i) => (\n <div key={i} {...getLineProps({ line })}>\n {line.map((token, key) => (\n <span key={key} {...getTokenProps({ token })}/>\n ))}\n </div>\n ))}\n </span>\n )}\n </Highlight>\n );\n});\n\n/** A value as indented JSON, formatted again only when the value changes. */\nconst FormattedJSON = React.memo(function FormattedJSON({ value }: { value: unknown }) {\n return <>{formatJSON(value)}</>;\n});\n"],"mappings":"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"}