@rebasepro/studio 0.0.1-canary.09e5ec5

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 (361) hide show
  1. package/LICENSE +114 -0
  2. package/README.md +159 -0
  3. package/dist/ApiExplorer-gMJt5JrS.js +1053 -0
  4. package/dist/ApiExplorer-gMJt5JrS.js.map +1 -0
  5. package/dist/AuthSimulationSelector-BF4rkRGp.js +118 -0
  6. package/dist/AuthSimulationSelector-BF4rkRGp.js.map +1 -0
  7. package/dist/BranchesView-DcHZtvXo.js +292 -0
  8. package/dist/BranchesView-DcHZtvXo.js.map +1 -0
  9. package/dist/CronJobsView-CijCToeK.js +456 -0
  10. package/dist/CronJobsView-CijCToeK.js.map +1 -0
  11. package/dist/JSEditor-D8nVp3Lp.js +1308 -0
  12. package/dist/JSEditor-D8nVp3Lp.js.map +1 -0
  13. package/dist/MonacoEditor-CMYEjiRf.js +161 -0
  14. package/dist/MonacoEditor-CMYEjiRf.js.map +1 -0
  15. package/dist/RLSEditor-DBH09u9v.js +1831 -0
  16. package/dist/RLSEditor-DBH09u9v.js.map +1 -0
  17. package/dist/SQLEditor-CkVx9vgr.js +1792 -0
  18. package/dist/SQLEditor-CkVx9vgr.js.map +1 -0
  19. package/dist/SchemaVisualizer-BgD5Zb77.js +1069 -0
  20. package/dist/SchemaVisualizer-BgD5Zb77.js.map +1 -0
  21. package/dist/StorageView-CTqGFhY9.js +907 -0
  22. package/dist/StorageView-CTqGFhY9.js.map +1 -0
  23. package/dist/common/src/collections/CollectionRegistry.d.ts +56 -0
  24. package/dist/common/src/collections/index.d.ts +1 -0
  25. package/dist/common/src/data/buildRebaseData.d.ts +14 -0
  26. package/dist/common/src/index.d.ts +3 -0
  27. package/dist/common/src/util/builders.d.ts +57 -0
  28. package/dist/common/src/util/callbacks.d.ts +6 -0
  29. package/dist/common/src/util/collections.d.ts +11 -0
  30. package/dist/common/src/util/common.d.ts +2 -0
  31. package/dist/common/src/util/conditions.d.ts +26 -0
  32. package/dist/common/src/util/entities.d.ts +58 -0
  33. package/dist/common/src/util/enums.d.ts +3 -0
  34. package/dist/common/src/util/index.d.ts +16 -0
  35. package/dist/common/src/util/navigation_from_path.d.ts +34 -0
  36. package/dist/common/src/util/navigation_utils.d.ts +20 -0
  37. package/dist/common/src/util/parent_references_from_path.d.ts +6 -0
  38. package/dist/common/src/util/paths.d.ts +14 -0
  39. package/dist/common/src/util/permissions.d.ts +5 -0
  40. package/dist/common/src/util/references.d.ts +2 -0
  41. package/dist/common/src/util/relations.d.ts +22 -0
  42. package/dist/common/src/util/resolutions.d.ts +72 -0
  43. package/dist/common/src/util/storage.d.ts +24 -0
  44. package/dist/core/src/components/AIIcon.d.ts +16 -0
  45. package/dist/core/src/components/ConfirmationDialog.d.ts +9 -0
  46. package/dist/core/src/components/Debug/UIReferenceView.d.ts +1 -0
  47. package/dist/core/src/components/Debug/UIStyleGuide.d.ts +1 -0
  48. package/dist/core/src/components/ErrorTooltip.d.ts +2 -0
  49. package/dist/core/src/components/ErrorView.d.ts +21 -0
  50. package/dist/core/src/components/LanguageToggle.d.ts +1 -0
  51. package/dist/core/src/components/LoginView/LoginView.d.ts +68 -0
  52. package/dist/core/src/components/LoginView/index.d.ts +2 -0
  53. package/dist/core/src/components/NotFoundPage.d.ts +1 -0
  54. package/dist/core/src/components/RebaseAuth.d.ts +10 -0
  55. package/dist/core/src/components/RebaseLogo.d.ts +7 -0
  56. package/dist/core/src/components/UnsavedChangesDialog.d.ts +9 -0
  57. package/dist/core/src/components/UserDisplay.d.ts +7 -0
  58. package/dist/core/src/components/UserSelectPopover.d.ts +62 -0
  59. package/dist/core/src/components/UserSettingsView.d.ts +1 -0
  60. package/dist/core/src/components/common/index.d.ts +6 -0
  61. package/dist/core/src/components/common/table_height.d.ts +5 -0
  62. package/dist/core/src/components/common/types.d.ts +63 -0
  63. package/dist/core/src/components/common/useColumnsIds.d.ts +9 -0
  64. package/dist/core/src/components/common/useDataTableController.d.ts +45 -0
  65. package/dist/core/src/components/common/useDebouncedData.d.ts +9 -0
  66. package/dist/core/src/components/common/useScrollRestoration.d.ts +14 -0
  67. package/dist/core/src/components/index.d.ts +16 -0
  68. package/dist/core/src/contexts/AdminModeController.d.ts +4 -0
  69. package/dist/core/src/contexts/AnalyticsContext.d.ts +3 -0
  70. package/dist/core/src/contexts/AuthControllerContext.d.ts +3 -0
  71. package/dist/core/src/contexts/CustomizationControllerContext.d.ts +3 -0
  72. package/dist/core/src/contexts/DataDriverContext.d.ts +3 -0
  73. package/dist/core/src/contexts/DatabaseAdminContext.d.ts +3 -0
  74. package/dist/core/src/contexts/DialogsProvider.d.ts +4 -0
  75. package/dist/core/src/contexts/EffectiveRoleController.d.ts +4 -0
  76. package/dist/core/src/contexts/InternalUserManagementContext.d.ts +3 -0
  77. package/dist/core/src/contexts/ModeController.d.ts +4 -0
  78. package/dist/core/src/contexts/RebaseClientInstanceContext.d.ts +6 -0
  79. package/dist/core/src/contexts/RebaseDataContext.d.ts +3 -0
  80. package/dist/core/src/contexts/SnackbarProvider.d.ts +2 -0
  81. package/dist/core/src/contexts/StorageSourceContext.d.ts +3 -0
  82. package/dist/core/src/contexts/UserConfigurationPersistenceContext.d.ts +3 -0
  83. package/dist/core/src/contexts/index.d.ts +13 -0
  84. package/dist/core/src/core/PluginLifecycleManager.d.ts +17 -0
  85. package/dist/core/src/core/PluginProviderStack.d.ts +21 -0
  86. package/dist/core/src/core/Rebase.d.ts +14 -0
  87. package/dist/core/src/core/RebaseProps.d.ts +136 -0
  88. package/dist/core/src/core/RebaseRouter.d.ts +4 -0
  89. package/dist/core/src/core/RebaseRoutes.d.ts +17 -0
  90. package/dist/core/src/core/index.d.ts +4 -0
  91. package/dist/core/src/hooks/ApiConfigContext.d.ts +24 -0
  92. package/dist/core/src/hooks/data/delete.d.ts +31 -0
  93. package/dist/core/src/hooks/data/save.d.ts +34 -0
  94. package/dist/core/src/hooks/data/useCollectionFetch.d.ts +51 -0
  95. package/dist/core/src/hooks/data/useData.d.ts +13 -0
  96. package/dist/core/src/hooks/data/useDataOrder.d.ts +12 -0
  97. package/dist/core/src/hooks/data/useEntityFetch.d.ts +38 -0
  98. package/dist/core/src/hooks/data/useRelationSelector.d.ts +52 -0
  99. package/dist/core/src/hooks/data/useUserSelector.d.ts +31 -0
  100. package/dist/core/src/hooks/index.d.ts +37 -0
  101. package/dist/core/src/hooks/useAdminModeController.d.ts +19 -0
  102. package/dist/core/src/hooks/useAnalyticsController.d.ts +5 -0
  103. package/dist/core/src/hooks/useAuthController.d.ts +11 -0
  104. package/dist/core/src/hooks/useAuthSubscription.d.ts +2 -0
  105. package/dist/core/src/hooks/useBackendStorageSource.d.ts +30 -0
  106. package/dist/core/src/hooks/useBridgeRegistration.d.ts +18 -0
  107. package/dist/core/src/hooks/useBrowserTitleAndIcon.d.ts +6 -0
  108. package/dist/core/src/hooks/useBuildAdminModeController.d.ts +6 -0
  109. package/dist/core/src/hooks/useBuildEffectiveRoleController.d.ts +8 -0
  110. package/dist/core/src/hooks/useBuildLocalConfigurationPersistence.d.ts +2 -0
  111. package/dist/core/src/hooks/useBuildModeController.d.ts +6 -0
  112. package/dist/core/src/hooks/useClipboard.d.ts +57 -0
  113. package/dist/core/src/hooks/useCollapsedGroups.d.ts +12 -0
  114. package/dist/core/src/hooks/useCustomizationController.d.ts +11 -0
  115. package/dist/core/src/hooks/useDialogsController.d.ts +11 -0
  116. package/dist/core/src/hooks/useEffectiveRoleController.d.ts +7 -0
  117. package/dist/core/src/hooks/useInternalUserManagementController.d.ts +12 -0
  118. package/dist/core/src/hooks/useLargeLayout.d.ts +1 -0
  119. package/dist/core/src/hooks/useModeController.d.ts +19 -0
  120. package/dist/core/src/hooks/usePermissions.d.ts +12 -0
  121. package/dist/core/src/hooks/useRebaseClient.d.ts +5 -0
  122. package/dist/core/src/hooks/useRebaseContext.d.ts +11 -0
  123. package/dist/core/src/hooks/useRebaseRegistry.d.ts +34 -0
  124. package/dist/core/src/hooks/useSlot.d.ts +18 -0
  125. package/dist/core/src/hooks/useSnackbarController.d.ts +20 -0
  126. package/dist/core/src/hooks/useStorageSource.d.ts +7 -0
  127. package/dist/core/src/hooks/useStudioBridge.d.ts +91 -0
  128. package/dist/core/src/hooks/useTranslation.d.ts +17 -0
  129. package/dist/core/src/hooks/useUnsavedChangesDialog.d.ts +12 -0
  130. package/dist/core/src/hooks/useUserConfigurationPersistence.d.ts +8 -0
  131. package/dist/core/src/hooks/useValidateAuthenticator.d.ts +21 -0
  132. package/dist/core/src/i18n/RebaseI18nProvider.d.ts +33 -0
  133. package/dist/core/src/index.d.ts +15 -0
  134. package/dist/core/src/internal/common.d.ts +3 -0
  135. package/dist/core/src/internal/useRestoreScroll.d.ts +6 -0
  136. package/dist/core/src/locales/de.d.ts +2 -0
  137. package/dist/core/src/locales/en.d.ts +10 -0
  138. package/dist/core/src/locales/es.d.ts +10 -0
  139. package/dist/core/src/locales/fr.d.ts +2 -0
  140. package/dist/core/src/locales/hi.d.ts +2 -0
  141. package/dist/core/src/locales/it.d.ts +2 -0
  142. package/dist/core/src/locales/pt.d.ts +7 -0
  143. package/dist/core/src/util/constants.d.ts +1 -0
  144. package/dist/core/src/util/createFormexStub.d.ts +2 -0
  145. package/dist/core/src/util/entity_cache.d.ts +27 -0
  146. package/dist/core/src/util/enums.d.ts +5 -0
  147. package/dist/core/src/util/icon_list.d.ts +5 -0
  148. package/dist/core/src/util/icon_synonyms.d.ts +1 -0
  149. package/dist/core/src/util/icons.d.ts +20 -0
  150. package/dist/core/src/util/index.d.ts +10 -0
  151. package/dist/core/src/util/previews.d.ts +4 -0
  152. package/dist/core/src/util/useStorageUploadController.d.ts +38 -0
  153. package/dist/core/src/util/useTraceUpdate.d.ts +2 -0
  154. package/dist/formex/src/Field.d.ts +52 -0
  155. package/dist/formex/src/Formex.d.ts +7 -0
  156. package/dist/formex/src/index.d.ts +5 -0
  157. package/dist/formex/src/types.d.ts +40 -0
  158. package/dist/formex/src/useCreateFormex.d.ts +14 -0
  159. package/dist/formex/src/utils.d.ts +16 -0
  160. package/dist/index.es.js +726 -0
  161. package/dist/index.es.js.map +1 -0
  162. package/dist/index.umd.js +9647 -0
  163. package/dist/index.umd.js.map +1 -0
  164. package/dist/studio/src/components/ApiExplorer/ApiExplorer.d.ts +9 -0
  165. package/dist/studio/src/components/ApiExplorer/EndpointDetail.d.ts +9 -0
  166. package/dist/studio/src/components/ApiExplorer/TryItPanel.d.ts +15 -0
  167. package/dist/studio/src/components/ApiExplorer/parseSpec.d.ts +16 -0
  168. package/dist/studio/src/components/ApiExplorer/types.d.ts +90 -0
  169. package/dist/studio/src/components/AuthSimulationSelector.d.ts +11 -0
  170. package/dist/studio/src/components/Branches/BranchesView.d.ts +1 -0
  171. package/dist/studio/src/components/CronJobs/CronJobsView.d.ts +1 -0
  172. package/dist/studio/src/components/JSEditor/JSEditor.d.ts +1 -0
  173. package/dist/studio/src/components/JSEditor/JSEditorSidebar.d.ts +21 -0
  174. package/dist/studio/src/components/JSEditor/JSMonacoEditor.d.ts +18 -0
  175. package/dist/studio/src/components/RLSEditor/PolicyEditor.d.ts +9 -0
  176. package/dist/studio/src/components/RLSEditor/RLSEditor.d.ts +19 -0
  177. package/dist/studio/src/components/RLSEditor/index.d.ts +1 -0
  178. package/dist/studio/src/components/RebaseStudio.d.ts +2 -0
  179. package/dist/studio/src/components/SQLEditor/ExplainVisualizer.d.ts +24 -0
  180. package/dist/studio/src/components/SQLEditor/MonacoEditor.d.ts +17 -0
  181. package/dist/studio/src/components/SQLEditor/SQLEditor.d.ts +11 -0
  182. package/dist/studio/src/components/SQLEditor/SQLEditorSidebar.d.ts +21 -0
  183. package/dist/studio/src/components/SQLEditor/SchemaBrowser.d.ts +8 -0
  184. package/dist/studio/src/components/SchemaVisualizer/RelationEdge.d.ts +3 -0
  185. package/dist/studio/src/components/SchemaVisualizer/SchemaVisualizer.d.ts +2 -0
  186. package/dist/studio/src/components/SchemaVisualizer/TableNode.d.ts +3 -0
  187. package/dist/studio/src/components/SchemaVisualizer/index.d.ts +5 -0
  188. package/dist/studio/src/components/SchemaVisualizer/schema-visualizer.utils.d.ts +42 -0
  189. package/dist/studio/src/components/SchemaVisualizer/useSchemaGraph.d.ts +37 -0
  190. package/dist/studio/src/components/StorageView/StorageView.d.ts +1 -0
  191. package/dist/studio/src/components/StudioHomePage.d.ts +9 -0
  192. package/dist/studio/src/index.d.ts +4 -0
  193. package/dist/studio/src/utils/entities.d.ts +0 -0
  194. package/dist/studio/src/utils/pgColumnToProperty.d.ts +6 -0
  195. package/dist/studio/src/utils/sql_utils.d.ts +52 -0
  196. package/dist/types/src/controllers/analytics_controller.d.ts +7 -0
  197. package/dist/types/src/controllers/auth.d.ts +119 -0
  198. package/dist/types/src/controllers/client.d.ts +170 -0
  199. package/dist/types/src/controllers/collection_registry.d.ts +45 -0
  200. package/dist/types/src/controllers/customization_controller.d.ts +60 -0
  201. package/dist/types/src/controllers/data.d.ts +168 -0
  202. package/dist/types/src/controllers/data_driver.d.ts +160 -0
  203. package/dist/types/src/controllers/database_admin.d.ts +11 -0
  204. package/dist/types/src/controllers/dialogs_controller.d.ts +36 -0
  205. package/dist/types/src/controllers/effective_role.d.ts +4 -0
  206. package/dist/types/src/controllers/email.d.ts +34 -0
  207. package/dist/types/src/controllers/index.d.ts +18 -0
  208. package/dist/types/src/controllers/local_config_persistence.d.ts +20 -0
  209. package/dist/types/src/controllers/navigation.d.ts +213 -0
  210. package/dist/types/src/controllers/registry.d.ts +54 -0
  211. package/dist/types/src/controllers/side_dialogs_controller.d.ts +67 -0
  212. package/dist/types/src/controllers/side_entity_controller.d.ts +90 -0
  213. package/dist/types/src/controllers/snackbar.d.ts +24 -0
  214. package/dist/types/src/controllers/storage.d.ts +171 -0
  215. package/dist/types/src/index.d.ts +4 -0
  216. package/dist/types/src/rebase_context.d.ts +105 -0
  217. package/dist/types/src/types/backend.d.ts +536 -0
  218. package/dist/types/src/types/builders.d.ts +15 -0
  219. package/dist/types/src/types/chips.d.ts +5 -0
  220. package/dist/types/src/types/collections.d.ts +856 -0
  221. package/dist/types/src/types/cron.d.ts +102 -0
  222. package/dist/types/src/types/data_source.d.ts +64 -0
  223. package/dist/types/src/types/entities.d.ts +145 -0
  224. package/dist/types/src/types/entity_actions.d.ts +98 -0
  225. package/dist/types/src/types/entity_callbacks.d.ts +173 -0
  226. package/dist/types/src/types/entity_link_builder.d.ts +7 -0
  227. package/dist/types/src/types/entity_overrides.d.ts +10 -0
  228. package/dist/types/src/types/entity_views.d.ts +61 -0
  229. package/dist/types/src/types/export_import.d.ts +21 -0
  230. package/dist/types/src/types/index.d.ts +23 -0
  231. package/dist/types/src/types/locales.d.ts +4 -0
  232. package/dist/types/src/types/modify_collections.d.ts +5 -0
  233. package/dist/types/src/types/plugins.d.ts +279 -0
  234. package/dist/types/src/types/properties.d.ts +1176 -0
  235. package/dist/types/src/types/property_config.d.ts +70 -0
  236. package/dist/types/src/types/relations.d.ts +336 -0
  237. package/dist/types/src/types/slots.d.ts +252 -0
  238. package/dist/types/src/types/translations.d.ts +870 -0
  239. package/dist/types/src/types/user_management_delegate.d.ts +121 -0
  240. package/dist/types/src/types/websockets.d.ts +78 -0
  241. package/dist/types/src/users/index.d.ts +2 -0
  242. package/dist/types/src/users/roles.d.ts +22 -0
  243. package/dist/types/src/users/user.d.ts +46 -0
  244. package/dist/ui/src/components/Alert.d.ts +12 -0
  245. package/dist/ui/src/components/Autocomplete.d.ts +21 -0
  246. package/dist/ui/src/components/Avatar.d.ts +11 -0
  247. package/dist/ui/src/components/Badge.d.ts +8 -0
  248. package/dist/ui/src/components/BooleanSwitch.d.ts +14 -0
  249. package/dist/ui/src/components/BooleanSwitchWithLabel.d.ts +17 -0
  250. package/dist/ui/src/components/Button.d.ts +14 -0
  251. package/dist/ui/src/components/Card.d.ts +9 -0
  252. package/dist/ui/src/components/CenteredView.d.ts +9 -0
  253. package/dist/ui/src/components/Checkbox.d.ts +13 -0
  254. package/dist/ui/src/components/Chip.d.ts +26 -0
  255. package/dist/ui/src/components/CircularProgress.d.ts +5 -0
  256. package/dist/ui/src/components/CircularProgressCenter.d.ts +11 -0
  257. package/dist/ui/src/components/Collapse.d.ts +9 -0
  258. package/dist/ui/src/components/ColorPicker.d.ts +30 -0
  259. package/dist/ui/src/components/Container.d.ts +8 -0
  260. package/dist/ui/src/components/DateTimeField.d.ts +24 -0
  261. package/dist/ui/src/components/DebouncedTextField.d.ts +2 -0
  262. package/dist/ui/src/components/Dialog.d.ts +39 -0
  263. package/dist/ui/src/components/DialogActions.d.ts +7 -0
  264. package/dist/ui/src/components/DialogContent.d.ts +7 -0
  265. package/dist/ui/src/components/DialogTitle.d.ts +10 -0
  266. package/dist/ui/src/components/ErrorBoundary.d.ts +11 -0
  267. package/dist/ui/src/components/ExpandablePanel.d.ts +12 -0
  268. package/dist/ui/src/components/FileUpload.d.ts +23 -0
  269. package/dist/ui/src/components/IconButton.d.ts +12 -0
  270. package/dist/ui/src/components/InfoLabel.d.ts +5 -0
  271. package/dist/ui/src/components/InputLabel.d.ts +11 -0
  272. package/dist/ui/src/components/Label.d.ts +7 -0
  273. package/dist/ui/src/components/LoadingButton.d.ts +7 -0
  274. package/dist/ui/src/components/Markdown.d.ts +10 -0
  275. package/dist/ui/src/components/Menu.d.ts +23 -0
  276. package/dist/ui/src/components/Menubar.d.ts +80 -0
  277. package/dist/ui/src/components/MultiSelect.d.ts +48 -0
  278. package/dist/ui/src/components/Paper.d.ts +6 -0
  279. package/dist/ui/src/components/Popover.d.ts +24 -0
  280. package/dist/ui/src/components/RadioGroup.d.ts +28 -0
  281. package/dist/ui/src/components/ResizablePanels.d.ts +18 -0
  282. package/dist/ui/src/components/SearchBar.d.ts +22 -0
  283. package/dist/ui/src/components/Select.d.ts +43 -0
  284. package/dist/ui/src/components/Separator.d.ts +5 -0
  285. package/dist/ui/src/components/Sheet.d.ts +22 -0
  286. package/dist/ui/src/components/Skeleton.d.ts +6 -0
  287. package/dist/ui/src/components/Slider.d.ts +21 -0
  288. package/dist/ui/src/components/Table.d.ts +34 -0
  289. package/dist/ui/src/components/Tabs.d.ts +19 -0
  290. package/dist/ui/src/components/TextField.d.ts +58 -0
  291. package/dist/ui/src/components/TextareaAutosize.d.ts +43 -0
  292. package/dist/ui/src/components/ToggleButtonGroup.d.ts +30 -0
  293. package/dist/ui/src/components/Tooltip.d.ts +19 -0
  294. package/dist/ui/src/components/Typography.d.ts +36 -0
  295. package/dist/ui/src/components/VirtualTable/VirtualTable.d.ts +11 -0
  296. package/dist/ui/src/components/VirtualTable/VirtualTableCell.d.ts +21 -0
  297. package/dist/ui/src/components/VirtualTable/VirtualTableHeader.d.ts +29 -0
  298. package/dist/ui/src/components/VirtualTable/VirtualTableHeaderRow.d.ts +2 -0
  299. package/dist/ui/src/components/VirtualTable/VirtualTableProps.d.ts +243 -0
  300. package/dist/ui/src/components/VirtualTable/VirtualTableRow.d.ts +3 -0
  301. package/dist/ui/src/components/VirtualTable/index.d.ts +3 -0
  302. package/dist/ui/src/components/VirtualTable/types.d.ts +38 -0
  303. package/dist/ui/src/components/common/SelectInputLabel.d.ts +5 -0
  304. package/dist/ui/src/components/index.d.ts +53 -0
  305. package/dist/ui/src/hooks/PortalContainerContext.d.ts +31 -0
  306. package/dist/ui/src/hooks/index.d.ts +6 -0
  307. package/dist/ui/src/hooks/useDebounceCallback.d.ts +1 -0
  308. package/dist/ui/src/hooks/useDebounceValue.d.ts +1 -0
  309. package/dist/ui/src/hooks/useDebouncedCallback.d.ts +1 -0
  310. package/dist/ui/src/hooks/useInjectStyles.d.ts +7 -0
  311. package/dist/ui/src/hooks/useOutsideAlerter.d.ts +5 -0
  312. package/dist/ui/src/icons/GitHubIcon.d.ts +2 -0
  313. package/dist/ui/src/icons/HandleIcon.d.ts +1 -0
  314. package/dist/ui/src/icons/Icon.d.ts +20 -0
  315. package/dist/ui/src/icons/cool_icon_keys.d.ts +1 -0
  316. package/dist/ui/src/icons/icon_keys.d.ts +1 -0
  317. package/dist/ui/src/icons/index.d.ts +6 -0
  318. package/dist/ui/src/index.d.ts +5 -0
  319. package/dist/ui/src/styles.d.ts +12 -0
  320. package/dist/ui/src/util/chip_colors.d.ts +4 -0
  321. package/dist/ui/src/util/cls.d.ts +2 -0
  322. package/dist/ui/src/util/debounce.d.ts +10 -0
  323. package/dist/ui/src/util/hash.d.ts +1 -0
  324. package/dist/ui/src/util/index.d.ts +4 -0
  325. package/dist/ui/src/util/key_to_icon_component.d.ts +1 -0
  326. package/package.json +84 -0
  327. package/src/components/ApiExplorer/ApiExplorer.tsx +290 -0
  328. package/src/components/ApiExplorer/EndpointDetail.tsx +271 -0
  329. package/src/components/ApiExplorer/TryItPanel.tsx +510 -0
  330. package/src/components/ApiExplorer/parseSpec.ts +104 -0
  331. package/src/components/ApiExplorer/types.ts +84 -0
  332. package/src/components/AuthSimulationSelector.tsx +77 -0
  333. package/src/components/Branches/BranchesView.tsx +370 -0
  334. package/src/components/CronJobs/CronJobsView.tsx +346 -0
  335. package/src/components/JSEditor/JSEditor.tsx +1033 -0
  336. package/src/components/JSEditor/JSEditorSidebar.tsx +340 -0
  337. package/src/components/JSEditor/JSMonacoEditor.tsx +390 -0
  338. package/src/components/RLSEditor/PolicyEditor.tsx +444 -0
  339. package/src/components/RLSEditor/RLSEditor.tsx +692 -0
  340. package/src/components/RLSEditor/index.ts +1 -0
  341. package/src/components/RebaseStudio.tsx +121 -0
  342. package/src/components/SQLEditor/ExplainVisualizer.tsx +128 -0
  343. package/src/components/SQLEditor/MonacoEditor.tsx +203 -0
  344. package/src/components/SQLEditor/SQLEditor.tsx +1419 -0
  345. package/src/components/SQLEditor/SQLEditorSidebar.tsx +174 -0
  346. package/src/components/SQLEditor/SchemaBrowser.tsx +158 -0
  347. package/src/components/SchemaVisualizer/RelationEdge.tsx +102 -0
  348. package/src/components/SchemaVisualizer/SchemaVisualizer.tsx +665 -0
  349. package/src/components/SchemaVisualizer/TableNode.tsx +257 -0
  350. package/src/components/SchemaVisualizer/index.ts +5 -0
  351. package/src/components/SchemaVisualizer/schema-visualizer.utils.ts +140 -0
  352. package/src/components/SchemaVisualizer/useSchemaGraph.ts +397 -0
  353. package/src/components/StorageView/StorageView.tsx +1035 -0
  354. package/src/components/StudioHomePage.tsx +357 -0
  355. package/src/index.ts +31 -0
  356. package/src/utils/entities.ts +2 -0
  357. package/src/utils/pgColumnToProperty.test.ts +401 -0
  358. package/src/utils/pgColumnToProperty.ts +275 -0
  359. package/src/utils/sql_utils.test.ts +265 -0
  360. package/src/utils/sql_utils.ts +291 -0
  361. package/src/vite-env.d.ts +1 -0
