@rebasepro/studio 0.4.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 (378) hide show
  1. package/README.md +73 -140
  2. package/dist/ApiExplorer-CdIwR9Ga.js +963 -0
  3. package/dist/ApiExplorer-CdIwR9Ga.js.map +1 -0
  4. package/dist/AuthSimulationSelector-iEZ-Or_1.js +56 -0
  5. package/dist/AuthSimulationSelector-iEZ-Or_1.js.map +1 -0
  6. package/dist/BranchesView-DncIRcZt.js +461 -0
  7. package/dist/BranchesView-DncIRcZt.js.map +1 -0
  8. package/dist/CronJobsView-4gdtJvoe.js +500 -0
  9. package/dist/CronJobsView-4gdtJvoe.js.map +1 -0
  10. package/dist/JSEditor-BhAbEjCP.js +1573 -0
  11. package/dist/JSEditor-BhAbEjCP.js.map +1 -0
  12. package/dist/LogsExplorer-CqtKILj8.js +240 -0
  13. package/dist/LogsExplorer-CqtKILj8.js.map +1 -0
  14. package/dist/MonacoEditor-COZqrIJ1.js +246 -0
  15. package/dist/MonacoEditor-COZqrIJ1.js.map +1 -0
  16. package/dist/RLSEditor-CTxYbBdW.js +1362 -0
  17. package/dist/RLSEditor-CTxYbBdW.js.map +1 -0
  18. package/dist/SQLEditor-BLuq_zDM.js +1964 -0
  19. package/dist/SQLEditor-BLuq_zDM.js.map +1 -0
  20. package/dist/SchemaVisualizer-BJK2u3C0.js +1068 -0
  21. package/dist/SchemaVisualizer-BJK2u3C0.js.map +1 -0
  22. package/dist/StorageView-nDaC2foF.js +1382 -0
  23. package/dist/StorageView-nDaC2foF.js.map +1 -0
  24. package/dist/{studio/src/components → components}/ApiExplorer/ApiExplorer.d.ts +2 -1
  25. package/dist/{studio/src/components → components}/ApiExplorer/EndpointDetail.d.ts +2 -1
  26. package/dist/{studio/src/components → components}/ApiExplorer/TryItPanel.d.ts +2 -1
  27. package/dist/{studio/src/components → components}/AuthSimulationSelector.d.ts +2 -1
  28. package/dist/components/Branches/BranchesView.d.ts +2 -0
  29. package/dist/components/CronJobs/CronJobsView.d.ts +2 -0
  30. package/dist/components/JSEditor/JSEditor.d.ts +2 -0
  31. package/dist/{studio/src/components → components}/JSEditor/JSEditorSidebar.d.ts +2 -1
  32. package/dist/{studio/src/components → components}/JSEditor/JSMonacoEditor.d.ts +2 -1
  33. package/dist/components/LogsExplorer/LogsExplorer.d.ts +2 -0
  34. package/dist/{studio/src/components → components}/RLSEditor/PolicyEditor.d.ts +2 -1
  35. package/dist/{studio/src/components → components}/RLSEditor/RLSEditor.d.ts +2 -7
  36. package/dist/{studio/src/components → components}/SQLEditor/MonacoEditor.d.ts +2 -1
  37. package/dist/{studio/src/components → components}/SQLEditor/SQLEditor.d.ts +2 -1
  38. package/dist/{studio/src/components → components}/SQLEditor/SQLEditorSidebar.d.ts +2 -1
  39. package/dist/{studio/src/components → components}/SQLEditor/SchemaBrowser.d.ts +2 -1
  40. package/dist/{studio/src/components → components}/SchemaVisualizer/RelationEdge.d.ts +1 -1
  41. package/dist/components/SchemaVisualizer/SchemaVisualizer.d.ts +3 -0
  42. package/dist/{studio/src/components → components}/SchemaVisualizer/TableNode.d.ts +1 -1
  43. package/dist/{studio/src/components → components}/SchemaVisualizer/schema-visualizer.utils.d.ts +0 -8
  44. package/dist/components/StorageView/StorageView.d.ts +2 -0
  45. package/dist/{studio/src/components → components}/StudioHomePage.d.ts +1 -1
  46. package/dist/index.es.js +688 -746
  47. package/dist/index.es.js.map +1 -1
  48. package/dist/index.umd.js +10303 -9572
  49. package/dist/index.umd.js.map +1 -1
  50. package/dist/{studio/src/utils → utils}/pgColumnToProperty.d.ts +1 -1
  51. package/package.json +22 -22
  52. package/src/components/ApiExplorer/TryItPanel.tsx +15 -18
  53. package/src/components/CronJobs/CronJobsView.tsx +1 -1
  54. package/src/components/JSEditor/JSEditor.tsx +10 -15
  55. package/src/components/LogsExplorer/LogsExplorer.tsx +6 -3
  56. package/src/components/RLSEditor/PolicyEditor.tsx +0 -1
  57. package/src/components/RLSEditor/RLSEditor.tsx +1 -1
  58. package/src/components/SQLEditor/SQLEditor.tsx +40 -30
  59. package/src/components/SchemaVisualizer/schema-visualizer.utils.ts +3 -3
  60. package/src/components/SchemaVisualizer/useSchemaGraph.ts +2 -2
  61. package/src/components/StorageView/StorageView.tsx +22 -11
  62. package/src/components/StudioHomePage.tsx +51 -15
  63. package/src/utils/parseSpec.test.ts +41 -20
  64. package/src/utils/pgColumnToProperty.ts +23 -20
  65. package/src/utils/sql_utils.ts +1 -1
  66. package/dist/ApiExplorer-CGHEF1uL.js +0 -1052
  67. package/dist/ApiExplorer-CGHEF1uL.js.map +0 -1
  68. package/dist/AuthSimulationSelector-DGoXkWSg.js +0 -105
  69. package/dist/AuthSimulationSelector-DGoXkWSg.js.map +0 -1
  70. package/dist/BranchesView-BiTEwIhd.js +0 -291
  71. package/dist/BranchesView-BiTEwIhd.js.map +0 -1
  72. package/dist/CronJobsView-3PM_qR8v.js +0 -472
  73. package/dist/CronJobsView-3PM_qR8v.js.map +0 -1
  74. package/dist/JSEditor-BCSoElPg.js +0 -1297
  75. package/dist/JSEditor-BCSoElPg.js.map +0 -1
  76. package/dist/LogsExplorer-_4sZadKn.js +0 -162
  77. package/dist/LogsExplorer-_4sZadKn.js.map +0 -1
  78. package/dist/MonacoEditor-CMYEjiRf.js +0 -161
  79. package/dist/MonacoEditor-CMYEjiRf.js.map +0 -1
  80. package/dist/RLSEditor-CHEExeSB.js +0 -1871
  81. package/dist/RLSEditor-CHEExeSB.js.map +0 -1
  82. package/dist/SQLEditor-BC0IOUQu.js +0 -1797
  83. package/dist/SQLEditor-BC0IOUQu.js.map +0 -1
  84. package/dist/SchemaVisualizer-BGpmzyXT.js +0 -1069
  85. package/dist/SchemaVisualizer-BGpmzyXT.js.map +0 -1
  86. package/dist/StorageView-B7AsN2qX.js +0 -869
  87. package/dist/StorageView-B7AsN2qX.js.map +0 -1
  88. package/dist/common/src/collections/CollectionRegistry.d.ts +0 -56
  89. package/dist/common/src/collections/default-collections.d.ts +0 -9
  90. package/dist/common/src/collections/index.d.ts +0 -2
  91. package/dist/common/src/data/buildRebaseData.d.ts +0 -14
  92. package/dist/common/src/data/query_builder.d.ts +0 -55
  93. package/dist/common/src/index.d.ts +0 -4
  94. package/dist/common/src/util/builders.d.ts +0 -57
  95. package/dist/common/src/util/callbacks.d.ts +0 -6
  96. package/dist/common/src/util/collections.d.ts +0 -11
  97. package/dist/common/src/util/common.d.ts +0 -2
  98. package/dist/common/src/util/conditions.d.ts +0 -26
  99. package/dist/common/src/util/entities.d.ts +0 -58
  100. package/dist/common/src/util/enums.d.ts +0 -3
  101. package/dist/common/src/util/index.d.ts +0 -16
  102. package/dist/common/src/util/navigation_from_path.d.ts +0 -34
  103. package/dist/common/src/util/navigation_utils.d.ts +0 -20
  104. package/dist/common/src/util/parent_references_from_path.d.ts +0 -6
  105. package/dist/common/src/util/paths.d.ts +0 -14
  106. package/dist/common/src/util/permissions.d.ts +0 -6
  107. package/dist/common/src/util/references.d.ts +0 -2
  108. package/dist/common/src/util/relations.d.ts +0 -22
  109. package/dist/common/src/util/resolutions.d.ts +0 -72
  110. package/dist/common/src/util/storage.d.ts +0 -24
  111. package/dist/core/src/components/AIIcon.d.ts +0 -16
  112. package/dist/core/src/components/BootstrapAdminBanner.d.ts +0 -4
  113. package/dist/core/src/components/ConfirmationDialog.d.ts +0 -9
  114. package/dist/core/src/components/Debug/UIReferenceView.d.ts +0 -1
  115. package/dist/core/src/components/Debug/UIStyleGuide.d.ts +0 -1
  116. package/dist/core/src/components/ErrorTooltip.d.ts +0 -2
  117. package/dist/core/src/components/ErrorView.d.ts +0 -21
  118. package/dist/core/src/components/LanguageToggle.d.ts +0 -1
  119. package/dist/core/src/components/LoginView/LoginView.d.ts +0 -109
  120. package/dist/core/src/components/LoginView/index.d.ts +0 -2
  121. package/dist/core/src/components/NotFoundPage.d.ts +0 -1
  122. package/dist/core/src/components/RebaseAuth.d.ts +0 -10
  123. package/dist/core/src/components/RebaseLogo.d.ts +0 -7
  124. package/dist/core/src/components/UnsavedChangesDialog.d.ts +0 -9
  125. package/dist/core/src/components/UserDisplay.d.ts +0 -7
  126. package/dist/core/src/components/UserSelectPopover.d.ts +0 -62
  127. package/dist/core/src/components/UserSettingsView.d.ts +0 -1
  128. package/dist/core/src/components/common/index.d.ts +0 -6
  129. package/dist/core/src/components/common/table_height.d.ts +0 -5
  130. package/dist/core/src/components/common/types.d.ts +0 -66
  131. package/dist/core/src/components/common/useColumnsIds.d.ts +0 -9
  132. package/dist/core/src/components/common/useDataTableController.d.ts +0 -45
  133. package/dist/core/src/components/common/useDebouncedData.d.ts +0 -9
  134. package/dist/core/src/components/common/useScrollRestoration.d.ts +0 -14
  135. package/dist/core/src/components/index.d.ts +0 -17
  136. package/dist/core/src/contexts/AdminModeController.d.ts +0 -4
  137. package/dist/core/src/contexts/AnalyticsContext.d.ts +0 -3
  138. package/dist/core/src/contexts/AuthControllerContext.d.ts +0 -3
  139. package/dist/core/src/contexts/CustomizationControllerContext.d.ts +0 -3
  140. package/dist/core/src/contexts/DataDriverContext.d.ts +0 -3
  141. package/dist/core/src/contexts/DatabaseAdminContext.d.ts +0 -3
  142. package/dist/core/src/contexts/DialogsProvider.d.ts +0 -4
  143. package/dist/core/src/contexts/EffectiveRoleController.d.ts +0 -4
  144. package/dist/core/src/contexts/InternalUserManagementContext.d.ts +0 -3
  145. package/dist/core/src/contexts/ModeController.d.ts +0 -4
  146. package/dist/core/src/contexts/RebaseClientInstanceContext.d.ts +0 -6
  147. package/dist/core/src/contexts/RebaseDataContext.d.ts +0 -3
  148. package/dist/core/src/contexts/SnackbarProvider.d.ts +0 -2
  149. package/dist/core/src/contexts/StorageSourceContext.d.ts +0 -3
  150. package/dist/core/src/contexts/UserConfigurationPersistenceContext.d.ts +0 -3
  151. package/dist/core/src/contexts/index.d.ts +0 -13
  152. package/dist/core/src/core/PluginLifecycleManager.d.ts +0 -17
  153. package/dist/core/src/core/PluginProviderStack.d.ts +0 -21
  154. package/dist/core/src/core/Rebase.d.ts +0 -14
  155. package/dist/core/src/core/RebaseProps.d.ts +0 -147
  156. package/dist/core/src/core/RebaseRouter.d.ts +0 -4
  157. package/dist/core/src/core/RebaseRoutes.d.ts +0 -17
  158. package/dist/core/src/core/index.d.ts +0 -4
  159. package/dist/core/src/hooks/ApiConfigContext.d.ts +0 -24
  160. package/dist/core/src/hooks/data/delete.d.ts +0 -31
  161. package/dist/core/src/hooks/data/save.d.ts +0 -34
  162. package/dist/core/src/hooks/data/useCollectionFetch.d.ts +0 -62
  163. package/dist/core/src/hooks/data/useData.d.ts +0 -13
  164. package/dist/core/src/hooks/data/useDataOrder.d.ts +0 -12
  165. package/dist/core/src/hooks/data/useEntityFetch.d.ts +0 -43
  166. package/dist/core/src/hooks/data/useRelationSelector.d.ts +0 -52
  167. package/dist/core/src/hooks/data/useUserSelector.d.ts +0 -31
  168. package/dist/core/src/hooks/index.d.ts +0 -37
  169. package/dist/core/src/hooks/useAdminModeController.d.ts +0 -19
  170. package/dist/core/src/hooks/useAnalyticsController.d.ts +0 -5
  171. package/dist/core/src/hooks/useAuthController.d.ts +0 -11
  172. package/dist/core/src/hooks/useAuthSubscription.d.ts +0 -2
  173. package/dist/core/src/hooks/useBackendStorageSource.d.ts +0 -30
  174. package/dist/core/src/hooks/useBridgeRegistration.d.ts +0 -18
  175. package/dist/core/src/hooks/useBrowserTitleAndIcon.d.ts +0 -6
  176. package/dist/core/src/hooks/useBuildAdminModeController.d.ts +0 -6
  177. package/dist/core/src/hooks/useBuildEffectiveRoleController.d.ts +0 -8
  178. package/dist/core/src/hooks/useBuildLocalConfigurationPersistence.d.ts +0 -2
  179. package/dist/core/src/hooks/useBuildModeController.d.ts +0 -6
  180. package/dist/core/src/hooks/useClipboard.d.ts +0 -57
  181. package/dist/core/src/hooks/useCollapsedGroups.d.ts +0 -27
  182. package/dist/core/src/hooks/useCustomizationController.d.ts +0 -11
  183. package/dist/core/src/hooks/useDialogsController.d.ts +0 -11
  184. package/dist/core/src/hooks/useEffectiveRoleController.d.ts +0 -7
  185. package/dist/core/src/hooks/useInternalUserManagementController.d.ts +0 -12
  186. package/dist/core/src/hooks/useLargeLayout.d.ts +0 -1
  187. package/dist/core/src/hooks/useModeController.d.ts +0 -19
  188. package/dist/core/src/hooks/usePermissions.d.ts +0 -12
  189. package/dist/core/src/hooks/useRebaseClient.d.ts +0 -5
  190. package/dist/core/src/hooks/useRebaseContext.d.ts +0 -11
  191. package/dist/core/src/hooks/useRebaseRegistry.d.ts +0 -34
  192. package/dist/core/src/hooks/useResolvedComponent.d.ts +0 -47
  193. package/dist/core/src/hooks/useSlot.d.ts +0 -18
  194. package/dist/core/src/hooks/useSnackbarController.d.ts +0 -20
  195. package/dist/core/src/hooks/useStorageSource.d.ts +0 -7
  196. package/dist/core/src/hooks/useStudioBridge.d.ts +0 -91
  197. package/dist/core/src/hooks/useTranslation.d.ts +0 -17
  198. package/dist/core/src/hooks/useUnsavedChangesDialog.d.ts +0 -12
  199. package/dist/core/src/hooks/useUserConfigurationPersistence.d.ts +0 -8
  200. package/dist/core/src/i18n/RebaseI18nProvider.d.ts +0 -33
  201. package/dist/core/src/index.d.ts +0 -15
  202. package/dist/core/src/internal/common.d.ts +0 -3
  203. package/dist/core/src/internal/useRestoreScroll.d.ts +0 -6
  204. package/dist/core/src/locales/de.d.ts +0 -2
  205. package/dist/core/src/locales/en.d.ts +0 -10
  206. package/dist/core/src/locales/es.d.ts +0 -10
  207. package/dist/core/src/locales/fr.d.ts +0 -2
  208. package/dist/core/src/locales/hi.d.ts +0 -2
  209. package/dist/core/src/locales/it.d.ts +0 -2
  210. package/dist/core/src/locales/pt.d.ts +0 -7
  211. package/dist/core/src/util/constants.d.ts +0 -1
  212. package/dist/core/src/util/createFormexStub.d.ts +0 -2
  213. package/dist/core/src/util/entity_cache.d.ts +0 -22
  214. package/dist/core/src/util/enums.d.ts +0 -5
  215. package/dist/core/src/util/icon_list.d.ts +0 -5
  216. package/dist/core/src/util/icons.d.ts +0 -20
  217. package/dist/core/src/util/index.d.ts +0 -8
  218. package/dist/core/src/util/previews.d.ts +0 -4
  219. package/dist/core/src/util/useStorageUploadController.d.ts +0 -38
  220. package/dist/formex/src/Field.d.ts +0 -52
  221. package/dist/formex/src/Formex.d.ts +0 -7
  222. package/dist/formex/src/index.d.ts +0 -5
  223. package/dist/formex/src/types.d.ts +0 -40
  224. package/dist/formex/src/useCreateFormex.d.ts +0 -14
  225. package/dist/formex/src/utils.d.ts +0 -16
  226. package/dist/studio/src/components/Branches/BranchesView.d.ts +0 -1
  227. package/dist/studio/src/components/CronJobs/CronJobsView.d.ts +0 -1
  228. package/dist/studio/src/components/JSEditor/JSEditor.d.ts +0 -1
  229. package/dist/studio/src/components/LogsExplorer/LogsExplorer.d.ts +0 -1
  230. package/dist/studio/src/components/SchemaVisualizer/SchemaVisualizer.d.ts +0 -2
  231. package/dist/studio/src/components/SchemaVisualizer/index.d.ts +0 -5
  232. package/dist/studio/src/components/StorageView/StorageView.d.ts +0 -1
  233. package/dist/studio/src/utils/entities.d.ts +0 -0
  234. package/dist/types/src/controllers/analytics_controller.d.ts +0 -7
  235. package/dist/types/src/controllers/auth.d.ts +0 -104
  236. package/dist/types/src/controllers/client.d.ts +0 -168
  237. package/dist/types/src/controllers/collection_registry.d.ts +0 -46
  238. package/dist/types/src/controllers/customization_controller.d.ts +0 -60
  239. package/dist/types/src/controllers/data.d.ts +0 -207
  240. package/dist/types/src/controllers/data_driver.d.ts +0 -218
  241. package/dist/types/src/controllers/database_admin.d.ts +0 -11
  242. package/dist/types/src/controllers/dialogs_controller.d.ts +0 -36
  243. package/dist/types/src/controllers/effective_role.d.ts +0 -4
  244. package/dist/types/src/controllers/email.d.ts +0 -36
  245. package/dist/types/src/controllers/index.d.ts +0 -18
  246. package/dist/types/src/controllers/local_config_persistence.d.ts +0 -20
  247. package/dist/types/src/controllers/navigation.d.ts +0 -225
  248. package/dist/types/src/controllers/registry.d.ts +0 -63
  249. package/dist/types/src/controllers/side_dialogs_controller.d.ts +0 -67
  250. package/dist/types/src/controllers/side_entity_controller.d.ts +0 -97
  251. package/dist/types/src/controllers/snackbar.d.ts +0 -24
  252. package/dist/types/src/controllers/storage.d.ts +0 -171
  253. package/dist/types/src/index.d.ts +0 -4
  254. package/dist/types/src/rebase_context.d.ts +0 -122
  255. package/dist/types/src/types/auth_adapter.d.ts +0 -301
  256. package/dist/types/src/types/backend.d.ts +0 -536
  257. package/dist/types/src/types/backend_hooks.d.ts +0 -172
  258. package/dist/types/src/types/builders.d.ts +0 -15
  259. package/dist/types/src/types/chips.d.ts +0 -5
  260. package/dist/types/src/types/collections.d.ts +0 -941
  261. package/dist/types/src/types/component_ref.d.ts +0 -47
  262. package/dist/types/src/types/cron.d.ts +0 -102
  263. package/dist/types/src/types/data_source.d.ts +0 -64
  264. package/dist/types/src/types/database_adapter.d.ts +0 -94
  265. package/dist/types/src/types/entities.d.ts +0 -145
  266. package/dist/types/src/types/entity_actions.d.ts +0 -104
  267. package/dist/types/src/types/entity_callbacks.d.ts +0 -173
  268. package/dist/types/src/types/entity_link_builder.d.ts +0 -7
  269. package/dist/types/src/types/entity_overrides.d.ts +0 -10
  270. package/dist/types/src/types/entity_views.d.ts +0 -87
  271. package/dist/types/src/types/export_import.d.ts +0 -21
  272. package/dist/types/src/types/formex.d.ts +0 -40
  273. package/dist/types/src/types/index.d.ts +0 -28
  274. package/dist/types/src/types/locales.d.ts +0 -4
  275. package/dist/types/src/types/modify_collections.d.ts +0 -5
  276. package/dist/types/src/types/plugins.d.ts +0 -282
  277. package/dist/types/src/types/properties.d.ts +0 -1181
  278. package/dist/types/src/types/property_config.d.ts +0 -74
  279. package/dist/types/src/types/relations.d.ts +0 -336
  280. package/dist/types/src/types/slots.d.ts +0 -262
  281. package/dist/types/src/types/translations.d.ts +0 -900
  282. package/dist/types/src/types/user_management_delegate.d.ts +0 -86
  283. package/dist/types/src/types/websockets.d.ts +0 -78
  284. package/dist/types/src/users/index.d.ts +0 -1
  285. package/dist/types/src/users/user.d.ts +0 -50
  286. package/dist/ui/src/components/Alert.d.ts +0 -12
  287. package/dist/ui/src/components/Autocomplete.d.ts +0 -21
  288. package/dist/ui/src/components/Avatar.d.ts +0 -11
  289. package/dist/ui/src/components/Badge.d.ts +0 -8
  290. package/dist/ui/src/components/BooleanSwitch.d.ts +0 -14
  291. package/dist/ui/src/components/BooleanSwitchWithLabel.d.ts +0 -17
  292. package/dist/ui/src/components/Button.d.ts +0 -14
  293. package/dist/ui/src/components/Card.d.ts +0 -8
  294. package/dist/ui/src/components/CenteredView.d.ts +0 -9
  295. package/dist/ui/src/components/Checkbox.d.ts +0 -13
  296. package/dist/ui/src/components/Chip.d.ts +0 -26
  297. package/dist/ui/src/components/CircularProgress.d.ts +0 -5
  298. package/dist/ui/src/components/CircularProgressCenter.d.ts +0 -11
  299. package/dist/ui/src/components/Collapse.d.ts +0 -9
  300. package/dist/ui/src/components/ColorPicker.d.ts +0 -30
  301. package/dist/ui/src/components/Container.d.ts +0 -8
  302. package/dist/ui/src/components/DateTimeField.d.ts +0 -24
  303. package/dist/ui/src/components/DebouncedTextField.d.ts +0 -2
  304. package/dist/ui/src/components/Dialog.d.ts +0 -39
  305. package/dist/ui/src/components/DialogActions.d.ts +0 -7
  306. package/dist/ui/src/components/DialogContent.d.ts +0 -7
  307. package/dist/ui/src/components/DialogTitle.d.ts +0 -10
  308. package/dist/ui/src/components/ErrorBoundary.d.ts +0 -33
  309. package/dist/ui/src/components/ExpandablePanel.d.ts +0 -12
  310. package/dist/ui/src/components/FileUpload.d.ts +0 -23
  311. package/dist/ui/src/components/FilterChip.d.ts +0 -34
  312. package/dist/ui/src/components/IconButton.d.ts +0 -12
  313. package/dist/ui/src/components/InfoLabel.d.ts +0 -5
  314. package/dist/ui/src/components/InputLabel.d.ts +0 -11
  315. package/dist/ui/src/components/Label.d.ts +0 -7
  316. package/dist/ui/src/components/LoadingButton.d.ts +0 -7
  317. package/dist/ui/src/components/Markdown.d.ts +0 -10
  318. package/dist/ui/src/components/Menu.d.ts +0 -23
  319. package/dist/ui/src/components/Menubar.d.ts +0 -80
  320. package/dist/ui/src/components/MultiSelect.d.ts +0 -48
  321. package/dist/ui/src/components/Paper.d.ts +0 -6
  322. package/dist/ui/src/components/Popover.d.ts +0 -24
  323. package/dist/ui/src/components/RadioGroup.d.ts +0 -28
  324. package/dist/ui/src/components/ResizablePanels.d.ts +0 -18
  325. package/dist/ui/src/components/SearchBar.d.ts +0 -26
  326. package/dist/ui/src/components/Select.d.ts +0 -43
  327. package/dist/ui/src/components/Separator.d.ts +0 -5
  328. package/dist/ui/src/components/Sheet.d.ts +0 -22
  329. package/dist/ui/src/components/Skeleton.d.ts +0 -6
  330. package/dist/ui/src/components/Slider.d.ts +0 -21
  331. package/dist/ui/src/components/Table.d.ts +0 -34
  332. package/dist/ui/src/components/Tabs.d.ts +0 -19
  333. package/dist/ui/src/components/TextField.d.ts +0 -58
  334. package/dist/ui/src/components/TextareaAutosize.d.ts +0 -43
  335. package/dist/ui/src/components/ToggleButtonGroup.d.ts +0 -30
  336. package/dist/ui/src/components/Tooltip.d.ts +0 -19
  337. package/dist/ui/src/components/Typography.d.ts +0 -36
  338. package/dist/ui/src/components/VirtualTable/VirtualTable.d.ts +0 -11
  339. package/dist/ui/src/components/VirtualTable/VirtualTableCell.d.ts +0 -21
  340. package/dist/ui/src/components/VirtualTable/VirtualTableHeader.d.ts +0 -29
  341. package/dist/ui/src/components/VirtualTable/VirtualTableHeaderRow.d.ts +0 -2
  342. package/dist/ui/src/components/VirtualTable/VirtualTableProps.d.ts +0 -249
  343. package/dist/ui/src/components/VirtualTable/VirtualTableRow.d.ts +0 -3
  344. package/dist/ui/src/components/VirtualTable/index.d.ts +0 -3
  345. package/dist/ui/src/components/VirtualTable/types.d.ts +0 -38
  346. package/dist/ui/src/components/common/SelectInputLabel.d.ts +0 -5
  347. package/dist/ui/src/components/index.d.ts +0 -58
  348. package/dist/ui/src/hooks/PortalContainerContext.d.ts +0 -31
  349. package/dist/ui/src/hooks/index.d.ts +0 -6
  350. package/dist/ui/src/hooks/useDebounceCallback.d.ts +0 -1
  351. package/dist/ui/src/hooks/useDebounceValue.d.ts +0 -1
  352. package/dist/ui/src/hooks/useDebouncedCallback.d.ts +0 -1
  353. package/dist/ui/src/hooks/useInjectStyles.d.ts +0 -7
  354. package/dist/ui/src/hooks/useOutsideAlerter.d.ts +0 -5
  355. package/dist/ui/src/icons/GitHubIcon.d.ts +0 -2
  356. package/dist/ui/src/icons/HandleIcon.d.ts +0 -1
  357. package/dist/ui/src/icons/Icon.d.ts +0 -20
  358. package/dist/ui/src/icons/cool_icon_keys.d.ts +0 -1
  359. package/dist/ui/src/icons/icon_keys.d.ts +0 -1
  360. package/dist/ui/src/icons/index.d.ts +0 -8
  361. package/dist/ui/src/index.d.ts +0 -5
  362. package/dist/ui/src/styles.d.ts +0 -12
  363. package/dist/ui/src/util/chip_colors.d.ts +0 -4
  364. package/dist/ui/src/util/cls.d.ts +0 -2
  365. package/dist/ui/src/util/debounce.d.ts +0 -10
  366. package/dist/ui/src/util/hash.d.ts +0 -1
  367. package/dist/ui/src/util/index.d.ts +0 -4
  368. package/dist/ui/src/util/key_to_icon_component.d.ts +0 -1
  369. package/src/components/SchemaVisualizer/index.ts +0 -5
  370. package/src/utils/entities.ts +0 -2
  371. /package/dist/{studio/src/components → components}/ApiExplorer/parseSpec.d.ts +0 -0
  372. /package/dist/{studio/src/components → components}/ApiExplorer/types.d.ts +0 -0
  373. /package/dist/{studio/src/components → components}/RLSEditor/index.d.ts +0 -0
  374. /package/dist/{studio/src/components → components}/RebaseStudio.d.ts +0 -0
  375. /package/dist/{studio/src/components → components}/SQLEditor/ExplainVisualizer.d.ts +0 -0
  376. /package/dist/{studio/src/components → components}/SchemaVisualizer/useSchemaGraph.d.ts +0 -0
  377. /package/dist/{studio/src/index.d.ts → index.d.ts} +0 -0
  378. /package/dist/{studio/src/utils → utils}/sql_utils.d.ts +0 -0
