@object-ui/app-shell 6.2.3 → 7.0.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.
- package/CHANGELOG.md +948 -0
- package/README.md +292 -0
- package/dist/assistant/assistantBus.d.ts +72 -0
- package/dist/assistant/assistantBus.js +133 -0
- package/dist/chrome/CommandPalette.d.ts +1 -1
- package/dist/chrome/CommandPalette.js +26 -22
- package/dist/chrome/ConditionalAuthWrapper.d.ts +1 -1
- package/dist/chrome/ConsoleToaster.d.ts +1 -1
- package/dist/chrome/ConsoleToaster.js +3 -1
- package/dist/chrome/ErrorBoundary.d.ts +1 -1
- package/dist/chrome/KeyboardShortcutsDialog.d.ts +1 -1
- package/dist/chrome/KeyboardShortcutsDialog.js +16 -5
- package/dist/chrome/LoadingScreen.d.ts +1 -1
- package/dist/chrome/LoadingScreen.js +22 -26
- package/dist/chrome/RouteFader.d.ts +1 -1
- package/dist/chrome/ThemeProvider.d.ts +1 -1
- package/dist/components/ManagedByBadge.d.ts +1 -1
- package/dist/console/AppContent.d.ts +1 -1
- package/dist/console/AppContent.js +170 -37
- package/dist/console/ConsoleShell.d.ts +7 -7
- package/dist/console/ConsoleShell.js +32 -3
- package/dist/console/ai/AiChatPage.d.ts +88 -1
- package/dist/console/ai/AiChatPage.js +743 -66
- package/dist/console/ai/ConversationsSidebar.d.ts +26 -1
- package/dist/console/ai/ConversationsSidebar.js +149 -34
- package/dist/console/ai/LiveCanvas.d.ts +22 -0
- package/dist/console/ai/LiveCanvas.js +78 -0
- package/dist/console/ai/reconcileTurn.d.ts +8 -0
- package/dist/console/ai/reconcileTurn.js +20 -0
- package/dist/console/auth/AuthPageLayout.d.ts +1 -1
- package/dist/console/auth/ForgotPasswordPage.d.ts +1 -1
- package/dist/console/auth/LoginPage.d.ts +1 -1
- package/dist/console/auth/RegisterPage.d.ts +1 -1
- package/dist/console/auth/RegisterPage.js +23 -3
- package/dist/console/cloud-connection/CloudConnectionPanel.d.ts +1 -0
- package/dist/console/cloud-connection/CloudConnectionPanel.js +169 -0
- package/dist/console/home/AppCard.d.ts +1 -1
- package/dist/console/home/AppCard.js +6 -12
- package/dist/console/home/HomeAppsStrip.d.ts +8 -0
- package/dist/console/home/HomeAppsStrip.js +61 -0
- package/dist/console/home/HomeLayout.d.ts +1 -1
- package/dist/console/home/HomeLayout.js +3 -1
- package/dist/console/home/HomePage.d.ts +1 -2
- package/dist/console/home/HomePage.js +149 -21
- package/dist/console/home/HomeRail.d.ts +22 -0
- package/dist/console/home/HomeRail.js +62 -0
- package/dist/console/home/QuickActions.d.ts +1 -1
- package/dist/console/home/QuickActions.js +3 -11
- package/dist/console/home/RecentApps.d.ts +1 -1
- package/dist/console/home/RecentApps.js +2 -2
- package/dist/console/home/StarredApps.d.ts +1 -1
- package/dist/console/home/StarredApps.js +2 -2
- package/dist/console/marketplace/InstalledListWidget.d.ts +1 -0
- package/dist/console/marketplace/InstalledListWidget.js +93 -0
- package/dist/console/marketplace/MarkdownText.d.ts +1 -1
- package/dist/console/marketplace/MarketplaceAccessDenied.d.ts +1 -1
- package/dist/console/marketplace/MarketplaceInstalledPage.d.ts +8 -14
- package/dist/console/marketplace/MarketplaceInstalledPage.js +14 -66
- package/dist/console/marketplace/MarketplacePackagePage.d.ts +1 -1
- package/dist/console/marketplace/MarketplacePackagePage.js +249 -8
- package/dist/console/marketplace/MarketplacePage.d.ts +1 -1
- package/dist/console/marketplace/MarketplacePage.js +60 -3
- package/dist/console/marketplace/PackageIcon.d.ts +1 -1
- package/dist/console/marketplace/PluginDisclosure.d.ts +14 -0
- package/dist/console/marketplace/PluginDisclosure.js +38 -0
- package/dist/console/marketplace/marketplaceApi.d.ts +123 -0
- package/dist/console/marketplace/marketplaceApi.js +254 -1
- package/dist/console/organizations/CreateWorkspaceDialog.d.ts +1 -1
- package/dist/console/organizations/OrganizationsLayout.d.ts +1 -1
- package/dist/console/organizations/OrganizationsPage.d.ts +1 -1
- package/dist/console/organizations/manage/AcceptInvitationPage.d.ts +1 -1
- package/dist/console/organizations/manage/InvitationsPage.d.ts +1 -1
- package/dist/console/organizations/manage/InviteMemberDialog.d.ts +1 -1
- package/dist/console/organizations/manage/MembersPage.d.ts +1 -1
- package/dist/console/organizations/manage/OrganizationLayout.d.ts +1 -1
- package/dist/console/organizations/manage/SettingsPage.d.ts +1 -1
- package/dist/context/CommandPaletteProvider.d.ts +44 -0
- package/dist/context/CommandPaletteProvider.js +71 -0
- package/dist/context/FavoritesProvider.d.ts +1 -1
- package/dist/context/NavigationContext.d.ts +1 -1
- package/dist/context/RecentItemsProvider.d.ts +2 -2
- package/dist/context/UserStateAdapters.d.ts +1 -1
- package/dist/context/index.d.ts +2 -0
- package/dist/context/index.js +1 -0
- package/dist/hooks/index.d.ts +5 -2
- package/dist/hooks/index.js +4 -1
- package/dist/hooks/useActionModal.d.ts +53 -0
- package/dist/hooks/useActionModal.js +111 -0
- package/dist/hooks/useChatConversation.d.ts +107 -4
- package/dist/hooks/useChatConversation.js +253 -25
- package/dist/hooks/useConsoleActionRuntime.d.ts +70 -0
- package/dist/hooks/useConsoleActionRuntime.js +560 -0
- package/dist/hooks/useConversationList.js +61 -3
- package/dist/hooks/useHomeInbox.d.ts +13 -0
- package/dist/hooks/useHomeInbox.js +142 -0
- package/dist/hooks/useNavPins.js +17 -23
- package/dist/hooks/useNavigationSync.d.ts +33 -0
- package/dist/hooks/useNavigationSync.js +98 -12
- package/dist/hooks/useReconcileOnError.d.ts +40 -0
- package/dist/hooks/useReconcileOnError.js +37 -0
- package/dist/hooks/useRecordApprovals.d.ts +18 -19
- package/dist/hooks/useRecordApprovals.js +24 -40
- package/dist/hooks/useResponsiveSidebar.js +14 -5
- package/dist/hooks/useSettleSignal.d.ts +19 -0
- package/dist/hooks/useSettleSignal.js +20 -0
- package/dist/hooks/useTrackRouteAsRecent.js +35 -0
- package/dist/hooks/useUrlOverlay.d.ts +62 -0
- package/dist/hooks/useUrlOverlay.js +88 -0
- package/dist/index.d.ts +16 -7
- package/dist/index.js +12 -4
- package/dist/layout/ActivityFeed.d.ts +1 -1
- package/dist/layout/AppHeader.d.ts +3 -2
- package/dist/layout/AppHeader.js +237 -72
- package/dist/layout/AppSidebar.d.ts +2 -1
- package/dist/layout/AppSidebar.js +26 -46
- package/dist/layout/AppSwitcher.d.ts +2 -1
- package/dist/layout/AppSwitcher.js +9 -5
- package/dist/layout/AuthPageLayout.d.ts +1 -1
- package/dist/layout/ConnectionStatus.d.ts +1 -1
- package/dist/layout/ConnectionStatus.js +9 -6
- package/dist/layout/ConsoleChatbotFab.d.ts +19 -1
- package/dist/layout/ConsoleChatbotFab.js +16 -2
- package/dist/layout/ConsoleFloatingChatbot.d.ts +32 -2
- package/dist/layout/ConsoleFloatingChatbot.js +374 -41
- package/dist/layout/ConsoleLayout.d.ts +1 -1
- package/dist/layout/ConsoleLayout.js +27 -11
- package/dist/layout/ContextSelectors.d.ts +44 -0
- package/dist/layout/ContextSelectors.js +218 -0
- package/dist/layout/InboxPopover.d.ts +6 -1
- package/dist/layout/InboxPopover.js +25 -6
- package/dist/layout/LocaleSwitcher.d.ts +1 -1
- package/dist/layout/LocalizedSidebarTrigger.d.ts +2 -0
- package/dist/layout/LocalizedSidebarTrigger.js +15 -0
- package/dist/layout/MobileViewSwitcherContext.d.ts +1 -1
- package/dist/layout/ModeToggle.d.ts +1 -1
- package/dist/layout/PageHeader.d.ts +1 -1
- package/dist/layout/UnifiedSidebar.d.ts +2 -1
- package/dist/layout/UnifiedSidebar.js +116 -15
- package/dist/observability/index.d.ts +1 -0
- package/dist/observability/index.js +1 -0
- package/dist/observability/settleSignal.d.ts +64 -0
- package/dist/observability/settleSignal.js +131 -0
- package/dist/preview/DraftChangesPanel.d.ts +19 -0
- package/dist/preview/DraftChangesPanel.js +114 -0
- package/dist/preview/DraftPreviewBar.d.ts +8 -0
- package/dist/preview/DraftPreviewBar.js +86 -0
- package/dist/preview/PreviewDraftEmptyState.d.ts +16 -0
- package/dist/preview/PreviewDraftEmptyState.js +47 -0
- package/dist/preview/PreviewModeContext.d.ts +57 -0
- package/dist/preview/PreviewModeContext.js +99 -0
- package/dist/preview/UnpublishedAppBar.d.ts +8 -0
- package/dist/preview/UnpublishedAppBar.js +79 -0
- package/dist/preview/draftStatus.d.ts +20 -0
- package/dist/preview/draftStatus.js +27 -0
- package/dist/preview/usePublishAllDrafts.d.ts +18 -0
- package/dist/preview/usePublishAllDrafts.js +106 -0
- package/dist/providers/AdapterProvider.d.ts +1 -1
- package/dist/providers/AdapterProvider.js +6 -1
- package/dist/providers/ExpressionProvider.d.ts +1 -1
- package/dist/providers/MetadataProvider.d.ts +17 -2
- package/dist/providers/MetadataProvider.js +183 -12
- package/dist/runtime-config.d.ts +46 -2
- package/dist/runtime-config.js +39 -2
- package/dist/services/builtinComponents.js +68 -59
- package/dist/skeletons/SkeletonDashboard.d.ts +1 -1
- package/dist/skeletons/SkeletonDetail.d.ts +1 -1
- package/dist/skeletons/SkeletonGrid.d.ts +1 -1
- package/dist/utils/appRoute.d.ts +21 -0
- package/dist/utils/appRoute.js +25 -0
- package/dist/utils/deriveRelatedLists.d.ts +54 -0
- package/dist/utils/deriveRelatedLists.js +91 -0
- package/dist/utils/index.d.ts +4 -0
- package/dist/utils/index.js +3 -0
- package/dist/utils/managedByEmptyState.d.ts +8 -1
- package/dist/utils/managedByEmptyState.js +13 -7
- package/dist/utils/preferLocal.d.ts +18 -0
- package/dist/utils/preferLocal.js +24 -0
- package/dist/views/ActionConfirmDialog.d.ts +1 -1
- package/dist/views/ActionConfirmDialog.js +3 -1
- package/dist/views/ActionParamDialog.d.ts +6 -1
- package/dist/views/ActionParamDialog.js +9 -3
- package/dist/views/ActionResultDialog.d.ts +13 -0
- package/dist/views/ActionResultDialog.js +134 -0
- package/dist/views/ComponentNavView.d.ts +14 -1
- package/dist/views/CreateViewDialog.d.ts +1 -1
- package/dist/views/DashboardConfigPanel.d.ts +28 -0
- package/dist/views/DashboardConfigPanel.js +81 -0
- package/dist/views/DashboardView.d.ts +4 -3
- package/dist/views/DashboardView.js +38 -239
- package/dist/views/FlowRunner.d.ts +59 -0
- package/dist/views/FlowRunner.js +153 -0
- package/dist/views/InterfaceListPage.d.ts +49 -0
- package/dist/views/InterfaceListPage.js +347 -0
- package/dist/views/MetadataInspector.d.ts +2 -2
- package/dist/views/ObjectView.d.ts +1 -1
- package/dist/views/ObjectView.js +209 -532
- package/dist/views/PageView.d.ts +8 -3
- package/dist/views/PageView.js +45 -32
- package/dist/views/RecordDetailView.d.ts +1 -1
- package/dist/views/RecordDetailView.js +363 -148
- package/dist/views/RecordFormPage.d.ts +1 -1
- package/dist/views/RecordFormPage.js +26 -1
- package/dist/views/ReportConfigPanel.d.ts +37 -0
- package/dist/views/ReportConfigPanel.js +85 -0
- package/dist/views/ReportView.d.ts +1 -1
- package/dist/views/ReportView.js +116 -7
- package/dist/views/RuntimeDraftBar.d.ts +30 -0
- package/dist/views/RuntimeDraftBar.js +112 -0
- package/dist/views/SearchResultsPage.d.ts +1 -1
- package/dist/views/SearchResultsPage.js +8 -18
- package/dist/views/ViewConfigPanel.d.ts +24 -17
- package/dist/views/ViewConfigPanel.js +121 -77
- package/dist/views/index.d.ts +1 -1
- package/dist/views/index.js +1 -1
- package/dist/views/metadata-admin/AuditPanel.d.ts +28 -0
- package/dist/views/metadata-admin/AuditPanel.js +79 -0
- package/dist/views/metadata-admin/DiagnosticsPage.d.ts +20 -0
- package/dist/views/metadata-admin/DiagnosticsPage.js +69 -0
- package/dist/views/metadata-admin/DirectoryPage.d.ts +16 -1
- package/dist/views/metadata-admin/DirectoryPage.js +113 -24
- package/dist/views/metadata-admin/DraftReviewPanel.d.ts +33 -0
- package/dist/views/metadata-admin/DraftReviewPanel.js +77 -0
- package/dist/views/metadata-admin/EmbeddedItemEditor.d.ts +17 -1
- package/dist/views/metadata-admin/EmbeddedItemEditor.js +15 -8
- package/dist/views/metadata-admin/JsonSourceEditor.d.ts +37 -0
- package/dist/views/metadata-admin/JsonSourceEditor.js +178 -0
- package/dist/views/metadata-admin/LayeredDiff.d.ts +39 -1
- package/dist/views/metadata-admin/LayeredDiff.js +171 -5
- package/dist/views/metadata-admin/MetadataDetailDrawer.d.ts +15 -1
- package/dist/views/metadata-admin/MetadataTypeActions.d.ts +48 -0
- package/dist/views/metadata-admin/MetadataTypeActions.js +165 -0
- package/dist/views/metadata-admin/PackagesPage.d.ts +18 -0
- package/dist/views/metadata-admin/PackagesPage.js +395 -0
- package/dist/views/metadata-admin/PageShell.d.ts +1 -1
- package/dist/views/metadata-admin/PageShell.js +9 -4
- package/dist/views/metadata-admin/PermissionMatrixEditor.d.ts +35 -1
- package/dist/views/metadata-admin/QuickFind.d.ts +21 -1
- package/dist/views/metadata-admin/QuickFind.js +6 -3
- package/dist/views/metadata-admin/RelatedPanel.d.ts +24 -1
- package/dist/views/metadata-admin/RelatedPanel.js +20 -18
- package/dist/views/metadata-admin/ResourceEditPage.d.ts +40 -1
- package/dist/views/metadata-admin/ResourceEditPage.js +1223 -60
- package/dist/views/metadata-admin/ResourceHistoryPage.d.ts +39 -1
- package/dist/views/metadata-admin/ResourceHistoryPage.js +66 -16
- package/dist/views/metadata-admin/ResourceListPage.d.ts +13 -1
- package/dist/views/metadata-admin/ResourceListPage.js +266 -30
- package/dist/views/metadata-admin/ResourceRouter.d.ts +23 -1
- package/dist/views/metadata-admin/SchemaForm.d.ts +34 -1
- package/dist/views/metadata-admin/SchemaForm.js +559 -49
- package/dist/views/metadata-admin/StudioHomePage.d.ts +22 -0
- package/dist/views/metadata-admin/StudioHomePage.js +213 -0
- package/dist/views/metadata-admin/anchors.js +237 -24
- package/dist/views/metadata-admin/clientValidation.d.ts +50 -0
- package/dist/views/metadata-admin/clientValidation.js +169 -0
- package/dist/views/metadata-admin/color-variant-field.d.ts +30 -0
- package/dist/views/metadata-admin/color-variant-field.js +38 -0
- package/dist/views/metadata-admin/createDerive.d.ts +75 -0
- package/dist/views/metadata-admin/createDerive.js +179 -0
- package/dist/views/metadata-admin/dashboard-schema.d.ts +12 -0
- package/dist/views/metadata-admin/dashboard-schema.js +80 -0
- package/dist/views/metadata-admin/datasource/DatasourceResourcePage.d.ts +35 -0
- package/dist/views/metadata-admin/datasource/DatasourceResourcePage.js +327 -0
- package/dist/views/metadata-admin/datasource/register.d.ts +1 -0
- package/dist/views/metadata-admin/datasource/register.js +24 -0
- package/dist/views/metadata-admin/default-inspector-registry.d.ts +49 -0
- package/dist/views/metadata-admin/default-inspector-registry.js +8 -0
- package/dist/views/metadata-admin/default-schemas.js +115 -10
- package/dist/views/metadata-admin/external/ExternalDatasourcePanel.d.ts +27 -0
- package/dist/views/metadata-admin/external/ExternalDatasourcePanel.js +69 -0
- package/dist/views/metadata-admin/external/ImportObjectDialog.d.ts +27 -0
- package/dist/views/metadata-admin/external/ImportObjectDialog.js +77 -0
- package/dist/views/metadata-admin/external/SchemaBrowser.d.ts +16 -0
- package/dist/views/metadata-admin/external/SchemaBrowser.js +74 -0
- package/dist/views/metadata-admin/external/ValidationPanel.d.ts +16 -0
- package/dist/views/metadata-admin/external/ValidationPanel.js +68 -0
- package/dist/views/metadata-admin/external/api.d.ts +100 -0
- package/dist/views/metadata-admin/external/api.js +124 -0
- package/dist/views/metadata-admin/i18n.d.ts +1 -0
- package/dist/views/metadata-admin/i18n.js +1166 -2
- package/dist/views/metadata-admin/index.d.ts +8 -5
- package/dist/views/metadata-admin/index.js +12 -2
- package/dist/views/metadata-admin/inspector-registry.d.ts +51 -0
- package/dist/views/metadata-admin/inspector-registry.js +11 -0
- package/dist/views/metadata-admin/inspectors/ActionDefaultInspector.d.ts +30 -0
- package/dist/views/metadata-admin/inspectors/ActionDefaultInspector.js +180 -0
- package/dist/views/metadata-admin/inspectors/AppNavInspector.d.ts +16 -0
- package/dist/views/metadata-admin/inspectors/AppNavInspector.js +110 -0
- package/dist/views/metadata-admin/inspectors/ConditionBuilder.d.ts +29 -0
- package/dist/views/metadata-admin/inspectors/ConditionBuilder.js +154 -0
- package/dist/views/metadata-admin/inspectors/DashboardDefaultInspector.d.ts +28 -0
- package/dist/views/metadata-admin/inspectors/DashboardDefaultInspector.js +110 -0
- package/dist/views/metadata-admin/inspectors/DashboardWidgetInspector.d.ts +18 -0
- package/dist/views/metadata-admin/inspectors/DashboardWidgetInspector.js +139 -0
- package/dist/views/metadata-admin/inspectors/DatasetDefaultInspector.d.ts +21 -0
- package/dist/views/metadata-admin/inspectors/DatasetDefaultInspector.js +107 -0
- package/dist/views/metadata-admin/inspectors/FlowEdgeInspector.d.ts +16 -0
- package/dist/views/metadata-admin/inspectors/FlowEdgeInspector.js +45 -0
- package/dist/views/metadata-admin/inspectors/FlowInspector.d.ts +12 -0
- package/dist/views/metadata-admin/inspectors/FlowInspector.js +9 -0
- package/dist/views/metadata-admin/inspectors/FlowKeyValueField.d.ts +30 -0
- package/dist/views/metadata-admin/inspectors/FlowKeyValueField.js +125 -0
- package/dist/views/metadata-admin/inspectors/FlowNodeConfigField.d.ts +18 -0
- package/dist/views/metadata-admin/inspectors/FlowNodeConfigField.js +40 -0
- package/dist/views/metadata-admin/inspectors/FlowNodeInspector.d.ts +14 -0
- package/dist/views/metadata-admin/inspectors/FlowNodeInspector.js +140 -0
- package/dist/views/metadata-admin/inspectors/FlowObjectListField.d.ts +26 -0
- package/dist/views/metadata-admin/inspectors/FlowObjectListField.js +105 -0
- package/dist/views/metadata-admin/inspectors/FlowReferenceField.d.ts +83 -0
- package/dist/views/metadata-admin/inspectors/FlowReferenceField.js +181 -0
- package/dist/views/metadata-admin/inspectors/FlowStringListField.d.ts +21 -0
- package/dist/views/metadata-admin/inspectors/FlowStringListField.js +60 -0
- package/dist/views/metadata-admin/inspectors/InspectorComboField.d.ts +40 -0
- package/dist/views/metadata-admin/inspectors/InspectorComboField.js +61 -0
- package/dist/views/metadata-admin/inspectors/ObjectDefaultInspector.d.ts +21 -0
- package/dist/views/metadata-admin/inspectors/ObjectDefaultInspector.js +54 -0
- package/dist/views/metadata-admin/inspectors/ObjectFieldInspector.d.ts +23 -0
- package/dist/views/metadata-admin/inspectors/ObjectFieldInspector.js +330 -0
- package/dist/views/metadata-admin/inspectors/PageBlockInspector.d.ts +48 -0
- package/dist/views/metadata-admin/inspectors/PageBlockInspector.js +332 -0
- package/dist/views/metadata-admin/inspectors/ReportDefaultInspector.d.ts +58 -0
- package/dist/views/metadata-admin/inspectors/ReportDefaultInspector.js +160 -0
- package/dist/views/metadata-admin/inspectors/ViewColumnInspector.d.ts +19 -0
- package/dist/views/metadata-admin/inspectors/ViewColumnInspector.js +144 -0
- package/dist/views/metadata-admin/inspectors/ViewInspector.d.ts +19 -0
- package/dist/views/metadata-admin/inspectors/ViewInspector.js +21 -0
- package/dist/views/metadata-admin/inspectors/ViewVariantInspector.d.ts +54 -0
- package/dist/views/metadata-admin/inspectors/ViewVariantInspector.js +191 -0
- package/dist/views/metadata-admin/inspectors/_shared.d.ts +124 -0
- package/dist/views/metadata-admin/inspectors/_shared.js +113 -0
- package/dist/views/metadata-admin/inspectors/expression-validate.d.ts +26 -0
- package/dist/views/metadata-admin/inspectors/expression-validate.js +66 -0
- package/dist/views/metadata-admin/inspectors/flow-node-config.d.ts +143 -0
- package/dist/views/metadata-admin/inspectors/flow-node-config.js +461 -0
- package/dist/views/metadata-admin/inspectors/index.d.ts +1 -0
- package/dist/views/metadata-admin/inspectors/index.js +45 -0
- package/dist/views/metadata-admin/inspectors/json-schema-to-fields.d.ts +40 -0
- package/dist/views/metadata-admin/inspectors/json-schema-to-fields.js +227 -0
- package/dist/views/metadata-admin/inspectors/useDatasetFields.d.ts +72 -0
- package/dist/views/metadata-admin/inspectors/useDatasetFields.js +0 -0
- package/dist/views/metadata-admin/mergeServerFields.d.ts +65 -0
- package/dist/views/metadata-admin/mergeServerFields.js +56 -0
- package/dist/views/metadata-admin/preview-registry.d.ts +55 -0
- package/dist/views/metadata-admin/previews/ActionPreview.d.ts +25 -0
- package/dist/views/metadata-admin/previews/ActionPreview.js +238 -0
- package/dist/views/metadata-admin/previews/AddWidgetPicker.d.ts +12 -0
- package/dist/views/metadata-admin/previews/AddWidgetPicker.js +56 -0
- package/dist/views/metadata-admin/previews/AgentPreview.d.ts +24 -0
- package/dist/views/metadata-admin/previews/AgentPreview.js +100 -0
- package/dist/views/metadata-admin/previews/AppNavCanvas.d.ts +31 -0
- package/dist/views/metadata-admin/previews/AppNavCanvas.js +260 -0
- package/dist/views/metadata-admin/previews/AppPreview.d.ts +16 -1
- package/dist/views/metadata-admin/previews/AppPreview.js +23 -14
- package/dist/views/metadata-admin/previews/BookPreview.d.ts +20 -0
- package/dist/views/metadata-admin/previews/BookPreview.js +132 -0
- package/dist/views/metadata-admin/previews/DashboardPreview.d.ts +16 -1
- package/dist/views/metadata-admin/previews/DashboardPreview.js +110 -8
- package/dist/views/metadata-admin/previews/DatasetPreview.d.ts +18 -0
- package/dist/views/metadata-admin/previews/DatasetPreview.js +89 -0
- package/dist/views/metadata-admin/previews/DatasourcePreview.d.ts +23 -0
- package/dist/views/metadata-admin/previews/DatasourcePreview.js +68 -0
- package/dist/views/metadata-admin/previews/EmailTemplatePreview.d.ts +14 -1
- package/dist/views/metadata-admin/previews/FieldStub.d.ts +30 -0
- package/dist/views/metadata-admin/previews/FieldStub.js +104 -0
- package/dist/views/metadata-admin/previews/FieldsListEditor.d.ts +50 -0
- package/dist/views/metadata-admin/previews/FieldsListEditor.js +97 -0
- package/dist/views/metadata-admin/previews/FlowCanvas.d.ts +43 -0
- package/dist/views/metadata-admin/previews/FlowCanvas.js +328 -0
- package/dist/views/metadata-admin/previews/FlowPreview.d.ts +20 -0
- package/dist/views/metadata-admin/previews/FlowPreview.js +92 -0
- package/dist/views/metadata-admin/previews/FlowRunsPanel.d.ts +46 -0
- package/dist/views/metadata-admin/previews/FlowRunsPanel.js +97 -0
- package/dist/views/metadata-admin/previews/FlowSimulatorPanel.d.ts +25 -0
- package/dist/views/metadata-admin/previews/FlowSimulatorPanel.js +170 -0
- package/dist/views/metadata-admin/previews/JobPreview.d.ts +28 -0
- package/dist/views/metadata-admin/previews/JobPreview.js +290 -0
- package/dist/views/metadata-admin/previews/ObjectFormCanvas.d.ts +30 -0
- package/dist/views/metadata-admin/previews/ObjectFormCanvas.js +547 -0
- package/dist/views/metadata-admin/previews/ObjectPreview.d.ts +14 -1
- package/dist/views/metadata-admin/previews/ObjectPreview.js +5 -30
- package/dist/views/metadata-admin/previews/OutlineStrip.d.ts +32 -0
- package/dist/views/metadata-admin/previews/OutlineStrip.js +8 -0
- package/dist/views/metadata-admin/previews/PageBlockCanvas.d.ts +49 -0
- package/dist/views/metadata-admin/previews/PageBlockCanvas.js +510 -0
- package/dist/views/metadata-admin/previews/PagePreview.d.ts +10 -1
- package/dist/views/metadata-admin/previews/PagePreview.js +90 -4
- package/dist/views/metadata-admin/previews/PermissionPreview.d.ts +27 -0
- package/dist/views/metadata-admin/previews/PermissionPreview.js +115 -0
- package/dist/views/metadata-admin/previews/PreviewShell.d.ts +29 -6
- package/dist/views/metadata-admin/previews/PreviewShell.js +16 -3
- package/dist/views/metadata-admin/previews/ReportPreview.d.ts +18 -1
- package/dist/views/metadata-admin/previews/ReportPreview.js +23 -15
- package/dist/views/metadata-admin/previews/RolePreview.d.ts +19 -0
- package/dist/views/metadata-admin/previews/RolePreview.js +14 -0
- package/dist/views/metadata-admin/previews/SkillPreview.d.ts +22 -0
- package/dist/views/metadata-admin/previews/SkillPreview.js +34 -0
- package/dist/views/metadata-admin/previews/ToolPreview.d.ts +25 -0
- package/dist/views/metadata-admin/previews/ToolPreview.js +122 -0
- package/dist/views/metadata-admin/previews/TranslationPreview.d.ts +25 -0
- package/dist/views/metadata-admin/previews/TranslationPreview.js +52 -0
- package/dist/views/metadata-admin/previews/ValidationPreview.d.ts +27 -0
- package/dist/views/metadata-admin/previews/ValidationPreview.js +110 -0
- package/dist/views/metadata-admin/previews/ViewColumnPanes.d.ts +62 -0
- package/dist/views/metadata-admin/previews/ViewColumnPanes.js +140 -0
- package/dist/views/metadata-admin/previews/ViewPreview.d.ts +23 -1
- package/dist/views/metadata-admin/previews/ViewPreview.js +101 -73
- package/dist/views/metadata-admin/previews/block-config.d.ts +82 -0
- package/dist/views/metadata-admin/previews/block-config.js +324 -0
- package/dist/views/metadata-admin/previews/block-types.d.ts +40 -0
- package/dist/views/metadata-admin/previews/block-types.js +110 -0
- package/dist/views/metadata-admin/previews/field-types.d.ts +53 -0
- package/dist/views/metadata-admin/previews/field-types.js +97 -0
- package/dist/views/metadata-admin/previews/flow-canvas-layout.d.ts +88 -0
- package/dist/views/metadata-admin/previews/flow-canvas-layout.js +190 -0
- package/dist/views/metadata-admin/previews/flow-canvas-parts.d.ts +88 -0
- package/dist/views/metadata-admin/previews/flow-canvas-parts.js +358 -0
- package/dist/views/metadata-admin/previews/form-preview.d.ts +24 -0
- package/dist/views/metadata-admin/previews/form-preview.js +29 -0
- package/dist/views/metadata-admin/previews/index.js +43 -0
- package/dist/views/metadata-admin/previews/object-fields-bridge.d.ts +66 -0
- package/dist/views/metadata-admin/previews/object-fields-bridge.js +171 -0
- package/dist/views/metadata-admin/previews/object-fields-io.d.ts +109 -0
- package/dist/views/metadata-admin/previews/object-fields-io.js +208 -0
- package/dist/views/metadata-admin/previews/simulator/flow-sim-types.d.ts +91 -0
- package/dist/views/metadata-admin/previews/simulator/flow-sim-types.js +2 -0
- package/dist/views/metadata-admin/previews/simulator/flow-sim-validate.d.ts +8 -0
- package/dist/views/metadata-admin/previews/simulator/flow-sim-validate.js +113 -0
- package/dist/views/metadata-admin/previews/simulator/flow-simulator.d.ts +44 -0
- package/dist/views/metadata-admin/previews/simulator/flow-simulator.js +316 -0
- package/dist/views/metadata-admin/previews/useDatasetCatalog.d.ts +47 -0
- package/dist/views/metadata-admin/previews/useDatasetCatalog.js +133 -0
- package/dist/views/metadata-admin/previews/useFlowNodePalette.d.ts +44 -0
- package/dist/views/metadata-admin/previews/useFlowNodePalette.js +124 -0
- package/dist/views/metadata-admin/previews/useMetaOptions.d.ts +8 -0
- package/dist/views/metadata-admin/previews/useMetaOptions.js +50 -0
- package/dist/views/metadata-admin/previews/useObjectFields.d.ts +23 -0
- package/dist/views/metadata-admin/previews/useObjectFields.js +79 -0
- package/dist/views/metadata-admin/previews/useObjectOptions.d.ts +8 -0
- package/dist/views/metadata-admin/previews/useObjectOptions.js +43 -0
- package/dist/views/metadata-admin/previews/view-column-io.d.ts +42 -0
- package/dist/views/metadata-admin/previews/view-column-io.js +73 -0
- package/dist/views/metadata-admin/previews/widget-types.d.ts +24 -0
- package/dist/views/metadata-admin/previews/widget-types.js +40 -0
- package/dist/views/metadata-admin/registry.d.ts +140 -19
- package/dist/views/metadata-admin/report-schema.d.ts +26 -0
- package/dist/views/metadata-admin/report-schema.js +121 -0
- package/dist/views/metadata-admin/useMetadata.d.ts +100 -2
- package/dist/views/metadata-admin/useMetadata.js +155 -4
- package/dist/views/metadata-admin/view-item-normalize.d.ts +20 -0
- package/dist/views/metadata-admin/view-item-normalize.js +68 -0
- package/dist/views/metadata-admin/view-schema.d.ts +16 -0
- package/dist/views/metadata-admin/view-schema.js +107 -0
- package/dist/views/metadata-admin/view-variant-model.d.ts +23 -0
- package/dist/views/metadata-admin/view-variant-model.js +64 -0
- package/dist/views/metadata-admin/widgets.d.ts +89 -1
- package/dist/views/metadata-admin/widgets.js +491 -17
- package/dist/views/runtime-metadata-persistence.d.ts +78 -0
- package/dist/views/runtime-metadata-persistence.js +89 -0
- package/dist/views/useOpenRecordList.d.ts +18 -0
- package/dist/views/useOpenRecordList.js +36 -0
- package/dist/views/userFilterUrlState.d.ts +15 -0
- package/dist/views/userFilterUrlState.js +53 -0
- package/dist/views/view-config-adapter.d.ts +38 -0
- package/dist/views/view-config-adapter.js +80 -0
- package/package.json +52 -34
- package/dist/views/DesignDrawer.d.ts +0 -28
- package/dist/views/DesignDrawer.js +0 -51
- package/dist/views/metadata-admin/DesignerEditorWrapper.d.ts +0 -68
- package/dist/views/metadata-admin/DesignerEditorWrapper.js +0 -158
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
|
|
3
|
+
/**
|
|
4
|
+
* ExternalDatasourcePanel — the Studio home for an External Datasource
|
|
5
|
+
* Federation datasource (ADR-0015 §6.4).
|
|
6
|
+
*
|
|
7
|
+
* Rendered inside `DatasourcePreview` whenever a datasource is federated
|
|
8
|
+
* (`schemaMode !== 'managed'`). It groups the buildable P5 surfaces:
|
|
9
|
+
*
|
|
10
|
+
* • Tables — browse remote tables + import them as Objects.
|
|
11
|
+
* • Validation — check declared objects against the live remote schema
|
|
12
|
+
* (doubles as on-demand drift detection).
|
|
13
|
+
*
|
|
14
|
+
* A header strip offers "Refresh catalog" (re-introspect + persist the
|
|
15
|
+
* `external_catalog` snapshot) and shows when the snapshot was last taken.
|
|
16
|
+
*
|
|
17
|
+
* The connection wizard (drivers / credentials / secrets) intentionally lives
|
|
18
|
+
* in System Settings, not here — this surface is metadata-design work.
|
|
19
|
+
*/
|
|
20
|
+
import * as React from 'react';
|
|
21
|
+
import { DatabaseZap, RefreshCw, Loader2, Clock } from 'lucide-react';
|
|
22
|
+
import { Button, Tabs, TabsList, TabsTrigger, TabsContent, } from '@object-ui/components';
|
|
23
|
+
import { SchemaBrowser } from './SchemaBrowser';
|
|
24
|
+
import { ValidationPanel } from './ValidationPanel';
|
|
25
|
+
import { refreshCatalog, ExternalServiceUnavailableError, } from './api';
|
|
26
|
+
export function ExternalDatasourcePanel({ datasource, schemaMode, allowWrites, }) {
|
|
27
|
+
const [catalog, setCatalog] = React.useState(null);
|
|
28
|
+
const [refreshing, setRefreshing] = React.useState(false);
|
|
29
|
+
const [error, setError] = React.useState(null);
|
|
30
|
+
const handleRefresh = React.useCallback(async () => {
|
|
31
|
+
if (!datasource)
|
|
32
|
+
return;
|
|
33
|
+
setRefreshing(true);
|
|
34
|
+
setError(null);
|
|
35
|
+
try {
|
|
36
|
+
const c = await refreshCatalog(datasource);
|
|
37
|
+
setCatalog(c);
|
|
38
|
+
}
|
|
39
|
+
catch (err) {
|
|
40
|
+
setError(err instanceof ExternalServiceUnavailableError
|
|
41
|
+
? 'Federation is not enabled on this server.'
|
|
42
|
+
: err instanceof Error
|
|
43
|
+
? err.message
|
|
44
|
+
: String(err));
|
|
45
|
+
}
|
|
46
|
+
finally {
|
|
47
|
+
setRefreshing(false);
|
|
48
|
+
}
|
|
49
|
+
}, [datasource]);
|
|
50
|
+
// Unsaved datasource: the REST routes key off a saved `:name`, so nothing
|
|
51
|
+
// can be introspected yet. Guide the user to save first.
|
|
52
|
+
if (!datasource) {
|
|
53
|
+
return (_jsx("div", { className: "rounded border bg-muted/20 p-3 text-xs text-muted-foreground", children: "Save the datasource first to browse its remote tables and validate federated objects." }));
|
|
54
|
+
}
|
|
55
|
+
return (_jsxs("div", { className: "rounded border bg-background", children: [_jsxs("div", { className: "flex flex-wrap items-center gap-x-3 gap-y-1.5 border-b bg-muted/30 px-3 py-2", children: [_jsxs("span", { className: "inline-flex items-center gap-1.5 text-xs font-medium", children: [_jsx(DatabaseZap, { className: "h-4 w-4 text-sky-500" }), "External Datasource"] }), _jsx("span", { className: "rounded border bg-background px-1.5 py-0.5 font-mono text-[10px] uppercase tracking-wider text-muted-foreground", children: schemaMode ?? 'external' }), _jsx("span", { className: `rounded px-1.5 py-0.5 text-[10px] uppercase tracking-wider ${allowWrites
|
|
56
|
+
? 'bg-amber-100 text-amber-800 dark:bg-amber-950/40 dark:text-amber-300'
|
|
57
|
+
: 'bg-muted text-muted-foreground'}`, children: allowWrites ? 'writes allowed' : 'read-only' }), _jsxs("div", { className: "ml-auto flex items-center gap-2", children: [catalog?.snapshotAt && (_jsxs("span", { className: "inline-flex items-center gap-1 text-[11px] text-muted-foreground", children: [_jsx(Clock, { className: "h-3 w-3" }), "snapshot ", formatSnapshot(catalog.snapshotAt)] })), _jsxs(Button, { variant: "outline", size: "sm", onClick: () => void handleRefresh(), disabled: refreshing, children: [refreshing ? (_jsx(Loader2, { className: "h-3.5 w-3.5 animate-spin" })) : (_jsx(RefreshCw, { className: "h-3.5 w-3.5" })), _jsx("span", { className: "ml-1.5", children: "Refresh catalog" })] })] })] }), error && (_jsx("div", { className: "border-b border-destructive/40 bg-destructive/5 px-3 py-2 text-xs text-destructive", children: error })), _jsxs(Tabs, { defaultValue: "tables", className: "p-3", children: [_jsxs(TabsList, { children: [_jsx(TabsTrigger, { value: "tables", children: "Tables" }), _jsx(TabsTrigger, { value: "validation", children: "Validation" })] }), _jsx(TabsContent, { value: "tables", className: "mt-3", children: _jsx(SchemaBrowser, { datasource: datasource }) }), _jsx(TabsContent, { value: "validation", className: "mt-3", children: _jsx(ValidationPanel, { datasource: datasource }) })] })] }));
|
|
58
|
+
}
|
|
59
|
+
function formatSnapshot(iso) {
|
|
60
|
+
const t = new Date(iso).getTime();
|
|
61
|
+
if (Number.isNaN(t))
|
|
62
|
+
return iso;
|
|
63
|
+
try {
|
|
64
|
+
return new Date(t).toLocaleString();
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
return iso;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ImportObjectDialog — the mapping/import step of the external-datasource
|
|
3
|
+
* Studio surface (ADR-0015 §6.4 "Mapping editor").
|
|
4
|
+
*
|
|
5
|
+
* Flow:
|
|
6
|
+
* 1. On open, POST `…/tables/:remote/draft` → an `ObjectDraft`
|
|
7
|
+
* (structured definition + reviewable `*.object.ts` source).
|
|
8
|
+
* 2. Show the suggested object name, any `// REVIEW:` columns the
|
|
9
|
+
* type-compat matrix flagged as lossy/unknown, and the generated
|
|
10
|
+
* source.
|
|
11
|
+
* 3. "Import as Object" PUTs the draft's definition to the metadata
|
|
12
|
+
* store (`/meta/object/:name`) and reports success.
|
|
13
|
+
*
|
|
14
|
+
* The dialog never mutates the remote schema — it only reads the draft and
|
|
15
|
+
* writes a local Object definition.
|
|
16
|
+
*/
|
|
17
|
+
import * as React from 'react';
|
|
18
|
+
import { type RemoteTable } from './api';
|
|
19
|
+
export interface ImportObjectDialogProps {
|
|
20
|
+
datasource: string;
|
|
21
|
+
table: RemoteTable | null;
|
|
22
|
+
open: boolean;
|
|
23
|
+
onOpenChange: (open: boolean) => void;
|
|
24
|
+
/** Notified after a successful import (so the parent can refresh). */
|
|
25
|
+
onImported?: (objectName: string) => void;
|
|
26
|
+
}
|
|
27
|
+
export declare function ImportObjectDialog({ datasource, table, open, onOpenChange, onImported, }: ImportObjectDialogProps): React.JSX.Element;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
|
|
3
|
+
/**
|
|
4
|
+
* ImportObjectDialog — the mapping/import step of the external-datasource
|
|
5
|
+
* Studio surface (ADR-0015 §6.4 "Mapping editor").
|
|
6
|
+
*
|
|
7
|
+
* Flow:
|
|
8
|
+
* 1. On open, POST `…/tables/:remote/draft` → an `ObjectDraft`
|
|
9
|
+
* (structured definition + reviewable `*.object.ts` source).
|
|
10
|
+
* 2. Show the suggested object name, any `// REVIEW:` columns the
|
|
11
|
+
* type-compat matrix flagged as lossy/unknown, and the generated
|
|
12
|
+
* source.
|
|
13
|
+
* 3. "Import as Object" PUTs the draft's definition to the metadata
|
|
14
|
+
* store (`/meta/object/:name`) and reports success.
|
|
15
|
+
*
|
|
16
|
+
* The dialog never mutates the remote schema — it only reads the draft and
|
|
17
|
+
* writes a local Object definition.
|
|
18
|
+
*/
|
|
19
|
+
import * as React from 'react';
|
|
20
|
+
import { AlertTriangle, Database, FileCode2, Loader2, CheckCircle2 } from 'lucide-react';
|
|
21
|
+
import { Button, Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter, } from '@object-ui/components';
|
|
22
|
+
import { generateObjectDraft, importObjectDraft, ExternalServiceUnavailableError, } from './api';
|
|
23
|
+
export function ImportObjectDialog({ datasource, table, open, onOpenChange, onImported, }) {
|
|
24
|
+
const [phase, setPhase] = React.useState('loading');
|
|
25
|
+
const [draft, setDraft] = React.useState(null);
|
|
26
|
+
const [error, setError] = React.useState(null);
|
|
27
|
+
// Load the draft whenever the dialog opens for a (new) table.
|
|
28
|
+
React.useEffect(() => {
|
|
29
|
+
if (!open || !table)
|
|
30
|
+
return;
|
|
31
|
+
let cancelled = false;
|
|
32
|
+
setPhase('loading');
|
|
33
|
+
setDraft(null);
|
|
34
|
+
setError(null);
|
|
35
|
+
(async () => {
|
|
36
|
+
try {
|
|
37
|
+
const d = await generateObjectDraft(datasource, table.name, {
|
|
38
|
+
remoteSchema: table.schema,
|
|
39
|
+
});
|
|
40
|
+
if (cancelled)
|
|
41
|
+
return;
|
|
42
|
+
setDraft(d);
|
|
43
|
+
setPhase('ready');
|
|
44
|
+
}
|
|
45
|
+
catch (err) {
|
|
46
|
+
if (cancelled)
|
|
47
|
+
return;
|
|
48
|
+
setError(err instanceof ExternalServiceUnavailableError
|
|
49
|
+
? 'Federation is not enabled on this server.'
|
|
50
|
+
: err instanceof Error
|
|
51
|
+
? err.message
|
|
52
|
+
: String(err));
|
|
53
|
+
setPhase('error');
|
|
54
|
+
}
|
|
55
|
+
})();
|
|
56
|
+
return () => {
|
|
57
|
+
cancelled = true;
|
|
58
|
+
};
|
|
59
|
+
}, [open, table, datasource]);
|
|
60
|
+
const handleImport = React.useCallback(async () => {
|
|
61
|
+
if (!draft)
|
|
62
|
+
return;
|
|
63
|
+
setPhase('importing');
|
|
64
|
+
setError(null);
|
|
65
|
+
try {
|
|
66
|
+
await importObjectDraft(draft);
|
|
67
|
+
setPhase('done');
|
|
68
|
+
onImported?.(draft.name);
|
|
69
|
+
}
|
|
70
|
+
catch (err) {
|
|
71
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
72
|
+
setPhase('ready');
|
|
73
|
+
}
|
|
74
|
+
}, [draft, onImported]);
|
|
75
|
+
const remoteLabel = table ? [table.schema, table.name].filter(Boolean).join('.') : '';
|
|
76
|
+
return (_jsx(Dialog, { open: open, onOpenChange: onOpenChange, children: _jsxs(DialogContent, { className: "max-w-2xl", children: [_jsxs(DialogHeader, { children: [_jsxs(DialogTitle, { className: "flex items-center gap-2", children: [_jsx(Database, { className: "h-4 w-4" }), "Import as Object"] }), _jsxs(DialogDescription, { children: ["Map remote table ", _jsx("span", { className: "font-mono", children: remoteLabel }), " into an ObjectStack object bound to ", _jsx("span", { className: "font-mono", children: datasource }), ". The remote schema is never modified."] })] }), phase === 'loading' && (_jsxs("div", { className: "flex items-center gap-2 py-8 justify-center text-sm text-muted-foreground", children: [_jsx(Loader2, { className: "h-4 w-4 animate-spin" }), " Generating draft\u2026"] })), phase === 'error' && (_jsx("div", { className: "rounded border border-destructive/40 bg-destructive/5 p-3 text-sm text-destructive", children: error })), phase === 'done' && draft && (_jsxs("div", { className: "flex flex-col items-center gap-2 py-8 text-center", children: [_jsx(CheckCircle2, { className: "h-8 w-8 text-emerald-500" }), _jsxs("div", { className: "text-sm", children: ["Imported object ", _jsx("span", { className: "font-mono font-medium", children: draft.name }), "."] }), _jsx("div", { className: "text-xs text-muted-foreground", children: "Review its binding and run validation to confirm it matches the remote table." })] })), (phase === 'ready' || phase === 'importing') && draft && (_jsxs("div", { className: "space-y-3", children: [_jsxs("div", { className: "flex flex-wrap items-baseline gap-x-2 text-sm", children: [_jsx("span", { className: "text-muted-foreground", children: "Object name" }), _jsx("span", { className: "font-mono font-medium", children: draft.name })] }), error && (_jsx("div", { className: "rounded border border-destructive/40 bg-destructive/5 p-2 text-xs text-destructive", children: error })), draft.review.length > 0 && (_jsxs("div", { className: "rounded border border-amber-300 bg-amber-50 dark:bg-amber-950/20 p-2.5", children: [_jsxs("div", { className: "flex items-center gap-1.5 text-xs font-medium text-amber-800 dark:text-amber-300", children: [_jsx(AlertTriangle, { className: "h-3.5 w-3.5" }), draft.review.length, " column", draft.review.length === 1 ? '' : 's', " need review"] }), _jsx("ul", { className: "mt-1.5 space-y-1 text-[11px] text-amber-900/90 dark:text-amber-200/80", children: draft.review.map((r) => (_jsxs("li", { className: "flex flex-wrap gap-x-1.5", children: [_jsx("span", { className: "font-mono", children: r.column }), _jsxs("span", { className: "text-amber-700/70 dark:text-amber-400/70", children: ["(", r.remoteType, ")"] }), _jsxs("span", { children: ["\u2014 ", r.note] })] }, r.column))) })] })), _jsxs("div", { className: "space-y-1.5", children: [_jsxs("div", { className: "flex items-center gap-1.5 text-[11px] font-medium text-muted-foreground uppercase tracking-wider", children: [_jsx(FileCode2, { className: "h-3 w-3" }), " Generated source"] }), _jsx("pre", { className: "max-h-64 overflow-auto rounded border bg-muted/30 p-2.5 text-[11px] leading-relaxed font-mono", children: draft.source })] })] })), _jsx(DialogFooter, { children: phase === 'done' ? (_jsx(Button, { onClick: () => onOpenChange(false), children: "Close" })) : (_jsxs(_Fragment, { children: [_jsx(Button, { variant: "ghost", onClick: () => onOpenChange(false), disabled: phase === 'importing', children: "Cancel" }), _jsx(Button, { onClick: handleImport, disabled: phase !== 'ready' || !draft, children: phase === 'importing' ? (_jsxs("span", { className: "flex items-center gap-1.5", children: [_jsx(Loader2, { className: "h-3.5 w-3.5 animate-spin" }), " Importing\u2026"] })) : ('Import as Object') })] })) })] }) }));
|
|
77
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SchemaBrowser — the "schema browser" surface of the external-datasource
|
|
3
|
+
* Studio panel (ADR-0015 §6.4).
|
|
4
|
+
*
|
|
5
|
+
* Lists the remote tables a federated datasource exposes (filtered server-side
|
|
6
|
+
* by `external.allowedSchemas`), with an optional client-side text filter and
|
|
7
|
+
* a per-table "Import" action that opens {@link ImportObjectDialog}.
|
|
8
|
+
*
|
|
9
|
+
* Data is fetched on demand (mount + explicit "Refresh"), never on a timer —
|
|
10
|
+
* introspecting a warehouse is expensive, so the user stays in control.
|
|
11
|
+
*/
|
|
12
|
+
import * as React from 'react';
|
|
13
|
+
export interface SchemaBrowserProps {
|
|
14
|
+
datasource: string;
|
|
15
|
+
}
|
|
16
|
+
export declare function SchemaBrowser({ datasource }: SchemaBrowserProps): React.JSX.Element;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
|
|
3
|
+
/**
|
|
4
|
+
* SchemaBrowser — the "schema browser" surface of the external-datasource
|
|
5
|
+
* Studio panel (ADR-0015 §6.4).
|
|
6
|
+
*
|
|
7
|
+
* Lists the remote tables a federated datasource exposes (filtered server-side
|
|
8
|
+
* by `external.allowedSchemas`), with an optional client-side text filter and
|
|
9
|
+
* a per-table "Import" action that opens {@link ImportObjectDialog}.
|
|
10
|
+
*
|
|
11
|
+
* Data is fetched on demand (mount + explicit "Refresh"), never on a timer —
|
|
12
|
+
* introspecting a warehouse is expensive, so the user stays in control.
|
|
13
|
+
*/
|
|
14
|
+
import * as React from 'react';
|
|
15
|
+
import { RefreshCw, Loader2, Search, Table2, Download, Columns3 } from 'lucide-react';
|
|
16
|
+
import { Button } from '@object-ui/components';
|
|
17
|
+
import { listRemoteTables, ExternalServiceUnavailableError, } from './api';
|
|
18
|
+
import { ImportObjectDialog } from './ImportObjectDialog';
|
|
19
|
+
export function SchemaBrowser({ datasource }) {
|
|
20
|
+
const [state, setState] = React.useState('idle');
|
|
21
|
+
const [tables, setTables] = React.useState([]);
|
|
22
|
+
const [error, setError] = React.useState(null);
|
|
23
|
+
const [query, setQuery] = React.useState('');
|
|
24
|
+
const [importing, setImporting] = React.useState(null);
|
|
25
|
+
const [dialogOpen, setDialogOpen] = React.useState(false);
|
|
26
|
+
const load = React.useCallback(async () => {
|
|
27
|
+
setState('loading');
|
|
28
|
+
setError(null);
|
|
29
|
+
try {
|
|
30
|
+
const rows = await listRemoteTables(datasource);
|
|
31
|
+
setTables(rows);
|
|
32
|
+
setState('loaded');
|
|
33
|
+
}
|
|
34
|
+
catch (err) {
|
|
35
|
+
if (err instanceof ExternalServiceUnavailableError) {
|
|
36
|
+
setState('unavailable');
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
40
|
+
setState('error');
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}, [datasource]);
|
|
44
|
+
React.useEffect(() => {
|
|
45
|
+
void load();
|
|
46
|
+
}, [load]);
|
|
47
|
+
const filtered = React.useMemo(() => {
|
|
48
|
+
const q = query.trim().toLowerCase();
|
|
49
|
+
if (!q)
|
|
50
|
+
return tables;
|
|
51
|
+
return tables.filter((t) => {
|
|
52
|
+
const label = [t.schema, t.name].filter(Boolean).join('.').toLowerCase();
|
|
53
|
+
return label.includes(q);
|
|
54
|
+
});
|
|
55
|
+
}, [tables, query]);
|
|
56
|
+
const openImport = (t) => {
|
|
57
|
+
setImporting(t);
|
|
58
|
+
setDialogOpen(true);
|
|
59
|
+
};
|
|
60
|
+
if (state === 'unavailable') {
|
|
61
|
+
return _jsx(UnavailableHint, {});
|
|
62
|
+
}
|
|
63
|
+
return (_jsxs("div", { className: "space-y-3", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsxs("div", { className: "relative flex-1", children: [_jsx(Search, { className: "absolute left-2 top-1/2 -translate-y-1/2 h-3.5 w-3.5 text-muted-foreground" }), _jsx("input", { value: query, onChange: (e) => setQuery(e.target.value), placeholder: "Filter tables\u2026", className: "w-full rounded border bg-background pl-7 pr-2 py-1.5 text-xs outline-none focus:ring-1 focus:ring-ring" })] }), _jsxs(Button, { variant: "outline", size: "sm", onClick: () => void load(), disabled: state === 'loading', children: [state === 'loading' ? (_jsx(Loader2, { className: "h-3.5 w-3.5 animate-spin" })) : (_jsx(RefreshCw, { className: "h-3.5 w-3.5" })), _jsx("span", { className: "ml-1.5", children: "Refresh" })] })] }), error && (_jsx("div", { className: "rounded border border-destructive/40 bg-destructive/5 p-2.5 text-xs text-destructive", children: error })), state === 'loading' && tables.length === 0 && (_jsxs("div", { className: "flex items-center justify-center gap-2 py-10 text-sm text-muted-foreground", children: [_jsx(Loader2, { className: "h-4 w-4 animate-spin" }), " Introspecting remote schema\u2026"] })), state === 'loaded' && filtered.length === 0 && (_jsx("div", { className: "py-10 text-center text-sm text-muted-foreground", children: tables.length === 0
|
|
64
|
+
? 'No remote tables found (check the datasource’s allowedSchemas).'
|
|
65
|
+
: 'No tables match the filter.' })), filtered.length > 0 && (_jsx("div", { className: "rounded border bg-background overflow-hidden", children: _jsxs("table", { className: "w-full text-xs", children: [_jsx("thead", { className: "bg-muted/40 text-muted-foreground", children: _jsxs("tr", { children: [_jsx("th", { className: "px-2.5 py-1.5 text-left font-medium", children: "Table" }), _jsx("th", { className: "px-2.5 py-1.5 text-right font-medium", children: "Columns" }), _jsx("th", { className: "px-2.5 py-1.5 text-right font-medium", children: "Rows (est.)" }), _jsx("th", { className: "px-2.5 py-1.5 w-px" })] }) }), _jsx("tbody", { className: "divide-y", children: filtered.map((t) => {
|
|
66
|
+
const key = [t.schema, t.name].filter(Boolean).join('.');
|
|
67
|
+
return (_jsxs("tr", { className: "hover:bg-muted/30", children: [_jsx("td", { className: "px-2.5 py-1.5", children: _jsxs("span", { className: "inline-flex items-center gap-1.5 font-mono", children: [_jsx(Table2, { className: "h-3.5 w-3.5 text-muted-foreground" }), t.schema && _jsxs("span", { className: "text-muted-foreground", children: [t.schema, "."] }), _jsx("span", { className: "font-medium", children: t.name })] }) }), _jsx("td", { className: "px-2.5 py-1.5 text-right tabular-nums", children: _jsxs("span", { className: "inline-flex items-center gap-1 text-muted-foreground", children: [_jsx(Columns3, { className: "h-3 w-3" }), t.columnCount] }) }), _jsx("td", { className: "px-2.5 py-1.5 text-right tabular-nums text-muted-foreground", children: typeof t.rowCountEstimate === 'number'
|
|
68
|
+
? t.rowCountEstimate.toLocaleString()
|
|
69
|
+
: '—' }), _jsx("td", { className: "px-2.5 py-1.5", children: _jsxs(Button, { variant: "ghost", size: "sm", onClick: () => openImport(t), children: [_jsx(Download, { className: "h-3.5 w-3.5" }), _jsx("span", { className: "ml-1.5", children: "Import" })] }) })] }, key));
|
|
70
|
+
}) })] }) })), _jsx(ImportObjectDialog, { datasource: datasource, table: importing, open: dialogOpen, onOpenChange: setDialogOpen })] }));
|
|
71
|
+
}
|
|
72
|
+
function UnavailableHint() {
|
|
73
|
+
return (_jsxs("div", { className: "rounded border border-amber-300 bg-amber-50 dark:bg-amber-950/20 p-3 text-xs text-amber-900 dark:text-amber-200", children: ["Federation is not enabled on this server. The", _jsx("span", { className: "font-mono", children: " external-datasource " }), "service must be registered for table browsing, drafting, and validation to work."] }));
|
|
74
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ValidationPanel — the "validation panel" surface of the external-datasource
|
|
3
|
+
* Studio panel (ADR-0015 §6.4).
|
|
4
|
+
*
|
|
5
|
+
* Runs `POST …/validate` on demand and renders, per federated Object bound to
|
|
6
|
+
* this datasource, whether it still matches the live remote table — plus the
|
|
7
|
+
* structured schema diffs (missing column, type mismatch, …) when it doesn't.
|
|
8
|
+
*
|
|
9
|
+
* This doubles as the on-demand "drift" view: a previously-green object that
|
|
10
|
+
* now reports `missing_column` / `type_mismatch` is exactly remote drift.
|
|
11
|
+
*/
|
|
12
|
+
import * as React from 'react';
|
|
13
|
+
export interface ValidationPanelProps {
|
|
14
|
+
datasource: string;
|
|
15
|
+
}
|
|
16
|
+
export declare function ValidationPanel({ datasource }: ValidationPanelProps): React.JSX.Element;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
|
|
3
|
+
/**
|
|
4
|
+
* ValidationPanel — the "validation panel" surface of the external-datasource
|
|
5
|
+
* Studio panel (ADR-0015 §6.4).
|
|
6
|
+
*
|
|
7
|
+
* Runs `POST …/validate` on demand and renders, per federated Object bound to
|
|
8
|
+
* this datasource, whether it still matches the live remote table — plus the
|
|
9
|
+
* structured schema diffs (missing column, type mismatch, …) when it doesn't.
|
|
10
|
+
*
|
|
11
|
+
* This doubles as the on-demand "drift" view: a previously-green object that
|
|
12
|
+
* now reports `missing_column` / `type_mismatch` is exactly remote drift.
|
|
13
|
+
*/
|
|
14
|
+
import * as React from 'react';
|
|
15
|
+
import { ShieldCheck, ShieldAlert, Loader2, PlayCircle, CheckCircle2 } from 'lucide-react';
|
|
16
|
+
import { Button } from '@object-ui/components';
|
|
17
|
+
import { validateDatasource, ExternalServiceUnavailableError, } from './api';
|
|
18
|
+
const DIFF_LABEL = {
|
|
19
|
+
missing_table: 'Missing table',
|
|
20
|
+
missing_column: 'Missing column',
|
|
21
|
+
type_mismatch: 'Type mismatch',
|
|
22
|
+
nullability_mismatch: 'Nullability mismatch',
|
|
23
|
+
unmapped_column: 'Unmapped column',
|
|
24
|
+
pk_mismatch: 'Primary-key mismatch',
|
|
25
|
+
};
|
|
26
|
+
export function ValidationPanel({ datasource }) {
|
|
27
|
+
const [state, setState] = React.useState('idle');
|
|
28
|
+
const [results, setResults] = React.useState([]);
|
|
29
|
+
const [ok, setOk] = React.useState(null);
|
|
30
|
+
const [error, setError] = React.useState(null);
|
|
31
|
+
const run = React.useCallback(async () => {
|
|
32
|
+
setState('running');
|
|
33
|
+
setError(null);
|
|
34
|
+
try {
|
|
35
|
+
const report = await validateDatasource(datasource);
|
|
36
|
+
setResults(report.results);
|
|
37
|
+
setOk(report.ok);
|
|
38
|
+
setState('done');
|
|
39
|
+
}
|
|
40
|
+
catch (err) {
|
|
41
|
+
if (err instanceof ExternalServiceUnavailableError) {
|
|
42
|
+
setState('unavailable');
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
46
|
+
setState('error');
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}, [datasource]);
|
|
50
|
+
if (state === 'unavailable') {
|
|
51
|
+
return (_jsx("div", { className: "rounded border border-amber-300 bg-amber-50 dark:bg-amber-950/20 p-3 text-xs text-amber-900 dark:text-amber-200", children: "Federation is not enabled on this server, so validation is unavailable." }));
|
|
52
|
+
}
|
|
53
|
+
return (_jsxs("div", { className: "space-y-3", children: [_jsxs("div", { className: "flex items-center justify-between gap-2", children: [_jsxs("p", { className: "text-xs text-muted-foreground", children: ["Check that every federated object on", ' ', _jsx("span", { className: "font-mono", children: datasource }), " still matches its live remote table."] }), _jsxs(Button, { variant: "outline", size: "sm", onClick: () => void run(), disabled: state === 'running', children: [state === 'running' ? (_jsx(Loader2, { className: "h-3.5 w-3.5 animate-spin" })) : (_jsx(PlayCircle, { className: "h-3.5 w-3.5" })), _jsx("span", { className: "ml-1.5", children: "Run validation" })] })] }), error && (_jsx("div", { className: "rounded border border-destructive/40 bg-destructive/5 p-2.5 text-xs text-destructive", children: error })), state === 'done' && ok !== null && (_jsxs("div", { className: `flex items-center gap-2 rounded border p-2.5 text-sm ${ok
|
|
54
|
+
? 'border-emerald-300 bg-emerald-50 dark:bg-emerald-950/20 text-emerald-800 dark:text-emerald-300'
|
|
55
|
+
: 'border-destructive/40 bg-destructive/5 text-destructive'}`, children: [ok ? _jsx(CheckCircle2, { className: "h-4 w-4" }) : _jsx(ShieldAlert, { className: "h-4 w-4" }), ok
|
|
56
|
+
? `All ${results.length} object${results.length === 1 ? '' : 's'} match the remote schema.`
|
|
57
|
+
: `${results.filter((r) => !r.ok).length} of ${results.length} object${results.length === 1 ? '' : 's'} diverge from the remote schema.`] })), state === 'done' && results.length === 0 && (_jsx("div", { className: "py-8 text-center text-sm text-muted-foreground", children: "No federated objects are bound to this datasource yet. Import a table from the Tables tab to get started." })), results.length > 0 && (_jsx("ul", { className: "space-y-2", children: results.map((r) => (_jsx(ResultRow, { result: r }, r.object))) }))] }));
|
|
58
|
+
}
|
|
59
|
+
function ResultRow({ result }) {
|
|
60
|
+
return (_jsxs("li", { className: "rounded border bg-background", children: [_jsxs("div", { className: "flex items-center gap-2 px-2.5 py-1.5", children: [result.ok ? (_jsx(ShieldCheck, { className: "h-3.5 w-3.5 text-emerald-500" })) : (_jsx(ShieldAlert, { className: "h-3.5 w-3.5 text-destructive" })), _jsx("span", { className: "font-mono text-xs font-medium", children: result.object }), !result.ok && (_jsxs("span", { className: "ml-auto text-[11px] text-muted-foreground", children: [result.diffs.length, " diff", result.diffs.length === 1 ? '' : 's'] }))] }), result.diffs.length > 0 && (_jsx("ul", { className: "border-t divide-y", children: result.diffs.map((d, i) => (_jsx(DiffRow, { diff: d }, `${d.kind}:${d.column ?? ''}:${i}`))) }))] }));
|
|
61
|
+
}
|
|
62
|
+
function DiffRow({ diff }) {
|
|
63
|
+
const where = [diff.remoteSchema, diff.remoteName].filter(Boolean).join('.');
|
|
64
|
+
const isError = diff.severity === 'error';
|
|
65
|
+
return (_jsxs("li", { className: "flex flex-wrap items-baseline gap-x-2 gap-y-0.5 px-2.5 py-1.5 text-[11px]", children: [_jsx("span", { className: `rounded px-1 py-0.5 font-medium uppercase tracking-wide text-[9px] ${isError
|
|
66
|
+
? 'bg-destructive/10 text-destructive'
|
|
67
|
+
: 'bg-amber-100 text-amber-800 dark:bg-amber-950/40 dark:text-amber-300'}`, children: DIFF_LABEL[diff.kind] ?? diff.kind }), where && _jsx("span", { className: "font-mono text-muted-foreground", children: where }), diff.column && _jsxs("span", { className: "font-mono", children: [".", diff.column] }), (diff.expected !== undefined || diff.actual !== undefined) && (_jsxs("span", { className: "text-muted-foreground", children: ["expected ", _jsx("span", { className: "font-mono", children: diff.expected ?? '—' }), ", actual", ' ', _jsx("span", { className: "font-mono", children: diff.actual ?? '—' })] }))] }));
|
|
68
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/** A remote table discovered via introspection (allowedSchemas-filtered). */
|
|
2
|
+
export interface RemoteTable {
|
|
3
|
+
schema?: string;
|
|
4
|
+
name: string;
|
|
5
|
+
columnCount: number;
|
|
6
|
+
rowCountEstimate?: number;
|
|
7
|
+
}
|
|
8
|
+
/** Options controlling how a remote table is drafted into an Object. */
|
|
9
|
+
export interface GenerateDraftOpts {
|
|
10
|
+
remoteSchema?: string;
|
|
11
|
+
rename?: Record<string, string>;
|
|
12
|
+
primaryKey?: string[];
|
|
13
|
+
includeColumns?: string[];
|
|
14
|
+
excludeColumns?: string[];
|
|
15
|
+
}
|
|
16
|
+
/** A generated Object draft: structured definition + `*.object.ts` source. */
|
|
17
|
+
export interface ObjectDraft {
|
|
18
|
+
name: string;
|
|
19
|
+
datasource: string;
|
|
20
|
+
definition: Record<string, unknown>;
|
|
21
|
+
source: string;
|
|
22
|
+
review: Array<{
|
|
23
|
+
column: string;
|
|
24
|
+
remoteType: string;
|
|
25
|
+
note: string;
|
|
26
|
+
}>;
|
|
27
|
+
}
|
|
28
|
+
export type SchemaDiffEntryKind = 'missing_table' | 'missing_column' | 'type_mismatch' | 'nullability_mismatch' | 'unmapped_column' | 'pk_mismatch';
|
|
29
|
+
/** A single divergence between a federated Object and its remote table. */
|
|
30
|
+
export interface SchemaDiffEntry {
|
|
31
|
+
kind: SchemaDiffEntryKind;
|
|
32
|
+
remoteSchema?: string;
|
|
33
|
+
remoteName?: string;
|
|
34
|
+
column?: string;
|
|
35
|
+
expected?: string;
|
|
36
|
+
actual?: string;
|
|
37
|
+
severity: 'error' | 'warning';
|
|
38
|
+
}
|
|
39
|
+
/** Per-object validation outcome. */
|
|
40
|
+
export interface SchemaValidationResult {
|
|
41
|
+
ok: boolean;
|
|
42
|
+
datasource: string;
|
|
43
|
+
object: string;
|
|
44
|
+
diffs: SchemaDiffEntry[];
|
|
45
|
+
}
|
|
46
|
+
/** A single remote column captured in a catalog snapshot. */
|
|
47
|
+
export interface ExternalColumn {
|
|
48
|
+
name: string;
|
|
49
|
+
sqlType: string;
|
|
50
|
+
nullable: boolean;
|
|
51
|
+
primaryKey?: boolean;
|
|
52
|
+
suggestedFieldType?: string;
|
|
53
|
+
}
|
|
54
|
+
/** A single remote table/view captured in a catalog snapshot. */
|
|
55
|
+
export interface ExternalTable {
|
|
56
|
+
remoteSchema?: string;
|
|
57
|
+
remoteName: string;
|
|
58
|
+
columns: ExternalColumn[];
|
|
59
|
+
indexes?: Array<{
|
|
60
|
+
name: string;
|
|
61
|
+
columns: string[];
|
|
62
|
+
unique: boolean;
|
|
63
|
+
}>;
|
|
64
|
+
rowCountEstimate?: number;
|
|
65
|
+
}
|
|
66
|
+
/** The persisted snapshot of a federated datasource's remote schema. */
|
|
67
|
+
export interface ExternalCatalog {
|
|
68
|
+
name: string;
|
|
69
|
+
datasource: string;
|
|
70
|
+
snapshotAt: string;
|
|
71
|
+
dialect?: string;
|
|
72
|
+
tables: ExternalTable[];
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Raised when the server replies `503 external_service_unavailable` — the
|
|
76
|
+
* federation service is not wired into this host. Callers render a friendly
|
|
77
|
+
* "enable federation on the server" message instead of a generic failure.
|
|
78
|
+
*/
|
|
79
|
+
export declare class ExternalServiceUnavailableError extends Error {
|
|
80
|
+
constructor();
|
|
81
|
+
}
|
|
82
|
+
/** List remote tables, optionally filtered to a single remote schema. */
|
|
83
|
+
export declare function listRemoteTables(datasource: string, opts?: {
|
|
84
|
+
schema?: string;
|
|
85
|
+
}): Promise<RemoteTable[]>;
|
|
86
|
+
/** Generate an Object draft (structured + `*.object.ts` source) from a table. */
|
|
87
|
+
export declare function generateObjectDraft(datasource: string, remoteName: string, opts?: GenerateDraftOpts): Promise<ObjectDraft>;
|
|
88
|
+
/** Refresh and return the cached remote-schema snapshot. */
|
|
89
|
+
export declare function refreshCatalog(datasource: string): Promise<ExternalCatalog>;
|
|
90
|
+
/** Validate every federated Object bound to this datasource. */
|
|
91
|
+
export declare function validateDatasource(datasource: string): Promise<{
|
|
92
|
+
ok: boolean;
|
|
93
|
+
results: SchemaValidationResult[];
|
|
94
|
+
}>;
|
|
95
|
+
/**
|
|
96
|
+
* Persist a generated Object draft as a real `object` metadata item
|
|
97
|
+
* (PUT `/api/v1/meta/object/:name`, mirroring `MetadataClient.save`). The
|
|
98
|
+
* draft's `definition` is the parseable ObjectSchema body.
|
|
99
|
+
*/
|
|
100
|
+
export declare function importObjectDraft(draft: ObjectDraft): Promise<void>;
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
|
|
2
|
+
/**
|
|
3
|
+
* Thin REST client for the External Datasource Federation routes
|
|
4
|
+
* (ADR-0015 §6.2, framework `registerExternalDatasourceRoutes`).
|
|
5
|
+
*
|
|
6
|
+
* Mounted server-side under `/api/v1/datasources/:name/external/*`:
|
|
7
|
+
*
|
|
8
|
+
* GET /tables[?schema=] → { tables: RemoteTable[] }
|
|
9
|
+
* POST /tables/:remote/draft → { draft: ObjectDraft }
|
|
10
|
+
* POST /refresh-catalog → { catalog: ExternalCatalog }
|
|
11
|
+
* POST /validate → { ok, results: SchemaValidationResult[] }
|
|
12
|
+
*
|
|
13
|
+
* Every route degrades to `503 external_service_unavailable` when the host
|
|
14
|
+
* has not wired the `external-datasource` service — callers surface that as a
|
|
15
|
+
* "federation not enabled on this server" hint rather than a hard error.
|
|
16
|
+
*
|
|
17
|
+
* All calls go through `createAuthenticatedFetch()` so the Bearer token,
|
|
18
|
+
* `X-Tenant-ID`, and `Accept-Language` are injected exactly like every other
|
|
19
|
+
* app-shell REST call (RecordDetailView, ObjectView, …).
|
|
20
|
+
*/
|
|
21
|
+
import { createAuthenticatedFetch } from '@object-ui/auth';
|
|
22
|
+
/**
|
|
23
|
+
* Raised when the server replies `503 external_service_unavailable` — the
|
|
24
|
+
* federation service is not wired into this host. Callers render a friendly
|
|
25
|
+
* "enable federation on the server" message instead of a generic failure.
|
|
26
|
+
*/
|
|
27
|
+
export class ExternalServiceUnavailableError extends Error {
|
|
28
|
+
constructor() {
|
|
29
|
+
super('external_service_unavailable');
|
|
30
|
+
this.name = 'ExternalServiceUnavailableError';
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
// ---------------------------------------------------------------------------
|
|
34
|
+
// Client
|
|
35
|
+
// ---------------------------------------------------------------------------
|
|
36
|
+
const authFetch = createAuthenticatedFetch();
|
|
37
|
+
function serverBase() {
|
|
38
|
+
const raw = import.meta.env?.VITE_SERVER_URL ?? '';
|
|
39
|
+
return raw.replace(/\/+$/, '');
|
|
40
|
+
}
|
|
41
|
+
function externalBase(datasource) {
|
|
42
|
+
return `${serverBase()}/api/v1/datasources/${encodeURIComponent(datasource)}/external`;
|
|
43
|
+
}
|
|
44
|
+
async function jsonOrThrow(res) {
|
|
45
|
+
if (res.status === 503) {
|
|
46
|
+
// Body is `{ error: 'external_service_unavailable' }` — treat distinctly.
|
|
47
|
+
let body;
|
|
48
|
+
try {
|
|
49
|
+
body = await res.json();
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
body = undefined;
|
|
53
|
+
}
|
|
54
|
+
const code = body && typeof body === 'object' && 'error' in body
|
|
55
|
+
? String(body.error)
|
|
56
|
+
: '';
|
|
57
|
+
if (code === 'external_service_unavailable')
|
|
58
|
+
throw new ExternalServiceUnavailableError();
|
|
59
|
+
}
|
|
60
|
+
if (!res.ok) {
|
|
61
|
+
let detail = `${res.status} ${res.statusText}`;
|
|
62
|
+
try {
|
|
63
|
+
const body = await res.json();
|
|
64
|
+
if (body && typeof body === 'object' && 'error' in body) {
|
|
65
|
+
detail = String(body.error);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
/* keep status-text detail */
|
|
70
|
+
}
|
|
71
|
+
throw new Error(detail);
|
|
72
|
+
}
|
|
73
|
+
return (await res.json());
|
|
74
|
+
}
|
|
75
|
+
/** List remote tables, optionally filtered to a single remote schema. */
|
|
76
|
+
export async function listRemoteTables(datasource, opts = {}) {
|
|
77
|
+
const qs = opts.schema ? `?schema=${encodeURIComponent(opts.schema)}` : '';
|
|
78
|
+
const res = await authFetch(`${externalBase(datasource)}/tables${qs}`, {
|
|
79
|
+
method: 'GET',
|
|
80
|
+
headers: { Accept: 'application/json' },
|
|
81
|
+
});
|
|
82
|
+
const data = await jsonOrThrow(res);
|
|
83
|
+
return data.tables ?? [];
|
|
84
|
+
}
|
|
85
|
+
/** Generate an Object draft (structured + `*.object.ts` source) from a table. */
|
|
86
|
+
export async function generateObjectDraft(datasource, remoteName, opts = {}) {
|
|
87
|
+
const res = await authFetch(`${externalBase(datasource)}/tables/${encodeURIComponent(remoteName)}/draft`, {
|
|
88
|
+
method: 'POST',
|
|
89
|
+
headers: { Accept: 'application/json', 'Content-Type': 'application/json' },
|
|
90
|
+
body: JSON.stringify(opts),
|
|
91
|
+
});
|
|
92
|
+
const data = await jsonOrThrow(res);
|
|
93
|
+
return data.draft;
|
|
94
|
+
}
|
|
95
|
+
/** Refresh and return the cached remote-schema snapshot. */
|
|
96
|
+
export async function refreshCatalog(datasource) {
|
|
97
|
+
const res = await authFetch(`${externalBase(datasource)}/refresh-catalog`, {
|
|
98
|
+
method: 'POST',
|
|
99
|
+
headers: { Accept: 'application/json' },
|
|
100
|
+
});
|
|
101
|
+
const data = await jsonOrThrow(res);
|
|
102
|
+
return data.catalog;
|
|
103
|
+
}
|
|
104
|
+
/** Validate every federated Object bound to this datasource. */
|
|
105
|
+
export async function validateDatasource(datasource) {
|
|
106
|
+
const res = await authFetch(`${externalBase(datasource)}/validate`, {
|
|
107
|
+
method: 'POST',
|
|
108
|
+
headers: { Accept: 'application/json' },
|
|
109
|
+
});
|
|
110
|
+
return jsonOrThrow(res);
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Persist a generated Object draft as a real `object` metadata item
|
|
114
|
+
* (PUT `/api/v1/meta/object/:name`, mirroring `MetadataClient.save`). The
|
|
115
|
+
* draft's `definition` is the parseable ObjectSchema body.
|
|
116
|
+
*/
|
|
117
|
+
export async function importObjectDraft(draft) {
|
|
118
|
+
const res = await authFetch(`${serverBase()}/api/v1/meta/object/${encodeURIComponent(draft.name)}`, {
|
|
119
|
+
method: 'PUT',
|
|
120
|
+
headers: { Accept: 'application/json', 'Content-Type': 'application/json' },
|
|
121
|
+
body: JSON.stringify(draft.definition),
|
|
122
|
+
});
|
|
123
|
+
await jsonOrThrow(res);
|
|
124
|
+
}
|
|
@@ -29,5 +29,6 @@ export declare function t(key: string, locale?: SupportedLocale | string): strin
|
|
|
29
29
|
* tFormat('engine.directory.description', 'zh-CN', { count: 28, writable: 4 })
|
|
30
30
|
*/
|
|
31
31
|
export declare function tFormat(key: string, locale: SupportedLocale | string | undefined, vars: Record<string, string | number>): string;
|
|
32
|
+
export declare function translateValidationMessage(message: string | undefined, locale?: SupportedLocale | string): string;
|
|
32
33
|
/** Returns the locale string most browsers report (matches navigator.language). */
|
|
33
34
|
export declare function detectLocale(): SupportedLocale;
|