@vertesia/ui 1.5.0-dev.20260807.073259Z → 1.5.0-dev.20260901.005903Z
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/README.md +1 -7
- package/lib/core/components/FormItem.d.ts.map +1 -1
- package/lib/core/components/FormItem.js +2 -3
- package/lib/core/components/FormItem.js.map +1 -1
- package/lib/core/components/InfoTip.d.ts +20 -0
- package/lib/core/components/InfoTip.d.ts.map +1 -0
- package/lib/core/components/InfoTip.js +18 -0
- package/lib/core/components/InfoTip.js.map +1 -0
- package/lib/core/components/index.d.ts +1 -0
- package/lib/core/components/index.d.ts.map +1 -1
- package/lib/core/components/index.js +1 -0
- package/lib/core/components/index.js.map +1 -1
- package/lib/core/components/shadcn/Panel.d.ts.map +1 -1
- package/lib/core/components/shadcn/Panel.js +3 -3
- package/lib/core/components/shadcn/Panel.js.map +1 -1
- package/lib/core/components/shadcn/filters/comboBox/DateCombobox.js +1 -1
- package/lib/core/components/shadcn/filters/comboBox/DateCombobox.js.map +1 -1
- package/lib/core/components/shadcn/filters/filter/dateFilter.d.ts.map +1 -1
- package/lib/core/components/shadcn/filters/filter/dateFilter.js +1 -1
- package/lib/core/components/shadcn/filters/filter/dateFilter.js.map +1 -1
- package/lib/core/components/shadcn/filters/filters.d.ts.map +1 -1
- package/lib/core/components/shadcn/filters/filters.js +1 -1
- package/lib/core/components/shadcn/filters/filters.js.map +1 -1
- package/lib/core/components/shadcn/index.d.ts +1 -0
- package/lib/core/components/shadcn/index.d.ts.map +1 -1
- package/lib/core/components/shadcn/index.js +1 -0
- package/lib/core/components/shadcn/index.js.map +1 -1
- package/lib/core/components/shadcn/modal/dialog.d.ts.map +1 -1
- package/lib/core/components/shadcn/modal/dialog.js +1 -3
- package/lib/core/components/shadcn/modal/dialog.js.map +1 -1
- package/lib/core/components/shadcn/overflowTabs.d.ts +59 -0
- package/lib/core/components/shadcn/overflowTabs.d.ts.map +1 -0
- package/lib/core/components/shadcn/overflowTabs.js +173 -0
- package/lib/core/components/shadcn/overflowTabs.js.map +1 -0
- package/lib/core/components/shadcn/selectBox.js +2 -2
- package/lib/core/components/shadcn/selectBox.js.map +1 -1
- package/lib/core/components/shadcn/theme/ThemeProvider.d.ts +3 -1
- package/lib/core/components/shadcn/theme/ThemeProvider.d.ts.map +1 -1
- package/lib/core/components/shadcn/theme/ThemeProvider.js +8 -9
- package/lib/core/components/shadcn/theme/ThemeProvider.js.map +1 -1
- package/lib/core/utils/dayjs.d.ts +12 -0
- package/lib/core/utils/dayjs.d.ts.map +1 -0
- package/lib/core/utils/dayjs.js +16 -0
- package/lib/core/utils/dayjs.js.map +1 -0
- package/lib/env/index.d.ts +17 -0
- package/lib/env/index.d.ts.map +1 -1
- package/lib/env/index.js +18 -1
- package/lib/env/index.js.map +1 -1
- package/lib/features/agent/PayloadBuilder.d.ts +1 -0
- package/lib/features/agent/PayloadBuilder.d.ts.map +1 -1
- package/lib/features/agent/PayloadBuilder.js +22 -5
- package/lib/features/agent/PayloadBuilder.js.map +1 -1
- package/lib/features/agent/chat/AgentRightPanel.d.ts.map +1 -1
- package/lib/features/agent/chat/AgentRightPanel.js +3 -135
- package/lib/features/agent/chat/AgentRightPanel.js.map +1 -1
- package/lib/features/agent/chat/ArtifactsTab.d.ts.map +1 -1
- package/lib/features/agent/chat/ArtifactsTab.js +1 -1
- package/lib/features/agent/chat/ArtifactsTab.js.map +1 -1
- package/lib/features/agent/chat/AskUserWidget.d.ts.map +1 -1
- package/lib/features/agent/chat/AskUserWidget.js +19 -4
- package/lib/features/agent/chat/AskUserWidget.js.map +1 -1
- package/lib/features/agent/chat/ModernAgentConversation.d.ts +6 -0
- package/lib/features/agent/chat/ModernAgentConversation.d.ts.map +1 -1
- package/lib/features/agent/chat/ModernAgentConversation.js +99 -29
- package/lib/features/agent/chat/ModernAgentConversation.js.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/ActiveWorkstreamsSummary.d.ts.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/ActiveWorkstreamsSummary.js +10 -9
- package/lib/features/agent/chat/ModernAgentOutput/ActiveWorkstreamsSummary.js.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/AllMessagesMixed.d.ts.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/AllMessagesMixed.js +5 -8
- package/lib/features/agent/chat/ModernAgentOutput/AllMessagesMixed.js.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/AttachmentPreview.d.ts.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/AttachmentPreview.js +45 -4
- package/lib/features/agent/chat/ModernAgentOutput/AttachmentPreview.js.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/BatchProgressPanel.js +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/BatchProgressPanel.js.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/Header.d.ts.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/Header.js +3 -3
- package/lib/features/agent/chat/ModernAgentOutput/Header.js.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/MessageItem.d.ts.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/MessageItem.js +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/MessageItem.js.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/StreamingMessage.d.ts.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/StreamingMessage.js +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/StreamingMessage.js.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/ToolCallGroup.js +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/ToolCallGroup.js.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/WorkstreamTabs.d.ts.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/WorkstreamTabs.js +9 -121
- package/lib/features/agent/chat/ModernAgentOutput/WorkstreamTabs.js.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/utils.d.ts +6 -0
- package/lib/features/agent/chat/ModernAgentOutput/utils.d.ts.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/utils.js +19 -11
- package/lib/features/agent/chat/ModernAgentOutput/utils.js.map +1 -1
- package/lib/features/agent/chat/VegaLiteChart.d.ts.map +1 -1
- package/lib/features/agent/chat/VegaLiteChart.js +11 -3
- package/lib/features/agent/chat/VegaLiteChart.js.map +1 -1
- package/lib/features/agent/chat/hooks/useAgentStream.d.ts.map +1 -1
- package/lib/features/agent/chat/hooks/useAgentStream.js +3 -0
- package/lib/features/agent/chat/hooks/useAgentStream.js.map +1 -1
- package/lib/features/document-viewer/UniversalDocumentViewer.d.ts.map +1 -1
- package/lib/features/document-viewer/UniversalDocumentViewer.js +1 -1
- package/lib/features/document-viewer/UniversalDocumentViewer.js.map +1 -1
- package/lib/features/facets/AgentRunnerFacetsNav.d.ts +14 -2
- package/lib/features/facets/AgentRunnerFacetsNav.d.ts.map +1 -1
- package/lib/features/facets/AgentRunnerFacetsNav.js +20 -2
- package/lib/features/facets/AgentRunnerFacetsNav.js.map +1 -1
- package/lib/features/facets/CollectionsFacetsNav.d.ts +3 -3
- package/lib/features/facets/CollectionsFacetsNav.d.ts.map +1 -1
- package/lib/features/facets/CollectionsFacetsNav.js +6 -1
- package/lib/features/facets/CollectionsFacetsNav.js.map +1 -1
- package/lib/features/facets/DocumentsFacetsNav.d.ts +3 -3
- package/lib/features/facets/DocumentsFacetsNav.d.ts.map +1 -1
- package/lib/features/facets/DocumentsFacetsNav.js +20 -8
- package/lib/features/facets/DocumentsFacetsNav.js.map +1 -1
- package/lib/features/facets/InteractionsFacetsNav.d.ts +3 -3
- package/lib/features/facets/InteractionsFacetsNav.d.ts.map +1 -1
- package/lib/features/facets/InteractionsFacetsNav.js +11 -1
- package/lib/features/facets/InteractionsFacetsNav.js.map +1 -1
- package/lib/features/facets/PromptsFacetsNav.d.ts +3 -3
- package/lib/features/facets/PromptsFacetsNav.d.ts.map +1 -1
- package/lib/features/facets/PromptsFacetsNav.js +6 -1
- package/lib/features/facets/PromptsFacetsNav.js.map +1 -1
- package/lib/features/facets/RunsFacetsNav.d.ts +4 -14
- package/lib/features/facets/RunsFacetsNav.d.ts.map +1 -1
- package/lib/features/facets/RunsFacetsNav.js +26 -15
- package/lib/features/facets/RunsFacetsNav.js.map +1 -1
- package/lib/features/facets/WorkflowExecutionsFacetsNav.d.ts +4 -3
- package/lib/features/facets/WorkflowExecutionsFacetsNav.d.ts.map +1 -1
- package/lib/features/facets/WorkflowExecutionsFacetsNav.js +18 -10
- package/lib/features/facets/WorkflowExecutionsFacetsNav.js.map +1 -1
- package/lib/features/facets/index.d.ts +1 -1
- package/lib/features/facets/index.d.ts.map +1 -1
- package/lib/features/facets/index.js.map +1 -1
- package/lib/features/facets/utils/SearchInterface.d.ts +4 -3
- package/lib/features/facets/utils/SearchInterface.d.ts.map +1 -1
- package/lib/features/facets/utils/SearchInterface.js +4 -0
- package/lib/features/facets/utils/SearchInterface.js.map +1 -1
- package/lib/features/layout/GenericPageNavHeader.d.ts +8 -1
- package/lib/features/layout/GenericPageNavHeader.d.ts.map +1 -1
- package/lib/features/layout/GenericPageNavHeader.js +9 -1
- package/lib/features/layout/GenericPageNavHeader.js.map +1 -1
- package/lib/features/magic-pdf/DownloadPopover.d.ts +3 -2
- package/lib/features/magic-pdf/DownloadPopover.d.ts.map +1 -1
- package/lib/features/magic-pdf/DownloadPopover.js.map +1 -1
- package/lib/features/magic-pdf/GroundedExtractionView.d.ts.map +1 -1
- package/lib/features/magic-pdf/GroundedExtractionView.js +51 -64
- package/lib/features/magic-pdf/GroundedExtractionView.js.map +1 -1
- package/lib/features/oauth/McpConnectionsButton.d.ts +1 -1
- package/lib/features/oauth/McpConnectionsButton.d.ts.map +1 -1
- package/lib/features/oauth/McpConnectionsButton.js +2 -2
- package/lib/features/oauth/McpConnectionsButton.js.map +1 -1
- package/lib/features/oauth/McpConnectionsDialog.d.ts +1 -1
- package/lib/features/oauth/McpConnectionsDialog.js +2 -2
- package/lib/features/oauth/McpConnectionsDialog.js.map +1 -1
- package/lib/features/oauth/useMcpConnections.d.ts +4 -5
- package/lib/features/oauth/useMcpConnections.d.ts.map +1 -1
- package/lib/features/oauth/useMcpConnections.js +20 -4
- package/lib/features/oauth/useMcpConnections.js.map +1 -1
- package/lib/features/pdf-viewer/PdfPageRenderer.d.ts.map +1 -1
- package/lib/features/pdf-viewer/PdfPageRenderer.js +9 -11
- package/lib/features/pdf-viewer/PdfPageRenderer.js.map +1 -1
- package/lib/features/pdf-viewer/lazyReactPdf.d.ts +10 -0
- package/lib/features/pdf-viewer/lazyReactPdf.d.ts.map +1 -0
- package/lib/features/pdf-viewer/lazyReactPdf.js +25 -0
- package/lib/features/pdf-viewer/lazyReactPdf.js.map +1 -0
- package/lib/features/store/collections/CollectionsTable.d.ts.map +1 -1
- package/lib/features/store/collections/CollectionsTable.js +1 -3
- package/lib/features/store/collections/CollectionsTable.js.map +1 -1
- package/lib/features/store/collections/EditCollectionView.js +1 -1
- package/lib/features/store/collections/EditCollectionView.js.map +1 -1
- package/lib/features/store/objects/ExportPropertiesModal.d.ts +3 -1
- package/lib/features/store/objects/ExportPropertiesModal.d.ts.map +1 -1
- package/lib/features/store/objects/ExportPropertiesModal.js +5 -5
- package/lib/features/store/objects/ExportPropertiesModal.js.map +1 -1
- package/lib/features/store/objects/components/ContentOverview.d.ts.map +1 -1
- package/lib/features/store/objects/components/ContentOverview.js +4 -10
- package/lib/features/store/objects/components/ContentOverview.js.map +1 -1
- package/lib/features/store/objects/components/TextEditorPanel.d.ts.map +1 -1
- package/lib/features/store/objects/components/TextEditorPanel.js +8 -3
- package/lib/features/store/objects/components/TextEditorPanel.js.map +1 -1
- package/lib/features/store/objects/layout/renderers.d.ts.map +1 -1
- package/lib/features/store/objects/layout/renderers.js +1 -5
- package/lib/features/store/objects/layout/renderers.js.map +1 -1
- package/lib/features/store/objects/search/DocumentSearchContext.d.ts +44 -62
- package/lib/features/store/objects/search/DocumentSearchContext.d.ts.map +1 -1
- package/lib/features/store/objects/search/DocumentSearchContext.js +47 -2
- package/lib/features/store/objects/search/DocumentSearchContext.js.map +1 -1
- package/lib/features/store/objects/selection/actions/DeleteObjectsAction.d.ts.map +1 -1
- package/lib/features/store/objects/selection/actions/DeleteObjectsAction.js +5 -0
- package/lib/features/store/objects/selection/actions/DeleteObjectsAction.js.map +1 -1
- package/lib/features/store/objects/upload/DocumentUploadModal.d.ts +6 -1
- package/lib/features/store/objects/upload/DocumentUploadModal.d.ts.map +1 -1
- package/lib/features/store/objects/upload/DocumentUploadModal.js +4 -3
- package/lib/features/store/objects/upload/DocumentUploadModal.js.map +1 -1
- package/lib/features/store/objects/upload/useSmartFileUploadProcessing.d.ts.map +1 -1
- package/lib/features/store/objects/upload/useSmartFileUploadProcessing.js +2 -2
- package/lib/features/store/objects/upload/useSmartFileUploadProcessing.js.map +1 -1
- package/lib/features/store/types/ContentObjectTypesTable.d.ts.map +1 -1
- package/lib/features/store/types/ContentObjectTypesTable.js +1 -3
- package/lib/features/store/types/ContentObjectTypesTable.js.map +1 -1
- package/lib/features/store/types/IntakePolicyEditor.d.ts.map +1 -1
- package/lib/features/store/types/IntakePolicyEditor.js +12 -2
- package/lib/features/store/types/IntakePolicyEditor.js.map +1 -1
- package/lib/features/store/types/IntakePolicyForm.d.ts.map +1 -1
- package/lib/features/store/types/IntakePolicyForm.js +15 -15
- package/lib/features/store/types/IntakePolicyForm.js.map +1 -1
- package/lib/features/store/types/ObjectSchemaEditor.d.ts.map +1 -1
- package/lib/features/store/types/ObjectSchemaEditor.js +6 -2
- package/lib/features/store/types/ObjectSchemaEditor.js.map +1 -1
- package/lib/features/store/types/TableLayoutEditor.d.ts.map +1 -1
- package/lib/features/store/types/TableLayoutEditor.js +2 -0
- package/lib/features/store/types/TableLayoutEditor.js.map +1 -1
- package/lib/features/store/types/TypeRegistry.d.ts +282 -0
- package/lib/features/store/types/TypeRegistry.d.ts.map +1 -1
- package/lib/features/store/types/search/ObjectTypeSearchContext.d.ts +281 -0
- package/lib/features/store/types/search/ObjectTypeSearchContext.d.ts.map +1 -1
- package/lib/features/user/UserInfo.d.ts.map +1 -1
- package/lib/features/user/UserInfo.js +2 -4
- package/lib/features/user/UserInfo.js.map +1 -1
- package/lib/features/views/ViewActions.d.ts +32 -0
- package/lib/features/views/ViewActions.d.ts.map +1 -0
- package/lib/features/views/ViewActions.js +186 -0
- package/lib/features/views/ViewActions.js.map +1 -0
- package/lib/features/views/ViewDropTarget.d.ts +15 -0
- package/lib/features/views/ViewDropTarget.d.ts.map +1 -0
- package/lib/features/views/ViewDropTarget.js +79 -0
- package/lib/features/views/ViewDropTarget.js.map +1 -0
- package/lib/features/views/ViewExperience.d.ts +3 -2
- package/lib/features/views/ViewExperience.d.ts.map +1 -1
- package/lib/features/views/ViewExperience.js +103 -12
- package/lib/features/views/ViewExperience.js.map +1 -1
- package/lib/features/views/ViewNavigation.d.ts +1 -1
- package/lib/features/views/ViewNavigation.d.ts.map +1 -1
- package/lib/features/views/ViewNavigation.js +14 -5
- package/lib/features/views/ViewNavigation.js.map +1 -1
- package/lib/features/views/ViewResults.d.ts +1 -1
- package/lib/features/views/ViewResults.d.ts.map +1 -1
- package/lib/features/views/ViewResults.js +124 -34
- package/lib/features/views/ViewResults.js.map +1 -1
- package/lib/features/views/index.d.ts +1 -0
- package/lib/features/views/index.d.ts.map +1 -1
- package/lib/features/views/index.js +1 -0
- package/lib/features/views/index.js.map +1 -1
- package/lib/features/views/types.d.ts +46 -1
- package/lib/features/views/types.d.ts.map +1 -1
- package/lib/features/views/viewState.d.ts.map +1 -1
- package/lib/features/views/viewState.js +34 -0
- package/lib/features/views/viewState.js.map +1 -1
- package/lib/i18n/LanguageProvider.d.ts +3 -1
- package/lib/i18n/LanguageProvider.d.ts.map +1 -1
- package/lib/i18n/LanguageProvider.js +9 -7
- package/lib/i18n/LanguageProvider.js.map +1 -1
- package/lib/i18n/instance.d.ts +2 -0
- package/lib/i18n/instance.d.ts.map +1 -1
- package/lib/i18n/instance.js +45 -26
- package/lib/i18n/instance.js.map +1 -1
- package/lib/i18n/locales/ar.json +296 -15
- package/lib/i18n/locales/de.json +294 -13
- package/lib/i18n/locales/en.json +65 -4
- package/lib/i18n/locales/es.json +295 -14
- package/lib/i18n/locales/fr.json +294 -13
- package/lib/i18n/locales/it.json +294 -13
- package/lib/i18n/locales/ja.json +292 -10
- package/lib/i18n/locales/ko.json +292 -10
- package/lib/i18n/locales/pt.json +294 -13
- package/lib/i18n/locales/ru.json +291 -10
- package/lib/i18n/locales/tr.json +291 -10
- package/lib/i18n/locales/zh-TW.json +292 -10
- package/lib/i18n/locales/zh.json +292 -10
- package/lib/router/RouteComponent.d.ts +8 -0
- package/lib/router/RouteComponent.d.ts.map +1 -1
- package/lib/router/RouteComponent.js +41 -9
- package/lib/router/RouteComponent.js.map +1 -1
- package/lib/session/UserSessionProvider.d.ts.map +1 -1
- package/lib/session/UserSessionProvider.js +20 -29
- package/lib/session/UserSessionProvider.js.map +1 -1
- package/lib/session/auth/composable.d.ts.map +1 -1
- package/lib/session/auth/composable.js +25 -19
- package/lib/session/auth/composable.js.map +1 -1
- package/lib/session/auth/domainRouting.d.ts +11 -0
- package/lib/session/auth/domainRouting.d.ts.map +1 -1
- package/lib/session/auth/domainRouting.js +13 -0
- package/lib/session/auth/domainRouting.js.map +1 -1
- package/lib/session/auth/firebase.js +1 -1
- package/lib/session/auth/firebase.js.map +1 -1
- package/lib/session/useUXTracking.d.ts.map +1 -1
- package/lib/session/useUXTracking.js +6 -1
- package/lib/session/useUXTracking.js.map +1 -1
- package/lib/shell/VertesiaShell.d.ts.map +1 -1
- package/lib/shell/VertesiaShell.js +2 -1
- package/lib/shell/VertesiaShell.js.map +1 -1
- package/lib/shell/apps/AppInstallationProvider.d.ts +4 -2
- package/lib/shell/apps/AppInstallationProvider.d.ts.map +1 -1
- package/lib/shell/apps/IframeAppContextSync.d.ts +3 -0
- package/lib/shell/apps/IframeAppContextSync.d.ts.map +1 -0
- package/lib/shell/apps/IframeAppContextSync.js +95 -0
- package/lib/shell/apps/IframeAppContextSync.js.map +1 -0
- package/lib/shell/apps/iframe-auth.d.ts +55 -0
- package/lib/shell/apps/iframe-auth.d.ts.map +1 -0
- package/lib/shell/apps/iframe-auth.js +154 -0
- package/lib/shell/apps/iframe-auth.js.map +1 -0
- package/lib/shell/apps/index.d.ts +2 -0
- package/lib/shell/apps/index.d.ts.map +1 -1
- package/lib/shell/apps/index.js +2 -0
- package/lib/shell/apps/index.js.map +1 -1
- package/lib/vertesia-ui-core.js +199 -4
- package/lib/vertesia-ui-core.js.map +1 -1
- package/lib/vertesia-ui-env.js +1 -1
- package/lib/vertesia-ui-env.js.map +1 -1
- package/lib/vertesia-ui-features.js +975 -35
- package/lib/vertesia-ui-features.js.map +1 -1
- package/lib/vertesia-ui-i18n.BJBGsq-8.chunk.js +5 -0
- package/lib/vertesia-ui-i18n.BJBGsq-8.chunk.js.map +1 -0
- package/lib/vertesia-ui-i18n.BY5YG5cX.chunk.js +5 -0
- package/lib/vertesia-ui-i18n.BY5YG5cX.chunk.js.map +1 -0
- package/lib/vertesia-ui-i18n.Bd5_1BXO.chunk.js +5 -0
- package/lib/vertesia-ui-i18n.Bd5_1BXO.chunk.js.map +1 -0
- package/lib/vertesia-ui-i18n.Bvwej2HH.chunk.js +5 -0
- package/lib/vertesia-ui-i18n.Bvwej2HH.chunk.js.map +1 -0
- package/lib/vertesia-ui-i18n.CMT3f4gf.chunk.js +5 -0
- package/lib/vertesia-ui-i18n.CMT3f4gf.chunk.js.map +1 -0
- package/lib/vertesia-ui-i18n.D56DNPJW.chunk.js +5 -0
- package/lib/vertesia-ui-i18n.D56DNPJW.chunk.js.map +1 -0
- package/lib/vertesia-ui-i18n.DDzKLNx6.chunk.js +5 -0
- package/lib/vertesia-ui-i18n.DDzKLNx6.chunk.js.map +1 -0
- package/lib/vertesia-ui-i18n.D_Am1LpF.chunk.js +5 -0
- package/lib/vertesia-ui-i18n.D_Am1LpF.chunk.js.map +1 -0
- package/lib/vertesia-ui-i18n.DrZizgGV.chunk.js +5 -0
- package/lib/vertesia-ui-i18n.DrZizgGV.chunk.js.map +1 -0
- package/lib/vertesia-ui-i18n.DwHsq86z.chunk.js +5 -0
- package/lib/vertesia-ui-i18n.DwHsq86z.chunk.js.map +1 -0
- package/lib/vertesia-ui-i18n.PLpo0Bbz.chunk.js +5 -0
- package/lib/vertesia-ui-i18n.PLpo0Bbz.chunk.js.map +1 -0
- package/lib/vertesia-ui-i18n.js +2 -38
- package/lib/vertesia-ui-i18n.js.map +1 -1
- package/lib/vertesia-ui-i18n.xVbXALqz.chunk.js +5 -0
- package/lib/vertesia-ui-i18n.xVbXALqz.chunk.js.map +1 -0
- package/lib/vertesia-ui-layout.js +80 -1
- package/lib/vertesia-ui-layout.js.map +1 -1
- package/lib/vertesia-ui-rich-text.js +278 -4
- package/lib/vertesia-ui-rich-text.js.map +1 -1
- package/lib/vertesia-ui-router.js +1 -1
- package/lib/vertesia-ui-router.js.map +1 -1
- package/lib/vertesia-ui-session.js +1 -1
- package/lib/vertesia-ui-session.js.map +1 -1
- package/lib/vertesia-ui-shell.js +118 -1
- package/lib/vertesia-ui-shell.js.map +1 -1
- package/lib/vertesia-ui-widgets.js +336 -20
- package/lib/vertesia-ui-widgets.js.map +1 -1
- package/lib/widgets/markdown/MarkdownRenderer.d.ts.map +1 -1
- package/lib/widgets/markdown/MarkdownRenderer.js +43 -2
- package/lib/widgets/markdown/MarkdownRenderer.js.map +1 -1
- package/lib/widgets/markdown/MermaidDiagram.d.ts.map +1 -1
- package/lib/widgets/markdown/MermaidDiagram.js +35 -22
- package/lib/widgets/markdown/MermaidDiagram.js.map +1 -1
- package/lib/widgets/monacoEditor/MonacoEditor.d.ts.map +1 -1
- package/lib/widgets/monacoEditor/MonacoEditor.js +14 -10
- package/lib/widgets/monacoEditor/MonacoEditor.js.map +1 -1
- package/lib/widgets/xml-viewer/hooks/useCollapsible.d.ts +1 -1
- package/package.json +24 -29
- package/src/core/components/FormItem.tsx +2 -5
- package/src/core/components/InfoTip.test.tsx +33 -0
- package/src/core/components/InfoTip.tsx +32 -0
- package/src/core/components/index.ts +1 -0
- package/src/core/components/shadcn/Panel.tsx +3 -7
- package/src/core/components/shadcn/filters/comboBox/DateCombobox.tsx +1 -1
- package/src/core/components/shadcn/filters/filter/dateFilter.tsx +1 -1
- package/src/core/components/shadcn/filters/filters.tsx +1 -1
- package/src/core/components/shadcn/index.ts +1 -0
- package/src/core/components/shadcn/modal/dialog.test.tsx +35 -0
- package/src/core/components/shadcn/modal/dialog.tsx +0 -4
- package/src/core/components/shadcn/overflowTabs.tsx +320 -0
- package/src/core/components/shadcn/selectBox.tsx +2 -2
- package/src/core/components/shadcn/theme/ThemeProvider.tsx +10 -9
- package/src/core/utils/dayjs.ts +17 -0
- package/src/css/base.css +78 -0
- package/src/env/index.test.ts +94 -0
- package/src/env/index.ts +36 -1
- package/src/features/agent/PayloadBuilder.test.ts +68 -0
- package/src/features/agent/PayloadBuilder.tsx +28 -4
- package/src/features/agent/chat/AgentRightPanel.tsx +2 -252
- package/src/features/agent/chat/ArtifactsTab.tsx +1 -0
- package/src/features/agent/chat/AskUserWidget.test.tsx +20 -1
- package/src/features/agent/chat/AskUserWidget.tsx +22 -6
- package/src/features/agent/chat/ModernAgentConversation.test.tsx +160 -0
- package/src/features/agent/chat/ModernAgentConversation.tsx +111 -31
- package/src/features/agent/chat/ModernAgentOutput/ActiveWorkstreamsSummary.tsx +86 -67
- package/src/features/agent/chat/ModernAgentOutput/AllMessagesMixed.test.tsx +90 -7
- package/src/features/agent/chat/ModernAgentOutput/AllMessagesMixed.tsx +4 -6
- package/src/features/agent/chat/ModernAgentOutput/AttachmentPreview.test.ts +103 -1
- package/src/features/agent/chat/ModernAgentOutput/AttachmentPreview.tsx +50 -4
- package/src/features/agent/chat/ModernAgentOutput/BatchProgressPanel.tsx +1 -1
- package/src/features/agent/chat/ModernAgentOutput/Header.tsx +18 -1
- package/src/features/agent/chat/ModernAgentOutput/MessageItem.tsx +1 -1
- package/src/features/agent/chat/ModernAgentOutput/StreamingMessage.tsx +1 -1
- package/src/features/agent/chat/ModernAgentOutput/ToolCallGroup.tsx +1 -1
- package/src/features/agent/chat/ModernAgentOutput/WorkstreamTabs.tsx +37 -167
- package/src/features/agent/chat/ModernAgentOutput/utils.test.ts +94 -0
- package/src/features/agent/chat/ModernAgentOutput/utils.ts +19 -10
- package/src/features/agent/chat/VegaLiteChart.tsx +32 -14
- package/src/features/agent/chat/hooks/useAgentStream.test.tsx +18 -0
- package/src/features/agent/chat/hooks/useAgentStream.ts +3 -0
- package/src/features/document-viewer/UniversalDocumentViewer.tsx +1 -1
- package/src/features/facets/AgentRunnerFacetsNav.tsx +44 -4
- package/src/features/facets/CollectionsFacetsNav.tsx +15 -4
- package/src/features/facets/DocumentsFacetsNav.tsx +25 -8
- package/src/features/facets/FacetQueryHandlers.test.ts +84 -0
- package/src/features/facets/InteractionsFacetsNav.tsx +20 -4
- package/src/features/facets/PromptsFacetsNav.tsx +15 -4
- package/src/features/facets/RunsFacetsNav.test.ts +59 -0
- package/src/features/facets/RunsFacetsNav.tsx +40 -30
- package/src/features/facets/WorkflowExecutionsFacetsNav.test.ts +57 -0
- package/src/features/facets/WorkflowExecutionsFacetsNav.tsx +36 -16
- package/src/features/facets/index.ts +1 -0
- package/src/features/facets/utils/SearchInterface.tsx +12 -3
- package/src/features/layout/GenericPageNavHeader.tsx +16 -0
- package/src/features/magic-pdf/DownloadPopover.tsx +1 -2
- package/src/features/magic-pdf/GroundedExtractionView.test.tsx +7 -1
- package/src/features/magic-pdf/GroundedExtractionView.tsx +162 -242
- package/src/features/oauth/McpConnectionsButton.test.tsx +18 -1
- package/src/features/oauth/McpConnectionsButton.tsx +6 -2
- package/src/features/oauth/McpConnectionsDialog.tsx +3 -3
- package/src/features/oauth/useMcpConnections.test.ts +1 -0
- package/src/features/oauth/useMcpConnections.ts +24 -7
- package/src/features/pdf-viewer/PdfPageRenderer.tsx +76 -71
- package/src/features/pdf-viewer/lazyReactPdf.ts +33 -0
- package/src/features/store/collections/CollectionsTable.tsx +1 -4
- package/src/features/store/collections/EditCollectionView.tsx +1 -1
- package/src/features/store/objects/ExportPropertiesModal.tsx +25 -16
- package/src/features/store/objects/components/ContentOverview.tsx +2 -28
- package/src/features/store/objects/components/TextEditorPanel.tsx +13 -3
- package/src/features/store/objects/layout/renderers.tsx +1 -6
- package/src/features/store/objects/search/DocumentSearchContext.test.ts +45 -0
- package/src/features/store/objects/search/DocumentSearchContext.ts +54 -4
- package/src/features/store/objects/selection/actions/DeleteObjectsAction.tsx +5 -0
- package/src/features/store/objects/upload/DocumentUploadModal.tsx +10 -3
- package/src/features/store/objects/upload/useSmartFileUploadProcessing.ts +15 -6
- package/src/features/store/types/ContentObjectTypesTable.tsx +1 -4
- package/src/features/store/types/IntakePolicyEditor.tsx +14 -5
- package/src/features/store/types/IntakePolicyForm.tsx +120 -20
- package/src/features/store/types/ObjectSchemaEditor.tsx +6 -2
- package/src/features/store/types/TableLayoutEditor.tsx +2 -0
- package/src/features/user/UserInfo.test.tsx +10 -0
- package/src/features/user/UserInfo.tsx +2 -7
- package/src/features/views/ViewActions.test.tsx +80 -0
- package/src/features/views/ViewActions.tsx +352 -0
- package/src/features/views/ViewDropTarget.test.tsx +150 -0
- package/src/features/views/ViewDropTarget.tsx +140 -0
- package/src/features/views/ViewExperience.test.tsx +72 -0
- package/src/features/views/ViewExperience.tsx +189 -22
- package/src/features/views/ViewMedia.test.tsx +180 -0
- package/src/features/views/ViewNavigation.test.tsx +42 -0
- package/src/features/views/ViewNavigation.tsx +43 -5
- package/src/features/views/ViewResults.tsx +243 -26
- package/src/features/views/index.ts +1 -0
- package/src/features/views/types.ts +50 -0
- package/src/features/views/viewState.test.ts +7 -1
- package/src/features/views/viewState.ts +32 -0
- package/src/i18n/LanguageProvider.tsx +15 -8
- package/src/i18n/instance.test.ts +30 -0
- package/src/i18n/instance.ts +67 -40
- package/src/i18n/locales/ar.json +1192 -911
- package/src/i18n/locales/de.json +1148 -867
- package/src/i18n/locales/en.json +65 -4
- package/src/i18n/locales/es.json +1159 -878
- package/src/i18n/locales/fr.json +1159 -878
- package/src/i18n/locales/it.json +1159 -878
- package/src/i18n/locales/ja.json +1148 -866
- package/src/i18n/locales/ko.json +1148 -866
- package/src/i18n/locales/pt.json +1159 -878
- package/src/i18n/locales/ru.json +1170 -889
- package/src/i18n/locales/tr.json +1148 -867
- package/src/i18n/locales/zh-TW.json +1148 -866
- package/src/i18n/locales/zh.json +1148 -866
- package/src/i18n/rtl.test.ts +16 -7
- package/src/rich-text/VertesiaRichTextEditor.test.tsx +33 -1
- package/src/router/RouteComponent.test.tsx +139 -0
- package/src/router/RouteComponent.tsx +54 -9
- package/src/session/UserSessionProvider.tsx +20 -31
- package/src/session/auth/composable.scope.test.ts +1 -1
- package/src/session/auth/composable.test.ts +61 -1
- package/src/session/auth/composable.ts +29 -23
- package/src/session/auth/domainRouting.test.ts +24 -1
- package/src/session/auth/domainRouting.ts +29 -0
- package/src/session/auth/firebase.ts +1 -1
- package/src/session/useUXTracking.tsx +6 -1
- package/src/shell/VertesiaShell.tsx +2 -0
- package/src/shell/apps/IframeAppContextSync.test.tsx +196 -0
- package/src/shell/apps/IframeAppContextSync.tsx +101 -0
- package/src/shell/apps/iframe-auth.test.ts +118 -0
- package/src/shell/apps/iframe-auth.ts +193 -0
- package/src/shell/apps/index.ts +2 -0
- package/src/widgets/markdown/ArtifactEditingSurface.test.tsx +12 -3
- package/src/widgets/markdown/MarkdownRenderer.tsx +50 -2
- package/src/widgets/markdown/MermaidDiagram.tsx +38 -22
- package/src/widgets/monacoEditor/MonacoEditor.tsx +27 -20
- package/lib/features/magic-pdf/GroundedExtractionAssistantPanel.d.ts +0 -25
- package/lib/features/magic-pdf/GroundedExtractionAssistantPanel.d.ts.map +0 -1
- package/lib/features/magic-pdf/GroundedExtractionAssistantPanel.js +0 -42
- package/lib/features/magic-pdf/GroundedExtractionAssistantPanel.js.map +0 -1
- package/src/features/magic-pdf/GroundedExtractionAssistantPanel.tsx +0 -86
|
@@ -92,6 +92,9 @@ function isVertesiaIssuedToken(token: string | undefined): token is string {
|
|
|
92
92
|
|
|
93
93
|
function canUseVertesiaTokenDirectly(token: string, accountId?: string, projectId?: string): boolean {
|
|
94
94
|
const decoded = decodeToken(token);
|
|
95
|
+
if (!decoded.exp || decoded.exp <= Date.now() / 1000 + 300) {
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
95
98
|
const hasAuthorizationClaims = Boolean(
|
|
96
99
|
decoded.permissions?.length ||
|
|
97
100
|
decoded.account_roles?.length ||
|
|
@@ -117,8 +120,7 @@ export async function fetchComposableToken(
|
|
|
117
120
|
ttl?: number,
|
|
118
121
|
retryCount = 0,
|
|
119
122
|
): Promise<string> {
|
|
120
|
-
|
|
121
|
-
Env.logger.info('Getting/refreshing composable token', {
|
|
123
|
+
Env.logger.debug('Getting/refreshing composable token', {
|
|
122
124
|
vertesia: {
|
|
123
125
|
account_id: accountId,
|
|
124
126
|
project_id: projectId,
|
|
@@ -128,14 +130,12 @@ export async function fetchComposableToken(
|
|
|
128
130
|
|
|
129
131
|
const idToken = await getIdToken(); //get from firebase
|
|
130
132
|
if (!idToken) {
|
|
131
|
-
console.log('No id token found - using cookie auth');
|
|
132
133
|
throw new Error('No id token found');
|
|
133
134
|
}
|
|
134
135
|
|
|
135
136
|
// Use STS endpoint - either configured or default to sts.vertesia.io
|
|
136
137
|
const stsEndpoint = Env.endpoints.sts;
|
|
137
|
-
|
|
138
|
-
Env.logger.info('Using STS for token generation', {
|
|
138
|
+
Env.logger.debug('Using STS for token generation', {
|
|
139
139
|
vertesia: {
|
|
140
140
|
account_id: accountId,
|
|
141
141
|
project_id: projectId,
|
|
@@ -176,8 +176,7 @@ export async function fetchComposableToken(
|
|
|
176
176
|
|
|
177
177
|
if (idToken && stsRes?.status === 404) {
|
|
178
178
|
// User not found in token-server - call ensure-user endpoint
|
|
179
|
-
|
|
180
|
-
Env.logger.info('404: User not found - calling ensure-user endpoint', {
|
|
179
|
+
Env.logger.debug('404: User not found - calling ensure-user endpoint', {
|
|
181
180
|
vertesia: {
|
|
182
181
|
account_id: accountId,
|
|
183
182
|
project_id: projectId,
|
|
@@ -195,8 +194,7 @@ export async function fetchComposableToken(
|
|
|
195
194
|
|
|
196
195
|
if (ensureResponse.status === 412) {
|
|
197
196
|
// No invite - trigger signup
|
|
198
|
-
|
|
199
|
-
Env.logger.info('412: No invite found - signup required', {
|
|
197
|
+
Env.logger.debug('412: No invite found - signup required', {
|
|
200
198
|
vertesia: {
|
|
201
199
|
account_id: accountId,
|
|
202
200
|
project_id: projectId,
|
|
@@ -234,8 +232,7 @@ export async function fetchComposableToken(
|
|
|
234
232
|
}
|
|
235
233
|
|
|
236
234
|
// User created/exists - retry token generation
|
|
237
|
-
|
|
238
|
-
Env.logger.info('User ensured - retrying token generation', {
|
|
235
|
+
Env.logger.debug('User ensured - retrying token generation', {
|
|
239
236
|
vertesia: {
|
|
240
237
|
account_id: accountId,
|
|
241
238
|
project_id: projectId,
|
|
@@ -245,8 +242,7 @@ export async function fetchComposableToken(
|
|
|
245
242
|
}
|
|
246
243
|
|
|
247
244
|
if (idToken && stsRes?.status === 412) {
|
|
248
|
-
|
|
249
|
-
Env.logger.error("412: auth succeeded but user doesn't exist - signup required", {
|
|
245
|
+
Env.logger.info("412: auth succeeded but user doesn't exist - signup required", {
|
|
250
246
|
vertesia: {
|
|
251
247
|
account_id: accountId,
|
|
252
248
|
project_id: projectId,
|
|
@@ -258,7 +254,7 @@ export async function fetchComposableToken(
|
|
|
258
254
|
Env.logger.error('No email found in id token');
|
|
259
255
|
throw new Error('No email found in id token');
|
|
260
256
|
}
|
|
261
|
-
Env.logger.
|
|
257
|
+
Env.logger.info('User not found', {
|
|
262
258
|
vertesia: {
|
|
263
259
|
account_id: accountId,
|
|
264
260
|
project_id: projectId,
|
|
@@ -354,8 +350,7 @@ export async function fetchComposableToken(
|
|
|
354
350
|
}
|
|
355
351
|
|
|
356
352
|
const { token } = await stsRes.json();
|
|
357
|
-
|
|
358
|
-
Env.logger.info('Successfully got token from STS');
|
|
353
|
+
Env.logger.debug('Successfully got token from STS');
|
|
359
354
|
return token;
|
|
360
355
|
} catch (error) {
|
|
361
356
|
if (
|
|
@@ -460,13 +455,24 @@ export async function getComposableToken(
|
|
|
460
455
|
if (!devAuthToken && !useInternalAuth && getFirebaseAuth().currentUser) {
|
|
461
456
|
//we have a firebase user, get the token from there
|
|
462
457
|
AUTH_TOKEN_RAW = await fetchComposableTokenFromFirebaseToken(selectedAccount, selectedProject);
|
|
463
|
-
} else if (!devAuthToken
|
|
464
|
-
//
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
458
|
+
} else if (!devAuthToken) {
|
|
459
|
+
// Embedded apps can reacquire a fresh credential from their host after their cached token expires.
|
|
460
|
+
const refreshCredential = (await Env.authTokenProvider?.()) ?? initToken ?? AUTH_TOKEN_RAW;
|
|
461
|
+
if (
|
|
462
|
+
refreshCredential &&
|
|
463
|
+
isVertesiaIssuedToken(refreshCredential) &&
|
|
464
|
+
canUseVertesiaTokenDirectly(refreshCredential, selectedAccount, selectedProject)
|
|
465
|
+
) {
|
|
466
|
+
AUTH_TOKEN_RAW = refreshCredential;
|
|
467
|
+
} else if (refreshCredential) {
|
|
468
|
+
AUTH_TOKEN_RAW = await fetchComposableToken(
|
|
469
|
+
() => Promise.resolve(refreshCredential),
|
|
470
|
+
selectedAccount,
|
|
471
|
+
selectedProject,
|
|
472
|
+
);
|
|
473
|
+
} else {
|
|
474
|
+
AUTH_TOKEN_RAW = undefined;
|
|
475
|
+
}
|
|
470
476
|
} else if (devAuthToken) {
|
|
471
477
|
AUTH_TOKEN_RAW = devAuthToken;
|
|
472
478
|
}
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import { afterEach, describe, expect, it } from 'vitest';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
centralAuthRedirectUrl,
|
|
4
|
+
mountRootUrl,
|
|
5
|
+
shouldRedirectToCentralAuth,
|
|
6
|
+
shouldUseFirebaseAuth,
|
|
7
|
+
} from './domainRouting';
|
|
3
8
|
|
|
4
9
|
// Stub document.baseURI to simulate the served `<base href>` (deep gateway mount) or its absence.
|
|
5
10
|
function setBaseURI(baseURI: string) {
|
|
@@ -30,6 +35,24 @@ describe('domainRouting', () => {
|
|
|
30
35
|
expect(shouldRedirectToCentralAuth()).toBe(true);
|
|
31
36
|
});
|
|
32
37
|
|
|
38
|
+
it('carries the selected account and project through central auth for a gateway-mounted app', () => {
|
|
39
|
+
const redirect = centralAuthRedirectUrl({
|
|
40
|
+
centralAuthUrl: 'https://internal-auth.vertesia.app/',
|
|
41
|
+
stsEndpoint: 'https://sts.example.test',
|
|
42
|
+
returnUrl: new URL('https://apps.example.test/tenants/t/apps/a/versions/v/app/?view=grid'),
|
|
43
|
+
state: 'state-1',
|
|
44
|
+
accountId: 'account-1',
|
|
45
|
+
projectId: 'project-1',
|
|
46
|
+
});
|
|
47
|
+
const returnUrl = new URL(redirect.searchParams.get('redirect_uri') || '');
|
|
48
|
+
|
|
49
|
+
expect(redirect.searchParams.get('sts')).toBe('https://sts.example.test');
|
|
50
|
+
expect(redirect.searchParams.get('state')).toBe('state-1');
|
|
51
|
+
expect(returnUrl.toString()).toBe(
|
|
52
|
+
'https://apps.example.test/tenants/t/apps/a/versions/v/app/?view=grid&p=project-1&a=account-1',
|
|
53
|
+
);
|
|
54
|
+
});
|
|
55
|
+
|
|
33
56
|
describe('mountRootUrl', () => {
|
|
34
57
|
it('returns the deep gateway mount root (dropping any deep route / query / hash)', () => {
|
|
35
58
|
const mount = 'https://gw.example.com/tenants/05948c_5ed5f4/apps/furniture-catalog/versions/v1/app/';
|
|
@@ -12,6 +12,35 @@ export function shouldRedirectToCentralAuth(_hostname?: string) {
|
|
|
12
12
|
return !shouldUseFirebaseAuth();
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
+
interface CentralAuthRedirectOptions {
|
|
16
|
+
centralAuthUrl: string;
|
|
17
|
+
stsEndpoint: string;
|
|
18
|
+
returnUrl: URL;
|
|
19
|
+
state: string;
|
|
20
|
+
accountId?: string;
|
|
21
|
+
projectId?: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** Build a central-auth round trip without losing the app's requested account/project selection. */
|
|
25
|
+
export function centralAuthRedirectUrl({
|
|
26
|
+
centralAuthUrl,
|
|
27
|
+
stsEndpoint,
|
|
28
|
+
returnUrl,
|
|
29
|
+
state,
|
|
30
|
+
accountId,
|
|
31
|
+
projectId,
|
|
32
|
+
}: CentralAuthRedirectOptions): URL {
|
|
33
|
+
const selectedReturnUrl = new URL(returnUrl);
|
|
34
|
+
if (projectId) selectedReturnUrl.searchParams.set('p', projectId);
|
|
35
|
+
if (accountId) selectedReturnUrl.searchParams.set('a', accountId);
|
|
36
|
+
|
|
37
|
+
const url = new URL(centralAuthUrl);
|
|
38
|
+
url.searchParams.set('sts', stsEndpoint);
|
|
39
|
+
url.searchParams.set('redirect_uri', selectedReturnUrl.toString());
|
|
40
|
+
url.searchParams.set('state', state);
|
|
41
|
+
return url;
|
|
42
|
+
}
|
|
43
|
+
|
|
15
44
|
/**
|
|
16
45
|
* The page URL to return to after a central-auth round-trip (`redirect_uri`).
|
|
17
46
|
*
|
|
@@ -139,7 +139,7 @@ export async function getFirebaseAuthToken(refresh?: boolean) {
|
|
|
139
139
|
return user
|
|
140
140
|
.getIdToken(refresh)
|
|
141
141
|
.then((token) => {
|
|
142
|
-
Env.logger.
|
|
142
|
+
Env.logger.debug('Got Firebase token', {
|
|
143
143
|
vertesia: {
|
|
144
144
|
user_email: user.email,
|
|
145
145
|
user_name: user.displayName,
|
|
@@ -23,7 +23,12 @@ export function useUXTracking() {
|
|
|
23
23
|
console.debug('track event', eventName, eventProperties);
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
//GA via firebase
|
|
26
|
+
// GA via firebase — needs a complete Firebase config. A partial one (no apiKey, as in
|
|
27
|
+
// central-auth deployments and local setups) would make the Installations SDK log an
|
|
28
|
+
// async FirebaseError on every event, so analytics is a no-op there.
|
|
29
|
+
if (!Env.firebase?.apiKey) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
27
32
|
logEvent(getFirebaseAnalytics(), eventName, { ...eventProperties, debug_mode: !Env.isProd });
|
|
28
33
|
};
|
|
29
34
|
|
|
@@ -3,6 +3,7 @@ import { TypeRegistryProvider, UserPermissionProvider } from '@vertesia/ui/featu
|
|
|
3
3
|
import { LanguageBoundI18nProvider, LanguageProvider, type SupportedLanguage } from '@vertesia/ui/i18n';
|
|
4
4
|
import { DevSessionProvider, UserSessionProvider } from '@vertesia/ui/session';
|
|
5
5
|
import type { ReactNode } from 'react';
|
|
6
|
+
import { IframeAppContextSync } from './apps/IframeAppContextSync.js';
|
|
6
7
|
import { SigninScreen } from './login/SigninScreen';
|
|
7
8
|
import { SplashScreen } from './SplashScreen';
|
|
8
9
|
|
|
@@ -35,6 +36,7 @@ export function VertesiaShell({
|
|
|
35
36
|
<ThemeProvider defaultTheme="system" storageKey="vite-ui-theme">
|
|
36
37
|
<LanguageProvider defaultLanguage={defaultLanguage}>
|
|
37
38
|
<LanguageBoundI18nProvider>
|
|
39
|
+
<IframeAppContextSync />
|
|
38
40
|
{!authToken && (
|
|
39
41
|
<>
|
|
40
42
|
<SplashScreen icon={loadingIcon} />
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
// @vitest-environment jsdom
|
|
2
|
+
|
|
3
|
+
import { act, cleanup, render, screen, waitFor } from '@testing-library/react';
|
|
4
|
+
import { afterEach, describe, expect, it, vi } from 'vitest';
|
|
5
|
+
import { ThemeProvider, useTheme } from '../../core/index.js';
|
|
6
|
+
import { LanguageProvider, useLanguage } from '../../i18n/index.js';
|
|
7
|
+
import { IframeAppContextSync } from './IframeAppContextSync.js';
|
|
8
|
+
import {
|
|
9
|
+
IFRAME_APP_CONTEXT,
|
|
10
|
+
IFRAME_APP_CONTEXT_REQUEST,
|
|
11
|
+
IFRAME_APP_HOST_ORIGIN_PARAM,
|
|
12
|
+
IFRAME_APP_LOCATION_CHANGE,
|
|
13
|
+
IFRAME_APP_NAVIGATE,
|
|
14
|
+
} from './iframe-auth.js';
|
|
15
|
+
|
|
16
|
+
const originalParent = Object.getOwnPropertyDescriptor(window, 'parent');
|
|
17
|
+
const originalReferrer = Object.getOwnPropertyDescriptor(document, 'referrer');
|
|
18
|
+
|
|
19
|
+
afterEach(() => {
|
|
20
|
+
cleanup();
|
|
21
|
+
window.history.replaceState(null, '', '/');
|
|
22
|
+
localStorage.clear();
|
|
23
|
+
sessionStorage.clear();
|
|
24
|
+
document.documentElement.classList.remove('light', 'dark');
|
|
25
|
+
if (originalParent) Object.defineProperty(window, 'parent', originalParent);
|
|
26
|
+
else Reflect.deleteProperty(window, 'parent');
|
|
27
|
+
if (originalReferrer) Object.defineProperty(document, 'referrer', originalReferrer);
|
|
28
|
+
else Reflect.deleteProperty(document, 'referrer');
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
function ContextProbe() {
|
|
32
|
+
const { theme } = useTheme();
|
|
33
|
+
const { language } = useLanguage();
|
|
34
|
+
return <div>{`${theme}:${language}`}</div>;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
describe('IframeAppContextSync', () => {
|
|
38
|
+
it('requests and applies host presentation state without overwriting standalone preferences', async () => {
|
|
39
|
+
const postMessage = vi.fn();
|
|
40
|
+
const parentWindow = { postMessage } as unknown as Window;
|
|
41
|
+
Object.defineProperty(window, 'parent', { configurable: true, value: parentWindow });
|
|
42
|
+
Object.defineProperty(document, 'referrer', {
|
|
43
|
+
configurable: true,
|
|
44
|
+
value: 'https://cloud.vertesia.io/app/sample',
|
|
45
|
+
});
|
|
46
|
+
localStorage.setItem('custom-theme', 'dark');
|
|
47
|
+
localStorage.setItem('custom-language', 'en');
|
|
48
|
+
|
|
49
|
+
render(
|
|
50
|
+
<ThemeProvider storageKey="custom-theme">
|
|
51
|
+
<LanguageProvider storageKey="custom-language">
|
|
52
|
+
<IframeAppContextSync />
|
|
53
|
+
<ContextProbe />
|
|
54
|
+
</LanguageProvider>
|
|
55
|
+
</ThemeProvider>,
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
expect(parentWindow.postMessage).toHaveBeenCalledWith(
|
|
59
|
+
{ type: IFRAME_APP_CONTEXT_REQUEST },
|
|
60
|
+
'https://cloud.vertesia.io',
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
window.dispatchEvent(
|
|
64
|
+
new MessageEvent('message', {
|
|
65
|
+
data: { type: IFRAME_APP_CONTEXT, theme: 'light', language: 'fr' },
|
|
66
|
+
origin: 'https://attacker.example.com',
|
|
67
|
+
source: parentWindow,
|
|
68
|
+
}),
|
|
69
|
+
);
|
|
70
|
+
expect(screen.getByText('dark:en')).toBeTruthy();
|
|
71
|
+
|
|
72
|
+
act(() => {
|
|
73
|
+
window.dispatchEvent(
|
|
74
|
+
new MessageEvent('message', {
|
|
75
|
+
data: { type: IFRAME_APP_CONTEXT, theme: 'light', language: 'fr' },
|
|
76
|
+
origin: 'https://cloud.vertesia.io',
|
|
77
|
+
source: parentWindow,
|
|
78
|
+
}),
|
|
79
|
+
);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
await waitFor(() => expect(screen.getByText('light:fr')).toBeTruthy());
|
|
83
|
+
expect(localStorage.getItem('custom-theme')).toBe('dark');
|
|
84
|
+
expect(localStorage.getItem('custom-language')).toBe('en');
|
|
85
|
+
expect(postMessage.mock.calls.filter(([message]) => message.type === IFRAME_APP_CONTEXT_REQUEST)).toHaveLength(
|
|
86
|
+
1,
|
|
87
|
+
);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it('applies same-origin host navigation without reloading the document', () => {
|
|
91
|
+
const parentWindow = { postMessage: vi.fn() } as unknown as Window;
|
|
92
|
+
Object.defineProperty(window, 'parent', { configurable: true, value: parentWindow });
|
|
93
|
+
Object.defineProperty(document, 'referrer', {
|
|
94
|
+
configurable: true,
|
|
95
|
+
value: 'https://cloud.vertesia.io/app/sample',
|
|
96
|
+
});
|
|
97
|
+
localStorage.setItem('vite-ui-theme', 'dark');
|
|
98
|
+
localStorage.setItem('vertesia-ui-language', 'en');
|
|
99
|
+
window.history.replaceState(null, '', '/app/');
|
|
100
|
+
const popstate = vi.fn();
|
|
101
|
+
window.addEventListener('popstate', popstate);
|
|
102
|
+
|
|
103
|
+
render(
|
|
104
|
+
<ThemeProvider>
|
|
105
|
+
<LanguageProvider>
|
|
106
|
+
<IframeAppContextSync />
|
|
107
|
+
</LanguageProvider>
|
|
108
|
+
</ThemeProvider>,
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
window.dispatchEvent(
|
|
112
|
+
new MessageEvent('message', {
|
|
113
|
+
data: { type: IFRAME_APP_NAVIGATE, url: 'https://attacker.example.com/stolen' },
|
|
114
|
+
origin: 'https://cloud.vertesia.io',
|
|
115
|
+
source: parentWindow,
|
|
116
|
+
}),
|
|
117
|
+
);
|
|
118
|
+
expect(window.location.pathname).toBe('/app/');
|
|
119
|
+
|
|
120
|
+
const target = `${window.location.origin}/app/reports?__vertesia_slot=content`;
|
|
121
|
+
window.dispatchEvent(
|
|
122
|
+
new MessageEvent('message', {
|
|
123
|
+
data: { type: IFRAME_APP_NAVIGATE, url: target },
|
|
124
|
+
origin: 'https://cloud.vertesia.io',
|
|
125
|
+
source: parentWindow,
|
|
126
|
+
}),
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
expect(window.location.pathname).toBe('/app/reports');
|
|
130
|
+
expect(window.location.search).toBe('?__vertesia_slot=content');
|
|
131
|
+
expect(popstate).toHaveBeenCalledTimes(1);
|
|
132
|
+
window.removeEventListener('popstate', popstate);
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
it('acknowledges host navigation when the iframe is already at the requested URL', () => {
|
|
136
|
+
const parentWindow = { postMessage: vi.fn() } as unknown as Window;
|
|
137
|
+
Object.defineProperty(window, 'parent', { configurable: true, value: parentWindow });
|
|
138
|
+
localStorage.setItem('vite-ui-theme', 'dark');
|
|
139
|
+
window.history.replaceState(
|
|
140
|
+
null,
|
|
141
|
+
'',
|
|
142
|
+
`/app/reports?${IFRAME_APP_HOST_ORIGIN_PARAM}=https%3A%2F%2Fcloud.vertesia.io`,
|
|
143
|
+
);
|
|
144
|
+
|
|
145
|
+
render(
|
|
146
|
+
<ThemeProvider>
|
|
147
|
+
<LanguageProvider>
|
|
148
|
+
<IframeAppContextSync />
|
|
149
|
+
</LanguageProvider>
|
|
150
|
+
</ThemeProvider>,
|
|
151
|
+
);
|
|
152
|
+
parentWindow.postMessage = vi.fn();
|
|
153
|
+
|
|
154
|
+
window.dispatchEvent(
|
|
155
|
+
new MessageEvent('message', {
|
|
156
|
+
data: { type: IFRAME_APP_NAVIGATE, url: window.location.href },
|
|
157
|
+
origin: 'https://cloud.vertesia.io',
|
|
158
|
+
source: parentWindow,
|
|
159
|
+
}),
|
|
160
|
+
);
|
|
161
|
+
|
|
162
|
+
expect(parentWindow.postMessage).toHaveBeenCalledWith(
|
|
163
|
+
{ type: IFRAME_APP_LOCATION_CHANGE, url: window.location.href },
|
|
164
|
+
'https://cloud.vertesia.io',
|
|
165
|
+
);
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
it('reports app-initiated history navigation to the embedding Studio', () => {
|
|
169
|
+
const parentWindow = { postMessage: vi.fn() } as unknown as Window;
|
|
170
|
+
Object.defineProperty(window, 'parent', { configurable: true, value: parentWindow });
|
|
171
|
+
window.history.replaceState(null, '', `/app/?${IFRAME_APP_HOST_ORIGIN_PARAM}=https%3A%2F%2Fcloud.vertesia.io`);
|
|
172
|
+
localStorage.setItem('vite-ui-theme', 'dark');
|
|
173
|
+
localStorage.setItem('vertesia-ui-language', 'en');
|
|
174
|
+
|
|
175
|
+
render(
|
|
176
|
+
<ThemeProvider>
|
|
177
|
+
<LanguageProvider>
|
|
178
|
+
<IframeAppContextSync />
|
|
179
|
+
</LanguageProvider>
|
|
180
|
+
</ThemeProvider>,
|
|
181
|
+
);
|
|
182
|
+
parentWindow.postMessage = vi.fn();
|
|
183
|
+
|
|
184
|
+
window.history.pushState(null, '', '/app/reports?period=week');
|
|
185
|
+
|
|
186
|
+
expect(parentWindow.postMessage).toHaveBeenCalledWith(
|
|
187
|
+
{
|
|
188
|
+
type: IFRAME_APP_LOCATION_CHANGE,
|
|
189
|
+
url:
|
|
190
|
+
`${window.location.origin}/app/reports?period=week&` +
|
|
191
|
+
`${IFRAME_APP_HOST_ORIGIN_PARAM}=https%3A%2F%2Fcloud.vertesia.io`,
|
|
192
|
+
},
|
|
193
|
+
'https://cloud.vertesia.io',
|
|
194
|
+
);
|
|
195
|
+
});
|
|
196
|
+
});
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
|
+
import { useTheme } from '../../core/components/shadcn/theme/ThemeProvider.js';
|
|
3
|
+
import { useLanguage } from '../../i18n/LanguageProvider.js';
|
|
4
|
+
import {
|
|
5
|
+
IFRAME_APP_CONTEXT_REQUEST,
|
|
6
|
+
IFRAME_APP_HOST_ORIGIN_PARAM,
|
|
7
|
+
IFRAME_APP_LOCATION_CHANGE,
|
|
8
|
+
type IframeAppContextRequest,
|
|
9
|
+
type IframeAppLocationChange,
|
|
10
|
+
isIframeAppContext,
|
|
11
|
+
isIframeAppNavigate,
|
|
12
|
+
resolveIframeHostOrigin,
|
|
13
|
+
} from './iframe-auth.js';
|
|
14
|
+
|
|
15
|
+
function preserveIframeHostOrigin(url: string | URL | null | undefined): string | URL | null | undefined {
|
|
16
|
+
if (url === null || url === undefined) return url;
|
|
17
|
+
const hostOrigin = new URL(window.location.href).searchParams.get(IFRAME_APP_HOST_ORIGIN_PARAM);
|
|
18
|
+
if (!hostOrigin) return url;
|
|
19
|
+
|
|
20
|
+
try {
|
|
21
|
+
const target = new URL(url, window.location.href);
|
|
22
|
+
if (target.origin !== window.location.origin) return url;
|
|
23
|
+
target.searchParams.set(IFRAME_APP_HOST_ORIGIN_PARAM, hostOrigin);
|
|
24
|
+
return target;
|
|
25
|
+
} catch {
|
|
26
|
+
return url;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** Applies context and navigation supplied by an embedding Studio without changing standalone preferences. */
|
|
31
|
+
export function IframeAppContextSync() {
|
|
32
|
+
const { setTheme } = useTheme();
|
|
33
|
+
const { setLanguage } = useLanguage();
|
|
34
|
+
|
|
35
|
+
useEffect(() => {
|
|
36
|
+
const parentOrigin = resolveIframeHostOrigin();
|
|
37
|
+
if (!parentOrigin) return;
|
|
38
|
+
|
|
39
|
+
const reportLocation = () => {
|
|
40
|
+
const message = {
|
|
41
|
+
type: IFRAME_APP_LOCATION_CHANGE,
|
|
42
|
+
url: window.location.href,
|
|
43
|
+
} satisfies IframeAppLocationChange;
|
|
44
|
+
window.parent.postMessage(message, parentOrigin);
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const originalPushState = window.history.pushState;
|
|
48
|
+
const originalReplaceState = window.history.replaceState;
|
|
49
|
+
const pushState: History['pushState'] = (data, unused, url) => {
|
|
50
|
+
originalPushState.call(window.history, data, unused, preserveIframeHostOrigin(url));
|
|
51
|
+
reportLocation();
|
|
52
|
+
};
|
|
53
|
+
const replaceState: History['replaceState'] = (data, unused, url) => {
|
|
54
|
+
originalReplaceState.call(window.history, data, unused, preserveIframeHostOrigin(url));
|
|
55
|
+
reportLocation();
|
|
56
|
+
};
|
|
57
|
+
window.history.pushState = pushState;
|
|
58
|
+
window.history.replaceState = replaceState;
|
|
59
|
+
|
|
60
|
+
const onMessage = (event: MessageEvent<unknown>) => {
|
|
61
|
+
if (event.source !== window.parent || event.origin !== parentOrigin) return;
|
|
62
|
+
if (isIframeAppContext(event.data)) {
|
|
63
|
+
const context = event.data;
|
|
64
|
+
setTheme(context.theme, { persist: false });
|
|
65
|
+
setLanguage(context.language, { persist: false });
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
if (isIframeAppNavigate(event.data)) {
|
|
69
|
+
let target: URL;
|
|
70
|
+
try {
|
|
71
|
+
target = new URL(event.data.url, window.location.href);
|
|
72
|
+
} catch {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
if (target.origin !== window.location.origin) return;
|
|
76
|
+
if (target.href === window.location.href) {
|
|
77
|
+
// Acknowledge no-op navigation so the host does not wait forever and suppress later app routing.
|
|
78
|
+
reportLocation();
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
window.history.replaceState(window.history.state, '', target);
|
|
82
|
+
window.dispatchEvent(new PopStateEvent('popstate', { state: window.history.state }));
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
const request = { type: IFRAME_APP_CONTEXT_REQUEST } satisfies IframeAppContextRequest;
|
|
86
|
+
window.addEventListener('message', onMessage);
|
|
87
|
+
window.addEventListener('popstate', reportLocation);
|
|
88
|
+
window.addEventListener('hashchange', reportLocation);
|
|
89
|
+
window.parent.postMessage(request, parentOrigin);
|
|
90
|
+
reportLocation();
|
|
91
|
+
return () => {
|
|
92
|
+
window.removeEventListener('message', onMessage);
|
|
93
|
+
window.removeEventListener('popstate', reportLocation);
|
|
94
|
+
window.removeEventListener('hashchange', reportLocation);
|
|
95
|
+
if (window.history.pushState === pushState) window.history.pushState = originalPushState;
|
|
96
|
+
if (window.history.replaceState === replaceState) window.history.replaceState = originalReplaceState;
|
|
97
|
+
};
|
|
98
|
+
}, [setLanguage, setTheme]);
|
|
99
|
+
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
// @vitest-environment jsdom
|
|
2
|
+
|
|
3
|
+
import { afterEach, describe, expect, it } from 'vitest';
|
|
4
|
+
import {
|
|
5
|
+
IFRAME_APP_HOST_ORIGIN_PARAM,
|
|
6
|
+
IFRAME_AUTH_REQUEST,
|
|
7
|
+
IFRAME_AUTH_RESPONSE,
|
|
8
|
+
requestIframeHostAuthToken,
|
|
9
|
+
resolveIframeHostOrigin,
|
|
10
|
+
} from './iframe-auth.js';
|
|
11
|
+
|
|
12
|
+
const originalParent = Object.getOwnPropertyDescriptor(window, 'parent');
|
|
13
|
+
const originalReferrer = Object.getOwnPropertyDescriptor(document, 'referrer');
|
|
14
|
+
|
|
15
|
+
afterEach(() => {
|
|
16
|
+
window.history.replaceState(null, '', '/');
|
|
17
|
+
window.sessionStorage.clear();
|
|
18
|
+
if (originalParent) Object.defineProperty(window, 'parent', originalParent);
|
|
19
|
+
else Reflect.deleteProperty(window, 'parent');
|
|
20
|
+
if (originalReferrer) Object.defineProperty(document, 'referrer', originalReferrer);
|
|
21
|
+
else Reflect.deleteProperty(document, 'referrer');
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
describe('iframe host authentication', () => {
|
|
25
|
+
it('resolves an explicit trusted host origin', () => {
|
|
26
|
+
const parentWindow = { postMessage: () => undefined } as unknown as Window;
|
|
27
|
+
Object.defineProperty(window, 'parent', { configurable: true, value: parentWindow });
|
|
28
|
+
window.history.replaceState(null, '', `/?${IFRAME_APP_HOST_ORIGIN_PARAM}=https%3A%2F%2Fcloud.vertesia.io`);
|
|
29
|
+
|
|
30
|
+
expect(resolveIframeHostOrigin()).toBe('https://cloud.vertesia.io');
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it('accepts a branch Studio UI origin', () => {
|
|
34
|
+
const parentWindow = { postMessage: () => undefined } as unknown as Window;
|
|
35
|
+
Object.defineProperty(window, 'parent', { configurable: true, value: parentWindow });
|
|
36
|
+
window.history.replaceState(
|
|
37
|
+
null,
|
|
38
|
+
'',
|
|
39
|
+
`/?${IFRAME_APP_HOST_ORIGIN_PARAM}=https%3A%2F%2Fdev-feat-iframe.ui.dev1.vertesia.io`,
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
expect(resolveIframeHostOrigin()).toBe('https://dev-feat-iframe.ui.dev1.vertesia.io');
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('rejects untrusted query and referrer origins', () => {
|
|
46
|
+
const parentWindow = { postMessage: () => undefined } as unknown as Window;
|
|
47
|
+
Object.defineProperty(window, 'parent', { configurable: true, value: parentWindow });
|
|
48
|
+
window.history.replaceState(null, '', `/?${IFRAME_APP_HOST_ORIGIN_PARAM}=https%3A%2F%2Fevil.example.com`);
|
|
49
|
+
Object.defineProperty(document, 'referrer', {
|
|
50
|
+
configurable: true,
|
|
51
|
+
value: 'https://referrer.example.com/embed',
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
expect(resolveIframeHostOrigin()).toBeUndefined();
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it('rejects a shared Vertesia app-gateway origin', () => {
|
|
58
|
+
const parentWindow = { postMessage: () => undefined } as unknown as Window;
|
|
59
|
+
Object.defineProperty(window, 'parent', { configurable: true, value: parentWindow });
|
|
60
|
+
window.history.replaceState(null, '', `/?${IFRAME_APP_HOST_ORIGIN_PARAM}=https%3A%2F%2Fapps.dev1.vertesia.io`);
|
|
61
|
+
|
|
62
|
+
expect(resolveIframeHostOrigin()).toBeUndefined();
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it('rejects an origin containing embedded credentials', () => {
|
|
66
|
+
const parentWindow = { postMessage: () => undefined } as unknown as Window;
|
|
67
|
+
Object.defineProperty(window, 'parent', { configurable: true, value: parentWindow });
|
|
68
|
+
window.history.replaceState(
|
|
69
|
+
null,
|
|
70
|
+
'',
|
|
71
|
+
`/?${IFRAME_APP_HOST_ORIGIN_PARAM}=https%3A%2F%2Fuser%3Asecret%40cloud.vertesia.io`,
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
expect(resolveIframeHostOrigin()).toBeUndefined();
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it('accepts a loopback host for a loopback child app', () => {
|
|
78
|
+
const parentWindow = { postMessage: () => undefined } as unknown as Window;
|
|
79
|
+
Object.defineProperty(window, 'parent', { configurable: true, value: parentWindow });
|
|
80
|
+
window.history.replaceState(null, '', `/?${IFRAME_APP_HOST_ORIGIN_PARAM}=http%3A%2F%2Flocalhost%3A5173`);
|
|
81
|
+
|
|
82
|
+
expect(resolveIframeHostOrigin()).toBe('http://localhost:5173');
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it('ignores an empty early response and waits for a usable host token', async () => {
|
|
86
|
+
const requests: unknown[] = [];
|
|
87
|
+
const parentWindow = { postMessage: (message: unknown) => requests.push(message) } as unknown as Window;
|
|
88
|
+
Object.defineProperty(window, 'parent', { configurable: true, value: parentWindow });
|
|
89
|
+
window.history.replaceState(null, '', `/?${IFRAME_APP_HOST_ORIGIN_PARAM}=https%3A%2F%2Fcloud.vertesia.io`);
|
|
90
|
+
|
|
91
|
+
let settled = false;
|
|
92
|
+
const tokenPromise = requestIframeHostAuthToken().then((token) => {
|
|
93
|
+
settled = true;
|
|
94
|
+
return token;
|
|
95
|
+
});
|
|
96
|
+
const request = requests[0] as { type: string; requestId: string };
|
|
97
|
+
expect(request.type).toBe(IFRAME_AUTH_REQUEST);
|
|
98
|
+
|
|
99
|
+
window.dispatchEvent(
|
|
100
|
+
new MessageEvent('message', {
|
|
101
|
+
data: { type: IFRAME_AUTH_RESPONSE, requestId: request.requestId },
|
|
102
|
+
origin: 'https://cloud.vertesia.io',
|
|
103
|
+
source: parentWindow,
|
|
104
|
+
}),
|
|
105
|
+
);
|
|
106
|
+
await Promise.resolve();
|
|
107
|
+
expect(settled).toBe(false);
|
|
108
|
+
|
|
109
|
+
window.dispatchEvent(
|
|
110
|
+
new MessageEvent('message', {
|
|
111
|
+
data: { type: IFRAME_AUTH_RESPONSE, requestId: request.requestId, token: 'fresh-token' },
|
|
112
|
+
origin: 'https://cloud.vertesia.io',
|
|
113
|
+
source: parentWindow,
|
|
114
|
+
}),
|
|
115
|
+
);
|
|
116
|
+
await expect(tokenPromise).resolves.toBe('fresh-token');
|
|
117
|
+
});
|
|
118
|
+
});
|