package/package.json ADDED
@@ -0,0 +1,84 @@
1
+ {
2
+ "name": "@rebasepro/studio",
3
+ "type": "module",
4
+ "version": "0.0.1-canary.09e5ec5",
5
+ "main": "./dist/index.umd.js",
6
+ "module": "./dist/index.es.js",
7
+ "types": "dist/index.d.ts",
8
+ "source": "src/index.ts",
9
+ "dependencies": {
10
+ "@monaco-editor/react": "^4.7.0",
11
+ "@types/dagre": "0.7.54",
12
+ "@xyflow/react": "12.10.2",
13
+ "dagre": "0.8.5",
14
+ "pgsql-ast-parser": "12.0.2",
15
+ "prism-react-renderer": "^2.4.1",
16
+ "@rebasepro/client": "0.0.1-canary.09e5ec5",
17
+ "@rebasepro/common": "0.0.1-canary.09e5ec5",
18
+ "@rebasepro/types": "0.0.1-canary.09e5ec5",
19
+ "@rebasepro/ui": "0.0.1-canary.09e5ec5",
20
+ "@rebasepro/utils": "0.0.1-canary.09e5ec5",
21
+ "@rebasepro/core": "0.0.1-canary.09e5ec5"
22
+ },
23
+ "peerDependencies": {
24
+ "react": ">=19.0.0",
25
+ "react-dom": ">=19.0.0",
26
+ "react-router": "^7.0.0",
27
+ "react-router-dom": "^7.0.0",
28
+ "@rebasepro/admin": "0.0.1-canary.09e5ec5"
29
+ },
30
+ "peerDependenciesMeta": {
31
+ "@rebasepro/admin": {
32
+ "optional": true
33
+ }
34
+ },
35
+ "exports": {
36
+ ".": {
37
+ "types": "./dist/index.d.ts",
38
+ "development": "./src/index.ts",
39
+ "import": "./dist/index.es.js",
40
+ "require": "./dist/index.umd.js"
41
+ },
42
+ "./package.json": "./package.json"
43
+ },
44
+ "browserslist": {
45
+ "production": [
46
+ ">0.2%",
47
+ "not dead",
48
+ "not op_mini all"
49
+ ],
50
+ "development": [
51
+ "last 1 chrome version",
52
+ "last 1 firefox version",
53
+ "last 1 safari version"
54
+ ]
55
+ },
56
+ "devDependencies": {
57
+ "@jest/globals": "^30.2.0",
58
+ "@types/react": "^19.0.8",
59
+ "@types/react-dom": "^19.0.3",
60
+ "@vitejs/plugin-react": "^4.7.0",
61
+ "babel-plugin-react-compiler": "^19.0.0-beta-af1b7da-20250417",
62
+ "eslint-plugin-react-compiler": "^19.1.0-rc.2",
63
+ "jest": "^29.7.0",
64
+ "react-router": "^7.13.1",
65
+ "react-router-dom": "^7.13.1",
66
+ "ts-jest": "^29.4.5",
67
+ "typescript": "^5.9.3",
68
+ "vite": "^7.2.4"
69
+ },
70
+ "files": [
71
+ "dist",
72
+ "src"
73
+ ],
74
+ "publishConfig": {
75
+ "access": "public"
76
+ },
77
+ "gitHead": "9ecf37abf793bd2f2daaaed6f517ee5ee19b01ae",
78
+ "scripts": {
79
+ "dev": "vite",
80
+ "test": "jest --passWithNoTests",
81
+ "build": "vite build && tsc --emitDeclarationOnly -p tsconfig.prod.json",
82
+ "clean": "rm -rf dist && find ./src -name '*.js' -type f | xargs rm -f"
83
+ }
84
+ }
@@ -0,0 +1,290 @@
1
+ import React, { useState, useEffect, useMemo } from "react";
2
+ import { useApiConfig, useAuthController } from "@rebasepro/core";
3
+ import {
4
+ CircularProgress,
5
+ Typography,
6
+ Alert,
7
+ cls,
8
+ Button,
9
+ Chip,
10
+ defaultBorderMixin,
11
+ SearchBar,
12
+ iconSize
13
+ } from "@rebasepro/ui";
14
+ import { BookOpenIcon, PlayIcon } from "lucide-react";
15
+ import { EndpointDetail } from "./EndpointDetail";
16
+ import { TryItPanel } from "./TryItPanel";
17
+ import type { OpenApiSpec, ParsedEndpoint } from "./types";
18
+ import { parseOpenApiSpec } from "./parseSpec";
19
+
20
+ /**
21
+ * Custom-built API Explorer for Rebase Studio.
22
+ * No external dependencies — renders the OpenAPI spec natively
23
+ * with deep integration into the Rebase auth system.
24
+ */
25
+ export function ApiExplorer() {
26
+ const apiConfig = useApiConfig();
27
+ const authController = useAuthController();
28
+ const apiUrl = apiConfig?.apiUrl;
29
+
30
+ const [spec, setSpec] = useState<OpenApiSpec | null>(null);
31
+ const [loading, setLoading] = useState(true);
32
+ const [error, setError] = useState<string | null>(null);
33
+
34
+ const [selectedEndpoint, setSelectedEndpoint] = useState<ParsedEndpoint | null>(null);
35
+ const [sidebarFilter, setSidebarFilter] = useState("");
36
+ const [tryItOpen, setTryItOpen] = useState(false);
37
+
38
+ // Fetch OpenAPI spec
39
+ useEffect(() => {
40
+ if (!apiUrl) return;
41
+ let cancelled = false;
42
+ const specUrl = `${apiUrl.replace(/\/+$/, "")}/api/docs`;
43
+
44
+ (async () => {
45
+ try {
46
+ const res = await fetch(specUrl);
47
+ if (!res.ok) throw new Error(`${res.status} ${res.statusText}`);
48
+ const data = await res.json();
49
+ if (!cancelled) {
50
+ setSpec(data);
51
+ setLoading(false);
52
+ }
53
+ } catch (err: any) {
54
+ if (!cancelled) {
55
+ setError(err.message ?? "Failed to load API spec");
56
+ setLoading(false);
57
+ }
58
+ }
59
+ })();
60
+ return () => {
61
+ cancelled = true;
62
+ };
63
+ }, [apiUrl]);
64
+
65
+ // Parse spec into grouped endpoints
66
+ const { groups, allEndpoints } = useMemo(() => {
67
+ if (!spec) return { groups: [],
68
+ allEndpoints: [] };
69
+ return parseOpenApiSpec(spec);
70
+ }, [spec]);
71
+
72
+ // Filter
73
+ const filteredGroups = useMemo(() => {
74
+ if (!sidebarFilter.trim()) return groups;
75
+ const q = sidebarFilter.toLowerCase();
76
+ return groups
77
+ .map((g) => ({
78
+ ...g,
79
+ endpoints: g.endpoints.filter(
80
+ (e) =>
81
+ e.path.toLowerCase().includes(q) ||
82
+ e.summary.toLowerCase().includes(q) ||
83
+ e.method.toLowerCase().includes(q)
84
+ )
85
+ }))
86
+ .filter((g) => g.endpoints.length > 0);
87
+ }, [groups, sidebarFilter]);
88
+
89
+ // Auto-select first endpoint
90
+ useEffect(() => {
91
+ if (!selectedEndpoint && allEndpoints.length > 0) {
92
+ setSelectedEndpoint(allEndpoints[0]);
93
+ }
94
+ }, [allEndpoints, selectedEndpoint]);
95
+
96
+ // ── States ───────────────────────────────────────────────────────
97
+ if (!apiUrl) {
98
+ return (
99
+ <div className="flex items-center justify-center h-full w-full p-8">
100
+ <Alert color="warning">
101
+ <Typography variant="body2">
102
+ No API URL configured. Ensure your app provides an{" "}
103
+ <code className="font-mono text-xs">apiUrl</code>.
104
+ </Typography>
105
+ </Alert>
106
+ </div>
107
+ );
108
+ }
109
+
110
+ if (loading) {
111
+ return (
112
+ <div className="flex flex-col items-center justify-center h-full w-full gap-4">
113
+ <CircularProgress size="medium"/>
114
+ <Typography variant="body2" className="text-text-secondary dark:text-text-secondary-dark animate-pulse">
115
+ Loading API specification…
116
+ </Typography>
117
+ </div>
118
+ );
119
+ }
120
+
121
+ if (error || !spec) {
122
+ return (
123
+ <div className="flex items-center justify-center h-full w-full p-8">
124
+ <Alert color="error">
125
+ <Typography variant="body2">{error ?? "Unknown error"}</Typography>
126
+ </Alert>
127
+ </div>
128
+ );
129
+ }
130
+
131
+ const METHOD_COLORS: Record<string, string> = {
132
+ get: "text-blue-600 dark:text-blue-400",
133
+ post: "text-emerald-600 dark:text-emerald-400",
134
+ put: "text-amber-600 dark:text-amber-400",
135
+ patch: "text-orange-600 dark:text-orange-400",
136
+ delete: "text-red-600 dark:text-red-400"
137
+ };
138
+
139
+ return (
140
+ <div className="flex h-full w-full overflow-hidden">
141
+ {/* ── Sidebar ──────────────────────────────────────── */}
142
+ <div
143
+ className={cls(
144
+ "w-72 min-w-[272px] flex flex-col h-full overflow-hidden border-r",
145
+ defaultBorderMixin,
146
+ "bg-surface-50 dark:bg-surface-900"
147
+ )}
148
+ >
149
+ {/* Header */}
150
+ <div className="p-4 space-y-3">
151
+ <div className="flex items-center gap-2">
152
+ <BookOpenIcon size={iconSize.medium} className="text-primary dark:text-primary-dark" />
153
+ <Typography variant="subtitle2" className="font-semibold">
154
+ {spec.info?.title ?? "API Reference"}
155
+ </Typography>
156
+ </div>
157
+ {spec.info?.version && (
158
+ <Chip size="smallest" colorScheme="cyanDarker">
159
+ v{spec.info.version}
160
+ </Chip>
161
+ )}
162
+ {/* Search */}
163
+ <div className="mb-2">
164
+ <SearchBar
165
+ placeholder="Filter endpoints…"
166
+ size="small"
167
+ onTextSearch={(val) => setSidebarFilter(val || "")}
168
+ />
169
+ </div>
170
+
171
+ {/* Auth status removed to avoid redundancy with the AuthSimulationSelector */}
172
+ </div>
173
+
174
+ {/* Endpoint list */}
175
+ <div className="flex-1 overflow-y-auto px-2 pb-4">
176
+ {filteredGroups.map((group) => (
177
+ <div key={group.tag} className="mb-3">
178
+ <Typography
179
+ variant="caption"
180
+ className="px-2 py-1.5 text-text-secondary dark:text-text-secondary-dark uppercase tracking-wider font-semibold text-[10px]"
181
+ >
182
+ {group.tag}
183
+ </Typography>
184
+ {group.endpoints.map((ep) => {
185
+ const isSelected = selectedEndpoint?.id === ep.id;
186
+ return (
187
+ <button
188
+ key={ep.id}
189
+ onClick={() => {
190
+ setSelectedEndpoint(ep);
191
+ setTryItOpen(false);
192
+ }}
193
+ className={cls(
194
+ "w-full flex items-center justify-between gap-2 px-2.5 py-1.5 rounded-lg text-left text-sm transition-all",
195
+ "hover:bg-surface-200 dark:hover:bg-surface-800",
196
+ isSelected
197
+ ? "bg-surface-200 dark:bg-surface-800 font-medium"
198
+ : "text-text-primary dark:text-text-primary-dark"
199
+ )}
200
+ >
201
+ <span className="truncate text-[13px] opacity-90">{ep.summary || ep.shortPath}</span>
202
+ <span
203
+ className={cls(
204
+ "text-[10px] font-bold uppercase shrink-0",
205
+ METHOD_COLORS[ep.method] ?? "text-text-secondary"
206
+ )}
207
+ >
208
+ {ep.method}
209
+ </span>
210
+ </button>
211
+ );
212
+ })}
213
+ </div>
214
+ ))}
215
+ {filteredGroups.length === 0 && (
216
+ <Typography
217
+ variant="body2"
218
+ className="text-center text-text-secondary dark:text-text-secondary-dark py-8"
219
+ >
220
+ No endpoints match
221
+ </Typography>
222
+ )}
223
+ </div>
224
+ </div>
225
+
226
+ {/* ── Main content ─────────────────────────────────── */}
227
+ <div className="flex-1 flex flex-col h-full overflow-hidden">
228
+ {selectedEndpoint ? (
229
+ <>
230
+ {/* Top bar */}
231
+ <div
232
+ className={cls(
233
+ "flex items-center justify-between px-5 py-3 gap-4 shrink-0 border-b z-10",
234
+ defaultBorderMixin,
235
+ "bg-surface-50/80 dark:bg-surface-950/80 backdrop-blur-md sticky top-0"
236
+ )}
237
+ >
238
+ <div className="flex items-center gap-3 min-w-0">
239
+ <span
240
+ className={cls(
241
+ "text-xs font-bold uppercase",
242
+ METHOD_COLORS[selectedEndpoint.method] ?? ""
243
+ )}
244
+ >
245
+ {selectedEndpoint.method}
246
+ </span>
247
+ <code className="text-sm font-mono text-text-primary dark:text-text-primary-dark truncate">
248
+ {selectedEndpoint.path}
249
+ </code>
250
+ </div>
251
+ <Button
252
+ variant={tryItOpen ? "filled" : "outlined"}
253
+ size="small"
254
+ onClick={() => setTryItOpen((v) => !v)}
255
+ >
256
+ <PlayIcon size={iconSize.small} className="mr-1" />
257
+ Try It
258
+ </Button>
259
+ </div>
260
+
261
+ {/* Body */}
262
+ <div className="flex-1 overflow-y-auto">
263
+ {tryItOpen ? (
264
+ <TryItPanel
265
+ key={selectedEndpoint.operationId || selectedEndpoint.path}
266
+ endpoint={selectedEndpoint}
267
+ apiUrl={apiUrl}
268
+ getAuthToken={apiConfig?.getAuthToken ?? authController.getAuthToken}
269
+ user={authController.user}
270
+ basePath={spec?.servers?.[0]?.url || ""}
271
+ />
272
+ ) : (
273
+ <EndpointDetail endpoint={selectedEndpoint} spec={spec}/>
274
+ )}
275
+ </div>
276
+ </>
277
+ ) : (
278
+ <div className="flex items-center justify-center h-full">
279
+ <Typography variant="body2" className="text-text-secondary dark:text-text-secondary-dark">
280
+ Select an endpoint from the sidebar
281
+ </Typography>
282
+ </div>
283
+ )}
284
+ </div>
285
+ </div>
286
+ );
287
+ }
288
+
289
+ ApiExplorer.displayName = "ApiExplorer";
290
+
@@ -0,0 +1,271 @@
1
+ import React from "react";
2
+ import { Typography, Chip, cls, defaultBorderMixin, iconSize } from "@rebasepro/ui";
3
+ import { SlidersHorizontalIcon, UploadIcon, ArrowRightFromLineIcon } from "lucide-react";
4
+ import type { ParsedEndpoint, OpenApiSpec, OpenApiSchema } from "./types";
5
+ import { resolveRef, resolveRefName } from "./parseSpec";
6
+
7
+ /**
8
+ * Renders the documentation view for a single API endpoint:
9
+ * parameters, request body schema, response schemas.
10
+ */
11
+ export function EndpointDetail({ endpoint, spec }: { endpoint: ParsedEndpoint; spec: OpenApiSpec }) {
12
+ return (
13
+ <div className="p-6 space-y-8 max-w-4xl">
14
+ {/* Summary / Description */}
15
+ {(endpoint.summary || endpoint.description) && (
16
+ <div>
17
+ {endpoint.summary && (
18
+ <Typography variant="h6" className="font-semibold mb-1">
19
+ {endpoint.summary}
20
+ </Typography>
21
+ )}
22
+ {endpoint.description && (
23
+ <Typography variant="body2" className="text-text-secondary dark:text-text-secondary-dark">
24
+ {endpoint.description}
25
+ </Typography>
26
+ )}
27
+ </div>
28
+ )}
29
+
30
+ {/* Parameters */}
31
+ {endpoint.parameters.length > 0 && (
32
+ <section>
33
+ <SectionHeading icon={<SlidersHorizontalIcon size={iconSize.small} className="text-text-secondary dark:text-text-secondary-dark" />} title="Parameters"/>
34
+ <div className={cls("rounded-lg border overflow-hidden", defaultBorderMixin)}>
35
+ <table className="w-full text-sm">
36
+ <thead>
37
+ <tr className="bg-surface-100 dark:bg-surface-900 text-left">
38
+ <th className="px-4 py-2 font-medium text-text-secondary dark:text-text-secondary-dark">
39
+ Name
40
+ </th>
41
+ <th className="px-4 py-2 font-medium text-text-secondary dark:text-text-secondary-dark">
42
+ In
43
+ </th>
44
+ <th className="px-4 py-2 font-medium text-text-secondary dark:text-text-secondary-dark">
45
+ Type
46
+ </th>
47
+ <th className="px-4 py-2 font-medium text-text-secondary dark:text-text-secondary-dark">
48
+ Description
49
+ </th>
50
+ </tr>
51
+ </thead>
52
+ <tbody>
53
+ {endpoint.parameters.map((p, i) => (
54
+ <tr
55
+ key={p.name + i}
56
+ className={cls("border-t", defaultBorderMixin)}
57
+ >
58
+ <td className="px-4 py-2.5">
59
+ <code className="text-xs font-mono font-semibold">{p.name}</code>
60
+ {p.required && <span className="text-red-500 ml-1 text-xs">*</span>}
61
+ </td>
62
+ <td className="px-4 py-2.5">
63
+ <Chip
64
+ size="smallest"
65
+ colorScheme={p.in === "path" ? "orangeDarker" : "cyanDarker"}
66
+ >
67
+ {p.in}
68
+ </Chip>
69
+ </td>
70
+ <td className="px-4 py-2.5 text-xs font-mono text-text-secondary dark:text-text-secondary-dark">
71
+ {schemaTypeLabel(p.schema)}
72
+ </td>
73
+ <td className="px-4 py-2.5 text-xs text-text-secondary dark:text-text-secondary-dark">
74
+ {p.description ?? "—"}
75
+ </td>
76
+ </tr>
77
+ ))}
78
+ </tbody>
79
+ </table>
80
+ </div>
81
+ </section>
82
+ )}
83
+
84
+ {/* Request Body */}
85
+ {endpoint.requestBody && (
86
+ <section>
87
+ <SectionHeading icon={<UploadIcon size={iconSize.small} className="text-text-secondary dark:text-text-secondary-dark" />} title="Request Body"/>
88
+ {Object.entries(endpoint.requestBody.content ?? {}).map(([contentType, media]) => (
89
+ <div key={contentType}>
90
+ <Chip size="smallest" colorScheme="blueDarker" className="mb-3">
91
+ {contentType}
92
+ </Chip>
93
+ {media.schema && <SchemaBlock schema={media.schema} spec={spec} depth={0}/>}
94
+ </div>
95
+ ))}
96
+ </section>
97
+ )}
98
+
99
+ {/* Responses */}
100
+ <section>
101
+ <SectionHeading icon={<ArrowRightFromLineIcon size={iconSize.small} className="text-text-secondary dark:text-text-secondary-dark" />} title="Responses"/>
102
+ <div className="space-y-3">
103
+ {Object.entries(endpoint.responses).map(([code, res]) => (
104
+ <div
105
+ key={code}
106
+ className={cls("rounded-lg border overflow-hidden", defaultBorderMixin)}
107
+ >
108
+ <div
109
+ className={cls(
110
+ "flex items-center gap-3 px-4 py-2.5",
111
+ "bg-surface-50 dark:bg-surface-900/50"
112
+ )}
113
+ >
114
+ <StatusBadge code={code}/>
115
+ <Typography
116
+ variant="body2"
117
+ className="text-text-secondary dark:text-text-secondary-dark text-xs"
118
+ >
119
+ {res.description}
120
+ </Typography>
121
+ </div>
122
+ {res.content &&
123
+ Object.entries(res.content).map(
124
+ ([ct, media]) =>
125
+ media.schema && (
126
+ <div
127
+ key={ct}
128
+ className={cls("px-4 py-3 border-t", defaultBorderMixin)}
129
+ >
130
+ <SchemaBlock schema={media.schema} spec={spec} depth={0}/>
131
+ </div>
132
+ )
133
+ )}
134
+ </div>
135
+ ))}
136
+ </div>
137
+ </section>
138
+ </div>
139
+ );
140
+ }
141
+
142
+ /* ── Schema Block ─────────────────────────────────────────────────── */
143
+
144
+ function SchemaBlock({ schema, spec, depth }: { schema: OpenApiSchema; spec: OpenApiSpec; depth: number }) {
145
+ // Resolve $ref
146
+ if (schema.$ref) {
147
+ const name = resolveRefName(schema.$ref);
148
+ const resolved = resolveRef(spec, schema.$ref);
149
+ return (
150
+ <div>
151
+ <Typography
152
+ variant="caption"
153
+ className="text-primary dark:text-primary-dark font-mono text-xs mb-2 block"
154
+ >
155
+ {name}
156
+ </Typography>
157
+ <SchemaBlock schema={resolved} spec={spec} depth={depth}/>
158
+ </div>
159
+ );
160
+ }
161
+
162
+ // Object with properties
163
+ if (schema.properties) {
164
+ const required = new Set(schema.required ?? []);
165
+ return (
166
+ <div
167
+ className={cls(
168
+ "rounded-lg overflow-hidden",
169
+ depth > 0 && `border ml-4 mt-1 ${defaultBorderMixin}`
170
+ )}
171
+ >
172
+ <table className="w-full text-xs">
173
+ <tbody>
174
+ {Object.entries(schema.properties).map(([key, prop]) => (
175
+ <tr
176
+ key={key}
177
+ className={cls("border-t first:border-t-0", defaultBorderMixin)}
178
+ >
179
+ <td className="px-3 py-2 align-top w-36">
180
+ <code className="font-mono font-semibold text-text-primary dark:text-text-primary-dark">
181
+ {key}
182
+ </code>
183
+ {required.has(key) && <span className="text-red-500 ml-0.5">*</span>}
184
+ {prop.readOnly && (
185
+ <span className="ml-1.5 text-[9px] text-text-secondary dark:text-text-secondary-dark italic">
186
+ read-only
187
+ </span>
188
+ )}
189
+ </td>
190
+ <td className="px-3 py-2 align-top w-28">
191
+ <span className="font-mono text-text-secondary dark:text-text-secondary-dark">
192
+ {schemaTypeLabel(prop)}
193
+ </span>
194
+ </td>
195
+ <td className="px-3 py-2 align-top text-text-secondary dark:text-text-secondary-dark">
196
+ {prop.description ?? ""}
197
+ {prop.enum && (
198
+ <div className="flex flex-wrap gap-1 mt-1">
199
+ {prop.enum.map((v) => (
200
+ <span
201
+ key={String(v)}
202
+ className="px-1.5 py-0.5 rounded bg-surface-200 dark:bg-surface-800 text-[10px] font-mono"
203
+ >
204
+ {String(v)}
205
+ </span>
206
+ ))}
207
+ </div>
208
+ )}
209
+ {prop.properties && <SchemaBlock schema={prop} spec={spec} depth={depth + 1}/>}
210
+ {prop.$ref && <SchemaBlock schema={prop} spec={spec} depth={depth + 1}/>}
211
+ </td>
212
+ </tr>
213
+ ))}
214
+ </tbody>
215
+ </table>
216
+ </div>
217
+ );
218
+ }
219
+
220
+ // Array
221
+ if (schema.type === "array" && schema.items) {
222
+ return (
223
+ <div>
224
+ <span className="font-mono text-xs text-text-secondary dark:text-text-secondary-dark">Array of:</span>
225
+ <SchemaBlock schema={schema.items} spec={spec} depth={depth + 1}/>
226
+ </div>
227
+ );
228
+ }
229
+
230
+ // Primitive
231
+ return (
232
+ <span className="font-mono text-xs text-text-secondary dark:text-text-secondary-dark">
233
+ {schemaTypeLabel(schema)}
234
+ </span>
235
+ );
236
+ }
237
+
238
+ /* ── Helpers ──────────────────────────────────────────────────────── */
239
+
240
+ function schemaTypeLabel(schema?: OpenApiSchema): string {
241
+ if (!schema) return "any";
242
+ if (schema.$ref) return resolveRefName(schema.$ref);
243
+ if (schema.type === "array") return `${schemaTypeLabel(schema.items)}[]`;
244
+ if (schema.format) return `${schema.type} (${schema.format})`;
245
+ return schema.type ?? "object";
246
+ }
247
+
248
+ function SectionHeading({ icon, title }: { icon: React.ReactNode; title: string }) {
249
+ return (
250
+ <div className="flex items-center gap-2 mb-3">
251
+ {icon}
252
+ <Typography variant="subtitle2" className="font-semibold text-sm">
253
+ {title}
254
+ </Typography>
255
+ </div>
256
+ );
257
+ }
258
+
259
+ function StatusBadge({ code }: { code: string }) {
260
+ const n = parseInt(code, 10);
261
+ const color =
262
+ n < 300
263
+ ? "text-emerald-600 dark:text-emerald-400"
264
+ : n < 400
265
+ ? "text-blue-600 dark:text-blue-400"
266
+ : n < 500
267
+ ? "text-amber-600 dark:text-amber-400"
268
+ : "text-red-600 dark:text-red-400";
269
+
270
+ return <span className={cls("text-xs font-bold font-mono", color)}>{code}</span>;
271
+ }