@rebasepro/studio 0.5.0 → 0.6.0

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 (369) hide show
  1. package/dist/ApiExplorer-CdIwR9Ga.js +963 -0
  2. package/dist/ApiExplorer-CdIwR9Ga.js.map +1 -0
  3. package/dist/AuthSimulationSelector-iEZ-Or_1.js +56 -0
  4. package/dist/AuthSimulationSelector-iEZ-Or_1.js.map +1 -0
  5. package/dist/BranchesView-DncIRcZt.js +461 -0
  6. package/dist/BranchesView-DncIRcZt.js.map +1 -0
  7. package/dist/CronJobsView-4gdtJvoe.js +500 -0
  8. package/dist/CronJobsView-4gdtJvoe.js.map +1 -0
  9. package/dist/JSEditor-BhAbEjCP.js +1573 -0
  10. package/dist/JSEditor-BhAbEjCP.js.map +1 -0
  11. package/dist/LogsExplorer-CqtKILj8.js +240 -0
  12. package/dist/LogsExplorer-CqtKILj8.js.map +1 -0
  13. package/dist/MonacoEditor-COZqrIJ1.js +246 -0
  14. package/dist/MonacoEditor-COZqrIJ1.js.map +1 -0
  15. package/dist/RLSEditor-CTxYbBdW.js +1362 -0
  16. package/dist/RLSEditor-CTxYbBdW.js.map +1 -0
  17. package/dist/SQLEditor-BLuq_zDM.js +1964 -0
  18. package/dist/SQLEditor-BLuq_zDM.js.map +1 -0
  19. package/dist/SchemaVisualizer-BJK2u3C0.js +1068 -0
  20. package/dist/SchemaVisualizer-BJK2u3C0.js.map +1 -0
  21. package/dist/StorageView-nDaC2foF.js +1382 -0
  22. package/dist/StorageView-nDaC2foF.js.map +1 -0
  23. package/dist/{studio/src/components → components}/ApiExplorer/ApiExplorer.d.ts +2 -1
  24. package/dist/{studio/src/components → components}/ApiExplorer/EndpointDetail.d.ts +2 -1
  25. package/dist/{studio/src/components → components}/ApiExplorer/TryItPanel.d.ts +2 -1
  26. package/dist/{studio/src/components → components}/AuthSimulationSelector.d.ts +2 -1
  27. package/dist/components/Branches/BranchesView.d.ts +2 -0
  28. package/dist/components/CronJobs/CronJobsView.d.ts +2 -0
  29. package/dist/components/JSEditor/JSEditor.d.ts +2 -0
  30. package/dist/{studio/src/components → components}/JSEditor/JSEditorSidebar.d.ts +2 -1
  31. package/dist/{studio/src/components → components}/JSEditor/JSMonacoEditor.d.ts +2 -1
  32. package/dist/components/LogsExplorer/LogsExplorer.d.ts +2 -0
  33. package/dist/{studio/src/components → components}/RLSEditor/PolicyEditor.d.ts +2 -1
  34. package/dist/{studio/src/components → components}/RLSEditor/RLSEditor.d.ts +2 -1
  35. package/dist/{studio/src/components → components}/SQLEditor/MonacoEditor.d.ts +2 -1
  36. package/dist/{studio/src/components → components}/SQLEditor/SQLEditor.d.ts +2 -1
  37. package/dist/{studio/src/components → components}/SQLEditor/SQLEditorSidebar.d.ts +2 -1
  38. package/dist/{studio/src/components → components}/SQLEditor/SchemaBrowser.d.ts +2 -1
  39. package/dist/{studio/src/components → components}/SchemaVisualizer/RelationEdge.d.ts +1 -1
  40. package/dist/components/SchemaVisualizer/SchemaVisualizer.d.ts +3 -0
  41. package/dist/{studio/src/components → components}/SchemaVisualizer/TableNode.d.ts +1 -1
  42. package/dist/components/StorageView/StorageView.d.ts +2 -0
  43. package/dist/{studio/src/components → components}/StudioHomePage.d.ts +1 -1
  44. package/dist/index.es.js +688 -746
  45. package/dist/index.es.js.map +1 -1
  46. package/dist/index.umd.js +10303 -9572
  47. package/dist/index.umd.js.map +1 -1
  48. package/package.json +22 -22
  49. package/src/components/ApiExplorer/TryItPanel.tsx +15 -18
  50. package/src/components/CronJobs/CronJobsView.tsx +1 -1
  51. package/src/components/JSEditor/JSEditor.tsx +9 -14
  52. package/src/components/LogsExplorer/LogsExplorer.tsx +6 -3
  53. package/src/components/RLSEditor/PolicyEditor.tsx +0 -1
  54. package/src/components/SQLEditor/SQLEditor.tsx +40 -30
  55. package/src/components/StorageView/StorageView.tsx +22 -11
  56. package/src/components/StudioHomePage.tsx +51 -15
  57. package/src/utils/parseSpec.test.ts +41 -20
  58. package/src/utils/pgColumnToProperty.ts +1 -1
  59. package/dist/ApiExplorer-CGHEF1uL.js +0 -1052
  60. package/dist/ApiExplorer-CGHEF1uL.js.map +0 -1
  61. package/dist/AuthSimulationSelector-DGoXkWSg.js +0 -105
  62. package/dist/AuthSimulationSelector-DGoXkWSg.js.map +0 -1
  63. package/dist/BranchesView-BiTEwIhd.js +0 -291
  64. package/dist/BranchesView-BiTEwIhd.js.map +0 -1
  65. package/dist/CronJobsView-3PM_qR8v.js +0 -472
  66. package/dist/CronJobsView-3PM_qR8v.js.map +0 -1
  67. package/dist/JSEditor-DfwRLBZg.js +0 -1297
  68. package/dist/JSEditor-DfwRLBZg.js.map +0 -1
  69. package/dist/LogsExplorer-_4sZadKn.js +0 -162
  70. package/dist/LogsExplorer-_4sZadKn.js.map +0 -1
  71. package/dist/MonacoEditor-CMYEjiRf.js +0 -161
  72. package/dist/MonacoEditor-CMYEjiRf.js.map +0 -1
  73. package/dist/RLSEditor-CHEExeSB.js +0 -1871
  74. package/dist/RLSEditor-CHEExeSB.js.map +0 -1
  75. package/dist/SQLEditor-CQXaI0iU.js +0 -1797
  76. package/dist/SQLEditor-CQXaI0iU.js.map +0 -1
  77. package/dist/SchemaVisualizer-BGpmzyXT.js +0 -1069
  78. package/dist/SchemaVisualizer-BGpmzyXT.js.map +0 -1
  79. package/dist/StorageView-B7AsN2qX.js +0 -869
  80. package/dist/StorageView-B7AsN2qX.js.map +0 -1
  81. package/dist/common/src/collections/CollectionRegistry.d.ts +0 -56
  82. package/dist/common/src/collections/default-collections.d.ts +0 -9
  83. package/dist/common/src/collections/index.d.ts +0 -2
  84. package/dist/common/src/data/buildRebaseData.d.ts +0 -14
  85. package/dist/common/src/data/query_builder.d.ts +0 -55
  86. package/dist/common/src/index.d.ts +0 -4
  87. package/dist/common/src/util/builders.d.ts +0 -57
  88. package/dist/common/src/util/callbacks.d.ts +0 -6
  89. package/dist/common/src/util/collections.d.ts +0 -11
  90. package/dist/common/src/util/common.d.ts +0 -2
  91. package/dist/common/src/util/conditions.d.ts +0 -26
  92. package/dist/common/src/util/entities.d.ts +0 -58
  93. package/dist/common/src/util/enums.d.ts +0 -3
  94. package/dist/common/src/util/index.d.ts +0 -16
  95. package/dist/common/src/util/navigation_from_path.d.ts +0 -34
  96. package/dist/common/src/util/navigation_utils.d.ts +0 -20
  97. package/dist/common/src/util/parent_references_from_path.d.ts +0 -6
  98. package/dist/common/src/util/paths.d.ts +0 -14
  99. package/dist/common/src/util/permissions.d.ts +0 -14
  100. package/dist/common/src/util/references.d.ts +0 -2
  101. package/dist/common/src/util/relations.d.ts +0 -22
  102. package/dist/common/src/util/resolutions.d.ts +0 -72
  103. package/dist/common/src/util/storage.d.ts +0 -24
  104. package/dist/core/src/components/AIIcon.d.ts +0 -16
  105. package/dist/core/src/components/BootstrapAdminBanner.d.ts +0 -4
  106. package/dist/core/src/components/ConfirmationDialog.d.ts +0 -9
  107. package/dist/core/src/components/Debug/UIReferenceView.d.ts +0 -1
  108. package/dist/core/src/components/Debug/UIStyleGuide.d.ts +0 -1
  109. package/dist/core/src/components/ErrorTooltip.d.ts +0 -2
  110. package/dist/core/src/components/ErrorView.d.ts +0 -21
  111. package/dist/core/src/components/LanguageToggle.d.ts +0 -1
  112. package/dist/core/src/components/LoginView/LoginView.d.ts +0 -109
  113. package/dist/core/src/components/LoginView/index.d.ts +0 -2
  114. package/dist/core/src/components/NotFoundPage.d.ts +0 -1
  115. package/dist/core/src/components/RebaseAuth.d.ts +0 -10
  116. package/dist/core/src/components/RebaseLogo.d.ts +0 -7
  117. package/dist/core/src/components/UnsavedChangesDialog.d.ts +0 -9
  118. package/dist/core/src/components/UserDisplay.d.ts +0 -7
  119. package/dist/core/src/components/UserSelectPopover.d.ts +0 -62
  120. package/dist/core/src/components/UserSettingsView.d.ts +0 -1
  121. package/dist/core/src/components/common/index.d.ts +0 -6
  122. package/dist/core/src/components/common/table_height.d.ts +0 -5
  123. package/dist/core/src/components/common/types.d.ts +0 -66
  124. package/dist/core/src/components/common/useColumnsIds.d.ts +0 -9
  125. package/dist/core/src/components/common/useDataTableController.d.ts +0 -45
  126. package/dist/core/src/components/common/useDebouncedData.d.ts +0 -9
  127. package/dist/core/src/components/common/useScrollRestoration.d.ts +0 -14
  128. package/dist/core/src/components/index.d.ts +0 -17
  129. package/dist/core/src/contexts/AdminModeController.d.ts +0 -4
  130. package/dist/core/src/contexts/AnalyticsContext.d.ts +0 -3
  131. package/dist/core/src/contexts/AuthControllerContext.d.ts +0 -3
  132. package/dist/core/src/contexts/CustomizationControllerContext.d.ts +0 -3
  133. package/dist/core/src/contexts/DataDriverContext.d.ts +0 -3
  134. package/dist/core/src/contexts/DatabaseAdminContext.d.ts +0 -3
  135. package/dist/core/src/contexts/DialogsProvider.d.ts +0 -4
  136. package/dist/core/src/contexts/EffectiveRoleController.d.ts +0 -4
  137. package/dist/core/src/contexts/InternalUserManagementContext.d.ts +0 -3
  138. package/dist/core/src/contexts/ModeController.d.ts +0 -4
  139. package/dist/core/src/contexts/RebaseClientInstanceContext.d.ts +0 -6
  140. package/dist/core/src/contexts/RebaseDataContext.d.ts +0 -3
  141. package/dist/core/src/contexts/SnackbarProvider.d.ts +0 -2
  142. package/dist/core/src/contexts/StorageSourceContext.d.ts +0 -3
  143. package/dist/core/src/contexts/UserConfigurationPersistenceContext.d.ts +0 -3
  144. package/dist/core/src/contexts/index.d.ts +0 -13
  145. package/dist/core/src/core/PluginLifecycleManager.d.ts +0 -17
  146. package/dist/core/src/core/PluginProviderStack.d.ts +0 -21
  147. package/dist/core/src/core/Rebase.d.ts +0 -14
  148. package/dist/core/src/core/RebaseProps.d.ts +0 -147
  149. package/dist/core/src/core/RebaseRouter.d.ts +0 -4
  150. package/dist/core/src/core/RebaseRoutes.d.ts +0 -17
  151. package/dist/core/src/core/index.d.ts +0 -4
  152. package/dist/core/src/hooks/ApiConfigContext.d.ts +0 -24
  153. package/dist/core/src/hooks/data/delete.d.ts +0 -31
  154. package/dist/core/src/hooks/data/save.d.ts +0 -34
  155. package/dist/core/src/hooks/data/useCollectionFetch.d.ts +0 -62
  156. package/dist/core/src/hooks/data/useData.d.ts +0 -13
  157. package/dist/core/src/hooks/data/useDataOrder.d.ts +0 -12
  158. package/dist/core/src/hooks/data/useEntityFetch.d.ts +0 -43
  159. package/dist/core/src/hooks/data/useRelationSelector.d.ts +0 -52
  160. package/dist/core/src/hooks/data/useUserSelector.d.ts +0 -31
  161. package/dist/core/src/hooks/index.d.ts +0 -37
  162. package/dist/core/src/hooks/useAdminModeController.d.ts +0 -19
  163. package/dist/core/src/hooks/useAnalyticsController.d.ts +0 -5
  164. package/dist/core/src/hooks/useAuthController.d.ts +0 -11
  165. package/dist/core/src/hooks/useAuthSubscription.d.ts +0 -2
  166. package/dist/core/src/hooks/useBackendStorageSource.d.ts +0 -30
  167. package/dist/core/src/hooks/useBridgeRegistration.d.ts +0 -18
  168. package/dist/core/src/hooks/useBrowserTitleAndIcon.d.ts +0 -6
  169. package/dist/core/src/hooks/useBuildAdminModeController.d.ts +0 -6
  170. package/dist/core/src/hooks/useBuildEffectiveRoleController.d.ts +0 -8
  171. package/dist/core/src/hooks/useBuildLocalConfigurationPersistence.d.ts +0 -2
  172. package/dist/core/src/hooks/useBuildModeController.d.ts +0 -6
  173. package/dist/core/src/hooks/useClipboard.d.ts +0 -57
  174. package/dist/core/src/hooks/useCollapsedGroups.d.ts +0 -27
  175. package/dist/core/src/hooks/useCustomizationController.d.ts +0 -11
  176. package/dist/core/src/hooks/useDialogsController.d.ts +0 -11
  177. package/dist/core/src/hooks/useEffectiveRoleController.d.ts +0 -7
  178. package/dist/core/src/hooks/useInternalUserManagementController.d.ts +0 -12
  179. package/dist/core/src/hooks/useLargeLayout.d.ts +0 -1
  180. package/dist/core/src/hooks/useModeController.d.ts +0 -19
  181. package/dist/core/src/hooks/usePermissions.d.ts +0 -12
  182. package/dist/core/src/hooks/useRebaseClient.d.ts +0 -5
  183. package/dist/core/src/hooks/useRebaseContext.d.ts +0 -11
  184. package/dist/core/src/hooks/useRebaseRegistry.d.ts +0 -34
  185. package/dist/core/src/hooks/useResolvedComponent.d.ts +0 -47
  186. package/dist/core/src/hooks/useSlot.d.ts +0 -18
  187. package/dist/core/src/hooks/useSnackbarController.d.ts +0 -20
  188. package/dist/core/src/hooks/useStorageSource.d.ts +0 -7
  189. package/dist/core/src/hooks/useStudioBridge.d.ts +0 -91
  190. package/dist/core/src/hooks/useTranslation.d.ts +0 -17
  191. package/dist/core/src/hooks/useUnsavedChangesDialog.d.ts +0 -12
  192. package/dist/core/src/hooks/useUserConfigurationPersistence.d.ts +0 -8
  193. package/dist/core/src/i18n/RebaseI18nProvider.d.ts +0 -33
  194. package/dist/core/src/index.d.ts +0 -15
  195. package/dist/core/src/internal/common.d.ts +0 -3
  196. package/dist/core/src/internal/useRestoreScroll.d.ts +0 -6
  197. package/dist/core/src/locales/de.d.ts +0 -2
  198. package/dist/core/src/locales/en.d.ts +0 -10
  199. package/dist/core/src/locales/es.d.ts +0 -10
  200. package/dist/core/src/locales/fr.d.ts +0 -2
  201. package/dist/core/src/locales/hi.d.ts +0 -2
  202. package/dist/core/src/locales/it.d.ts +0 -2
  203. package/dist/core/src/locales/pt.d.ts +0 -7
  204. package/dist/core/src/util/constants.d.ts +0 -1
  205. package/dist/core/src/util/createFormexStub.d.ts +0 -2
  206. package/dist/core/src/util/entity_cache.d.ts +0 -22
  207. package/dist/core/src/util/enums.d.ts +0 -5
  208. package/dist/core/src/util/icon_list.d.ts +0 -5
  209. package/dist/core/src/util/icons.d.ts +0 -20
  210. package/dist/core/src/util/index.d.ts +0 -8
  211. package/dist/core/src/util/previews.d.ts +0 -4
  212. package/dist/core/src/util/useStorageUploadController.d.ts +0 -38
  213. package/dist/formex/src/Field.d.ts +0 -52
  214. package/dist/formex/src/Formex.d.ts +0 -7
  215. package/dist/formex/src/index.d.ts +0 -5
  216. package/dist/formex/src/types.d.ts +0 -40
  217. package/dist/formex/src/useCreateFormex.d.ts +0 -14
  218. package/dist/formex/src/utils.d.ts +0 -16
  219. package/dist/studio/src/components/Branches/BranchesView.d.ts +0 -1
  220. package/dist/studio/src/components/CronJobs/CronJobsView.d.ts +0 -1
  221. package/dist/studio/src/components/JSEditor/JSEditor.d.ts +0 -1
  222. package/dist/studio/src/components/LogsExplorer/LogsExplorer.d.ts +0 -1
  223. package/dist/studio/src/components/SchemaVisualizer/SchemaVisualizer.d.ts +0 -2
  224. package/dist/studio/src/components/StorageView/StorageView.d.ts +0 -1
  225. package/dist/types/src/controllers/analytics_controller.d.ts +0 -7
  226. package/dist/types/src/controllers/auth.d.ts +0 -104
  227. package/dist/types/src/controllers/client.d.ts +0 -168
  228. package/dist/types/src/controllers/collection_registry.d.ts +0 -46
  229. package/dist/types/src/controllers/customization_controller.d.ts +0 -60
  230. package/dist/types/src/controllers/data.d.ts +0 -207
  231. package/dist/types/src/controllers/data_driver.d.ts +0 -218
  232. package/dist/types/src/controllers/database_admin.d.ts +0 -11
  233. package/dist/types/src/controllers/dialogs_controller.d.ts +0 -36
  234. package/dist/types/src/controllers/effective_role.d.ts +0 -4
  235. package/dist/types/src/controllers/email.d.ts +0 -36
  236. package/dist/types/src/controllers/index.d.ts +0 -18
  237. package/dist/types/src/controllers/local_config_persistence.d.ts +0 -20
  238. package/dist/types/src/controllers/navigation.d.ts +0 -225
  239. package/dist/types/src/controllers/registry.d.ts +0 -63
  240. package/dist/types/src/controllers/side_dialogs_controller.d.ts +0 -67
  241. package/dist/types/src/controllers/side_entity_controller.d.ts +0 -97
  242. package/dist/types/src/controllers/snackbar.d.ts +0 -24
  243. package/dist/types/src/controllers/storage.d.ts +0 -171
  244. package/dist/types/src/index.d.ts +0 -4
  245. package/dist/types/src/rebase_context.d.ts +0 -122
  246. package/dist/types/src/types/auth_adapter.d.ts +0 -301
  247. package/dist/types/src/types/backend.d.ts +0 -571
  248. package/dist/types/src/types/backend_hooks.d.ts +0 -172
  249. package/dist/types/src/types/builders.d.ts +0 -15
  250. package/dist/types/src/types/chips.d.ts +0 -5
  251. package/dist/types/src/types/collections.d.ts +0 -961
  252. package/dist/types/src/types/component_ref.d.ts +0 -47
  253. package/dist/types/src/types/cron.d.ts +0 -102
  254. package/dist/types/src/types/data_source.d.ts +0 -64
  255. package/dist/types/src/types/database_adapter.d.ts +0 -94
  256. package/dist/types/src/types/entities.d.ts +0 -145
  257. package/dist/types/src/types/entity_actions.d.ts +0 -104
  258. package/dist/types/src/types/entity_callbacks.d.ts +0 -173
  259. package/dist/types/src/types/entity_link_builder.d.ts +0 -7
  260. package/dist/types/src/types/entity_overrides.d.ts +0 -10
  261. package/dist/types/src/types/entity_views.d.ts +0 -87
  262. package/dist/types/src/types/export_import.d.ts +0 -21
  263. package/dist/types/src/types/formex.d.ts +0 -40
  264. package/dist/types/src/types/index.d.ts +0 -28
  265. package/dist/types/src/types/locales.d.ts +0 -4
  266. package/dist/types/src/types/modify_collections.d.ts +0 -5
  267. package/dist/types/src/types/plugins.d.ts +0 -282
  268. package/dist/types/src/types/properties.d.ts +0 -1173
  269. package/dist/types/src/types/property_config.d.ts +0 -74
  270. package/dist/types/src/types/relations.d.ts +0 -336
  271. package/dist/types/src/types/slots.d.ts +0 -262
  272. package/dist/types/src/types/translations.d.ts +0 -900
  273. package/dist/types/src/types/user_management_delegate.d.ts +0 -86
  274. package/dist/types/src/types/websockets.d.ts +0 -78
  275. package/dist/types/src/users/index.d.ts +0 -1
  276. package/dist/types/src/users/user.d.ts +0 -50
  277. package/dist/ui/src/components/Alert.d.ts +0 -12
  278. package/dist/ui/src/components/Autocomplete.d.ts +0 -21
  279. package/dist/ui/src/components/Avatar.d.ts +0 -11
  280. package/dist/ui/src/components/Badge.d.ts +0 -8
  281. package/dist/ui/src/components/BooleanSwitch.d.ts +0 -14
  282. package/dist/ui/src/components/BooleanSwitchWithLabel.d.ts +0 -17
  283. package/dist/ui/src/components/Button.d.ts +0 -14
  284. package/dist/ui/src/components/Card.d.ts +0 -8
  285. package/dist/ui/src/components/CenteredView.d.ts +0 -9
  286. package/dist/ui/src/components/Checkbox.d.ts +0 -13
  287. package/dist/ui/src/components/Chip.d.ts +0 -26
  288. package/dist/ui/src/components/CircularProgress.d.ts +0 -5
  289. package/dist/ui/src/components/CircularProgressCenter.d.ts +0 -11
  290. package/dist/ui/src/components/Collapse.d.ts +0 -9
  291. package/dist/ui/src/components/ColorPicker.d.ts +0 -30
  292. package/dist/ui/src/components/Container.d.ts +0 -8
  293. package/dist/ui/src/components/DateTimeField.d.ts +0 -24
  294. package/dist/ui/src/components/DebouncedTextField.d.ts +0 -2
  295. package/dist/ui/src/components/Dialog.d.ts +0 -39
  296. package/dist/ui/src/components/DialogActions.d.ts +0 -7
  297. package/dist/ui/src/components/DialogContent.d.ts +0 -7
  298. package/dist/ui/src/components/DialogTitle.d.ts +0 -10
  299. package/dist/ui/src/components/ErrorBoundary.d.ts +0 -33
  300. package/dist/ui/src/components/ExpandablePanel.d.ts +0 -12
  301. package/dist/ui/src/components/FileUpload.d.ts +0 -23
  302. package/dist/ui/src/components/FilterChip.d.ts +0 -34
  303. package/dist/ui/src/components/IconButton.d.ts +0 -12
  304. package/dist/ui/src/components/InfoLabel.d.ts +0 -5
  305. package/dist/ui/src/components/InputLabel.d.ts +0 -11
  306. package/dist/ui/src/components/Label.d.ts +0 -7
  307. package/dist/ui/src/components/LoadingButton.d.ts +0 -7
  308. package/dist/ui/src/components/Markdown.d.ts +0 -10
  309. package/dist/ui/src/components/Menu.d.ts +0 -23
  310. package/dist/ui/src/components/Menubar.d.ts +0 -80
  311. package/dist/ui/src/components/MultiSelect.d.ts +0 -48
  312. package/dist/ui/src/components/Paper.d.ts +0 -6
  313. package/dist/ui/src/components/Popover.d.ts +0 -24
  314. package/dist/ui/src/components/RadioGroup.d.ts +0 -28
  315. package/dist/ui/src/components/ResizablePanels.d.ts +0 -18
  316. package/dist/ui/src/components/SearchBar.d.ts +0 -26
  317. package/dist/ui/src/components/Select.d.ts +0 -43
  318. package/dist/ui/src/components/Separator.d.ts +0 -5
  319. package/dist/ui/src/components/Sheet.d.ts +0 -22
  320. package/dist/ui/src/components/Skeleton.d.ts +0 -6
  321. package/dist/ui/src/components/Slider.d.ts +0 -21
  322. package/dist/ui/src/components/Table.d.ts +0 -34
  323. package/dist/ui/src/components/Tabs.d.ts +0 -19
  324. package/dist/ui/src/components/TextField.d.ts +0 -58
  325. package/dist/ui/src/components/TextareaAutosize.d.ts +0 -43
  326. package/dist/ui/src/components/ToggleButtonGroup.d.ts +0 -30
  327. package/dist/ui/src/components/Tooltip.d.ts +0 -19
  328. package/dist/ui/src/components/Typography.d.ts +0 -36
  329. package/dist/ui/src/components/VirtualTable/VirtualTable.d.ts +0 -11
  330. package/dist/ui/src/components/VirtualTable/VirtualTableCell.d.ts +0 -21
  331. package/dist/ui/src/components/VirtualTable/VirtualTableHeader.d.ts +0 -29
  332. package/dist/ui/src/components/VirtualTable/VirtualTableHeaderRow.d.ts +0 -2
  333. package/dist/ui/src/components/VirtualTable/VirtualTableProps.d.ts +0 -249
  334. package/dist/ui/src/components/VirtualTable/VirtualTableRow.d.ts +0 -3
  335. package/dist/ui/src/components/VirtualTable/index.d.ts +0 -3
  336. package/dist/ui/src/components/VirtualTable/types.d.ts +0 -38
  337. package/dist/ui/src/components/common/SelectInputLabel.d.ts +0 -5
  338. package/dist/ui/src/components/index.d.ts +0 -58
  339. package/dist/ui/src/hooks/PortalContainerContext.d.ts +0 -31
  340. package/dist/ui/src/hooks/index.d.ts +0 -6
  341. package/dist/ui/src/hooks/useDebounceCallback.d.ts +0 -1
  342. package/dist/ui/src/hooks/useDebounceValue.d.ts +0 -1
  343. package/dist/ui/src/hooks/useDebouncedCallback.d.ts +0 -1
  344. package/dist/ui/src/hooks/useInjectStyles.d.ts +0 -7
  345. package/dist/ui/src/hooks/useOutsideAlerter.d.ts +0 -5
  346. package/dist/ui/src/icons/GitHubIcon.d.ts +0 -2
  347. package/dist/ui/src/icons/HandleIcon.d.ts +0 -1
  348. package/dist/ui/src/icons/Icon.d.ts +0 -20
  349. package/dist/ui/src/icons/cool_icon_keys.d.ts +0 -1
  350. package/dist/ui/src/icons/icon_keys.d.ts +0 -1
  351. package/dist/ui/src/icons/index.d.ts +0 -8
  352. package/dist/ui/src/index.d.ts +0 -5
  353. package/dist/ui/src/styles.d.ts +0 -12
  354. package/dist/ui/src/util/chip_colors.d.ts +0 -4
  355. package/dist/ui/src/util/cls.d.ts +0 -2
  356. package/dist/ui/src/util/debounce.d.ts +0 -10
  357. package/dist/ui/src/util/hash.d.ts +0 -1
  358. package/dist/ui/src/util/index.d.ts +0 -4
  359. package/dist/ui/src/util/key_to_icon_component.d.ts +0 -1
  360. /package/dist/{studio/src/components → components}/ApiExplorer/parseSpec.d.ts +0 -0
  361. /package/dist/{studio/src/components → components}/ApiExplorer/types.d.ts +0 -0
  362. /package/dist/{studio/src/components → components}/RLSEditor/index.d.ts +0 -0
  363. /package/dist/{studio/src/components → components}/RebaseStudio.d.ts +0 -0
  364. /package/dist/{studio/src/components → components}/SQLEditor/ExplainVisualizer.d.ts +0 -0
  365. /package/dist/{studio/src/components → components}/SchemaVisualizer/schema-visualizer.utils.d.ts +0 -0
  366. /package/dist/{studio/src/components → components}/SchemaVisualizer/useSchemaGraph.d.ts +0 -0
  367. /package/dist/{studio/src/index.d.ts → index.d.ts} +0 -0
  368. /package/dist/{studio/src/utils → utils}/pgColumnToProperty.d.ts +0 -0
  369. /package/dist/{studio/src/utils → utils}/sql_utils.d.ts +0 -0