@@ -1,1797 +0,0 @@
1
- import { jsx, jsxs, Fragment } from "react/jsx-runtime";
2
- import { c } from "react-compiler-runtime";
3
- import { useTranslation, ErrorView, useRebaseContext, useStudioSideEntityController, useSnackbarController, useStudioCollectionRegistry, ConfirmationDialog, IconForView } from "@rebasepro/core";
4
- import { useState, useMemo, useRef, useCallback, useEffect } from "react";
5
- import { createPortal } from "react-dom";
6
- import { CircularProgress, Typography, IconButton, RefreshCwIcon, iconSize, cls, defaultBorderMixin, CopyIcon, Menu, MenuItem, MoreVerticalIcon, Button, Tabs, Tab, Trash2Icon, Collapse, ResizablePanels, TerminalIcon, XIcon, PlusIcon, Tooltip, MenuIcon, Checkbox, DatabaseIcon, PlayIcon, Dialog, DialogTitle, DialogContent, TextField, DialogActions, VirtualTable, PencilIcon, TextareaAutosize } from "@rebasepro/ui";
7
- import { M as MonacoEditor } from "./MonacoEditor-CMYEjiRf.js";
8
- import { parseFirst } from "pgsql-ast-parser";
9
- import { toSnakeCase } from "@rebasepro/utils";
10
- const SchemaBrowser = ({
11
- onTableClick,
12
- schemas,
13
- isSchemaLoading,
14
- schemaError,
15
- onRetrySchema
16
- }) => {
17
- const [expandedSchemas, setExpandedSchemas] = useState({
18
- public: true
19
- });
20
- const [expandedTables, setExpandedTables] = useState({});
21
- const {
22
- t
23
- } = useTranslation();
24
- if (isSchemaLoading) return /* @__PURE__ */ jsx("div", { className: "p-4 flex justify-center", children: /* @__PURE__ */ jsx(CircularProgress, { size: "small" }) });
25
- if (schemaError) return /* @__PURE__ */ jsx("div", { className: "p-2", children: /* @__PURE__ */ jsx(ErrorView, { error: schemaError, onRetry: onRetrySchema }) });
26
- return /* @__PURE__ */ jsxs("div", { className: "flex flex-col h-full overflow-hidden", children: [
27
- /* @__PURE__ */ jsxs("div", { className: cls("flex items-center justify-between px-3 py-2 border-b bg-surface-50 dark:bg-surface-900 min-h-[48px]", defaultBorderMixin), children: [
28
- /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "font-bold uppercase tracking-wider text-text-disabled dark:text-text-disabled-dark", children: t("studio_schema_tables") }),
29
- /* @__PURE__ */ jsx(IconButton, { size: "small", onClick: onRetrySchema, title: "Refresh schema", children: /* @__PURE__ */ jsx(RefreshCwIcon, { size: iconSize.smallest }) })
30
- ] }),
31
- /* @__PURE__ */ jsx("div", { className: "flex-grow overflow-y-auto no-scrollbar p-1", children: Object.keys(schemas).length === 0 ? /* @__PURE__ */ jsx("div", { className: "p-4 text-center", children: /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-text-disabled dark:text-text-disabled-dark italic", children: t("studio_schema_no_tables") }) }) : Object.entries(schemas).map(([schemaName, tables]) => /* @__PURE__ */ jsxs("div", { className: "mb-2", children: [
32
- /* @__PURE__ */ jsxs("div", { className: "flex items-center p-1 cursor-pointer hover:bg-surface-100 dark:hover:bg-surface-950 rounded transition-colors", onClick: () => setExpandedSchemas((prev) => ({
33
- ...prev,
34
- [schemaName]: !prev[schemaName]
35
- })), children: [
36
- /* @__PURE__ */ jsx("svg", { className: cls("w-3 h-3 mr-1 transition-transform", expandedSchemas[schemaName] ? "rotate-90" : ""), fill: "currentColor", viewBox: "0 0 20 20", 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" }) }),
37
- /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-text-primary dark:text-text-primary-dark font-medium text-xs truncate flex-grow", children: schemaName })
38
- ] }),
39
- expandedSchemas[schemaName] && /* @__PURE__ */ jsx("div", { className: "ml-3 mt-1 space-y-1", children: tables.map((table) => /* @__PURE__ */ jsxs("div", { children: [
40
- /* @__PURE__ */ jsxs("div", { className: "flex items-center p-1 cursor-pointer hover:bg-surface-100 dark:hover:bg-surface-950 rounded transition-colors group relative", onClick: () => setExpandedTables((prev_0) => ({
41
- ...prev_0,
42
- [`${schemaName}.${table.tableName}`]: !prev_0[`${schemaName}.${table.tableName}`]
43
- })), children: [
44
- /* @__PURE__ */ jsx("svg", { className: cls("w-3 h-3 mr-1 transition-transform shrink-0", expandedTables[`${schemaName}.${table.tableName}`] ? "rotate-90" : ""), fill: "currentColor", viewBox: "0 0 20 20", 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" }) }),
45
- /* @__PURE__ */ jsx("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", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M3 10h18M3 14h18m-9-4v8m-7 0h14a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z" }) }),
46
- /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-text-secondary dark:text-text-secondary-dark text-xs truncate flex-1 min-w-0", children: table.tableName }),
47
- /* @__PURE__ */ jsxs("div", { className: "flex opacity-0 group-hover:opacity-100 focus-within:opacity-100 absolute right-1 items-center bg-surface-100 dark:bg-surface-800 px-1 gap-1 rounded transition-opacity", children: [
48
- /* @__PURE__ */ jsx(IconButton, { size: "small", onClick: (e) => {
49
- e.stopPropagation();
50
- navigator.clipboard.writeText(table.tableName);
51
- }, title: "CopyIcon table name", children: /* @__PURE__ */ jsx(CopyIcon, { size: iconSize.small }) }),
52
- /* @__PURE__ */ jsxs(Menu, { trigger: /* @__PURE__ */ jsx(IconButton, { size: "small", onClick: (e_0) => e_0.stopPropagation(), title: "Generate SQL templates", children: /* @__PURE__ */ jsx(MoreVerticalIcon, { size: iconSize.small }) }), children: [
53
- /* @__PURE__ */ jsx(MenuItem, { dense: true, className: "text-xs", onClick: (e_1) => {
54
- e_1.stopPropagation();
55
- onTableClick?.(`SELECT * FROM ${schemaName !== "public" ? `${schemaName}.` : ""}${table.tableName} LIMIT 100;`);
56
- }, children: "SELECT (Top 100)" }),
57
- /* @__PURE__ */ jsx(MenuItem, { dense: true, className: "text-xs", onClick: (e_2) => {
58
- e_2.stopPropagation();
59
- onTableClick?.(`SELECT
60
- ${table.columns.map((c2) => c2.name).join(",\n ")}
61
- FROM ${schemaName !== "public" ? `${schemaName}.` : ""}${table.tableName};`);
62
- }, children: "SELECT (All columns)" }),
63
- /* @__PURE__ */ jsx(MenuItem, { dense: true, className: "text-xs", onClick: (e_3) => {
64
- e_3.stopPropagation();
65
- onTableClick?.(`INSERT INTO ${schemaName !== "public" ? `${schemaName}.` : ""}${table.tableName} (
66
- ${table.columns.map((c_0) => c_0.name).join(",\n ")}
67
- ) VALUES (
68
- ${table.columns.map(() => "?").join(",\n ")}
69
- );`);
70
- }, children: "INSERT statement" }),
71
- /* @__PURE__ */ jsx(MenuItem, { dense: true, className: "text-xs", onClick: (e_4) => {
72
- e_4.stopPropagation();
73
- onTableClick?.(`UPDATE ${schemaName !== "public" ? `${schemaName}.` : ""}${table.tableName}
74
- SET
75
- ${table.columns.map((c_1) => `${c_1.name} = ?`).join(",\n ")}
76
- WHERE id = ?;`);
77
- }, children: "UPDATE statement" })
78
- ] }),
79
- /* @__PURE__ */ jsx(Button, { variant: "text", size: "small", className: "text-[10px] text-primary uppercase min-h-0 py-0.5 px-1 font-medium ml-1 flex-shrink-0 leading-none h-[22px]", onClick: (e_5) => {
80
- e_5.stopPropagation();
81
- onTableClick?.(`SELECT * FROM ${schemaName !== "public" ? `${schemaName}.` : ""}${table.tableName} LIMIT 100;`);
82
- }, children: "SELECT" })
83
- ] })
84
- ] }),
85
- expandedTables[`${schemaName}.${table.tableName}`] && /* @__PURE__ */ jsx("div", { className: cls("ml-5 mt-1 space-y-0.5 border-l", defaultBorderMixin), children: table.columns.map((col) => /* @__PURE__ */ jsxs("div", { className: "flex items-center p-1 group pl-2 hover:bg-surface-50 dark:hover:bg-surface-950 rounded-r relative min-h-[28px]", children: [
86
- /* @__PURE__ */ jsx("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", children: /* @__PURE__ */ jsx("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" }) }),
87
- /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-text-primary dark:text-text-primary-dark text-[11px] truncate flex-grow mr-2", children: col.name }),
88
- /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-text-disabled dark:text-text-disabled-dark text-[9px] truncate mr-1 uppercase shrink-0", title: col.dataType, children: col.dataType }),
89
- /* @__PURE__ */ jsx(IconButton, { size: "smallest", className: "opacity-0 group-hover:opacity-100 absolute right-1 bg-surface-50 dark:bg-surface-800 transition-colors pointer-events-auto", onClick: (e_6) => {
90
- e_6.stopPropagation();
91
- navigator.clipboard.writeText(col.name);
92
- }, title: "CopyIcon column name", children: /* @__PURE__ */ jsx(CopyIcon, { size: iconSize.smallest }) })
93
- ] }, col.name)) })
94
- ] }, table.tableName)) })
95
- ] }, schemaName)) })
96
- ] });
97
- };
98
- const SQLEditorSidebar = ({
99
- onSelectSnippet,
100
- onTableClick,
101
- snippets,
102
- history,
103
- onDeleteSnippet,
104
- schemas,
105
- isSchemaLoading,
106
- schemaError,
107
- onRetrySchema
108
- }) => {
109
- const [activeTab, setActiveTab] = useState("schema");
110
- const {
111
- t
112
- } = useTranslation();
113
- return /* @__PURE__ */ jsxs("div", { className: cls("flex flex-col h-full w-full bg-white dark:bg-surface-950 border-r", defaultBorderMixin), children: [
114
- /* @__PURE__ */ jsxs(Tabs, { value: activeTab, onValueChange: (v) => setActiveTab(v), variant: "boxy", className: "border-b border-surface-200 dark:border-surface-950", children: [
115
- /* @__PURE__ */ jsx(Tab, { value: "schema", children: t("studio_sql_sidebar_schema") }),
116
- /* @__PURE__ */ jsx(Tab, { value: "snippets", children: t("studio_sql_sidebar_snippets") }),
117
- /* @__PURE__ */ jsx(Tab, { value: "history", children: t("studio_sql_sidebar_history") })
118
- ] }),
119
- /* @__PURE__ */ jsxs("div", { className: "flex-grow overflow-hidden relative", children: [
120
- activeTab === "schema" && /* @__PURE__ */ jsx(SchemaBrowser, { onTableClick, schemas, isSchemaLoading, schemaError, onRetrySchema }),
121
- activeTab === "snippets" && (() => {
122
- const favorites = snippets.filter((s) => s.isFavorite);
123
- const others = snippets.filter((s_0) => !s_0.isFavorite);
124
- return /* @__PURE__ */ jsxs("div", { className: "flex flex-col h-full", children: [
125
- /* @__PURE__ */ jsx("div", { className: cls("flex items-center justify-between px-3 py-2 border-b bg-surface-50 dark:bg-surface-900 min-h-[48px]", defaultBorderMixin), children: /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "font-bold uppercase tracking-wider text-text-disabled dark:text-text-disabled-dark", children: t("studio_sql_sidebar_snippets") }) }),
126
- /* @__PURE__ */ jsx("div", { className: "flex-grow overflow-y-auto p-2 space-y-2 no-scrollbar", children: snippets.length === 0 ? /* @__PURE__ */ jsx("div", { className: "p-4 text-center", children: /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-text-disabled dark:text-text-disabled-dark", children: t("studio_sql_sidebar_no_snippets") }) }) : /* @__PURE__ */ jsxs(Fragment, { children: [
127
- favorites.length > 0 && /* @__PURE__ */ jsxs("div", { className: "mb-4", children: [
128
- /* @__PURE__ */ jsxs(Typography, { variant: "caption", className: "text-[10px] font-bold uppercase tracking-wider text-text-disabled dark:text-text-disabled-dark mb-2 px-1 flex items-center", children: [
129
- /* @__PURE__ */ jsx("svg", { className: "w-3 h-3 mr-1 text-red-500", fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ jsx("path", { fillRule: "evenodd", d: "M3.172 5.172a4 4 0 015.656 0L10 6.343l1.172-1.171a4 4 0 115.656 5.656L10 17.657l-6.828-6.829a4 4 0 010-5.656z", clipRule: "evenodd" }) }),
130
- "Favorites"
131
- ] }),
132
- /* @__PURE__ */ jsx("div", { className: "space-y-2", children: favorites.map((snippet) => /* @__PURE__ */ jsxs("div", { 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), onClick: () => onSelectSnippet(snippet.sql), children: [
133
- /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-text-primary dark:text-text-primary-dark font-medium text-[13px] truncate pr-6", children: snippet.name }),
134
- /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-text-secondary dark:text-text-secondary-dark text-[10px] block mt-1 truncate", children: snippet.sql }),
135
- /* @__PURE__ */ jsx(IconButton, { size: "smallest", className: "absolute right-1 top-1 opacity-0 group-hover:opacity-100 text-text-disabled hover:text-red-500 transition-opacity", onClick: (e) => {
136
- e.stopPropagation();
137
- onDeleteSnippet(snippet.id);
138
- }, children: /* @__PURE__ */ jsx(Trash2Icon, { size: iconSize.smallest }) })
139
- ] }, snippet.id)) })
140
- ] }),
141
- others.length > 0 && /* @__PURE__ */ jsxs("div", { children: [
142
- favorites.length > 0 && /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-[10px] font-bold uppercase tracking-wider text-text-disabled dark:text-text-disabled-dark mb-2 px-1 mt-4", children: "Others" }),
143
- /* @__PURE__ */ jsx("div", { className: "space-y-2", children: others.map((snippet_0) => /* @__PURE__ */ jsxs("div", { 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), onClick: () => onSelectSnippet(snippet_0.sql), children: [
144
- /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-text-primary dark:text-text-primary-dark font-medium text-[13px] truncate pr-6", children: snippet_0.name }),
145
- /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-text-secondary dark:text-text-secondary-dark text-[10px] block mt-1 truncate", children: snippet_0.sql }),
146
- /* @__PURE__ */ jsx(IconButton, { size: "smallest", className: "absolute right-1 top-1 opacity-0 group-hover:opacity-100 text-text-disabled hover:text-red-500 transition-opacity", onClick: (e_0) => {
147
- e_0.stopPropagation();
148
- onDeleteSnippet(snippet_0.id);
149
- }, children: /* @__PURE__ */ jsx(Trash2Icon, { size: iconSize.smallest }) })
150
- ] }, snippet_0.id)) })
151
- ] })
152
- ] }) })
153
- ] });
154
- })(),
155
- activeTab === "history" && /* @__PURE__ */ jsxs("div", { className: "flex flex-col h-full", children: [
156
- /* @__PURE__ */ jsx("div", { className: cls("flex items-center justify-between px-3 py-2 border-b bg-surface-50 dark:bg-surface-900 min-h-[48px]", defaultBorderMixin), children: /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "font-bold uppercase tracking-wider text-text-disabled dark:text-text-disabled-dark", children: t("studio_sql_sidebar_history") }) }),
157
- /* @__PURE__ */ jsx("div", { className: "flex-grow overflow-y-auto p-1 space-y-1 no-scrollbar", children: history.length === 0 ? /* @__PURE__ */ jsx("div", { className: "p-4 text-center", children: /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-text-disabled dark:text-text-disabled-dark", children: t("studio_sql_sidebar_no_history") }) }) : [...history].reverse().map((sql, i) => /* @__PURE__ */ jsxs("div", { className: "p-2 py-1.5 rounded hover:bg-surface-100 dark:hover:bg-surface-950 cursor-pointer group transition-colors flex items-start", onClick: () => onSelectSnippet(sql), children: [
158
- /* @__PURE__ */ jsx("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", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" }) }),
159
- /* @__PURE__ */ jsx(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", children: sql })
160
- ] }, i)) })
161
- ] })
162
- ] })
163
- ] });
164
- };
165
- function extractTablesFromQuery(sqlString) {
166
- try {
167
- const ast = parseFirst(sqlString);
168
- if (ast.type !== "select") return [];
169
- const tables = [];
170
- const processFrom = (fromItems) => {
171
- for (const item of fromItems) {
172
- if (item.type === "table" && item.name) {
173
- tables.push({
174
- name: item.name.name,
175
- alias: item.name.alias
176
- });
177
- }
178
- if (item.type === "join") {
179
- if (item.left) processFrom([item.left]);
180
- if (item.right) processFrom([item.right]);
181
- }
182
- }
183
- };
184
- if (ast.from) {
185
- processFrom(ast.from);
186
- }
187
- return tables;
188
- } catch {
189
- return [];
190
- }
191
- }
192
- function resolveQueryCollections(sqlString, schemas, collections, resultColumns) {
193
- const tables = extractTablesFromQuery(sqlString);
194
- if (tables.length === 0) return [];
195
- const selectColumns = [];
196
- try {
197
- const ast = parseFirst(sqlString);
198
- if (ast.type === "select" && ast.columns) {
199
- for (const col of ast.columns) {
200
- if (col.expr?.type === "ref") {
201
- selectColumns.push({
202
- table: col.expr.table?.name,
203
- column: col.expr.name,
204
- alias: col.alias?.name
205
- });
206
- }
207
- }
208
- }
209
- } catch {
210
- }
211
- const results = [];
212
- for (const table of tables) {
213
- const matched = collections.find((c2) => {
214
- const tableName = c2.table || toSnakeCase(c2.slug);
215
- return tableName === table.name;
216
- });
217
- if (!matched) continue;
218
- const tableColumns = [];
219
- for (const schemaEntries of Object.values(schemas)) {
220
- const tableInfo = schemaEntries.find((t) => t.tableName === table.name);
221
- if (tableInfo) {
222
- tableColumns.push(...tableInfo.columns.map((c2) => c2.name));
223
- break;
224
- }
225
- }
226
- let pkColumn;
227
- const tableRef = table.alias || table.name;
228
- const idSelectCol = selectColumns.find((sc) => sc.column === "id" && (!sc.table || sc.table === tableRef || sc.table === table.name));
229
- if (idSelectCol) {
230
- pkColumn = idSelectCol.alias || idSelectCol.column;
231
- }
232
- if (!pkColumn && resultColumns) {
233
- if (resultColumns.includes("id")) {
234
- pkColumn = "id";
235
- }
236
- }
237
- if (!pkColumn && tableColumns.includes("id")) {
238
- pkColumn = "id";
239
- }
240
- results.push({
241
- tableName: table.name,
242
- tableAlias: table.alias,
243
- collection: matched,
244
- columns: tableColumns,
245
- pkColumn
246
- });
247
- }
248
- return results;
249
- }
250
- function determineTableAndPK(sqlString, columnKey, schemas) {
251
- try {
252
- const tables = extractTablesFromQuery(sqlString);
253
- const ast = parseFirst(sqlString);
254
- if (ast.type !== "select") {
255
- return {
256
- error: "Inline editing is only supported for SELECT queries."
257
- };
258
- }
259
- if (tables.length === 0) {
260
- return {
261
- error: "Could not find any tables in the query."
262
- };
263
- }
264
- const selectColumns = [];
265
- if (ast.columns) {
266
- for (const col of ast.columns) {
267
- if (col.expr?.type === "ref") {
268
- selectColumns.push({
269
- table: col.expr.table?.name,
270
- column: col.expr.name,
271
- alias: col.alias?.name
272
- });
273
- }
274
- }
275
- }
276
- const resolvedColumn = selectColumns.find((sc) => sc.alias === columnKey || !sc.alias && sc.column === columnKey);
277
- const actualDbColumnName = resolvedColumn?.column ?? columnKey;
278
- const columnTableRef = resolvedColumn?.table;
279
- let resolvedTableName = null;
280
- if (tables.length === 1) {
281
- resolvedTableName = tables[0].name;
282
- } else {
283
- if (columnTableRef) {
284
- const matchedTable = tables.find((t) => t.alias === columnTableRef || t.name === columnTableRef);
285
- if (matchedTable) {
286
- resolvedTableName = matchedTable.name;
287
- }
288
- }
289
- if (!resolvedTableName) {
290
- const matchedTables = tables.filter((t) => {
291
- for (const schema of Object.values(schemas)) {
292
- const tableInfo = schema.find((ti) => ti.tableName === t.name);
293
- if (tableInfo && tableInfo.columns.some((c2) => c2.name === actualDbColumnName)) {
294
- return true;
295
- }
296
- }
297
- return false;
298
- });
299
- if (matchedTables.length === 1) {
300
- resolvedTableName = matchedTables[0].name;
301
- } else if (matchedTables.length > 1) {
302
- return {
303
- error: `Ambiguous column "${columnKey}": Found in multiple queried tables.`
304
- };
305
- } else {
306
- return {
307
- error: `Could not find column "${columnKey}" in the queried tables.`
308
- };
309
- }
310
- }
311
- }
312
- if (!resolvedTableName) {
313
- return {
314
- error: "Could not resolve the target table."
315
- };
316
- }
317
- let pkDbColumns = [];
318
- for (const schema of Object.values(schemas)) {
319
- const tableInfo = schema.find((t) => t.tableName === resolvedTableName);
320
- if (tableInfo) {
321
- pkDbColumns = tableInfo.columns.filter((c2) => c2.isPrimaryKey).map((c2) => c2.name);
322
- break;
323
- }
324
- }
325
- if (pkDbColumns.length === 0) {
326
- return {
327
- error: `Table "${resolvedTableName}" has no primary key defined.`
328
- };
329
- }
330
- const tableEntry = tables.find((t) => t.name === resolvedTableName);
331
- const tableAlias = tableEntry?.alias;
332
- const primaryKeys = pkDbColumns.map((dbCol) => {
333
- const selectCol = selectColumns.find((sc) => sc.column === dbCol && (!sc.table || sc.table === (tableAlias || resolvedTableName)));
334
- return {
335
- dbColumn: dbCol,
336
- resultColumn: selectCol?.alias || selectCol?.column || dbCol
337
- };
338
- });
339
- return {
340
- tableName: resolvedTableName,
341
- primaryKeys
342
- };
343
- } catch (e) {
344
- console.warn("Failed to parse SQL AST:", e);
345
- const message = e instanceof Error ? e.message : String(e);
346
- return {
347
- error: `Could not safely parse query for inline editing: ${message}`
348
- };
349
- }
350
- }
351
- const ExplainVisualizer = (t0) => {
352
- const $ = c(77);
353
- const {
354
- plan,
355
- isRoot: t1
356
- } = t0;
357
- const isRoot = t1 === void 0 ? true : t1;
358
- const [expanded, setExpanded] = useState(true);
359
- const hasChildren = plan.Plans && plan.Plans.length > 0;
360
- const cost = plan["Total Cost"];
361
- let costColor = "text-green-500 dark:text-green-400";
362
- if (cost > 1e3) {
363
- costColor = "text-red-500 dark:text-red-400";
364
- } else {
365
- if (cost > 100) {
366
- costColor = "text-orange-500 dark:text-orange-400";
367
- }
368
- }
369
- const t2 = isRoot ? "p-4" : "pl-6 mt-2 relative";
370
- let t3;
371
- if ($[0] !== t2) {
372
- t3 = cls("flex flex-col", t2);
373
- $[0] = t2;
374
- $[1] = t3;
375
- } else {
376
- t3 = $[1];
377
- }
378
- let t4;
379
- if ($[2] !== isRoot) {
380
- t4 = !isRoot && /* @__PURE__ */ jsx("div", { className: "absolute left-2.5 top-0 bottom-0 w-px bg-surface-200 dark:bg-surface-950 -z-10" });
381
- $[2] = isRoot;
382
- $[3] = t4;
383
- } else {
384
- t4 = $[3];
385
- }
386
- let t5;
387
- if ($[4] !== isRoot) {
388
- t5 = !isRoot && /* @__PURE__ */ jsx("div", { className: "absolute left-2.5 top-5 w-3 h-px bg-surface-200 dark:bg-surface-950 -z-10" });
389
- $[4] = isRoot;
390
- $[5] = t5;
391
- } else {
392
- t5 = $[5];
393
- }
394
- let t6;
395
- let t7;
396
- if ($[6] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
397
- t6 = cls("border rounded-md bg-white dark:bg-surface-900 text-text-primary dark:text-text-primary-dark shadow-xs relative z-10 w-[420px] max-w-full", defaultBorderMixin);
398
- t7 = cls("px-4 py-3 flex justify-between items-center cursor-pointer select-none");
399
- $[6] = t6;
400
- $[7] = t7;
401
- } else {
402
- t6 = $[6];
403
- t7 = $[7];
404
- }
405
- let t8;
406
- if ($[8] !== expanded) {
407
- t8 = () => setExpanded(!expanded);
408
- $[8] = expanded;
409
- $[9] = t8;
410
- } else {
411
- t8 = $[9];
412
- }
413
- let t9;
414
- if ($[10] !== expanded || $[11] !== hasChildren) {
415
- t9 = hasChildren ? /* @__PURE__ */ jsx("svg", { className: cls("w-4 h-4 text-text-secondary transition-transform", !expanded ? "-rotate-90" : ""), fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 9l-7 7-7-7" }) }) : /* @__PURE__ */ jsx("div", { className: "w-4 h-4" });
416
- $[10] = expanded;
417
- $[11] = hasChildren;
418
- $[12] = t9;
419
- } else {
420
- t9 = $[12];
421
- }
422
- const t10 = plan["Node Type"];
423
- let t11;
424
- if ($[13] !== t10) {
425
- t11 = /* @__PURE__ */ jsx(Typography, { variant: "body1", className: "flex items-center", children: t10 });
426
- $[13] = t10;
427
- $[14] = t11;
428
- } else {
429
- t11 = $[14];
430
- }
431
- let t12;
432
- if ($[15] !== plan) {
433
- t12 = plan["Relation Name"] && /* @__PURE__ */ jsxs("span", { className: "font-mono text-[11px] text-text-secondary dark:text-text-secondary-dark px-2 py-0.5 rounded bg-surface-200 dark:bg-surface-950 ml-2", children: [
434
- "on ",
435
- plan["Relation Name"],
436
- " ",
437
- plan.Alias && plan.Alias !== plan["Relation Name"] ? `(${plan.Alias})` : ""
438
- ] });
439
- $[15] = plan;
440
- $[16] = t12;
441
- } else {
442
- t12 = $[16];
443
- }
444
- let t13;
445
- if ($[17] !== t11 || $[18] !== t12 || $[19] !== t9) {
446
- t13 = /* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-2", children: [
447
- t9,
448
- t11,
449
- t12
450
- ] });
451
- $[17] = t11;
452
- $[18] = t12;
453
- $[19] = t9;
454
- $[20] = t13;
455
- } else {
456
- t13 = $[20];
457
- }
458
- let t14;
459
- if ($[21] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
460
- t14 = /* @__PURE__ */ jsx("span", { className: "text-[10px] uppercase text-text-disabled dark:text-text-disabled-dark font-semibold tracking-wide leading-tight mb-0.5", children: "Cost" });
461
- $[21] = t14;
462
- } else {
463
- t14 = $[21];
464
- }
465
- let t15;
466
- if ($[22] !== costColor) {
467
- t15 = cls("font-mono font-medium text-[13px] leading-none", costColor);
468
- $[22] = costColor;
469
- $[23] = t15;
470
- } else {
471
- t15 = $[23];
472
- }
473
- let t16;
474
- if ($[24] !== cost) {
475
- t16 = cost.toFixed(2);
476
- $[24] = cost;
477
- $[25] = t16;
478
- } else {
479
- t16 = $[25];
480
- }
481
- let t17;
482
- if ($[26] !== t15 || $[27] !== t16) {
483
- t17 = /* @__PURE__ */ jsxs("div", { className: "flex flex-col text-right", children: [
484
- t14,
485
- /* @__PURE__ */ jsx("span", { className: t15, children: t16 })
486
- ] });
487
- $[26] = t15;
488
- $[27] = t16;
489
- $[28] = t17;
490
- } else {
491
- t17 = $[28];
492
- }
493
- let t18;
494
- if ($[29] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
495
- t18 = /* @__PURE__ */ jsx("span", { className: "text-[10px] uppercase text-text-disabled dark:text-text-disabled-dark font-semibold tracking-wide leading-tight mb-0.5", children: "Rows" });
496
- $[29] = t18;
497
- } else {
498
- t18 = $[29];
499
- }
500
- const t19 = plan["Plan Rows"];
501
- let t20;
502
- if ($[30] !== t19) {
503
- t20 = /* @__PURE__ */ jsxs("div", { className: "flex flex-col text-right", children: [
504
- t18,
505
- /* @__PURE__ */ jsx("span", { className: "font-mono text-[13px] text-text-secondary dark:text-text-secondary-dark leading-none", children: t19 })
506
- ] });
507
- $[30] = t19;
508
- $[31] = t20;
509
- } else {
510
- t20 = $[31];
511
- }
512
- let t21;
513
- if ($[32] !== t17 || $[33] !== t20) {
514
- t21 = /* @__PURE__ */ jsxs("div", { className: "flex space-x-6 items-center", children: [
515
- t17,
516
- t20
517
- ] });
518
- $[32] = t17;
519
- $[33] = t20;
520
- $[34] = t21;
521
- } else {
522
- t21 = $[34];
523
- }
524
- let t22;
525
- if ($[35] !== t13 || $[36] !== t21 || $[37] !== t8) {
526
- t22 = /* @__PURE__ */ jsxs("div", { className: t7, onClick: t8, children: [
527
- t13,
528
- t21
529
- ] });
530
- $[35] = t13;
531
- $[36] = t21;
532
- $[37] = t8;
533
- $[38] = t22;
534
- } else {
535
- t22 = $[38];
536
- }
537
- let t23;
538
- if ($[39] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
539
- t23 = /* @__PURE__ */ jsx("span", { className: "text-text-disabled dark:text-text-disabled-dark", children: "Startup Cost:" });
540
- $[39] = t23;
541
- } else {
542
- t23 = $[39];
543
- }
544
- const t24 = plan["Startup Cost"];
545
- let t25;
546
- if ($[40] !== t24) {
547
- t25 = t24.toFixed(2);
548
- $[40] = t24;
549
- $[41] = t25;
550
- } else {
551
- t25 = $[41];
552
- }
553
- let t26;
554
- if ($[42] !== t25) {
555
- t26 = /* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-2", children: [
556
- t23,
557
- /* @__PURE__ */ jsx("span", { className: "font-mono font-medium", children: t25 })
558
- ] });
559
- $[42] = t25;
560
- $[43] = t26;
561
- } else {
562
- t26 = $[43];
563
- }
564
- let t27;
565
- if ($[44] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
566
- t27 = /* @__PURE__ */ jsx("span", { className: "text-text-disabled dark:text-text-disabled-dark", children: "Width:" });
567
- $[44] = t27;
568
- } else {
569
- t27 = $[44];
570
- }
571
- const t28 = plan["Plan Width"];
572
- let t29;
573
- if ($[45] !== t28) {
574
- t29 = /* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-2", children: [
575
- t27,
576
- /* @__PURE__ */ jsxs("span", { className: "font-mono font-medium", children: [
577
- t28,
578
- " bytes"
579
- ] })
580
- ] });
581
- $[45] = t28;
582
- $[46] = t29;
583
- } else {
584
- t29 = $[46];
585
- }
586
- let t30;
587
- if ($[47] !== t26 || $[48] !== t29) {
588
- t30 = /* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-6", children: [
589
- t26,
590
- t29
591
- ] });
592
- $[47] = t26;
593
- $[48] = t29;
594
- $[49] = t30;
595
- } else {
596
- t30 = $[49];
597
- }
598
- let t31;
599
- if ($[50] !== plan.Filter) {
600
- t31 = plan.Filter && /* @__PURE__ */ jsxs("div", { className: "mt-1", children: [
601
- /* @__PURE__ */ jsx("span", { className: "text-text-disabled dark:text-text-disabled-dark block mb-1", children: "Filter:" }),
602
- /* @__PURE__ */ jsx("code", { className: "block w-full p-2 bg-surface-50 dark:bg-surface-950 border dark:border-surface-950 rounded font-mono text-[12px] truncate", children: plan.Filter })
603
- ] });
604
- $[50] = plan.Filter;
605
- $[51] = t31;
606
- } else {
607
- t31 = $[51];
608
- }
609
- let t32;
610
- if ($[52] !== plan) {
611
- t32 = plan["Index Cond"] && /* @__PURE__ */ jsxs("div", { className: "mt-1", children: [
612
- /* @__PURE__ */ jsx("span", { className: "text-text-disabled dark:text-text-disabled-dark block mb-1", children: "Index Cond:" }),
613
- /* @__PURE__ */ jsx("code", { className: "block w-full p-2 bg-surface-50 dark:bg-surface-950 border dark:border-surface-950 rounded font-mono text-[12px] truncate", children: plan["Index Cond"] })
614
- ] });
615
- $[52] = plan;
616
- $[53] = t32;
617
- } else {
618
- t32 = $[53];
619
- }
620
- let t33;
621
- if ($[54] !== plan) {
622
- t33 = plan["Hash Cond"] && /* @__PURE__ */ jsxs("div", { className: "mt-1", children: [
623
- /* @__PURE__ */ jsx("span", { className: "text-text-disabled dark:text-text-disabled-dark block mb-1", children: "Hash Cond:" }),
624
- /* @__PURE__ */ jsx("code", { className: "block w-full p-2 bg-surface-50 dark:bg-surface-950 border dark:border-surface-950 rounded font-mono text-[12px] truncate", children: plan["Hash Cond"] })
625
- ] });
626
- $[54] = plan;
627
- $[55] = t33;
628
- } else {
629
- t33 = $[55];
630
- }
631
- let t34;
632
- if ($[56] !== t30 || $[57] !== t31 || $[58] !== t32 || $[59] !== t33) {
633
- t34 = /* @__PURE__ */ jsxs("div", { className: "px-4 py-3 border-t border-surface-200 dark:border-surface-950 text-[13px] flex flex-col gap-2", children: [
634
- t30,
635
- t31,
636
- t32,
637
- t33
638
- ] });
639
- $[56] = t30;
640
- $[57] = t31;
641
- $[58] = t32;
642
- $[59] = t33;
643
- $[60] = t34;
644
- } else {
645
- t34 = $[60];
646
- }
647
- let t35;
648
- if ($[61] !== expanded || $[62] !== t34) {
649
- t35 = /* @__PURE__ */ jsx(Collapse, { in: expanded, children: t34 });
650
- $[61] = expanded;
651
- $[62] = t34;
652
- $[63] = t35;
653
- } else {
654
- t35 = $[63];
655
- }
656
- let t36;
657
- if ($[64] !== t22 || $[65] !== t35) {
658
- t36 = /* @__PURE__ */ jsxs("div", { className: t6, children: [
659
- t22,
660
- t35
661
- ] });
662
- $[64] = t22;
663
- $[65] = t35;
664
- $[66] = t36;
665
- } else {
666
- t36 = $[66];
667
- }
668
- let t37;
669
- if ($[67] !== expanded || $[68] !== hasChildren || $[69] !== plan.Plans) {
670
- t37 = expanded && hasChildren && /* @__PURE__ */ jsx("div", { className: "flex flex-col space-y-2 mt-[-4px]", children: plan.Plans.map(_temp$1) });
671
- $[67] = expanded;
672
- $[68] = hasChildren;
673
- $[69] = plan.Plans;
674
- $[70] = t37;
675
- } else {
676
- t37 = $[70];
677
- }
678
- let t38;
679
- if ($[71] !== t3 || $[72] !== t36 || $[73] !== t37 || $[74] !== t4 || $[75] !== t5) {
680
- t38 = /* @__PURE__ */ jsxs("div", { className: t3, children: [
681
- t4,
682
- t5,
683
- t36,
684
- t37
685
- ] });
686
- $[71] = t3;
687
- $[72] = t36;
688
- $[73] = t37;
689
- $[74] = t4;
690
- $[75] = t5;
691
- $[76] = t38;
692
- } else {
693
- t38 = $[76];
694
- }
695
- return t38;
696
- };
697
- function _temp$1(childPlan, idx) {
698
- return /* @__PURE__ */ jsx(ExplainVisualizer, { plan: childPlan, isRoot: false }, idx);
699
- }
700
- const FixedEditorOverlay = (t0) => {
701
- const $ = c(26);
702
- const {
703
- displayValue,
704
- onSave,
705
- onCancel
706
- } = t0;
707
- const [rect, setRect] = useState(null);
708
- let t1;
709
- if ($[0] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
710
- t1 = {
711
- width: 1e3,
712
- height: 1e3
713
- };
714
- $[0] = t1;
715
- } else {
716
- t1 = $[0];
717
- }
718
- const [windowSize, setWindowSize] = useState(t1);
719
- const anchorRef = useRef(null);
720
- let t2;
721
- let t3;
722
- if ($[1] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
723
- t2 = () => {
724
- if (anchorRef.current && anchorRef.current.parentElement) {
725
- setRect(anchorRef.current.parentElement.getBoundingClientRect());
726
- }
727
- if (typeof window !== "undefined") {
728
- setWindowSize({
729
- width: window.innerWidth,
730
- height: window.innerHeight
731
- });
732
- const handleResize = () => setWindowSize({
733
- width: window.innerWidth,
734
- height: window.innerHeight
735
- });
736
- window.addEventListener("resize", handleResize);
737
- return () => window.removeEventListener("resize", handleResize);
738
- }
739
- };
740
- t3 = [];
741
- $[1] = t2;
742
- $[2] = t3;
743
- } else {
744
- t2 = $[1];
745
- t3 = $[2];
746
- }
747
- useEffect(t2, t3);
748
- if (!rect) {
749
- let t42;
750
- if ($[3] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
751
- t42 = /* @__PURE__ */ jsx("div", { ref: anchorRef, className: "w-full h-full min-h-[20px]" });
752
- $[3] = t42;
753
- } else {
754
- t42 = $[3];
755
- }
756
- return t42;
757
- }
758
- let top = rect.top - 2;
759
- let left = rect.left - 2;
760
- const minWidth = Math.max(rect.width + 4, 250);
761
- const minHeight = rect.height + 4;
762
- if (left + minWidth > windowSize.width) {
763
- left = Math.max(10, windowSize.width - minWidth - 10);
764
- }
765
- const maxAvailableHeight = Math.max(50, windowSize.height - top - 10);
766
- const resolvedMaxHeight = Math.min(300, maxAvailableHeight);
767
- if (top + minHeight > windowSize.height) {
768
- top = Math.max(10, windowSize.height - minHeight - 10);
769
- }
770
- const t4 = top;
771
- const t5 = left;
772
- const t6 = Math.min(400, windowSize.width - left - 10);
773
- let t7;
774
- if ($[4] !== left || $[5] !== minHeight || $[6] !== minWidth || $[7] !== t6 || $[8] !== top) {
775
- t7 = {
776
- top: t4,
777
- left: t5,
778
- minWidth,
779
- minHeight,
780
- maxWidth: t6
781
- };
782
- $[4] = left;
783
- $[5] = minHeight;
784
- $[6] = minWidth;
785
- $[7] = t6;
786
- $[8] = top;
787
- $[9] = t7;
788
- } else {
789
- t7 = $[9];
790
- }
791
- let t8;
792
- if ($[10] !== resolvedMaxHeight) {
793
- t8 = {
794
- minHeight: "32px",
795
- maxHeight: resolvedMaxHeight
796
- };
797
- $[10] = resolvedMaxHeight;
798
- $[11] = t8;
799
- } else {
800
- t8 = $[11];
801
- }
802
- let t10;
803
- let t9;
804
- if ($[12] !== onCancel || $[13] !== onSave) {
805
- t9 = (e_0) => {
806
- onSave(e_0.target.value || null);
807
- onCancel();
808
- };
809
- t10 = (e_1) => {
810
- if (e_1.key === "Enter" && !e_1.shiftKey) {
811
- e_1.preventDefault();
812
- onSave(e_1.currentTarget.value || null);
813
- onCancel();
814
- }
815
- if (e_1.key === "Escape") {
816
- onCancel();
817
- }
818
- };
819
- $[12] = onCancel;
820
- $[13] = onSave;
821
- $[14] = t10;
822
- $[15] = t9;
823
- } else {
824
- t10 = $[14];
825
- t9 = $[15];
826
- }
827
- let t11;
828
- if ($[16] !== displayValue || $[17] !== t10 || $[18] !== t8 || $[19] !== t9) {
829
- t11 = /* @__PURE__ */ jsx(TextareaAutosize, { className: "w-full h-full bg-transparent outline-none border-none ring-0 font-mono text-[13px] text-text-primary dark:text-text-primary-dark px-4 py-1.5 resize-none overflow-y-auto", defaultValue: displayValue, autoFocus: true, style: t8, onFocus: _temp, onBlur: t9, onKeyDown: t10 });
830
- $[16] = displayValue;
831
- $[17] = t10;
832
- $[18] = t8;
833
- $[19] = t9;
834
- $[20] = t11;
835
- } else {
836
- t11 = $[20];
837
- }
838
- let t12;
839
- if ($[21] !== t11 || $[22] !== t7) {
840
- t12 = createPortal(/* @__PURE__ */ jsx("div", { className: "fixed z-[9999] bg-surface-50 dark:bg-surface-900 border-2 border-primary dark:border-primary-dark shadow-xl flex flex-col", style: t7, children: t11 }), document.body);
841
- $[21] = t11;
842
- $[22] = t7;
843
- $[23] = t12;
844
- } else {
845
- t12 = $[23];
846
- }
847
- let t13;
848
- if ($[24] !== t12) {
849
- t13 = /* @__PURE__ */ jsx("div", { ref: anchorRef, className: "w-full h-full min-h-[20px]", children: t12 });
850
- $[24] = t12;
851
- $[25] = t13;
852
- } else {
853
- t13 = $[25];
854
- }
855
- return t13;
856
- };
857
- const getStoragePrefix = (baseUrl) => {
858
- if (!baseUrl) return "default";
859
- return baseUrl.replace(/^https?:\/\//, "").replace(/[^a-zA-Z0-9]/g, "_");
860
- };
861
- const SQLEditor = () => {
862
- const {
863
- databaseAdmin,
864
- client
865
- } = useRebaseContext();
866
- const sideEntityController = useStudioSideEntityController();
867
- const snackbarController = useSnackbarController();
868
- const collectionRegistry = useStudioCollectionRegistry();
869
- const {
870
- t
871
- } = useTranslation();
872
- const projectPrefix = useMemo(() => getStoragePrefix(client?.baseUrl), [client?.baseUrl]);
873
- const [schemas, setSchemas] = useState({});
874
- const [isSchemaLoading, setIsSchemaLoading] = useState(true);
875
- const schemaFetchedRef = useRef(false);
876
- const [schemaError, setSchemaError] = useState(null);
877
- const [selectedDatabase, setSelectedDatabase] = useState(() => {
878
- const projectPrefixSync = client?.baseUrl ? client.baseUrl.replace(/^https?:\/\//, "").replace(/[^a-zA-Z0-9]/g, "_") : "default";
879
- return localStorage.getItem(`rebase_sql_selected_db_${projectPrefixSync}`) || void 0;
880
- });
881
- const [selectedRole, setSelectedRole] = useState(() => {
882
- const projectPrefixSync_0 = client?.baseUrl ? client.baseUrl.replace(/^https?:\/\//, "").replace(/[^a-zA-Z0-9]/g, "_") : "default";
883
- return localStorage.getItem(`rebase_sql_selected_role_${projectPrefixSync_0}`) || void 0;
884
- });
885
- const [availableDatabases, setAvailableDatabases] = useState([]);
886
- const [availableRoles, setAvailableRoles] = useState([]);
887
- const [isLoadingConfig, setIsLoadingConfig] = useState(true);
888
- const [connectionConfigError, setConnectionConfigError] = useState(null);
889
- const [tabs, setTabs] = useState(() => {
890
- const projectPrefixSync_1 = client?.baseUrl ? client.baseUrl.replace(/^https?:\/\//, "").replace(/[^a-zA-Z0-9]/g, "_") : "default";
891
- const saved = localStorage.getItem(`rebase_sql_tabs_${projectPrefixSync_1}`);
892
- if (saved) {
893
- const parsed = JSON.parse(saved);
894
- return parsed.map((t_0) => ({
895
- ...t_0,
896
- results: null,
897
- loading: false,
898
- error: null,
899
- execTime: null,
900
- lastExecutedSql: null
901
- }));
902
- }
903
- return [{
904
- id: "1",
905
- name: "Query 1",
906
- sql: "SELECT * FROM ",
907
- database: localStorage.getItem(`rebase_sql_selected_db_${projectPrefixSync_1}`) || void 0,
908
- role: localStorage.getItem(`rebase_sql_selected_role_${projectPrefixSync_1}`) || void 0,
909
- results: null,
910
- loading: false,
911
- error: null,
912
- execTime: null,
913
- lastExecutedSql: null
914
- }];
915
- });
916
- const [activeTabId, setActiveTabId] = useState(() => {
917
- const projectPrefixSync_2 = client?.baseUrl ? client.baseUrl.replace(/^https?:\/\//, "").replace(/[^a-zA-Z0-9]/g, "_") : "default";
918
- return localStorage.getItem(`rebase_sql_active_tab_${projectPrefixSync_2}`) || "1";
919
- });
920
- const activeTab = tabs.find((t_1) => t_1.id === activeTabId) || tabs[0];
921
- const updateActiveTab = useCallback((update) => {
922
- setTabs((prev) => prev.map((t_2) => t_2.id === activeTabId ? {
923
- ...t_2,
924
- ...update
925
- } : t_2));
926
- }, [activeTabId]);
927
- const sql = activeTab.sql;
928
- const results = activeTab.results;
929
- const loading = activeTab.loading;
930
- const error = activeTab.error;
931
- const execTime = activeTab.execTime;
932
- const setSql = (newSql) => updateActiveTab({
933
- sql: newSql
934
- });
935
- useEffect(() => {
936
- let mounted = true;
937
- const fetchConnectionConfig = async () => {
938
- if (!databaseAdmin?.fetchAvailableDatabases || !databaseAdmin?.fetchAvailableRoles || !databaseAdmin?.executeSql) {
939
- setConnectionConfigError(t("studio_sql_sql_not_supported"));
940
- setIsLoadingConfig(false);
941
- return;
942
- }
943
- try {
944
- const [dbs, roles, currentDbFromApi, currentUserResult] = await Promise.all([databaseAdmin.fetchAvailableDatabases(), databaseAdmin.fetchAvailableRoles(), typeof databaseAdmin?.fetchCurrentDatabase === "function" ? databaseAdmin.fetchCurrentDatabase() : Promise.resolve(void 0), databaseAdmin.executeSql("SELECT current_user AS role").catch(() => [])]);
945
- if (mounted) {
946
- setAvailableDatabases(dbs);
947
- setAvailableRoles(roles);
948
- const loadedDb = localStorage.getItem(`rebase_sql_selected_db_${projectPrefix}`) || void 0;
949
- const loadedRole = localStorage.getItem(`rebase_sql_selected_role_${projectPrefix}`) || void 0;
950
- const initialActiveTabId = localStorage.getItem(`rebase_sql_active_tab_${projectPrefix}`) || "1";
951
- let initialTabs = [];
952
- try {
953
- const savedTabs = localStorage.getItem(`rebase_sql_tabs_${projectPrefix}`);
954
- if (savedTabs) initialTabs = JSON.parse(savedTabs);
955
- } catch (e) {
956
- }
957
- const currentActiveTab = initialTabs.find((t_3) => t_3.id === initialActiveTabId);
958
- let actualDb = currentActiveTab?.database || loadedDb;
959
- if (actualDb && !dbs.includes(actualDb)) actualDb = void 0;
960
- if (!actualDb && dbs.length > 0) {
961
- actualDb = currentDbFromApi && dbs.includes(currentDbFromApi) ? currentDbFromApi : dbs[0];
962
- }
963
- if (actualDb) {
964
- setSelectedDatabase(actualDb);
965
- localStorage.setItem(`rebase_sql_selected_db_${projectPrefix}`, actualDb);
966
- setTabs((prev_0) => prev_0.map((t_4) => t_4.id === initialActiveTabId && (!t_4.database || !dbs.includes(t_4.database)) ? {
967
- ...t_4,
968
- database: actualDb
969
- } : t_4));
970
- }
971
- const currentUser = currentUserResult?.[0]?.role;
972
- let actualRole = currentActiveTab?.role || loadedRole;
973
- if (actualRole && !roles.includes(actualRole)) actualRole = void 0;
974
- if (!actualRole && roles.length > 0) {
975
- if (currentUser && roles.includes(currentUser)) {
976
- actualRole = currentUser;
977
- } else {
978
- actualRole = roles.includes("postgres") ? "postgres" : roles[0];
979
- }
980
- }
981
- if (actualRole) {
982
- setSelectedRole(actualRole);
983
- localStorage.setItem(`rebase_sql_selected_role_${projectPrefix}`, actualRole);
984
- setTabs((prev_1) => prev_1.map((t_5) => t_5.id === initialActiveTabId && (!t_5.role || !roles.includes(t_5.role)) ? {
985
- ...t_5,
986
- role: actualRole
987
- } : t_5));
988
- }
989
- }
990
- } catch (err) {
991
- console.error("Failed to fetch databases or roles:", err);
992
- if (mounted) {
993
- const message = err instanceof Error ? err.message : String(err);
994
- setConnectionConfigError(t("studio_sql_fetch_error", {
995
- message
996
- }));
997
- }
998
- } finally {
999
- if (mounted) {
1000
- setIsLoadingConfig(false);
1001
- }
1002
- }
1003
- };
1004
- fetchConnectionConfig();
1005
- return () => {
1006
- mounted = false;
1007
- };
1008
- }, [databaseAdmin, projectPrefix]);
1009
- const handleDatabaseChange = (db, tabId) => {
1010
- setSelectedDatabase(db);
1011
- localStorage.setItem(`rebase_sql_selected_db_${projectPrefix}`, db);
1012
- setTabs((prev_2) => prev_2.map((t_6) => t_6.id === activeTabId ? {
1013
- ...t_6,
1014
- database: db
1015
- } : t_6));
1016
- schemaFetchedRef.current = false;
1017
- };
1018
- const handleRoleChange = (role, tabId_0) => {
1019
- setSelectedRole(role);
1020
- localStorage.setItem(`rebase_sql_selected_role_${projectPrefix}`, role);
1021
- setTabs((prev_3) => prev_3.map((t_7) => t_7.id === activeTabId ? {
1022
- ...t_7,
1023
- role
1024
- } : t_7));
1025
- };
1026
- const handleTabChange = useCallback((newTabId) => {
1027
- setActiveTabId(newTabId);
1028
- const newTab = tabs.find((t_8) => t_8.id === newTabId);
1029
- if (newTab) {
1030
- if (newTab.database && newTab.database !== selectedDatabase) {
1031
- setSelectedDatabase(newTab.database);
1032
- localStorage.setItem(`rebase_sql_selected_db_${projectPrefix}`, newTab.database);
1033
- schemaFetchedRef.current = false;
1034
- } else if (!newTab.database && selectedDatabase) {
1035
- setTabs((prev_4) => prev_4.map((t_9) => t_9.id === newTabId ? {
1036
- ...t_9,
1037
- database: selectedDatabase
1038
- } : t_9));
1039
- }
1040
- if (newTab.role && newTab.role !== selectedRole) {
1041
- setSelectedRole(newTab.role);
1042
- localStorage.setItem(`rebase_sql_selected_role_${projectPrefix}`, newTab.role);
1043
- } else if (!newTab.role && selectedRole) {
1044
- setTabs((prev_5) => prev_5.map((t_10) => t_10.id === newTabId ? {
1045
- ...t_10,
1046
- role: selectedRole
1047
- } : t_10));
1048
- }
1049
- }
1050
- }, [tabs, selectedDatabase, selectedRole, projectPrefix]);
1051
- const fetchSchema = useCallback(async () => {
1052
- if (!databaseAdmin?.executeSql) {
1053
- setSchemaError(t("studio_sql_sql_not_supported"));
1054
- setIsSchemaLoading(false);
1055
- return;
1056
- }
1057
- setIsSchemaLoading(true);
1058
- setSchemaError(null);
1059
- try {
1060
- const sql_0 = `
1061
- SELECT
1062
- c.table_schema as schema,
1063
- c.table_name as "table",
1064
- c.column_name as "column",
1065
- c.data_type as "data_type",
1066
- CASE WHEN kcu.column_name IS NOT NULL THEN true ELSE false END as "is_pk"
1067
- FROM
1068
- information_schema.columns c
1069
- LEFT JOIN information_schema.table_constraints tc
1070
- ON tc.table_schema = c.table_schema
1071
- AND tc.table_name = c.table_name
1072
- AND tc.constraint_type = 'PRIMARY KEY'
1073
- LEFT JOIN information_schema.key_column_usage kcu
1074
- ON kcu.constraint_name = tc.constraint_name
1075
- AND kcu.table_schema = tc.table_schema
1076
- AND kcu.table_name = tc.table_name
1077
- AND kcu.column_name = c.column_name
1078
- WHERE
1079
- c.table_schema NOT IN ('information_schema', 'pg_catalog')
1080
- ORDER BY
1081
- c.table_schema, c.table_name, c.ordinal_position;
1082
- `;
1083
- const result = await databaseAdmin.executeSql(sql_0, {
1084
- database: selectedDatabase
1085
- });
1086
- const processGrouped = (data) => {
1087
- const grouped = data.reduce((acc, curr) => {
1088
- const schema = curr.schema || curr.SCHEMA || curr.table_schema || "public";
1089
- const table = curr.table || curr.TABLE || curr.table_name;
1090
- const column = curr.column || curr.COLUMN || curr.column_name;
1091
- const dataType = curr.data_type || curr.DATA_TYPE || "";
1092
- const isPrimaryKey = curr.is_pk === true || curr.is_pk === "true";
1093
- if (!acc[schema]) acc[schema] = [];
1094
- let tableInfo = acc[schema].find((t_11) => t_11.tableName === table);
1095
- if (!tableInfo) {
1096
- tableInfo = {
1097
- schemaName: schema,
1098
- tableName: table,
1099
- columns: []
1100
- };
1101
- acc[schema].push(tableInfo);
1102
- }
1103
- tableInfo.columns.push({
1104
- name: column,
1105
- dataType,
1106
- isPrimaryKey
1107
- });
1108
- return acc;
1109
- }, {});
1110
- setSchemas(grouped);
1111
- };
1112
- if (!result || !Array.isArray(result)) {
1113
- if (result && typeof result === "object" && "rows" in result && Array.isArray(result.rows)) {
1114
- processGrouped(result.rows);
1115
- } else {
1116
- setSchemaError(t("studio_sql_unexpected_format", {
1117
- type: typeof result
1118
- }));
1119
- setSchemas({});
1120
- }
1121
- } else if (result.length === 0) {
1122
- setSchemas({});
1123
- setSchemaError(t("studio_sql_no_tables"));
1124
- } else {
1125
- processGrouped(result);
1126
- }
1127
- schemaFetchedRef.current = true;
1128
- } catch (e_0) {
1129
- console.error("Schema fetch error:", e_0);
1130
- const message_0 = e_0 instanceof Error ? e_0.message : String(e_0);
1131
- setSchemaError(t("studio_sql_schema_fetch_error", {
1132
- message: message_0
1133
- }));
1134
- } finally {
1135
- setIsSchemaLoading(false);
1136
- }
1137
- }, [databaseAdmin, selectedDatabase]);
1138
- useEffect(() => {
1139
- if (!isLoadingConfig && !schemaFetchedRef.current) {
1140
- fetchSchema();
1141
- }
1142
- }, [fetchSchema, isLoadingConfig, selectedDatabase]);
1143
- const [autoLimit, setAutoLimit] = useState(true);
1144
- const [isConfirmDialogOpen, setIsConfirmDialogOpen] = useState(false);
1145
- const [pendingAction, setPendingAction] = useState(null);
1146
- const [editingCell, setEditingCell] = useState(null);
1147
- const handleDoubleClick = useCallback((rowIndex, columnKey, initialValue, rowData) => {
1148
- if (!activeTab.lastExecutedSql) {
1149
- snackbarController.open({
1150
- type: "error",
1151
- message: t("studio_sql_cannot_edit_missing_query")
1152
- });
1153
- return;
1154
- }
1155
- const resolution = determineTableAndPK(activeTab.lastExecutedSql, columnKey, schemas);
1156
- if (resolution.error || !resolution.primaryKeys || resolution.primaryKeys.length === 0) {
1157
- snackbarController.open({
1158
- type: "error",
1159
- message: resolution.error || t("studio_sql_cannot_resolve_table")
1160
- });
1161
- return;
1162
- }
1163
- const missingPKs = resolution.primaryKeys.filter((pk) => rowData[pk.resultColumn] === void 0 || rowData[pk.resultColumn] === null);
1164
- if (missingPKs.length > 0) {
1165
- snackbarController.open({
1166
- type: "error",
1167
- message: t("studio_sql_missing_pk", {
1168
- columns: missingPKs.map((pk_0) => `"${pk_0.resultColumn}"`).join(", ")
1169
- })
1170
- });
1171
- return;
1172
- }
1173
- setEditingCell({
1174
- rowIndex,
1175
- columnKey,
1176
- initialValue
1177
- });
1178
- }, [activeTab.lastExecutedSql, schemas, snackbarController]);
1179
- const handleCellSave = useCallback(async (newValue, rowData_0, columnKey_0, rowIndex_0) => {
1180
- if (!editingCell || !activeTab.lastExecutedSql) return;
1181
- setEditingCell(null);
1182
- if (newValue === editingCell.initialValue) return;
1183
- const resolution_0 = determineTableAndPK(activeTab.lastExecutedSql, columnKey_0, schemas);
1184
- if (resolution_0.error || !resolution_0.tableName || !resolution_0.primaryKeys || resolution_0.primaryKeys.length === 0) {
1185
- snackbarController.open({
1186
- type: "error",
1187
- message: resolution_0.error || "Resolution failed."
1188
- });
1189
- return;
1190
- }
1191
- const tableName = resolution_0.tableName;
1192
- const formatValue = (val) => {
1193
- if (val === null || val === void 0) return "NULL";
1194
- if (typeof val === "number") return val;
1195
- if (typeof val === "boolean") return val ? "TRUE" : "FALSE";
1196
- return `'${String(val).replace(/'/g, "''")}'`;
1197
- };
1198
- const resolveDbColumnName = (resultColKey) => {
1199
- try {
1200
- const ast = parseFirst(activeTab.lastExecutedSql);
1201
- if (ast.type === "select" && ast.columns) {
1202
- for (const col of ast.columns) {
1203
- if (col.expr?.type === "ref") {
1204
- const alias = col.alias?.name;
1205
- const colName = col.expr.name;
1206
- if (alias === resultColKey || !alias && colName === resultColKey) {
1207
- return colName;
1208
- }
1209
- }
1210
- }
1211
- }
1212
- } catch {
1213
- }
1214
- return resultColKey;
1215
- };
1216
- const dbColumnName = resolveDbColumnName(columnKey_0);
1217
- const whereConditions = resolution_0.primaryKeys.map((pk_1) => `"${pk_1.dbColumn}" = ${formatValue(rowData_0[pk_1.resultColumn])}`).join(" AND ");
1218
- const updateSql = `UPDATE "${tableName}" SET "${dbColumnName}" = ${formatValue(newValue)} WHERE ${whereConditions};`;
1219
- try {
1220
- if (databaseAdmin?.executeSql) {
1221
- await databaseAdmin.executeSql(updateSql, {
1222
- database: selectedDatabase,
1223
- role: selectedRole
1224
- });
1225
- const newResults_0 = [...activeTab.results || []];
1226
- if (newResults_0[rowIndex_0]) {
1227
- newResults_0[rowIndex_0] = {
1228
- ...newResults_0[rowIndex_0],
1229
- [columnKey_0]: newValue
1230
- };
1231
- }
1232
- updateActiveTab({
1233
- results: newResults_0
1234
- });
1235
- snackbarController.open({
1236
- type: "success",
1237
- message: t("studio_sql_row_updated")
1238
- });
1239
- }
1240
- } catch (e_1) {
1241
- snackbarController.open({
1242
- type: "error",
1243
- message: t("studio_sql_update_failed", {
1244
- message: e_1 instanceof Error ? e_1.message : String(e_1)
1245
- })
1246
- });
1247
- }
1248
- }, [editingCell, schemas, activeTab.lastExecutedSql, activeTab.results, databaseAdmin, updateActiveTab, snackbarController, selectedDatabase, selectedRole]);
1249
- const [columnWidths, setColumnWidths] = useState(() => {
1250
- const projectPrefixSync_3 = client?.baseUrl ? client.baseUrl.replace(/^https?:\/\//, "").replace(/[^a-zA-Z0-9]/g, "_") : "default";
1251
- const saved_0 = localStorage.getItem(`rebase_sql_column_widths_${projectPrefixSync_3}`);
1252
- return saved_0 ? JSON.parse(saved_0) : {};
1253
- });
1254
- const [snippets, setSnippets] = useState([]);
1255
- const [history, setHistory] = useState([]);
1256
- const [isSaveDialogOpen, setIsSaveDialogOpen] = useState(false);
1257
- const [newSnippetName, setNewSnippetName] = useState("");
1258
- useEffect(() => {
1259
- const savedSnippets = localStorage.getItem(`rebase_sql_snippets_${projectPrefix}`);
1260
- if (savedSnippets) {
1261
- setSnippets(JSON.parse(savedSnippets));
1262
- } else {
1263
- setSnippets([]);
1264
- }
1265
- const savedHistory = localStorage.getItem(`rebase_sql_history_${projectPrefix}`);
1266
- if (savedHistory) {
1267
- setHistory(JSON.parse(savedHistory));
1268
- } else {
1269
- setHistory([]);
1270
- }
1271
- }, [projectPrefix]);
1272
- useEffect(() => {
1273
- const sanitizedTabs = tabs.map((t_12) => ({
1274
- id: t_12.id,
1275
- name: t_12.name,
1276
- sql: t_12.sql,
1277
- database: t_12.database,
1278
- role: t_12.role
1279
- }));
1280
- localStorage.setItem(`rebase_sql_tabs_${projectPrefix}`, JSON.stringify(sanitizedTabs));
1281
- }, [tabs, projectPrefix]);
1282
- useEffect(() => {
1283
- localStorage.setItem(`rebase_sql_active_tab_${projectPrefix}`, activeTabId);
1284
- }, [activeTabId, projectPrefix]);
1285
- const saveSnippets = (newSnippets) => {
1286
- setSnippets(newSnippets);
1287
- localStorage.setItem(`rebase_sql_snippets_${projectPrefix}`, JSON.stringify(newSnippets));
1288
- };
1289
- const saveHistory = (newHistory) => {
1290
- setHistory(newHistory);
1291
- localStorage.setItem(`rebase_sql_history_${projectPrefix}`, JSON.stringify(newHistory.slice(-50)));
1292
- };
1293
- const handleDeleteSnippet = (id) => {
1294
- saveSnippets(snippets.filter((s) => s.id !== id));
1295
- };
1296
- const handleAddTab = () => {
1297
- const newId = Math.random().toString(36).substring(2, 9);
1298
- let maxNumber = 0;
1299
- tabs.forEach((tab) => {
1300
- const match = tab.name.match(/^Query (\d+)$/);
1301
- if (match) {
1302
- const num = parseInt(match[1], 10);
1303
- if (num > maxNumber) maxNumber = num;
1304
- }
1305
- });
1306
- const name = `Query ${maxNumber + 1}`;
1307
- setTabs((prev_6) => [...prev_6, {
1308
- id: newId,
1309
- name,
1310
- sql: "SELECT * FROM ",
1311
- database: selectedDatabase,
1312
- role: selectedRole,
1313
- results: null,
1314
- loading: false,
1315
- error: null,
1316
- execTime: null,
1317
- lastExecutedSql: null
1318
- }]);
1319
- setActiveTabId(newId);
1320
- };
1321
- const handleCloseTab = (id_0, e_2) => {
1322
- e_2.stopPropagation();
1323
- if (tabs.length === 1) return;
1324
- const tabIndex = tabs.findIndex((t_13) => t_13.id === id_0);
1325
- const newTabs = tabs.filter((t_14) => t_14.id !== id_0);
1326
- setTabs(newTabs);
1327
- if (activeTabId === id_0) {
1328
- const nextIndex = Math.min(tabIndex, newTabs.length - 1);
1329
- if (newTabs[nextIndex]) {
1330
- setActiveTabId(newTabs[nextIndex].id);
1331
- }
1332
- }
1333
- };
1334
- const handleColumnResize = useCallback(({
1335
- key,
1336
- width
1337
- }) => {
1338
- setColumnWidths((prev_7) => {
1339
- const newWidths = {
1340
- ...prev_7,
1341
- [activeTab.sql]: {
1342
- ...prev_7[activeTab.sql] || {},
1343
- [key]: width
1344
- }
1345
- };
1346
- localStorage.setItem(`rebase_sql_column_widths_${projectPrefix}`, JSON.stringify(newWidths));
1347
- return newWidths;
1348
- });
1349
- }, [activeTab.sql, projectPrefix]);
1350
- const handlePrettify = () => {
1351
- const formatted = activeTab.sql.replace(/\s+/g, " ").replace(/\s?,\s?/g, ", ").replace(/\s?=\s?/g, " = ").trim();
1352
- setSql(formatted);
1353
- };
1354
- const handleExplain = async () => {
1355
- const explainSql = `EXPLAIN (FORMAT JSON, ANALYZE) ${activeTab.sql}`;
1356
- updateActiveTab({
1357
- loading: true,
1358
- error: null,
1359
- results: null
1360
- });
1361
- const start = performance.now();
1362
- try {
1363
- if (databaseAdmin?.executeSql) {
1364
- const result_0 = await databaseAdmin.executeSql(explainSql, {
1365
- database: selectedDatabase,
1366
- role: selectedRole
1367
- });
1368
- updateActiveTab({
1369
- results: result_0,
1370
- execTime: Math.round(performance.now() - start)
1371
- });
1372
- }
1373
- } catch (e_3) {
1374
- const message_1 = e_3 instanceof Error ? e_3.message : String(e_3);
1375
- updateActiveTab({
1376
- error: message_1 || t("studio_sql_error_explaining")
1377
- });
1378
- } finally {
1379
- updateActiveTab({
1380
- loading: false
1381
- });
1382
- }
1383
- };
1384
- const executeRun = useCallback(async (sqlOverride) => {
1385
- let sqlToRun = sqlOverride || activeTab.sql;
1386
- const upperSql = sqlToRun.toUpperCase();
1387
- const isAggregate = /\b(COUNT|SUM|AVG|MIN|MAX)\s*\(/i.test(sqlToRun);
1388
- const isExplain = /\bEXPLAIN\b/i.test(sqlToRun);
1389
- if (autoLimit && upperSql.includes("SELECT") && !upperSql.includes("LIMIT") && !isAggregate && !isExplain) {
1390
- sqlToRun = sqlToRun.trim().replace(/;$/, "");
1391
- sqlToRun = `${sqlToRun} LIMIT 1000;`;
1392
- }
1393
- updateActiveTab({
1394
- loading: true,
1395
- error: null,
1396
- results: null
1397
- });
1398
- const start_0 = performance.now();
1399
- try {
1400
- if (databaseAdmin?.executeSql) {
1401
- const result_1 = await databaseAdmin.executeSql(sqlToRun, {
1402
- database: selectedDatabase,
1403
- role: selectedRole
1404
- });
1405
- updateActiveTab({
1406
- results: result_1,
1407
- execTime: Math.round(performance.now() - start_0),
1408
- lastExecutedSql: sqlToRun
1409
- });
1410
- if (history[history.length - 1] !== activeTab.sql) {
1411
- saveHistory([...history, activeTab.sql]);
1412
- }
1413
- } else {
1414
- updateActiveTab({
1415
- error: t("studio_sql_execution_not_supported")
1416
- });
1417
- }
1418
- } catch (e_4) {
1419
- const message_2 = e_4 instanceof Error ? e_4.message : String(e_4);
1420
- updateActiveTab({
1421
- error: message_2 || t("studio_sql_error_executing")
1422
- });
1423
- } finally {
1424
- updateActiveTab({
1425
- loading: false
1426
- });
1427
- }
1428
- }, [activeTab.sql, autoLimit, databaseAdmin, history, updateActiveTab, selectedDatabase, selectedRole]);
1429
- const handleRun = useCallback(async (selectedText) => {
1430
- const sqlTarget = selectedText || activeTab.sql;
1431
- if (!sqlTarget.trim()) return;
1432
- const destructiveKeywords = ["DELETE", "DROP", "TRUNCATE", "UPDATE"];
1433
- const hasDestructive = destructiveKeywords.some((kw) => sqlTarget.toUpperCase().includes(kw));
1434
- const hasWhere = sqlTarget.toUpperCase().includes("WHERE");
1435
- if (hasDestructive && (!hasWhere || sqlTarget.toUpperCase().includes("DROP") || sqlTarget.toUpperCase().includes("TRUNCATE"))) {
1436
- setPendingAction(() => () => executeRun(selectedText));
1437
- setIsConfirmDialogOpen(true);
1438
- return;
1439
- }
1440
- executeRun(selectedText);
1441
- }, [activeTab.sql, executeRun]);
1442
- useEffect(() => {
1443
- const handleKeyDown = (e_5) => {
1444
- if ((e_5.metaKey || e_5.ctrlKey) && e_5.key === "Enter") {
1445
- const activeElement = document.activeElement;
1446
- const isInput = activeElement?.tagName === "INPUT" || activeElement?.tagName === "TEXTAREA";
1447
- const isMonaco = activeElement?.className?.includes("monaco-mouse-cursor-text");
1448
- if (!isMonaco && !isInput) {
1449
- e_5.preventDefault();
1450
- handleRun();
1451
- }
1452
- }
1453
- };
1454
- window.addEventListener("keydown", handleKeyDown);
1455
- return () => window.removeEventListener("keydown", handleKeyDown);
1456
- }, [handleRun]);
1457
- const handleSaveSnippet = () => {
1458
- if (!newSnippetName.trim() || !sql.trim()) return;
1459
- const newSnippet = {
1460
- id: Math.random().toString(36).substring(2, 9),
1461
- name: newSnippetName,
1462
- sql,
1463
- createdAt: Date.now()
1464
- };
1465
- saveSnippets([...snippets, newSnippet]);
1466
- setNewSnippetName("");
1467
- setIsSaveDialogOpen(false);
1468
- snackbarController.open({
1469
- type: "success",
1470
- message: t("studio_sql_snippet_saved", {
1471
- name: newSnippetName
1472
- })
1473
- });
1474
- };
1475
- const handleExportCSV = () => {
1476
- if (!results || results.length === 0) return;
1477
- const headers = Object.keys(results[0]).join(",");
1478
- const rows = results.map((row) => Object.values(row).map((val_0) => {
1479
- const str = String(val_0);
1480
- return str.includes(",") ? `"${str}"` : str;
1481
- }).join(","));
1482
- const csv = [headers, ...rows].join("\n");
1483
- const blob = new Blob([csv], {
1484
- type: "text/csv"
1485
- });
1486
- const url = window.URL.createObjectURL(blob);
1487
- const a = document.createElement("a");
1488
- a.href = url;
1489
- a.download = `query_results_${(/* @__PURE__ */ new Date()).toISOString().slice(0, 19)}.csv`;
1490
- a.click();
1491
- window.URL.revokeObjectURL(url);
1492
- };
1493
- const handleExportJSON = () => {
1494
- if (!results || results.length === 0) return;
1495
- const json = JSON.stringify(results, null, 2);
1496
- const blob_0 = new Blob([json], {
1497
- type: "application/json"
1498
- });
1499
- const url_0 = window.URL.createObjectURL(blob_0);
1500
- const a_0 = document.createElement("a");
1501
- a_0.href = url_0;
1502
- a_0.download = `query_results_${(/* @__PURE__ */ new Date()).toISOString().slice(0, 19)}.json`;
1503
- a_0.click();
1504
- window.URL.revokeObjectURL(url_0);
1505
- };
1506
- const handleExportMarkdown = () => {
1507
- if (!results || results.length === 0) return;
1508
- const headers_0 = Object.keys(results[0]);
1509
- const headerRow = `| ${headers_0.join(" | ")} |`;
1510
- const dividerRow = `| ${headers_0.map(() => "---").join(" | ")} |`;
1511
- const dataRows = results.map((row_0) => `| ${headers_0.map((header) => {
1512
- const val_1 = row_0[header];
1513
- if (val_1 === null) return "null";
1514
- if (val_1 === void 0) return "";
1515
- return String(val_1).replace(/\|/g, "\\|").replace(/\n/g, " ");
1516
- }).join(" | ")} |`);
1517
- const markdown = [headerRow, dividerRow, ...dataRows].join("\n");
1518
- navigator.clipboard.writeText(markdown).then(() => {
1519
- snackbarController.open({
1520
- type: "success",
1521
- message: t("studio_sql_markdown_copied")
1522
- });
1523
- }).catch(() => {
1524
- snackbarController.open({
1525
- type: "error",
1526
- message: t("studio_sql_markdown_copy_failed")
1527
- });
1528
- });
1529
- };
1530
- const renderResults = () => {
1531
- if (loading) {
1532
- return /* @__PURE__ */ jsx("div", { className: "flex-grow flex items-center justify-center", children: /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
1533
- /* @__PURE__ */ jsx(CircularProgress, { size: "medium" }),
1534
- /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "mt-4 text-text-secondary dark:text-text-secondary-dark font-mono tracking-tight animate-pulse", children: t("studio_sql_executing_query") })
1535
- ] }) });
1536
- }
1537
- if (error) {
1538
- return /* @__PURE__ */ jsx("div", { className: "flex-grow flex items-center justify-center p-6 overflow-auto", children: /* @__PURE__ */ jsx(ErrorView, { title: t("studio_sql_query_error"), error }) });
1539
- }
1540
- if (!results) {
1541
- return /* @__PURE__ */ jsx("div", { className: "flex-grow flex items-center justify-center text-text-disabled dark:text-text-disabled-dark", children: /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
1542
- /* @__PURE__ */ jsx("svg", { className: "w-12 h-12 mx-auto mb-4 opacity-50", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 1, 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 4m0 5c0 2.21-3.582 4-8 4s-8-1.79-8-4" }) }),
1543
- /* @__PURE__ */ jsx(Typography, { variant: "body2", children: t("studio_sql_run_query_placeholder") })
1544
- ] }) });
1545
- }
1546
- if (results.length === 1 && results[0]["QUERY PLAN"] && Array.isArray(results[0]["QUERY PLAN"])) {
1547
- try {
1548
- const plan = results[0]["QUERY PLAN"][0].Plan;
1549
- if (plan) {
1550
- return /* @__PURE__ */ jsxs("div", { className: "flex-grow overflow-auto p-4 bg-surface-50 dark:bg-surface-900 flex flex-col items-start", children: [
1551
- /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "font-bold text-text-secondary mb-4 tracking-wider uppercase", children: t("studio_sql_visual_execution_plan") }),
1552
- /* @__PURE__ */ jsx("div", { className: "pb-12", children: /* @__PURE__ */ jsx(ExplainVisualizer, { plan }) })
1553
- ] });
1554
- }
1555
- } catch (e_6) {
1556
- console.warn("Failed to parse EXPLAIN JSON output:", e_6);
1557
- }
1558
- }
1559
- if (results.length === 0) {
1560
- return /* @__PURE__ */ jsxs("div", { className: "flex-grow p-6 flex flex-col items-center justify-center", children: [
1561
- /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-text-secondary dark:text-text-secondary-dark font-mono border-b border-surface-200 dark:border-surface-950 pb-2 mb-2", children: t("studio_sql_success") }),
1562
- /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-text-disabled dark:text-text-disabled-dark", children: t("studio_sql_no_results") })
1563
- ] });
1564
- }
1565
- const savedWidths = columnWidths[activeTab.sql] || {};
1566
- const resultColumnKeys = Object.keys(results[0]);
1567
- const matchedCollections = (() => {
1568
- if (!activeTab.lastExecutedSql || !collectionRegistry.collections) return [];
1569
- try {
1570
- return resolveQueryCollections(activeTab.lastExecutedSql, schemas, collectionRegistry.collections, resultColumnKeys);
1571
- } catch {
1572
- return [];
1573
- }
1574
- })();
1575
- const actionableCollections = matchedCollections.filter((mc) => mc.pkColumn && resultColumnKeys.includes(mc.pkColumn));
1576
- const getRowEntityActions = (rowData_1) => {
1577
- if (!rowData_1) return [];
1578
- return actionableCollections.filter((mc_0) => rowData_1[mc_0.pkColumn] != null).map((mc_1) => ({
1579
- collection: mc_1,
1580
- entityId: rowData_1[mc_1.pkColumn]
1581
- }));
1582
- };
1583
- const dataColumns = resultColumnKeys.map((key_0) => ({
1584
- key: key_0,
1585
- title: key_0,
1586
- width: savedWidths[key_0] ?? 150,
1587
- sortable: false,
1588
- resizable: true
1589
- }));
1590
- const columns = actionableCollections.length > 0 ? [{
1591
- key: "__cms_action__",
1592
- title: "",
1593
- width: 36,
1594
- sortable: false,
1595
- resizable: false
1596
- }, ...dataColumns] : dataColumns;
1597
- return /* @__PURE__ */ jsxs("div", { className: "flex-grow flex flex-col overflow-hidden min-h-0", children: [
1598
- actionableCollections.length > 0 && /* @__PURE__ */ jsxs("div", { className: cls("px-4 py-1.5 border-b flex items-center gap-2 shrink-0 bg-surface-50 dark:bg-surface-900", defaultBorderMixin), children: [
1599
- /* @__PURE__ */ jsx(Tooltip, { title: t("studio_sql_cms_collections_tooltip"), children: /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-[10px] font-bold uppercase tracking-widest text-text-disabled dark:text-text-disabled-dark mr-1 shrink-0 cursor-help", children: t("studio_sql_cms") }) }),
1600
- /* @__PURE__ */ jsx("div", { className: "flex items-center gap-1.5 overflow-x-auto no-scrollbar", children: actionableCollections.map((mc_2) => /* @__PURE__ */ jsx(Tooltip, { title: `Table "${mc_2.tableName}" → ${mc_2.collection.name} (PK: ${mc_2.pkColumn})`, children: /* @__PURE__ */ jsxs("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", children: [
1601
- typeof mc_2.collection.icon === "string" && /* @__PURE__ */ jsx(IconForView, { collectionOrView: mc_2.collection, className: "text-[12px]" }),
1602
- mc_2.collection.name
1603
- ] }) }, mc_2.tableName)) })
1604
- ] }),
1605
- /* @__PURE__ */ jsx("div", { className: "flex-grow relative h-full min-h-0 min-w-0", children: /* @__PURE__ */ jsx(VirtualTable, { data: results, columns, rowHeight: 32, headerHeight: 32, extraData: editingCell, onColumnResizeEnd: handleColumnResize, cellRenderer: ({
1606
- rowData: rowData_2,
1607
- column: column_0,
1608
- rowIndex: rowIndex_1
1609
- }) => {
1610
- if (column_0.key === "__cms_action__") {
1611
- const rowActions = getRowEntityActions(rowData_2 ?? {});
1612
- if (rowActions.length === 0) {
1613
- return /* @__PURE__ */ jsx("div", { className: "h-full w-full" });
1614
- }
1615
- if (rowActions.length === 1) {
1616
- const ra = rowActions[0];
1617
- return /* @__PURE__ */ jsx("div", { className: "h-full flex items-center justify-center", children: /* @__PURE__ */ jsx(Tooltip, { title: t("studio_sql_edit_entity", {
1618
- name: ra.collection.collection.name,
1619
- id: String(ra.entityId)
1620
- }), children: /* @__PURE__ */ jsx(IconButton, { size: "small", className: "text-surface-400 dark:text-surface-500 hover:text-surface-600 dark:hover:text-surface-300 transition-colors", onClick: (e_7) => {
1621
- e_7.stopPropagation();
1622
- sideEntityController?.open({
1623
- path: ra.collection.collection.slug,
1624
- entityId: ra.entityId,
1625
- collection: ra.collection.collection,
1626
- updateUrl: false
1627
- });
1628
- }, children: /* @__PURE__ */ jsx(PencilIcon, { size: iconSize.smallest }) }) }) });
1629
- }
1630
- return /* @__PURE__ */ jsx("div", { className: "h-full flex items-center justify-center", children: /* @__PURE__ */ jsx(Menu, { trigger: /* @__PURE__ */ jsx(IconButton, { size: "small", className: "text-surface-400 dark:text-surface-500 hover:text-surface-600 dark:hover:text-surface-300 transition-colors", onClick: (e_8) => e_8.stopPropagation(), children: /* @__PURE__ */ jsx(MoreVerticalIcon, { size: iconSize.smallest }) }), children: rowActions.map((ra_0) => /* @__PURE__ */ jsx(MenuItem, { dense: true, onClick: () => {
1631
- sideEntityController?.open({
1632
- path: ra_0.collection.collection.slug,
1633
- entityId: ra_0.entityId,
1634
- collection: ra_0.collection.collection,
1635
- updateUrl: false
1636
- });
1637
- }, children: t("studio_sql_edit_entity", {
1638
- name: ra_0.collection.collection.name,
1639
- id: String(ra_0.entityId)
1640
- }) }, ra_0.collection.tableName)) }) });
1641
- }
1642
- const isEditing = editingCell?.rowIndex === rowIndex_1 && editingCell?.columnKey === column_0.key;
1643
- const value = rowData_2 ? rowData_2[column_0.key] : null;
1644
- const displayValue = typeof value === "object" && value !== null ? JSON.stringify(value) : String(value ?? "");
1645
- if (isEditing) {
1646
- return /* @__PURE__ */ jsx(FixedEditorOverlay, { displayValue, onSave: (val_2) => handleCellSave(val_2, rowData_2 ?? {}, column_0.key, rowIndex_1), onCancel: () => setEditingCell(null) });
1647
- }
1648
- return /* @__PURE__ */ jsx("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 cursor-text group/cell", onDoubleClick: () => handleDoubleClick(rowIndex_1, column_0.key, displayValue, rowData_2 ?? {}), children: /* @__PURE__ */ jsx("div", { className: "truncate flex-grow", title: displayValue, children: displayValue === "" ? /* @__PURE__ */ jsx("span", { className: "text-text-disabled dark:text-text-disabled-dark italic text-[11px]", children: "NULL" }) : displayValue }) });
1649
- } }) }),
1650
- /* @__PURE__ */ jsxs("div", { className: cls("p-2 px-4 border-t bg-surface-50 dark:bg-surface-900 flex justify-between items-center shrink-0", defaultBorderMixin), children: [
1651
- /* @__PURE__ */ jsxs("div", { className: "flex space-x-4", children: [
1652
- /* @__PURE__ */ jsxs("div", { className: "flex items-center text-[11px]", children: [
1653
- /* @__PURE__ */ jsx("span", { className: "font-bold text-text-disabled dark:text-text-disabled-dark mr-2 uppercase tracking-tighter", children: t("studio_sql_rows") }),
1654
- /* @__PURE__ */ jsx("span", { className: "font-mono text-text-secondary dark:text-text-secondary-dark", children: results.length })
1655
- ] }),
1656
- /* @__PURE__ */ jsxs("div", { className: "flex items-center text-[11px]", children: [
1657
- /* @__PURE__ */ jsx("span", { className: "font-bold text-text-disabled dark:text-text-disabled-dark mr-2 uppercase tracking-tighter", children: t("studio_sql_time") }),
1658
- /* @__PURE__ */ jsxs("span", { className: "font-mono text-text-secondary dark:text-text-secondary-dark", children: [
1659
- execTime,
1660
- "ms"
1661
- ] })
1662
- ] })
1663
- ] }),
1664
- /* @__PURE__ */ jsxs("div", { className: "flex gap-2 overflow-x-auto no-scrollbar items-center px-2", children: [
1665
- /* @__PURE__ */ jsx(Button, { size: "small", variant: "text", className: "text-[10px] uppercase font-bold text-text-secondary dark:text-text-secondary-dark whitespace-nowrap", onClick: handleExportMarkdown, children: t("studio_sql_copy_markdown") }),
1666
- /* @__PURE__ */ jsx(Button, { size: "small", variant: "text", className: "text-[10px] uppercase font-bold text-text-secondary dark:text-text-secondary-dark whitespace-nowrap", onClick: handleExportJSON, children: t("studio_sql_export_json") }),
1667
- /* @__PURE__ */ jsx(Button, { size: "small", variant: "text", className: "text-[10px] uppercase font-bold text-text-secondary dark:text-text-secondary-dark whitespace-nowrap", onClick: handleExportCSV, children: t("studio_sql_export_csv") })
1668
- ] })
1669
- ] })
1670
- ] });
1671
- };
1672
- const [sidebarSize, setSidebarSize] = useState(() => {
1673
- try {
1674
- const projectPrefixSync_4 = client?.baseUrl ? client.baseUrl.replace(/^https?:\/\//, "").replace(/[^a-zA-Z0-9]/g, "_") : "default";
1675
- const saved_1 = localStorage.getItem(`rebase_sql_editor_sidebar_size_${projectPrefixSync_4}`);
1676
- return saved_1 !== null ? parseFloat(saved_1) : 20;
1677
- } catch (e_9) {
1678
- return 20;
1679
- }
1680
- });
1681
- const [editorHeight, setEditorHeight] = useState(() => {
1682
- try {
1683
- const projectPrefixSync_5 = client?.baseUrl ? client.baseUrl.replace(/^https?:\/\//, "").replace(/[^a-zA-Z0-9]/g, "_") : "default";
1684
- const saved_2 = localStorage.getItem(`rebase_sql_editor_height_${projectPrefixSync_5}`);
1685
- return saved_2 !== null ? parseFloat(saved_2) : 50;
1686
- } catch (e_10) {
1687
- return 50;
1688
- }
1689
- });
1690
- useEffect(() => {
1691
- try {
1692
- localStorage.setItem(`rebase_sql_editor_sidebar_size_${projectPrefix}`, sidebarSize.toString());
1693
- } catch (e_11) {
1694
- }
1695
- }, [sidebarSize, projectPrefix]);
1696
- useEffect(() => {
1697
- try {
1698
- localStorage.setItem(`rebase_sql_editor_height_${projectPrefix}`, editorHeight.toString());
1699
- } catch (e_12) {
1700
- }
1701
- }, [editorHeight, projectPrefix]);
1702
- const activeSnippet = snippets.find((s_0) => s_0.sql === activeTab.sql);
1703
- const isFavorite = activeSnippet?.isFavorite || false;
1704
- return /* @__PURE__ */ jsxs("div", { className: "flex h-full w-full bg-white dark:bg-surface-950 overflow-hidden text-text-primary dark:text-text-primary-dark", children: [
1705
- /* @__PURE__ */ jsx(ResizablePanels, { orientation: "horizontal", panelSizePercent: sidebarSize, onPanelSizeChange: setSidebarSize, minPanelSizePx: 220, firstPanel: /* @__PURE__ */ jsx(SQLEditorSidebar, { snippets, history, onSelectSnippet: setSql, onTableClick: setSql, onDeleteSnippet: handleDeleteSnippet, schemas, isSchemaLoading, schemaError, onRetrySchema: fetchSchema }), secondPanel: /* @__PURE__ */ jsxs("div", { className: "flex-grow flex flex-col min-w-0 h-full w-full", children: [
1706
- /* @__PURE__ */ jsxs("div", { className: cls("flex items-center justify-between pr-2 border-b bg-white dark:bg-surface-950", defaultBorderMixin), children: [
1707
- /* @__PURE__ */ jsx("div", { className: "flex items-center flex-grow overflow-hidden mr-4", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center no-scrollbar overflow-x-auto min-w-0", children: [
1708
- /* @__PURE__ */ jsx(Tabs, { value: activeTabId, onValueChange: handleTabChange, variant: "boxy", className: "w-[unset] flex-shrink-0", innerClassName: "bg-white dark:bg-surface-950", children: tabs.map((tab_0) => /* @__PURE__ */ jsxs(Tab, { value: tab_0.id, className: "flex items-center justify-between group max-w-[200px]", children: [
1709
- /* @__PURE__ */ jsx(TerminalIcon, { size: iconSize.smallest, className: "text-blue-500 mr-1.5 flex-shrink-0" }),
1710
- /* @__PURE__ */ jsx("span", { className: "truncate", children: tab_0.name }),
1711
- tabs.length > 1 && /* @__PURE__ */ jsx(IconButton, { size: "smallest", onClick: (e_13) => handleCloseTab(tab_0.id, e_13), className: "ml-1 !p-0.5 opacity-0 group-hover:opacity-100 hover:text-red-500 transition-opacity", children: /* @__PURE__ */ jsx(XIcon, { size: iconSize.smallest }) })
1712
- ] }, tab_0.id)) }),
1713
- /* @__PURE__ */ jsx(IconButton, { size: "small", onClick: handleAddTab, className: "ml-2 flex-shrink-0", children: /* @__PURE__ */ jsx(PlusIcon, { size: iconSize.smallest }) })
1714
- ] }) }),
1715
- /* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center justify-end pr-2 gap-1.5", children: [
1716
- /* @__PURE__ */ jsx(Tooltip, { title: t("studio_sql_format_sql"), children: /* @__PURE__ */ jsx(IconButton, { size: "small", onClick: handlePrettify, children: /* @__PURE__ */ jsx(MenuIcon, { size: iconSize.smallest }) }) }),
1717
- /* @__PURE__ */ jsx(Button, { variant: "text", size: "small", onClick: handleExplain, disabled: loading, children: t("studio_sql_explain") }),
1718
- /* @__PURE__ */ jsx("div", { className: "h-4 w-px bg-surface-200 dark:bg-surface-950 mx-1" }),
1719
- /* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-2 px-2", onClick: (e_14) => {
1720
- setAutoLimit(!autoLimit);
1721
- e_14.stopPropagation();
1722
- }, children: [
1723
- /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-[11px] text-text-secondary cursor-pointer select-none", children: t("studio_sql_limit_1000") }),
1724
- /* @__PURE__ */ jsx("div", { onClick: (e_15) => e_15.stopPropagation(), children: /* @__PURE__ */ jsx(Checkbox, { checked: autoLimit, onCheckedChange: setAutoLimit, size: "smallest", padding: false }) })
1725
- ] }),
1726
- /* @__PURE__ */ jsx("div", { className: "h-4 w-px bg-surface-200 dark:bg-surface-950 mx-1" }),
1727
- /* @__PURE__ */ jsx(Tooltip, { title: isFavorite ? t("studio_sql_remove_from_favorites") : t("studio_sql_add_to_favorites"), children: /* @__PURE__ */ jsx(IconButton, { size: "small", onClick: () => {
1728
- if (!activeSnippet) {
1729
- snackbarController.open({
1730
- type: "info",
1731
- message: t("studio_sql_save_first_to_favorite")
1732
- });
1733
- return;
1734
- }
1735
- saveSnippets(snippets.map((s_1) => s_1.id === activeSnippet.id ? {
1736
- ...s_1,
1737
- isFavorite: !s_1.isFavorite
1738
- } : s_1));
1739
- }, children: /* @__PURE__ */ jsx("svg", { className: `w-4 h-4 ${isFavorite ? "text-red-500 fill-current" : "text-text-disabled dark:text-text-disabled-dark hover:text-text-primary"}`, fill: isFavorite ? "currentColor" : "none", stroke: "currentColor", strokeWidth: 2, viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z" }) }) }) }),
1740
- /* @__PURE__ */ jsx(Button, { variant: "text", size: "small", onClick: () => setIsSaveDialogOpen(true), children: t("studio_sql_save") }),
1741
- /* @__PURE__ */ jsx("div", { className: "h-4 w-px bg-surface-200 dark:bg-surface-950 mx-1" }),
1742
- /* @__PURE__ */ jsx(Menu, { trigger: /* @__PURE__ */ jsxs(Button, { size: "small", variant: "outlined", className: "text-text-secondary dark:text-text-secondary-dark font-medium mr-2", children: [
1743
- /* @__PURE__ */ jsx(DatabaseIcon, { size: iconSize.small, className: "mr-1.5 text-text-disabled dark:text-text-disabled-dark" }),
1744
- /* @__PURE__ */ jsx("span", { className: "max-w-[160px] truncate", children: isLoadingConfig ? "..." : `${selectedDatabase || t("studio_sql_select_db")}${selectedRole ? ` (${selectedRole})` : ""}` })
1745
- ] }), children: /* @__PURE__ */ jsxs("div", { className: "max-h-64 overflow-y-auto", children: [
1746
- /* @__PURE__ */ jsx("div", { className: "px-3 py-1.5 border-b border-surface-200 dark:border-surface-950 mb-1", children: /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "font-bold uppercase tracking-wider text-[9px] text-text-disabled dark:text-text-disabled-dark", children: t("studio_sql_database") }) }),
1747
- isLoadingConfig ? /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center p-4", children: /* @__PURE__ */ jsx(CircularProgress, { size: "small" }) }) : connectionConfigError ? /* @__PURE__ */ jsx("div", { className: "px-3 py-2 text-xs text-red-500 dark:text-red-400 max-w-[200px] break-words", children: connectionConfigError }) : /* @__PURE__ */ jsxs(Fragment, { children: [
1748
- availableDatabases.map((db_0) => /* @__PURE__ */ jsx(MenuItem, { dense: true, onClick: () => handleDatabaseChange(db_0), className: cls("text-xs", selectedDatabase === db_0 && "text-primary dark:text-primary-dark"), children: db_0 }, db_0)),
1749
- /* @__PURE__ */ jsx("div", { className: "px-3 py-1.5 border-y border-surface-200 dark:border-surface-950 mb-1 mt-1", children: /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "font-bold uppercase tracking-wider text-[9px] text-text-disabled dark:text-text-disabled-dark", children: t("studio_sql_role") }) }),
1750
- availableRoles.map((role_0) => /* @__PURE__ */ jsxs(MenuItem, { dense: true, onClick: () => handleRoleChange(role_0), className: cls("text-xs", selectedRole === role_0 && "text-primary dark:text-primary-dark"), children: [
1751
- role_0,
1752
- role_0 === "postgres" ? " " + t("studio_sql_admin") : ""
1753
- ] }, role_0))
1754
- ] })
1755
- ] }) }),
1756
- /* @__PURE__ */ jsxs(Button, { onClick: () => handleRun(), disabled: loading, size: "small", color: "primary", children: [
1757
- loading ? /* @__PURE__ */ jsx(CircularProgress, { size: "smallest", className: "mr-2" }) : /* @__PURE__ */ jsx(PlayIcon, { size: iconSize.smallest, className: "mr-2" }),
1758
- t("studio_sql_run")
1759
- ] })
1760
- ] })
1761
- ] }),
1762
- /* @__PURE__ */ jsx(ResizablePanels, { orientation: "vertical", panelSizePercent: editorHeight, onPanelSizeChange: setEditorHeight, minPanelSizePx: 100, firstPanel: /* @__PURE__ */ jsx("div", { className: "h-full w-full relative flex flex-col min-h-0", children: /* @__PURE__ */ jsx(MonacoEditor, { value: sql, onChange: (v) => setSql(v || ""), onRun: handleRun, schemas }) }), secondPanel: /* @__PURE__ */ jsxs("div", { className: "h-full w-full flex flex-col bg-surface-50 dark:bg-surface-950 overflow-hidden min-h-0", children: [
1763
- /* @__PURE__ */ jsx("div", { className: cls("p-2 px-4 bg-surface-100 dark:bg-surface-900 border-b shrink-0 flex items-center", defaultBorderMixin), children: /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "font-bold text-text-disabled dark:text-text-disabled-dark uppercase tracking-widest text-[10px]", children: t("studio_sql_query_results") }) }),
1764
- /* @__PURE__ */ jsx("div", { className: "flex-grow flex flex-col min-h-0 overflow-hidden", children: renderResults() })
1765
- ] }) })
1766
- ] }) }),
1767
- /* @__PURE__ */ jsxs(Dialog, { open: isSaveDialogOpen, onOpenChange: setIsSaveDialogOpen, children: [
1768
- /* @__PURE__ */ jsx(DialogTitle, { children: t("studio_sql_save_snippet") }),
1769
- /* @__PURE__ */ jsx(DialogContent, { children: /* @__PURE__ */ jsxs("div", { className: "py-4 flex flex-col gap-4", children: [
1770
- /* @__PURE__ */ jsx(TextField, { label: t("studio_sql_snippet_name"), autoFocus: true, placeholder: t("studio_sql_snippet_name_placeholder"), value: newSnippetName, onChange: (e_16) => setNewSnippetName(e_16.target.value), onKeyDown: (e_17) => {
1771
- if (e_17.key === "Enter") {
1772
- e_17.preventDefault();
1773
- handleSaveSnippet();
1774
- }
1775
- } }),
1776
- /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-text-disabled dark:text-text-disabled-dark block", children: t("studio_sql_snippet_saved_local") })
1777
- ] }) }),
1778
- /* @__PURE__ */ jsxs(DialogActions, { children: [
1779
- /* @__PURE__ */ jsx(Button, { variant: "text", onClick: () => setIsSaveDialogOpen(false), children: t("studio_sql_cancel") }),
1780
- /* @__PURE__ */ jsx(Button, { onClick: handleSaveSnippet, color: "primary", disabled: !newSnippetName.trim(), children: t("studio_sql_save") })
1781
- ] })
1782
- ] }),
1783
- /* @__PURE__ */ jsx(ConfirmationDialog, { open: isConfirmDialogOpen, onCancel: () => setIsConfirmDialogOpen(false), title: t("studio_sql_dangerous_operation"), body: t("studio_sql_dangerous_operation_body"), onAccept: () => {
1784
- if (pendingAction) pendingAction();
1785
- setIsConfirmDialogOpen(false);
1786
- } })
1787
- ] });
1788
- };
1789
- function _temp(e) {
1790
- const val = e.target.value;
1791
- e.target.value = "";
1792
- e.target.value = val;
1793
- }
1794
- export {
1795
- SQLEditor
1796
- };
1797
- //# sourceMappingURL=SQLEditor-BC0IOUQu.js.map