@@ -0,0 +1,1573 @@
1
+ import { t as AuthSimulationSelector } from "./AuthSimulationSelector-iEZ-Or_1.js";
2
+ import { ErrorView, IconForView, useApiConfig, useModeController, useRebaseClient, useRebaseContext, useSnackbarController, useStudioCollectionRegistry, useStudioSideEntityController, useTranslation } from "@rebasepro/core";
3
+ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
4
+ 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
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
6
+ import { Highlight, themes } from "prism-react-renderer";
7
+ import { toSnakeCase } from "@rebasepro/utils";
8
+ import { createRebaseClient } from "@rebasepro/client";
9
+ import Editor from "@monaco-editor/react";
10
+ //#region src/components/JSEditor/JSMonacoEditor.tsx
11
+ /** Ambient type definitions for the Rebase client SDK injected into Monaco. */
12
+ var REBASE_CLIENT_TYPES = `
13
+ // ─── Rebase Client SDK Type Definitions ─────────────────────────────
14
+
15
+ interface Entity<M extends Record<string, any> = any> {
16
+ id: string | number;
17
+ path: string;
18
+ values: M;
19
+ }
20
+
21
+ interface FindParams {
22
+ limit?: number;
23
+ offset?: number;
24
+ page?: number;
25
+ where?: Record<string, string>;
26
+ orderBy?: string;
27
+ include?: string[];
28
+ searchString?: string;
29
+ }
30
+
31
+ interface FindResponse<M extends Record<string, any> = any> {
32
+ data: Entity<M>[];
33
+ meta: {
34
+ total: number;
35
+ limit: number;
36
+ offset: number;
37
+ hasMore: boolean;
38
+ };
39
+ }
40
+
41
+ type FilterOperator = "=" | "!=" | ">" | ">=" | "<" | "<=" | "in" | "not-in" | "array-contains" | "array-contains-any" | "is" | "is_not" | "like" | "ilike";
42
+
43
+ interface QueryBuilder<M extends Record<string, any> = any> {
44
+ where(column: keyof M & string, operator: FilterOperator, value: any): QueryBuilder<M>;
45
+ orderBy(column: keyof M & string, direction?: "asc" | "desc"): QueryBuilder<M>;
46
+ limit(count: number): QueryBuilder<M>;
47
+ offset(count: number): QueryBuilder<M>;
48
+ search(searchString: string): QueryBuilder<M>;
49
+ find(): Promise<FindResponse<M>>;
50
+ findOne(): Promise<Entity<M> | undefined>;
51
+ count(): Promise<number>;
52
+ }
53
+
54
+ interface CollectionClient<M extends Record<string, any> = any> {
55
+ find(params?: FindParams): Promise<FindResponse<M>>;
56
+ findById(id: string | number): Promise<Entity<M> | undefined>;
57
+ create(data: Partial<M>, id?: string | number): Promise<Entity<M>>;
58
+ update(id: string | number, data: Partial<M>): Promise<Entity<M>>;
59
+ delete(id: string | number): Promise<void>;
60
+ where(column: keyof M & string, operator: FilterOperator, value: any): QueryBuilder<M>;
61
+ orderBy(column: keyof M & string, direction?: "asc" | "desc"): QueryBuilder<M>;
62
+ limit(count: number): QueryBuilder<M>;
63
+ offset(count: number): QueryBuilder<M>;
64
+ search(searchString: string): QueryBuilder<M>;
65
+ listen?(params: FindParams | undefined, onUpdate: (response: FindResponse<M>) => void, onError?: (error: Error) => void): () => void;
66
+ listenById?(id: string | number, onUpdate: (entity: Entity<M> | undefined) => void, onError?: (error: Error) => void): () => void;
67
+ count?(params?: FindParams): Promise<number>;
68
+ }
69
+
70
+ interface RebaseUser {
71
+ uid: string;
72
+ email: string | null;
73
+ displayName: string | null;
74
+ photoURL: string | null;
75
+ emailVerified?: boolean;
76
+ roles?: string[];
77
+ providerId: string;
78
+ isAnonymous: boolean;
79
+ }
80
+
81
+ interface RebaseSession {
82
+ accessToken: string;
83
+ refreshToken: string;
84
+ expiresAt: number;
85
+ user: RebaseUser;
86
+ }
87
+
88
+ type AuthChangeEvent = 'SIGNED_IN' | 'SIGNED_OUT' | 'TOKEN_REFRESHED' | 'USER_UPDATED';
89
+
90
+ interface RebaseAuth {
91
+ signInWithEmail(email: string, password: string): Promise<{ user: RebaseUser; accessToken: string; refreshToken: string }>;
92
+ signUp(email: string, password: string, displayName?: string): Promise<{ user: RebaseUser; accessToken: string; refreshToken: string }>;
93
+ signInWithGoogle(idToken: string): Promise<{ user: RebaseUser; accessToken: string; refreshToken: string }>;
94
+ signOut(): Promise<void>;
95
+ refreshSession(): Promise<RebaseSession>;
96
+ getUser(): Promise<RebaseUser>;
97
+ updateUser(updates: { displayName?: string; photoURL?: string }): Promise<RebaseUser>;
98
+ resetPasswordForEmail(email: string): Promise<{ success: boolean; message: string }>;
99
+ resetPassword(token: string, password: string): Promise<{ success: boolean; message: string }>;
100
+ changePassword(oldPassword: string, newPassword: string): Promise<{ success: boolean; message: string }>;
101
+ sendVerificationEmail(): Promise<{ success: boolean; message: string }>;
102
+ verifyEmail(token: string): Promise<{ success: boolean; message: string }>;
103
+ getSessions(): Promise<RebaseSession[]>;
104
+ revokeSession(sessionId: string): Promise<{ success: boolean }>;
105
+ revokeAllSessions(): Promise<{ success: boolean }>;
106
+ getSession(): RebaseSession | null;
107
+ onAuthStateChange(callback: (event: AuthChangeEvent, session: RebaseSession | null) => void): () => void;
108
+ }
109
+
110
+ interface AdminUser {
111
+ uid: string;
112
+ email: string;
113
+ displayName: string | null;
114
+ photoURL: string | null;
115
+ provider: string;
116
+ roles: string[];
117
+ createdAt: string;
118
+ updatedAt: string;
119
+ }
120
+
121
+ interface RebaseAdmin {
122
+ listUsers(): Promise<{ users: AdminUser[] }>;
123
+ getUser(userId: string): Promise<{ user: AdminUser }>;
124
+ createUser(data: { email: string; displayName?: string; password?: string; roles?: string[] }): Promise<{ user: AdminUser }>;
125
+ updateUser(userId: string, data: { email?: string; displayName?: string; password?: string; roles?: string[] }): Promise<{ user: AdminUser }>;
126
+ deleteUser(userId: string): Promise<{ success: boolean }>;
127
+ bootstrap(): Promise<{ success: boolean; message: string; user: { uid: string; roles: string[] } }>;
128
+ }
129
+
130
+ interface UploadFileProps {
131
+ file: FileIcon;
132
+ fileName?: string;
133
+ path?: string;
134
+ metadata?: Record<string, unknown>;
135
+ bucket?: string;
136
+ }
137
+
138
+ interface UploadFileResult {
139
+ path: string;
140
+ bucket?: string;
141
+ downloadUrl?: string;
142
+ }
143
+
144
+ interface DownloadConfig {
145
+ url: string | null;
146
+ fileNotFound?: boolean;
147
+ metadata?: Record<string, unknown>;
148
+ }
149
+
150
+ interface StorageSource {
151
+ putObject(props: UploadFileProps): Promise<UploadFileResult>;
152
+ getSignedUrl(pathOrUrl: string, bucket?: string): Promise<DownloadConfig>;
153
+ getObject(path: string, bucket?: string): Promise<FileIcon | null>;
154
+ deleteObject(path: string, bucket?: string): Promise<void>;
155
+ listObjects(path: string, options?: { bucket?: string; maxResults?: number; pageToken?: string }): Promise<unknown>;
156
+ }
157
+
158
+ type RebaseData = {
159
+ /** Look up a collection by slug. */
160
+ collection(slug: string): CollectionClient;
161
+ } & {
162
+ /** Dynamic collection access — e.g. client.data.authors */
163
+ [collectionSlug: string]: CollectionClient;
164
+ };
165
+
166
+ /**
167
+ * The Rebase client instance. Use \`client.data\`, \`client.auth\`, \`client.admin\`,
168
+ * \`client.storage\`, and \`client.call()\` to interact with your Rebase backend.
169
+ *
170
+ * @example
171
+ * // Query a collection
172
+ * const result = await client.data.products.find({ limit: 10 });
173
+ *
174
+ * // Create a record
175
+ * await client.data.products.create({ name: "Camera", price: 299 });
176
+ *
177
+ * // Fluent query
178
+ * const expensive = await client.data.products.where("price", ">", 100).orderBy("price", "desc").limit(5).find();
179
+ *
180
+ * // Auth
181
+ * const session = client.auth.getSession();
182
+ *
183
+ * // Admin
184
+ * const { users } = await client.admin.listUsers();
185
+ *
186
+ * // Custom endpoint
187
+ * const result = await client.call("/my-endpoint", { myData: 123 });
188
+ */
189
+ interface RebaseClient {
190
+ /** Data access — dynamic collection accessors */
191
+ data: RebaseData;
192
+ /** Authentication methods */
193
+ auth: RebaseAuth;
194
+ /** User/role admin methods */
195
+ admin: RebaseAdmin;
196
+ /** Storage operations */
197
+ storage?: StorageSource;
198
+ /** Call a custom server-side endpoint */
199
+ call<T = unknown>(endpoint: string, payload?: unknown): Promise<T>;
200
+ /** Direct collection access (shorthand) */
201
+ [collectionSlug: string]: unknown;
202
+ }
203
+
204
+ /** The pre-configured client instance. Already authenticated with the current user session. */
205
+ declare const client: RebaseClient;
206
+
207
+ /** Execution context with user and collection information. */
208
+ interface JSEditorContext {
209
+ /** The user the script is running as. */
210
+ user: {
211
+ uid: string;
212
+ displayName: string | null;
213
+ email: string | null;
214
+ roles?: string[];
215
+ } | null;
216
+ /** Registered collections with their property names. */
217
+ collections: Array<{
218
+ slug: string;
219
+ name: string;
220
+ properties: string[];
221
+ }>;
222
+ }
223
+
224
+ /** Execution context — contains info about the selected user and registered collections. */
225
+ declare const context: JSEditorContext;
226
+ `;
227
+ var JSMonacoEditor = ({ value, onChange, onRun, className, readOnly = false, autoFocus = true, collectionSlugs = [], collections = [] }) => {
228
+ const { mode } = useModeController();
229
+ const editorRef = useRef(null);
230
+ const monacoRef = useRef(null);
231
+ const onRunRef = useRef(onRun);
232
+ onRunRef.current = onRun;
233
+ const typesRegisteredRef = useRef(false);
234
+ const handleEditorOnMount = (editorInstance, monaco) => {
235
+ editorRef.current = editorInstance;
236
+ monacoRef.current = monaco;
237
+ editorInstance.addAction({
238
+ id: "run-script",
239
+ label: "Run Script",
240
+ keybindings: [monaco.KeyMod.CtrlCmd | monaco.KeyCode.Enter],
241
+ contextMenuGroupId: "operation",
242
+ contextMenuOrder: 0,
243
+ run: () => {
244
+ if (onRunRef.current) {
245
+ const selection = editorInstance.getSelection();
246
+ let selectedText;
247
+ if (selection && !selection.isEmpty()) selectedText = editorInstance.getModel()?.getValueInRange(selection)?.trim();
248
+ onRunRef.current(selectedText || void 0);
249
+ }
250
+ }
251
+ });
252
+ if (!typesRegisteredRef.current) {
253
+ typesRegisteredRef.current = true;
254
+ const ts = monaco.languages.typescript;
255
+ ts.typescriptDefaults.setCompilerOptions({
256
+ target: ts.ScriptTarget.ESNext,
257
+ module: ts.ModuleKind.ESNext,
258
+ allowJs: true,
259
+ checkJs: false,
260
+ strict: false,
261
+ noEmit: true,
262
+ allowNonTsExtensions: true
263
+ });
264
+ ts.typescriptDefaults.setDiagnosticsOptions({ diagnosticCodesToIgnore: [1375, 1108] });
265
+ ts.typescriptDefaults.addExtraLib(REBASE_CLIENT_TYPES, "ts:rebase-client.d.ts");
266
+ if (collections.length > 0) {
267
+ const lines = [];
268
+ for (const col of collections) {
269
+ const ifaceName = col.slug.replace(/[^a-zA-Z0-9_]/g, "_");
270
+ const propsType = col.properties.length > 0 ? `{ ${col.properties.map((p) => `${p}: any`).join("; ")} }` : "Record<string, any>";
271
+ lines.push(`/** Collection: ${col.name} (${col.slug}) */`);
272
+ lines.push(`interface ${ifaceName}_Row ${propsType}`);
273
+ lines.push(`declare namespace client.data { const ${col.slug}: CollectionClient<${ifaceName}_Row>; }`);
274
+ }
275
+ ts.typescriptDefaults.addExtraLib(lines.join("\n"), "ts:rebase-collections.d.ts");
276
+ } else if (collectionSlugs.length > 0) {
277
+ const collectionHints = collectionSlugs.map((slug) => `/** Collection: ${slug} */\ndeclare namespace client.data { const ${slug}: CollectionClient; }`).join("\n");
278
+ ts.typescriptDefaults.addExtraLib(collectionHints, "ts:rebase-collections.d.ts");
279
+ }
280
+ }
281
+ if (autoFocus) editorInstance.focus();
282
+ };
283
+ return /* @__PURE__ */ jsx("div", {
284
+ className: cls("relative w-full h-full overflow-hidden", className),
285
+ children: /* @__PURE__ */ jsx(Editor, {
286
+ height: "100%",
287
+ defaultLanguage: "typescript",
288
+ path: "rebase-script.ts",
289
+ value,
290
+ onChange,
291
+ onMount: handleEditorOnMount,
292
+ theme: mode === "dark" ? "vs-dark" : "vs",
293
+ options: {
294
+ minimap: { enabled: false },
295
+ fontSize: 14,
296
+ lineNumbers: "on",
297
+ scrollBeyondLastLine: false,
298
+ automaticLayout: true,
299
+ readOnly,
300
+ tabSize: 2,
301
+ wordWrap: "on",
302
+ suggestOnTriggerCharacters: true,
303
+ quickSuggestions: true,
304
+ parameterHints: { enabled: true }
305
+ }
306
+ })
307
+ });
308
+ };
309
+ //#endregion
310
+ //#region src/components/JSEditor/JSEditorSidebar.tsx
311
+ var QUICK_REFERENCE = [
312
+ {
313
+ label: "Find all",
314
+ code: "const result = await client.data.collection(\"COLLECTION\").find({ limit: 20 });\nreturn result;",
315
+ description: "Fetch records with pagination"
316
+ },
317
+ {
318
+ label: "Find by ID",
319
+ code: "const item = await client.data.collection(\"COLLECTION\").findById(\"ID\");\nreturn item;",
320
+ description: "Fetch a single record"
321
+ },
322
+ {
323
+ label: "Create",
324
+ code: "const created = await client.data.collection(\"COLLECTION\").create({\n // your fields here\n});\nreturn created;",
325
+ description: "Insert a new record"
326
+ },
327
+ {
328
+ label: "Update",
329
+ code: "const updated = await client.data.collection(\"COLLECTION\").update(\"ID\", {\n // fields to update\n});\nreturn updated;",
330
+ description: "Update an existing record"
331
+ },
332
+ {
333
+ label: "Delete",
334
+ code: "await client.data.collection(\"COLLECTION\").delete(\"ID\");\nreturn { success: true };",
335
+ description: "Delete a record"
336
+ },
337
+ {
338
+ label: "Fluent query",
339
+ code: "const result = await client.data.collection(\"COLLECTION\")\n .where(\"field\", \">\", value)\n .orderBy(\"field\", \"desc\")\n .limit(10)\n .find();\nreturn result;",
340
+ description: "Chained query builder"
341
+ },
342
+ {
343
+ label: "Auth: Current session",
344
+ code: "const session = client.auth.getSession();\nreturn session;",
345
+ description: "Get current auth session"
346
+ },
347
+ {
348
+ label: "Admin: List users",
349
+ code: "const { users } = await client.admin.listUsers();\nreturn users;",
350
+ description: "List all registered users"
351
+ },
352
+ {
353
+ label: "Custom endpoint",
354
+ code: "const result = await client.call(\"/my-endpoint\", { key: \"value\" });\nreturn result;",
355
+ description: "Call a custom API endpoint"
356
+ }
357
+ ];
358
+ var JSEditorSidebar = ({ collections, snippets, history, onSelectSnippet, onDeleteSnippet, onInsertCode }) => {
359
+ const [activeTab, setActiveTab] = useState("collections");
360
+ return /* @__PURE__ */ jsxs("div", {
361
+ className: cls("flex flex-col h-full w-full bg-white dark:bg-surface-950 border-r", defaultBorderMixin),
362
+ children: [/* @__PURE__ */ jsxs(Tabs, {
363
+ value: activeTab,
364
+ onValueChange: (v) => setActiveTab(v),
365
+ variant: "boxy",
366
+ className: "border-b border-surface-200 dark:border-surface-950",
367
+ children: [
368
+ /* @__PURE__ */ jsx(Tab, {
369
+ value: "collections",
370
+ children: /* @__PURE__ */ jsx(Tooltip, {
371
+ title: "Browse collections",
372
+ children: /* @__PURE__ */ jsx("span", {
373
+ className: "text-xs",
374
+ children: "Collections"
375
+ })
376
+ })
377
+ }),
378
+ /* @__PURE__ */ jsx(Tab, {
379
+ value: "reference",
380
+ children: /* @__PURE__ */ jsx(Tooltip, {
381
+ title: "SDK quick reference",
382
+ children: /* @__PURE__ */ jsx("span", {
383
+ className: "text-xs",
384
+ children: "Reference"
385
+ })
386
+ })
387
+ }),
388
+ /* @__PURE__ */ jsx(Tab, {
389
+ value: "snippets",
390
+ children: /* @__PURE__ */ jsx("span", {
391
+ className: "text-xs",
392
+ children: "Snippets"
393
+ })
394
+ }),
395
+ /* @__PURE__ */ jsx(Tab, {
396
+ value: "history",
397
+ children: /* @__PURE__ */ jsx("span", {
398
+ className: "text-xs",
399
+ children: "History"
400
+ })
401
+ })
402
+ ]
403
+ }), /* @__PURE__ */ jsxs("div", {
404
+ className: "flex-grow overflow-hidden relative",
405
+ children: [
406
+ activeTab === "collections" && /* @__PURE__ */ jsxs("div", {
407
+ className: "flex flex-col h-full",
408
+ children: [/* @__PURE__ */ jsx("div", {
409
+ className: cls("flex items-center justify-between px-3 py-2 border-b bg-surface-50 dark:bg-surface-900 min-h-[48px]", defaultBorderMixin),
410
+ children: /* @__PURE__ */ jsx(Typography, {
411
+ variant: "caption",
412
+ className: "font-bold uppercase tracking-wider text-text-disabled dark:text-text-disabled-dark",
413
+ children: "Collections"
414
+ })
415
+ }), /* @__PURE__ */ jsx("div", {
416
+ className: "flex-grow overflow-y-auto p-1 space-y-1 no-scrollbar",
417
+ children: collections.length === 0 ? /* @__PURE__ */ jsx("div", {
418
+ className: "p-4 text-center",
419
+ children: /* @__PURE__ */ jsx(Typography, {
420
+ variant: "caption",
421
+ className: "text-text-disabled dark:text-text-disabled-dark",
422
+ children: "No collections found"
423
+ })
424
+ }) : collections.map((col) => /* @__PURE__ */ jsx(CollectionItem, {
425
+ collection: col,
426
+ onInsertCode
427
+ }, col.slug))
428
+ })]
429
+ }),
430
+ activeTab === "reference" && /* @__PURE__ */ jsxs("div", {
431
+ className: "flex flex-col h-full",
432
+ children: [/* @__PURE__ */ jsx("div", {
433
+ className: cls("flex items-center justify-between px-3 py-2 border-b bg-surface-50 dark:bg-surface-900 min-h-[48px]", defaultBorderMixin),
434
+ children: /* @__PURE__ */ jsx(Typography, {
435
+ variant: "caption",
436
+ className: "font-bold uppercase tracking-wider text-text-disabled dark:text-text-disabled-dark",
437
+ children: "SDK Reference"
438
+ })
439
+ }), /* @__PURE__ */ jsx("div", {
440
+ className: "flex-grow overflow-y-auto p-2 space-y-2 no-scrollbar",
441
+ children: QUICK_REFERENCE.map((ref, i) => /* @__PURE__ */ jsxs("div", {
442
+ className: cls("group p-2.5 rounded-lg border hover:border-primary/40 dark:hover:border-primary/40", "bg-white dark:bg-surface-900 transition-all cursor-pointer", defaultBorderMixin),
443
+ onClick: () => onInsertCode(ref.code),
444
+ children: [/* @__PURE__ */ jsxs("div", {
445
+ className: "flex items-center justify-between mb-1",
446
+ children: [/* @__PURE__ */ jsx(Typography, {
447
+ variant: "body2",
448
+ className: "text-text-primary dark:text-text-primary-dark font-semibold text-[13px]",
449
+ children: ref.label
450
+ }), /* @__PURE__ */ jsx("svg", {
451
+ className: "w-3.5 h-3.5 text-text-disabled group-hover:text-primary transition-colors",
452
+ fill: "none",
453
+ stroke: "currentColor",
454
+ viewBox: "0 0 24 24",
455
+ children: /* @__PURE__ */ jsx("path", {
456
+ strokeLinecap: "round",
457
+ strokeLinejoin: "round",
458
+ strokeWidth: 2,
459
+ 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"
460
+ })
461
+ })]
462
+ }), /* @__PURE__ */ jsx(Typography, {
463
+ variant: "caption",
464
+ className: "text-text-disabled dark:text-text-disabled-dark text-[10px] leading-tight",
465
+ children: ref.description
466
+ })]
467
+ }, i))
468
+ })]
469
+ }),
470
+ activeTab === "snippets" && (() => {
471
+ const favorites = snippets.filter((s) => s.isFavorite);
472
+ const others = snippets.filter((s) => !s.isFavorite);
473
+ return /* @__PURE__ */ jsxs("div", {
474
+ className: "flex flex-col h-full",
475
+ children: [/* @__PURE__ */ jsx("div", {
476
+ className: cls("flex items-center justify-between px-3 py-2 border-b bg-surface-50 dark:bg-surface-900 min-h-[48px]", defaultBorderMixin),
477
+ children: /* @__PURE__ */ jsx(Typography, {
478
+ variant: "caption",
479
+ className: "font-bold uppercase tracking-wider text-text-disabled dark:text-text-disabled-dark",
480
+ children: "Snippets"
481
+ })
482
+ }), /* @__PURE__ */ jsx("div", {
483
+ className: "flex-grow overflow-y-auto p-2 space-y-2 no-scrollbar",
484
+ children: snippets.length === 0 ? /* @__PURE__ */ jsx("div", {
485
+ className: "p-4 text-center",
486
+ children: /* @__PURE__ */ jsx(Typography, {
487
+ variant: "caption",
488
+ className: "text-text-disabled dark:text-text-disabled-dark",
489
+ children: "No saved snippets yet. Use the save button to store reusable code."
490
+ })
491
+ }) : /* @__PURE__ */ jsxs(Fragment, { children: [favorites.length > 0 && /* @__PURE__ */ jsxs("div", {
492
+ className: "mb-3",
493
+ children: [/* @__PURE__ */ jsxs(Typography, {
494
+ variant: "caption",
495
+ className: "text-[10px] font-bold uppercase tracking-wider text-text-disabled dark:text-text-disabled-dark mb-2 px-1 flex items-center",
496
+ children: [/* @__PURE__ */ jsx("svg", {
497
+ className: "w-3 h-3 mr-1 text-amber-500",
498
+ fill: "currentColor",
499
+ viewBox: "0 0 20 20",
500
+ children: /* @__PURE__ */ jsx("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" })
501
+ }), "Favorites"]
502
+ }), /* @__PURE__ */ jsx("div", {
503
+ className: "space-y-2",
504
+ children: favorites.map((snippet) => /* @__PURE__ */ jsx(SnippetItem, {
505
+ snippet,
506
+ onSelect: onSelectSnippet,
507
+ onDelete: onDeleteSnippet
508
+ }, snippet.id))
509
+ })]
510
+ }), others.length > 0 && /* @__PURE__ */ jsxs("div", { children: [favorites.length > 0 && /* @__PURE__ */ jsx(Typography, {
511
+ variant: "caption",
512
+ className: "text-[10px] font-bold uppercase tracking-wider text-text-disabled dark:text-text-disabled-dark mb-2 px-1",
513
+ children: "Others"
514
+ }), /* @__PURE__ */ jsx("div", {
515
+ className: "space-y-2",
516
+ children: others.map((snippet) => /* @__PURE__ */ jsx(SnippetItem, {
517
+ snippet,
518
+ onSelect: onSelectSnippet,
519
+ onDelete: onDeleteSnippet
520
+ }, snippet.id))
521
+ })] })] })
522
+ })]
523
+ });
524
+ })(),
525
+ activeTab === "history" && /* @__PURE__ */ jsxs("div", {
526
+ className: "flex flex-col h-full",
527
+ children: [/* @__PURE__ */ jsx("div", {
528
+ className: cls("flex items-center justify-between px-3 py-2 border-b bg-surface-50 dark:bg-surface-900 min-h-[48px]", defaultBorderMixin),
529
+ children: /* @__PURE__ */ jsx(Typography, {
530
+ variant: "caption",
531
+ className: "font-bold uppercase tracking-wider text-text-disabled dark:text-text-disabled-dark",
532
+ children: "History"
533
+ })
534
+ }), /* @__PURE__ */ jsx("div", {
535
+ className: "flex-grow overflow-y-auto p-1 space-y-1 no-scrollbar",
536
+ children: history.length === 0 ? /* @__PURE__ */ jsx("div", {
537
+ className: "p-4 text-center",
538
+ children: /* @__PURE__ */ jsx(Typography, {
539
+ variant: "caption",
540
+ className: "text-text-disabled dark:text-text-disabled-dark",
541
+ children: "No execution history yet"
542
+ })
543
+ }) : [...history].reverse().map((code, i) => /* @__PURE__ */ jsxs("div", {
544
+ className: "p-2 py-1.5 rounded hover:bg-surface-100 dark:hover:bg-surface-950 cursor-pointer group transition-colors flex items-start",
545
+ onClick: () => onSelectSnippet(code),
546
+ children: [/* @__PURE__ */ jsx("svg", {
547
+ 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",
548
+ fill: "none",
549
+ stroke: "currentColor",
550
+ viewBox: "0 0 24 24",
551
+ children: /* @__PURE__ */ jsx("path", {
552
+ strokeLinecap: "round",
553
+ strokeLinejoin: "round",
554
+ strokeWidth: 2,
555
+ d: "M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"
556
+ })
557
+ }), /* @__PURE__ */ jsx(Typography, {
558
+ variant: "caption",
559
+ 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",
560
+ children: code.length > 120 ? code.substring(0, 120) + "…" : code
561
+ })]
562
+ }, i))
563
+ })]
564
+ })
565
+ ]
566
+ })]
567
+ });
568
+ };
569
+ function CollectionItem({ collection, onInsertCode }) {
570
+ const [expanded, setExpanded] = useState(false);
571
+ return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsxs("div", {
572
+ className: "flex items-center p-1 cursor-pointer hover:bg-surface-100 dark:hover:bg-surface-950 rounded transition-colors group relative",
573
+ onClick: () => setExpanded(!expanded),
574
+ children: [
575
+ /* @__PURE__ */ jsx("svg", {
576
+ className: cls("w-3 h-3 mr-1 transition-transform", expanded && "rotate-90"),
577
+ fill: "currentColor",
578
+ viewBox: "0 0 20 20",
579
+ children: /* @__PURE__ */ jsx("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" })
580
+ }),
581
+ /* @__PURE__ */ jsx("svg", {
582
+ className: "w-3.5 h-3.5 mr-1 shrink-0 text-text-disabled dark:text-text-disabled-dark",
583
+ fill: "none",
584
+ stroke: "currentColor",
585
+ viewBox: "0 0 24 24",
586
+ children: /* @__PURE__ */ jsx("path", {
587
+ strokeLinecap: "round",
588
+ strokeLinejoin: "round",
589
+ strokeWidth: 2,
590
+ 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"
591
+ })
592
+ }),
593
+ /* @__PURE__ */ jsx(Typography, {
594
+ variant: "body2",
595
+ className: "text-text-secondary dark:text-text-secondary-dark text-xs truncate flex-1 min-w-0",
596
+ children: collection.slug
597
+ }),
598
+ /* @__PURE__ */ jsx(Tooltip, {
599
+ title: "Insert find() snippet",
600
+ children: /* @__PURE__ */ jsx(IconButton, {
601
+ size: "smallest",
602
+ className: "opacity-0 group-hover:opacity-100 text-text-disabled hover:text-primary transition-all",
603
+ onClick: (e) => {
604
+ e.stopPropagation();
605
+ onInsertCode(`const result = await client.data.${collection.slug}.find({ limit: 20 });\nreturn result;`);
606
+ },
607
+ children: /* @__PURE__ */ jsx(PlusIcon, { size: iconSize.smallest })
608
+ })
609
+ })
610
+ ]
611
+ }), expanded && collection.properties.length > 0 && /* @__PURE__ */ jsx("div", {
612
+ className: cls("ml-5 mt-1 space-y-0.5 border-l", defaultBorderMixin),
613
+ children: collection.properties.map((prop) => /* @__PURE__ */ jsxs("div", {
614
+ className: "flex items-center p-1 pl-2 hover:bg-surface-50 dark:hover:bg-surface-950 rounded-r cursor-pointer transition-colors group/prop relative min-h-[28px]",
615
+ onClick: () => onInsertCode(`"${prop}"`),
616
+ children: [/* @__PURE__ */ jsx("svg", {
617
+ className: "w-3 h-3 mr-1.5 text-text-disabled dark:text-text-disabled-dark shrink-0",
618
+ fill: "none",
619
+ stroke: "currentColor",
620
+ viewBox: "0 0 24 24",
621
+ children: /* @__PURE__ */ jsx("path", {
622
+ strokeLinecap: "round",
623
+ strokeLinejoin: "round",
624
+ strokeWidth: 1.5,
625
+ 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"
626
+ })
627
+ }), /* @__PURE__ */ jsx(Typography, {
628
+ variant: "caption",
629
+ className: "text-text-primary dark:text-text-primary-dark text-[11px] truncate flex-grow font-mono",
630
+ children: prop
631
+ })]
632
+ }, prop))
633
+ })] });
634
+ }
635
+ function SnippetItem({ snippet, onSelect, onDelete }) {
636
+ return /* @__PURE__ */ jsxs("div", {
637
+ className: cls("group p-2 rounded border hover:border-surface-400 dark:hover:border-surface-600 bg-white dark:bg-surface-900 transition-all cursor-pointer relative", defaultBorderMixin),
638
+ onClick: () => onSelect(snippet.code),
639
+ children: [
640
+ /* @__PURE__ */ jsx(Typography, {
641
+ variant: "body2",
642
+ className: "text-text-primary dark:text-text-primary-dark font-medium text-[13px] truncate pr-6",
643
+ children: snippet.name
644
+ }),
645
+ /* @__PURE__ */ jsx(Typography, {
646
+ variant: "caption",
647
+ className: "text-text-secondary dark:text-text-secondary-dark text-[10px] block mt-1 truncate font-mono",
648
+ children: snippet.code
649
+ }),
650
+ /* @__PURE__ */ jsx(IconButton, {
651
+ size: "smallest",
652
+ className: "absolute right-1 top-1 opacity-0 group-hover:opacity-100 text-text-disabled hover:text-red-500 transition-opacity",
653
+ onClick: (e) => {
654
+ e.stopPropagation();
655
+ onDelete(snippet.id);
656
+ },
657
+ children: /* @__PURE__ */ jsx(Trash2Icon, { size: iconSize.smallest })
658
+ })
659
+ ]
660
+ });
661
+ }
662
+ //#endregion
663
+ //#region src/components/JSEditor/JSEditor.tsx
664
+ var STORAGE_PREFIX = "rebase_js_";
665
+ var DEFAULT_CODE = `// Available: client (RebaseClient)
666
+ // Press Cmd+Enter (Ctrl+Enter) to run
667
+ //
668
+ // Examples:
669
+ // const result = await client.data.collection("your_collection").find({ limit: 10 });
670
+ // const users = await client.admin.listUsers();
671
+ // const session = client.auth.getSession();
672
+
673
+ const result = await client.data.collection("your_collection").find({ limit: 10 });
674
+ return result;
675
+ `;
676
+ function loadFromStorage(key, fallback) {
677
+ try {
678
+ const raw = localStorage.getItem(STORAGE_PREFIX + key);
679
+ return raw ? JSON.parse(raw) : fallback;
680
+ } catch {
681
+ return fallback;
682
+ }
683
+ }
684
+ function saveToStorage(key, value) {
685
+ try {
686
+ localStorage.setItem(STORAGE_PREFIX + key, JSON.stringify(value));
687
+ } catch {}
688
+ }
689
+ function formatJSON(value) {
690
+ try {
691
+ return JSON.stringify(value, null, 2);
692
+ } catch {
693
+ return String(value);
694
+ }
695
+ }
696
+ /**
697
+ * Given the raw SDK result, try to detect which collections are present.
698
+ * JS SDK results typically come back as `{ data: [{ id, values }] }` or plain arrays.
699
+ * The heuristic: if the executed code contains `collection("<slug>")` or `client.data.<slug>`,
700
+ * and the result has rows with an "id" column, we match those slugs.
701
+ */
702
+ function detectCollectionsInResult(code, resultValue, collections) {
703
+ if (!resultValue || !collections?.length) return [];
704
+ const mentionedSlugs = /* @__PURE__ */ new Set();
705
+ const collectionCallRegex = /\.collection\(["']([^"']+)["']\)/g;
706
+ let m;
707
+ while ((m = collectionCallRegex.exec(code)) !== null) mentionedSlugs.add(m[1]);
708
+ const dotAccessRegex = /client\.data\.([a-zA-Z_][a-zA-Z0-9_]*)\./g;
709
+ while ((m = dotAccessRegex.exec(code)) !== null) if (![
710
+ "collection",
711
+ "find",
712
+ "findById",
713
+ "create",
714
+ "update",
715
+ "delete"
716
+ ].includes(m[1])) mentionedSlugs.add(m[1]);
717
+ if (mentionedSlugs.size === 0) return [];
718
+ let rows = [];
719
+ const rv = resultValue;
720
+ if (rv?.data && Array.isArray(rv.data)) rows = rv.data;
721
+ else if (Array.isArray(resultValue)) rows = resultValue;
722
+ if (!(rows.length > 0 && rows.some((r) => r?.id != null))) return [];
723
+ const matched = [];
724
+ for (const slug of mentionedSlugs) {
725
+ const normalised = toSnakeCase(slug);
726
+ const col = collections.find((c) => {
727
+ const tableName = ("table" in c ? c.table : void 0) || toSnakeCase(c.slug);
728
+ return c.slug === slug || tableName === normalised || toSnakeCase(c.slug) === normalised;
729
+ });
730
+ if (col) matched.push({
731
+ collectionSlug: col.slug,
732
+ collection: col,
733
+ pkColumn: "id"
734
+ });
735
+ }
736
+ return matched;
737
+ }
738
+ function JSEditor() {
739
+ const rebaseContext = useRebaseContext();
740
+ const rebaseClient = useRebaseClient();
741
+ const apiConfig = useApiConfig();
742
+ const snackbar = useSnackbarController();
743
+ const collectionRegistry = useStudioCollectionRegistry();
744
+ const sideEntityController = useStudioSideEntityController();
745
+ const { t } = useTranslation();
746
+ const currentUser = rebaseContext.authController?.user;
747
+ const [tabs, setTabs] = useState(() => loadFromStorage("tabs", [{
748
+ id: "1",
749
+ name: "Script 1",
750
+ code: DEFAULT_CODE
751
+ }]));
752
+ const [activeTabId, setActiveTabId] = useState(() => loadFromStorage("activeTab", "1"));
753
+ const [result, setResult] = useState(null);
754
+ const [isRunning, setIsRunning] = useState(false);
755
+ const [snippets, setSnippets] = useState(() => loadFromStorage("snippets", []));
756
+ const [history, setHistory] = useState(() => loadFromStorage("history", []));
757
+ const [showSaveDialog, setShowSaveDialog] = useState(false);
758
+ const [snippetName, setSnippetName] = useState("");
759
+ const [resultView, setResultView] = useState("json");
760
+ const [selectedUser, setSelectedUser] = useState(null);
761
+ const [authMode, setAuthMode] = useState("jwt");
762
+ const [sidebarSize, setSidebarSize] = useState(() => {
763
+ try {
764
+ const stored = localStorage.getItem("rebase_js_sidebar_size");
765
+ return stored ? Number(stored) : 18;
766
+ } catch {
767
+ return 18;
768
+ }
769
+ });
770
+ const [editorHeight, setEditorHeight] = useState(() => {
771
+ try {
772
+ const stored = localStorage.getItem("rebase_js_editor_height");
773
+ return stored ? Number(stored) : 55;
774
+ } catch {
775
+ return 55;
776
+ }
777
+ });
778
+ const activeTab = tabs.find((t) => t.id === activeTabId) ?? tabs[0];
779
+ const collectionInfos = useMemo(() => {
780
+ return (collectionRegistry?.collections ?? []).map((col) => ({
781
+ slug: col.slug,
782
+ name: col.name,
783
+ properties: Object.keys(col.properties ?? {})
784
+ }));
785
+ }, [collectionRegistry?.collections]);
786
+ const collectionSlugs = useMemo(() => collectionInfos.map((c) => c.slug), [collectionInfos]);
787
+ const users = useMemo(() => {
788
+ const managed = [];
789
+ if (currentUser) managed.push({
790
+ uid: currentUser.uid,
791
+ displayName: currentUser.displayName,
792
+ email: currentUser.email,
793
+ photoURL: currentUser.photoURL,
794
+ roles: currentUser.roles
795
+ });
796
+ return managed;
797
+ }, [currentUser]);
798
+ const currentSelectableUser = useMemo(() => {
799
+ if (!currentUser) return null;
800
+ return {
801
+ uid: currentUser.uid,
802
+ displayName: currentUser.displayName,
803
+ email: currentUser.email,
804
+ photoURL: currentUser.photoURL,
805
+ roles: currentUser.roles
806
+ };
807
+ }, [currentUser]);
808
+ useEffect(() => {
809
+ saveToStorage("tabs", tabs);
810
+ }, [tabs]);
811
+ useEffect(() => {
812
+ saveToStorage("activeTab", activeTabId);
813
+ }, [activeTabId]);
814
+ useEffect(() => {
815
+ saveToStorage("snippets", snippets);
816
+ }, [snippets]);
817
+ useEffect(() => {
818
+ saveToStorage("history", history);
819
+ }, [history]);
820
+ useEffect(() => {
821
+ try {
822
+ localStorage.setItem("rebase_js_sidebar_size", sidebarSize.toString());
823
+ } catch {}
824
+ }, [sidebarSize]);
825
+ useEffect(() => {
826
+ try {
827
+ localStorage.setItem("rebase_js_editor_height", editorHeight.toString());
828
+ } catch {}
829
+ }, [editorHeight]);
830
+ const updateActiveCode = useCallback((code) => {
831
+ setTabs((prev) => prev.map((t) => t.id === activeTabId ? {
832
+ ...t,
833
+ code: code ?? ""
834
+ } : t));
835
+ }, [activeTabId]);
836
+ const addTab = useCallback(() => {
837
+ const id = String(Date.now());
838
+ const newTab = {
839
+ id,
840
+ name: `Script ${tabs.length + 1}`,
841
+ code: DEFAULT_CODE
842
+ };
843
+ setTabs((prev) => [...prev, newTab]);
844
+ setActiveTabId(id);
845
+ }, [tabs.length]);
846
+ const closeTab = useCallback((tabId) => {
847
+ setTabs((prev) => {
848
+ const filtered = prev.filter((t) => t.id !== tabId);
849
+ if (filtered.length === 0) {
850
+ const fresh = {
851
+ id: String(Date.now()),
852
+ name: "Script 1",
853
+ code: DEFAULT_CODE
854
+ };
855
+ setActiveTabId(fresh.id);
856
+ return [fresh];
857
+ }
858
+ if (activeTabId === tabId) setActiveTabId(filtered[filtered.length - 1].id);
859
+ return filtered;
860
+ });
861
+ }, [activeTabId]);
862
+ const buildClient = useCallback(async () => {
863
+ const apiUrl = apiConfig?.apiUrl;
864
+ const getAuthToken = apiConfig?.getAuthToken;
865
+ if (!apiUrl) throw new Error("API URL not configured. Make sure apiUrl is set.");
866
+ if (authMode === "none") return {
867
+ client: createRebaseClient({
868
+ baseUrl: apiUrl,
869
+ token: void 0
870
+ }),
871
+ isScoped: true
872
+ };
873
+ if (!selectedUser || currentUser && selectedUser.uid === currentUser.uid) {
874
+ if (!rebaseClient) throw new Error("Application client is not initialized.");
875
+ return {
876
+ client: rebaseClient,
877
+ isScoped: false
878
+ };
879
+ }
880
+ let token;
881
+ if (getAuthToken) token = await getAuthToken() ?? void 0;
882
+ if (!token) throw new Error("No auth token available. Please sign in first.");
883
+ return {
884
+ client: createRebaseClient({
885
+ baseUrl: apiUrl,
886
+ token
887
+ }),
888
+ isScoped: true
889
+ };
890
+ }, [
891
+ apiConfig,
892
+ rebaseClient,
893
+ selectedUser,
894
+ currentUser,
895
+ authMode
896
+ ]);
897
+ const executeCode = useCallback(async (codeOverride) => {
898
+ const code = codeOverride ?? activeTab?.code ?? "";
899
+ if (!code.trim()) return;
900
+ setIsRunning(true);
901
+ setResult(null);
902
+ setHistory((prev) => {
903
+ return [...prev.filter((h) => h !== code), code].slice(-50);
904
+ });
905
+ const consoleEntries = [];
906
+ const startTime = performance.now();
907
+ let scopedClientToCleanUp = null;
908
+ const originalConsole = {
909
+ log: console.log,
910
+ warn: console.warn,
911
+ error: console.error,
912
+ info: console.info
913
+ };
914
+ const captureConsole = (type) => (...args) => {
915
+ consoleEntries.push({
916
+ type,
917
+ args,
918
+ timestamp: Date.now()
919
+ });
920
+ originalConsole[type](...args);
921
+ };
922
+ try {
923
+ console.log = captureConsole("log");
924
+ console.warn = captureConsole("warn");
925
+ console.error = captureConsole("error");
926
+ console.info = captureConsole("info");
927
+ const { client, isScoped } = await buildClient();
928
+ if (isScoped) scopedClientToCleanUp = client;
929
+ const context = {
930
+ user: selectedUser ?? (currentUser ? {
931
+ uid: currentUser.uid,
932
+ displayName: currentUser.displayName,
933
+ email: currentUser.email,
934
+ roles: currentUser.roles
935
+ } : null),
936
+ collections: collectionInfos
937
+ };
938
+ const AsyncFunction = Object.getPrototypeOf(async function() {}).constructor;
939
+ const value = await new AsyncFunction("client", "context", code)(client, context);
940
+ setResult({
941
+ value,
942
+ console: consoleEntries,
943
+ duration: performance.now() - startTime,
944
+ timestamp: Date.now()
945
+ });
946
+ const resultObj = value;
947
+ if (resultObj?.data && Array.isArray(resultObj.data)) setResultView("table");
948
+ else if (consoleEntries.length > 0 && value === void 0) setResultView("console");
949
+ else setResultView("json");
950
+ } catch (err) {
951
+ setResult({
952
+ value: void 0,
953
+ console: consoleEntries,
954
+ duration: performance.now() - startTime,
955
+ error: err instanceof Error ? err.message : String(err),
956
+ timestamp: Date.now()
957
+ });
958
+ setResultView("json");
959
+ } finally {
960
+ console.log = originalConsole.log;
961
+ console.warn = originalConsole.warn;
962
+ console.error = originalConsole.error;
963
+ console.info = originalConsole.info;
964
+ setIsRunning(false);
965
+ if (scopedClientToCleanUp) scopedClientToCleanUp.ws?.disconnect();
966
+ }
967
+ }, [
968
+ activeTab?.code,
969
+ buildClient,
970
+ selectedUser,
971
+ currentUser,
972
+ collectionInfos
973
+ ]);
974
+ const saveSnippet = useCallback(() => {
975
+ if (!snippetName.trim() || !activeTab?.code.trim()) return;
976
+ const snippet = {
977
+ id: String(Date.now()),
978
+ name: snippetName.trim(),
979
+ code: activeTab.code,
980
+ createdAt: Date.now()
981
+ };
982
+ setSnippets((prev) => [snippet, ...prev]);
983
+ setShowSaveDialog(false);
984
+ setSnippetName("");
985
+ snackbar.open({
986
+ type: "success",
987
+ message: "Snippet saved"
988
+ });
989
+ }, [
990
+ snippetName,
991
+ activeTab?.code,
992
+ snackbar
993
+ ]);
994
+ const deleteSnippet = useCallback((id) => {
995
+ setSnippets((prev) => prev.filter((s) => s.id !== id));
996
+ }, []);
997
+ const exportResult = useCallback(() => {
998
+ if (!result?.value) return;
999
+ const blob = new Blob([formatJSON(result.value)], { type: "application/json" });
1000
+ const url = URL.createObjectURL(blob);
1001
+ const a = document.createElement("a");
1002
+ a.href = url;
1003
+ a.download = `rebase-result-${Date.now()}.json`;
1004
+ a.click();
1005
+ URL.revokeObjectURL(url);
1006
+ }, [result]);
1007
+ const tableData = useMemo(() => {
1008
+ if (!result?.value) return {
1009
+ columns: [],
1010
+ data: []
1011
+ };
1012
+ let rows = [];
1013
+ const val = result.value;
1014
+ if (val?.data && Array.isArray(val.data)) rows = val.data.map((entity) => ({
1015
+ id: entity.id,
1016
+ ...entity.values ?? {},
1017
+ ...entity.values ? {} : entity
1018
+ }));
1019
+ else if (Array.isArray(result.value)) rows = result.value;
1020
+ if (rows.length === 0) return {
1021
+ columns: [],
1022
+ data: []
1023
+ };
1024
+ const keys = /* @__PURE__ */ new Set();
1025
+ rows.slice(0, 20).forEach((row) => {
1026
+ if (row && typeof row === "object") Object.keys(row).forEach((k) => keys.add(k));
1027
+ });
1028
+ return {
1029
+ columns: Array.from(keys).map((key) => ({
1030
+ key,
1031
+ title: key,
1032
+ width: key === "id" ? 100 : 200
1033
+ })),
1034
+ data: rows
1035
+ };
1036
+ }, [result]);
1037
+ const matchedCollections = useMemo(() => {
1038
+ if (!result?.value || result.error) return [];
1039
+ return detectCollectionsInResult(activeTab?.code ?? "", result.value, collectionRegistry?.collections ?? []);
1040
+ }, [
1041
+ result,
1042
+ activeTab?.code,
1043
+ collectionRegistry?.collections
1044
+ ]);
1045
+ const getRowEntityActions = useCallback((rowData) => {
1046
+ if (!rowData || matchedCollections.length === 0) return [];
1047
+ return matchedCollections.filter((mc) => rowData[mc.pkColumn] != null).map((mc) => ({
1048
+ collection: mc,
1049
+ entityId: rowData[mc.pkColumn]
1050
+ }));
1051
+ }, [matchedCollections]);
1052
+ const handleExportCSV = useCallback(() => {
1053
+ if (tableData.data.length === 0) return;
1054
+ const csv = [tableData.columns.map((c) => c.key).join(","), ...tableData.data.map((row) => tableData.columns.map((c) => {
1055
+ const val = row[c.key];
1056
+ const str = val === null || val === void 0 ? "" : String(val);
1057
+ return str.includes(",") ? `"${str}"` : str;
1058
+ }).join(","))].join("\n");
1059
+ const blob = new Blob([csv], { type: "text/csv" });
1060
+ const url = URL.createObjectURL(blob);
1061
+ const a = document.createElement("a");
1062
+ a.href = url;
1063
+ a.download = `js_results_${(/* @__PURE__ */ new Date()).toISOString().slice(0, 19)}.csv`;
1064
+ a.click();
1065
+ URL.revokeObjectURL(url);
1066
+ }, [tableData]);
1067
+ const handleExportMarkdown = useCallback(() => {
1068
+ if (tableData.data.length === 0) return;
1069
+ const headers = tableData.columns.map((c) => c.key);
1070
+ const markdown = [
1071
+ `| ${headers.join(" | ")} |`,
1072
+ `| ${headers.map(() => "---").join(" | ")} |`,
1073
+ ...tableData.data.map((row) => `| ${headers.map((h) => {
1074
+ const val = row[h];
1075
+ if (val === null || val === void 0) return "";
1076
+ return String(val).replace(/\|/g, "\\|").replace(/\n/g, " ");
1077
+ }).join(" | ")} |`)
1078
+ ].join("\n");
1079
+ navigator.clipboard.writeText(markdown).then(() => {
1080
+ snackbar.open({
1081
+ type: "success",
1082
+ message: t("studio_sql_markdown_copied")
1083
+ });
1084
+ }).catch(() => {
1085
+ snackbar.open({
1086
+ type: "error",
1087
+ message: t("studio_sql_markdown_copy_failed")
1088
+ });
1089
+ });
1090
+ }, [
1091
+ tableData,
1092
+ snackbar,
1093
+ t
1094
+ ]);
1095
+ return /* @__PURE__ */ jsxs("div", {
1096
+ className: "flex flex-col h-full w-full",
1097
+ children: [/* @__PURE__ */ jsx("div", {
1098
+ className: "flex-grow overflow-hidden",
1099
+ children: /* @__PURE__ */ jsx(ResizablePanels, {
1100
+ orientation: "horizontal",
1101
+ panelSizePercent: sidebarSize,
1102
+ onPanelSizeChange: setSidebarSize,
1103
+ minPanelSizePx: 200,
1104
+ firstPanel: /* @__PURE__ */ jsx(JSEditorSidebar, {
1105
+ collections: collectionInfos,
1106
+ snippets,
1107
+ history,
1108
+ onSelectSnippet: (code) => updateActiveCode(code),
1109
+ onDeleteSnippet: deleteSnippet,
1110
+ onInsertCode: (code) => updateActiveCode(code)
1111
+ }),
1112
+ secondPanel: /* @__PURE__ */ jsxs("div", {
1113
+ className: "flex flex-col h-full overflow-hidden",
1114
+ children: [/* @__PURE__ */ jsxs("div", {
1115
+ className: cls("flex items-center justify-between pr-2 border-b bg-white dark:bg-surface-950", defaultBorderMixin),
1116
+ children: [/* @__PURE__ */ jsx("div", {
1117
+ className: "flex items-center flex-grow overflow-hidden mr-4",
1118
+ children: /* @__PURE__ */ jsxs("div", {
1119
+ className: "flex items-center no-scrollbar overflow-x-auto min-w-0",
1120
+ children: [/* @__PURE__ */ jsx(Tabs, {
1121
+ value: activeTabId,
1122
+ onValueChange: setActiveTabId,
1123
+ variant: "boxy",
1124
+ className: "w-[unset] flex-shrink-0",
1125
+ innerClassName: "bg-white dark:bg-surface-950",
1126
+ children: tabs.map((tab) => /* @__PURE__ */ jsxs(Tab, {
1127
+ value: tab.id,
1128
+ className: "flex items-center justify-between group max-w-[200px]",
1129
+ children: [
1130
+ /* @__PURE__ */ jsx(TerminalIcon, {
1131
+ size: iconSize.smallest,
1132
+ className: "text-amber-500 mr-1.5 flex-shrink-0"
1133
+ }),
1134
+ /* @__PURE__ */ jsx("span", {
1135
+ className: "truncate",
1136
+ children: tab.name
1137
+ }),
1138
+ tabs.length > 1 && /* @__PURE__ */ jsx(IconButton, {
1139
+ size: "smallest",
1140
+ onClick: (e) => {
1141
+ e.stopPropagation();
1142
+ closeTab(tab.id);
1143
+ },
1144
+ className: "ml-1 !p-0.5 opacity-0 group-hover:opacity-100 hover:text-red-500 transition-opacity",
1145
+ children: /* @__PURE__ */ jsx(XIcon, { size: iconSize.smallest })
1146
+ })
1147
+ ]
1148
+ }, tab.id))
1149
+ }), /* @__PURE__ */ jsx(IconButton, {
1150
+ size: "small",
1151
+ onClick: addTab,
1152
+ className: "ml-2 flex-shrink-0",
1153
+ children: /* @__PURE__ */ jsx(PlusIcon, { size: iconSize.smallest })
1154
+ })]
1155
+ })
1156
+ }), /* @__PURE__ */ jsxs("div", {
1157
+ className: "flex shrink-0 items-center justify-end gap-1.5",
1158
+ children: [
1159
+ /* @__PURE__ */ jsx(Tooltip, {
1160
+ title: "SaveIcon as snippet",
1161
+ children: /* @__PURE__ */ jsx(IconButton, {
1162
+ size: "small",
1163
+ onClick: () => {
1164
+ setSnippetName("");
1165
+ setShowSaveDialog(true);
1166
+ },
1167
+ disabled: !activeTab?.code.trim(),
1168
+ children: /* @__PURE__ */ jsx(SaveIcon, { size: iconSize.smallest })
1169
+ })
1170
+ }),
1171
+ result?.value != null && /* @__PURE__ */ jsx(Tooltip, {
1172
+ title: "Export result as JSON",
1173
+ children: /* @__PURE__ */ jsx(IconButton, {
1174
+ size: "small",
1175
+ onClick: exportResult,
1176
+ children: /* @__PURE__ */ jsx(DownloadIcon, { size: iconSize.smallest })
1177
+ })
1178
+ }),
1179
+ /* @__PURE__ */ jsxs(Button, {
1180
+ size: "small",
1181
+ color: "primary",
1182
+ disabled: isRunning || !activeTab?.code.trim(),
1183
+ onClick: () => executeCode(),
1184
+ children: [isRunning ? /* @__PURE__ */ jsx(CircularProgress, {
1185
+ size: "smallest",
1186
+ className: "mr-2"
1187
+ }) : /* @__PURE__ */ jsx(PlayIcon, {
1188
+ size: iconSize.smallest,
1189
+ className: "mr-2"
1190
+ }), "Run"]
1191
+ })
1192
+ ]
1193
+ })]
1194
+ }), /* @__PURE__ */ jsx("div", {
1195
+ className: "flex-grow overflow-hidden",
1196
+ children: /* @__PURE__ */ jsx(ResizablePanels, {
1197
+ orientation: "vertical",
1198
+ panelSizePercent: editorHeight,
1199
+ onPanelSizeChange: setEditorHeight,
1200
+ minPanelSizePx: 100,
1201
+ firstPanel: /* @__PURE__ */ jsxs("div", {
1202
+ className: "h-full w-full overflow-hidden flex flex-col",
1203
+ children: [/* @__PURE__ */ jsx("div", {
1204
+ className: "p-2 px-3 border-b border-surface-200 dark:border-surface-950 bg-surface-50 dark:bg-surface-900 flex items-center shrink-0",
1205
+ children: /* @__PURE__ */ jsx(AuthSimulationSelector, {
1206
+ authMode,
1207
+ setAuthMode,
1208
+ selectedUser,
1209
+ setSelectedUser,
1210
+ users,
1211
+ loading: false,
1212
+ currentUser: currentSelectableUser
1213
+ })
1214
+ }), /* @__PURE__ */ jsx("div", {
1215
+ className: "flex-1 min-h-0",
1216
+ children: /* @__PURE__ */ jsx(JSMonacoEditor, {
1217
+ value: activeTab?.code ?? "",
1218
+ onChange: updateActiveCode,
1219
+ onRun: (selectedText) => executeCode(selectedText),
1220
+ collectionSlugs,
1221
+ collections: collectionInfos,
1222
+ autoFocus: true
1223
+ })
1224
+ })]
1225
+ }),
1226
+ secondPanel: /* @__PURE__ */ jsxs("div", {
1227
+ className: "h-full w-full flex flex-col bg-surface-50 dark:bg-surface-950 overflow-hidden min-h-0",
1228
+ children: [
1229
+ /* @__PURE__ */ jsxs("div", {
1230
+ className: cls("p-2 px-4 bg-surface-100 dark:bg-surface-900 border-b shrink-0 flex items-center", defaultBorderMixin),
1231
+ children: [/* @__PURE__ */ jsx(Typography, {
1232
+ variant: "caption",
1233
+ className: "font-bold text-text-disabled dark:text-text-disabled-dark uppercase tracking-widest text-[10px]",
1234
+ children: t("studio_sql_query_results")
1235
+ }), result && /* @__PURE__ */ jsxs(Fragment, { children: [
1236
+ /* @__PURE__ */ jsx("div", { className: "flex-grow" }),
1237
+ /* @__PURE__ */ jsxs(Tabs, {
1238
+ value: resultView,
1239
+ onValueChange: (val) => setResultView(val),
1240
+ variant: "pill",
1241
+ className: "w-[unset] mr-2",
1242
+ children: [
1243
+ /* @__PURE__ */ jsx(Tab, {
1244
+ value: "json",
1245
+ children: "JSON"
1246
+ }),
1247
+ tableData.data.length > 0 && /* @__PURE__ */ jsx(Tab, {
1248
+ value: "table",
1249
+ children: "Table"
1250
+ }),
1251
+ result.console.length > 0 && /* @__PURE__ */ jsxs(Tab, {
1252
+ value: "console",
1253
+ children: [
1254
+ "Console (",
1255
+ result.console.length,
1256
+ ")"
1257
+ ]
1258
+ })
1259
+ ]
1260
+ }),
1261
+ /* @__PURE__ */ jsx(Chip, {
1262
+ size: "smallest",
1263
+ colorScheme: result.error ? "redDarker" : "greenDarker",
1264
+ children: result.error ? "Error" : `${result.duration.toFixed(0)}ms`
1265
+ })
1266
+ ] })]
1267
+ }),
1268
+ /* @__PURE__ */ jsxs("div", {
1269
+ className: "flex-grow flex flex-col min-h-0 overflow-hidden",
1270
+ children: [
1271
+ isRunning && /* @__PURE__ */ jsx("div", {
1272
+ className: "flex-grow flex items-center justify-center",
1273
+ children: /* @__PURE__ */ jsxs("div", {
1274
+ className: "text-center",
1275
+ children: [/* @__PURE__ */ jsx(CircularProgress, { size: "medium" }), /* @__PURE__ */ jsx(Typography, {
1276
+ variant: "body2",
1277
+ className: "mt-4 text-text-secondary dark:text-text-secondary-dark font-mono tracking-tight animate-pulse",
1278
+ children: "EXECUTING SCRIPT..."
1279
+ })]
1280
+ })
1281
+ }),
1282
+ !isRunning && !result && /* @__PURE__ */ jsx("div", {
1283
+ className: "flex-grow flex items-center justify-center text-text-disabled dark:text-text-disabled-dark",
1284
+ children: /* @__PURE__ */ jsxs("div", {
1285
+ className: "text-center",
1286
+ children: [/* @__PURE__ */ jsx("svg", {
1287
+ className: "w-12 h-12 mx-auto mb-4 opacity-50",
1288
+ fill: "none",
1289
+ stroke: "currentColor",
1290
+ viewBox: "0 0 24 24",
1291
+ children: /* @__PURE__ */ jsx("path", {
1292
+ strokeLinecap: "round",
1293
+ strokeLinejoin: "round",
1294
+ strokeWidth: 1,
1295
+ 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"
1296
+ })
1297
+ }), /* @__PURE__ */ jsxs(Typography, {
1298
+ variant: "body2",
1299
+ children: [
1300
+ "Write JavaScript and press ",
1301
+ /* @__PURE__ */ jsx("kbd", {
1302
+ className: "px-1.5 py-0.5 rounded bg-surface-200 dark:bg-surface-700 text-[11px] font-mono",
1303
+ children: "⌘ Enter"
1304
+ }),
1305
+ " to run"
1306
+ ]
1307
+ })]
1308
+ })
1309
+ }),
1310
+ !isRunning && result?.error && /* @__PURE__ */ jsx("div", {
1311
+ className: "flex-grow flex items-center justify-center p-6 overflow-auto",
1312
+ children: /* @__PURE__ */ jsx(ErrorView, {
1313
+ title: "Execution Error",
1314
+ error: result.error
1315
+ })
1316
+ }),
1317
+ !isRunning && result && !result.error && resultView === "json" && /* @__PURE__ */ jsx("pre", {
1318
+ 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",
1319
+ children: result.value === void 0 ? /* @__PURE__ */ jsx("span", {
1320
+ className: "text-text-disabled italic",
1321
+ children: "undefined (no return value)"
1322
+ }) : /* @__PURE__ */ jsx(JSONHighlight, { value: result.value })
1323
+ }),
1324
+ !isRunning && result && !result.error && resultView === "table" && tableData.data.length > 0 && /* @__PURE__ */ jsxs("div", {
1325
+ className: "flex-grow flex flex-col overflow-hidden min-h-0",
1326
+ children: [matchedCollections.length > 0 && /* @__PURE__ */ jsxs("div", {
1327
+ className: cls("px-4 py-1.5 border-b flex items-center gap-2 shrink-0 bg-surface-50 dark:bg-surface-900", defaultBorderMixin),
1328
+ children: [/* @__PURE__ */ jsx(Tooltip, {
1329
+ title: t("studio_sql_cms_collections_tooltip"),
1330
+ children: /* @__PURE__ */ jsx(Typography, {
1331
+ variant: "caption",
1332
+ className: "text-[10px] font-bold uppercase tracking-widest text-text-disabled dark:text-text-disabled-dark mr-1 shrink-0 cursor-help",
1333
+ children: t("studio_sql_cms")
1334
+ })
1335
+ }), /* @__PURE__ */ jsx("div", {
1336
+ className: "flex items-center gap-1.5 overflow-x-auto no-scrollbar",
1337
+ children: matchedCollections.map((mc) => /* @__PURE__ */ jsx(Tooltip, {
1338
+ title: `${mc.collection.name} (${mc.collectionSlug})`,
1339
+ children: /* @__PURE__ */ jsxs("span", {
1340
+ 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",
1341
+ children: [typeof mc.collection.icon === "string" && /* @__PURE__ */ jsx(IconForView, {
1342
+ collectionOrView: { icon: mc.collection.icon },
1343
+ className: "text-[12px]"
1344
+ }), mc.collection.name]
1345
+ })
1346
+ }, mc.collectionSlug))
1347
+ })]
1348
+ }), /* @__PURE__ */ jsx("div", {
1349
+ className: "flex-grow relative h-full min-h-0 min-w-0",
1350
+ children: /* @__PURE__ */ jsx(VirtualTable, {
1351
+ data: tableData.data,
1352
+ columns: matchedCollections.length > 0 ? [{
1353
+ key: "__entity_action__",
1354
+ title: "",
1355
+ width: 36,
1356
+ sortable: false,
1357
+ resizable: false
1358
+ }, ...tableData.columns] : tableData.columns,
1359
+ rowHeight: 32,
1360
+ headerHeight: 32,
1361
+ cellRenderer: ({ rowData, column, rowIndex }) => {
1362
+ if (column.key === "__entity_action__") {
1363
+ const rowActions = getRowEntityActions(rowData ?? {});
1364
+ if (rowActions.length === 0) return /* @__PURE__ */ jsx("div", { className: "h-full w-full" });
1365
+ if (rowActions.length === 1) {
1366
+ const ra = rowActions[0];
1367
+ return /* @__PURE__ */ jsx("div", {
1368
+ className: "h-full flex items-center justify-center",
1369
+ children: /* @__PURE__ */ jsx(Tooltip, {
1370
+ title: t("studio_sql_edit_entity", {
1371
+ name: ra.collection.collection.name,
1372
+ id: String(ra.entityId)
1373
+ }),
1374
+ children: /* @__PURE__ */ jsx(IconButton, {
1375
+ size: "small",
1376
+ className: "text-surface-400 dark:text-surface-500 hover:text-surface-600 dark:hover:text-surface-300",
1377
+ onClick: (e) => {
1378
+ e.stopPropagation();
1379
+ sideEntityController.open({
1380
+ path: ra.collection.collectionSlug,
1381
+ entityId: ra.entityId,
1382
+ collection: ra.collection.collection,
1383
+ updateUrl: false
1384
+ });
1385
+ },
1386
+ children: /* @__PURE__ */ jsx(PencilIcon, { size: iconSize.smallest })
1387
+ })
1388
+ })
1389
+ });
1390
+ }
1391
+ return /* @__PURE__ */ jsx("div", {
1392
+ className: "h-full flex items-center justify-center",
1393
+ children: /* @__PURE__ */ jsx(Menu, {
1394
+ trigger: /* @__PURE__ */ jsx(IconButton, {
1395
+ size: "small",
1396
+ className: "text-surface-400 dark:text-surface-500 hover:text-surface-600 dark:hover:text-surface-300",
1397
+ onClick: (e) => e.stopPropagation(),
1398
+ children: /* @__PURE__ */ jsx(MoreVerticalIcon, { size: iconSize.smallest })
1399
+ }),
1400
+ children: rowActions.map((ra) => /* @__PURE__ */ jsx(MenuItem, {
1401
+ dense: true,
1402
+ onClick: () => {
1403
+ sideEntityController.open({
1404
+ path: ra.collection.collectionSlug,
1405
+ entityId: ra.entityId,
1406
+ collection: ra.collection.collection,
1407
+ updateUrl: false
1408
+ });
1409
+ },
1410
+ children: t("studio_sql_edit_entity", {
1411
+ name: ra.collection.collection.name,
1412
+ id: String(ra.entityId)
1413
+ })
1414
+ }, ra.collection.collectionSlug))
1415
+ })
1416
+ });
1417
+ }
1418
+ if (!rowData) return null;
1419
+ const val = rowData[column.key];
1420
+ const displayValue = typeof val === "object" && val !== null ? JSON.stringify(val) : String(val ?? "");
1421
+ return /* @__PURE__ */ jsx("div", {
1422
+ 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",
1423
+ children: /* @__PURE__ */ jsx("div", {
1424
+ className: "truncate flex-grow",
1425
+ title: displayValue,
1426
+ children: displayValue === "" ? /* @__PURE__ */ jsx("span", {
1427
+ className: "text-text-disabled dark:text-text-disabled-dark italic text-[11px]",
1428
+ children: "NULL"
1429
+ }) : displayValue
1430
+ })
1431
+ });
1432
+ }
1433
+ })
1434
+ })]
1435
+ }),
1436
+ !isRunning && result && resultView === "console" && /* @__PURE__ */ jsxs("div", {
1437
+ className: "flex-grow overflow-auto p-2 space-y-1 font-mono text-[12px]",
1438
+ children: [result.console.length === 0 ? /* @__PURE__ */ jsx(Typography, {
1439
+ variant: "caption",
1440
+ className: "text-text-disabled p-2",
1441
+ children: "No console output"
1442
+ }) : result.console.map((entry, i) => /* @__PURE__ */ jsxs("div", {
1443
+ className: cls("px-2 py-1 rounded flex items-start gap-2", entry.type === "error" && "bg-red-50 dark:bg-red-950/30 text-red-700 dark:text-red-400", entry.type === "warn" && "bg-amber-50 dark:bg-amber-950/30 text-amber-700 dark:text-amber-400", entry.type === "log" && "text-text-primary dark:text-text-primary-dark", entry.type === "info" && "text-blue-700 dark:text-blue-400"),
1444
+ children: [/* @__PURE__ */ jsx("span", {
1445
+ className: "text-[10px] opacity-50 flex-shrink-0 mt-0.5",
1446
+ children: entry.type === "error" ? "❌" : entry.type === "warn" ? "⚠️" : entry.type === "info" ? "ℹ️" : "›"
1447
+ }), /* @__PURE__ */ jsx("span", {
1448
+ className: "whitespace-pre-wrap break-words",
1449
+ children: entry.args.map((a) => typeof a === "object" ? JSON.stringify(a, null, 2) : String(a)).join(" ")
1450
+ })]
1451
+ }, i)), result.value !== void 0 && /* @__PURE__ */ jsxs("div", {
1452
+ className: cls("px-2 py-1 mt-2 border-t pt-2", defaultBorderMixin),
1453
+ children: [/* @__PURE__ */ jsx(Typography, {
1454
+ variant: "caption",
1455
+ className: "text-text-disabled text-[10px] uppercase tracking-wider mb-1 block",
1456
+ children: "Return Value"
1457
+ }), /* @__PURE__ */ jsx("pre", {
1458
+ className: "text-text-primary dark:text-text-primary-dark whitespace-pre-wrap break-words text-[12px]",
1459
+ children: formatJSON(result.value)
1460
+ })]
1461
+ })]
1462
+ })
1463
+ ]
1464
+ }),
1465
+ !isRunning && result && !result.error && resultView === "table" && tableData.data.length > 0 && /* @__PURE__ */ jsxs("div", {
1466
+ className: cls("p-2 px-4 border-t bg-surface-50 dark:bg-surface-900 flex justify-between items-center shrink-0", defaultBorderMixin),
1467
+ children: [/* @__PURE__ */ jsxs("div", {
1468
+ className: "flex space-x-4",
1469
+ children: [/* @__PURE__ */ jsxs("div", {
1470
+ className: "flex items-center text-[11px]",
1471
+ children: [/* @__PURE__ */ jsx("span", {
1472
+ className: "font-bold text-text-disabled dark:text-text-disabled-dark mr-2 uppercase tracking-tighter",
1473
+ children: t("studio_sql_rows")
1474
+ }), /* @__PURE__ */ jsx("span", {
1475
+ className: "font-mono text-text-secondary dark:text-text-secondary-dark",
1476
+ children: tableData.data.length
1477
+ })]
1478
+ }), /* @__PURE__ */ jsxs("div", {
1479
+ className: "flex items-center text-[11px]",
1480
+ children: [/* @__PURE__ */ jsx("span", {
1481
+ className: "font-bold text-text-disabled dark:text-text-disabled-dark mr-2 uppercase tracking-tighter",
1482
+ children: t("studio_sql_time")
1483
+ }), /* @__PURE__ */ jsxs("span", {
1484
+ className: "font-mono text-text-secondary dark:text-text-secondary-dark",
1485
+ children: [result.duration.toFixed(0), "ms"]
1486
+ })]
1487
+ })]
1488
+ }), /* @__PURE__ */ jsxs("div", {
1489
+ className: "flex gap-2 overflow-x-auto no-scrollbar items-center px-2",
1490
+ children: [
1491
+ /* @__PURE__ */ jsx(Button, {
1492
+ size: "small",
1493
+ variant: "text",
1494
+ className: "text-[10px] uppercase font-bold text-text-secondary dark:text-text-secondary-dark whitespace-nowrap",
1495
+ onClick: handleExportMarkdown,
1496
+ children: t("studio_sql_copy_markdown")
1497
+ }),
1498
+ /* @__PURE__ */ jsx(Button, {
1499
+ size: "small",
1500
+ variant: "text",
1501
+ className: "text-[10px] uppercase font-bold text-text-secondary dark:text-text-secondary-dark whitespace-nowrap",
1502
+ onClick: exportResult,
1503
+ children: t("studio_sql_export_json")
1504
+ }),
1505
+ /* @__PURE__ */ jsx(Button, {
1506
+ size: "small",
1507
+ variant: "text",
1508
+ className: "text-[10px] uppercase font-bold text-text-secondary dark:text-text-secondary-dark whitespace-nowrap",
1509
+ onClick: handleExportCSV,
1510
+ children: t("studio_sql_export_csv")
1511
+ })
1512
+ ]
1513
+ })]
1514
+ })
1515
+ ]
1516
+ })
1517
+ })
1518
+ })]
1519
+ })
1520
+ })
1521
+ }), /* @__PURE__ */ jsxs(Dialog, {
1522
+ open: showSaveDialog,
1523
+ onOpenChange: setShowSaveDialog,
1524
+ children: [
1525
+ /* @__PURE__ */ jsx(DialogTitle, { children: "SaveIcon Snippet" }),
1526
+ /* @__PURE__ */ jsx(DialogContent, { children: /* @__PURE__ */ jsx(TextField, {
1527
+ label: "Snippet name",
1528
+ value: snippetName,
1529
+ onChange: (e) => setSnippetName(e.target.value),
1530
+ placeholder: "e.g. List all products",
1531
+ autoFocus: true,
1532
+ onKeyDown: (e) => {
1533
+ if (e.key === "Enter") saveSnippet();
1534
+ }
1535
+ }) }),
1536
+ /* @__PURE__ */ jsxs(DialogActions, { children: [/* @__PURE__ */ jsx(Button, {
1537
+ variant: "text",
1538
+ onClick: () => setShowSaveDialog(false),
1539
+ children: "Cancel"
1540
+ }), /* @__PURE__ */ jsx(Button, {
1541
+ variant: "filled",
1542
+ color: "primary",
1543
+ onClick: saveSnippet,
1544
+ disabled: !snippetName.trim(),
1545
+ children: "Save"
1546
+ })] })
1547
+ ]
1548
+ })]
1549
+ });
1550
+ }
1551
+ function JSONHighlight({ value }) {
1552
+ const json = formatJSON(value);
1553
+ const { mode } = useModeController();
1554
+ return /* @__PURE__ */ jsx(Highlight, {
1555
+ theme: mode === "dark" ? themes.vsDark : themes.github,
1556
+ code: json,
1557
+ language: "json",
1558
+ children: ({ style, tokens, getLineProps, getTokenProps }) => /* @__PURE__ */ jsx("span", {
1559
+ style: {
1560
+ ...style,
1561
+ backgroundColor: "transparent"
1562
+ },
1563
+ children: tokens.map((line, i) => /* @__PURE__ */ jsx("div", {
1564
+ ...getLineProps({ line }),
1565
+ children: line.map((token, key) => /* @__PURE__ */ jsx("span", { ...getTokenProps({ token }) }, key))
1566
+ }, i))
1567
+ })
1568
+ });
1569
+ }
1570
+ //#endregion
1571
+ export { JSEditor };
1572
+
1573
+ //# sourceMappingURL=JSEditor-BhAbEjCP.js.map