@trilogy-data/trilogy-studio-components 0.1.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/README.md +6 -0
- package/dist/ChatCreatorModal-DTcvWDQi.js +192 -0
- package/dist/Dashboard-C8re96eZ.js +5104 -0
- package/dist/DashboardCreatorInline-Do-CDJgS.js +150 -0
- package/dist/DashboardMobile-BOrq0rBy.js +310 -0
- package/dist/LLMConnectionList-DVM5t-P2.js +4692 -0
- package/dist/LLMView-lUTKOMbr.js +558 -0
- package/dist/Manager-CXJNoqU2.js +4 -0
- package/dist/ResultComponent-C4EGIBY0.js +155 -0
- package/dist/Sidebar-BGKtM2n0.js +1841 -0
- package/dist/TutorialPage-CGjDXmYk.js +482 -0
- package/dist/WelcomePage-C6obXIyG.js +75 -0
- package/dist/abap-D0Neqhq6.js +1404 -0
- package/dist/apex-B5LhxkeG.js +332 -0
- package/dist/azcli-BrBH0QTU.js +74 -0
- package/dist/bat-BfzAov64.js +106 -0
- package/dist/bicep-C3bCSWel.js +108 -0
- package/dist/cameligo-sFL5plcd.js +180 -0
- package/dist/chats/chat.d.ts +63 -0
- package/dist/chats/chat.d.ts.map +1 -0
- package/dist/chats/index.d.ts +3 -0
- package/dist/chats/index.d.ts.map +1 -0
- package/dist/clojure-CfeExRz0.js +767 -0
- package/dist/coffee-Xws5K0WL.js +238 -0
- package/dist/components/AssetAutoImporter.vue.d.ts +10 -0
- package/dist/components/AssetAutoImporter.vue.d.ts.map +1 -0
- package/dist/components/ChartControlPanel.vue.d.ts +54 -0
- package/dist/components/ChartControlPanel.vue.d.ts.map +1 -0
- package/dist/components/CodeBlock.vue.d.ts +39 -0
- package/dist/components/CodeBlock.vue.d.ts.map +1 -0
- package/dist/components/ConceptTable.vue.d.ts +16 -0
- package/dist/components/ConceptTable.vue.d.ts.map +1 -0
- package/dist/components/ContextMenu.vue.d.ts +67 -0
- package/dist/components/ContextMenu.vue.d.ts.map +1 -0
- package/dist/components/DataTable.vue.d.ts +204 -0
- package/dist/components/DataTable.vue.d.ts.map +1 -0
- package/dist/components/DrilldownPane.vue.d.ts +94 -0
- package/dist/components/DrilldownPane.vue.d.ts.map +1 -0
- package/dist/components/EditableTitle.vue.d.ts +32 -0
- package/dist/components/EditableTitle.vue.d.ts.map +1 -0
- package/dist/components/ErrorMessage.vue.d.ts +20 -0
- package/dist/components/ErrorMessage.vue.d.ts.map +1 -0
- package/dist/components/HighlightComponent.vue.d.ts +21 -0
- package/dist/components/HighlightComponent.vue.d.ts.map +1 -0
- package/dist/components/HintComponent.vue.d.ts +12 -0
- package/dist/components/HintComponent.vue.d.ts.map +1 -0
- package/dist/components/InlineErrorMessage.vue.d.ts +3 -0
- package/dist/components/InlineErrorMessage.vue.d.ts.map +1 -0
- package/dist/components/LoadingButton.vue.d.ts +121 -0
- package/dist/components/LoadingButton.vue.d.ts.map +1 -0
- package/dist/components/LoadingView.vue.d.ts +21 -0
- package/dist/components/LoadingView.vue.d.ts.map +1 -0
- package/dist/components/MarkdownRenderer.vue.d.ts +39 -0
- package/dist/components/MarkdownRenderer.vue.d.ts.map +1 -0
- package/dist/components/PopupModal.vue.d.ts +50 -0
- package/dist/components/PopupModal.vue.d.ts.map +1 -0
- package/dist/components/SimpleEditor.vue.d.ts +246 -0
- package/dist/components/SimpleEditor.vue.d.ts.map +1 -0
- package/dist/components/StatusIcon.vue.d.ts +9 -0
- package/dist/components/StatusIcon.vue.d.ts.map +1 -0
- package/dist/components/SymbolsPane.vue.d.ts +96 -0
- package/dist/components/SymbolsPane.vue.d.ts.map +1 -0
- package/dist/components/Tooltip.vue.d.ts +40 -0
- package/dist/components/Tooltip.vue.d.ts.map +1 -0
- package/dist/components/VegaLiteChart.vue.d.ts +183 -0
- package/dist/components/VegaLiteChart.vue.d.ts.map +1 -0
- package/dist/components/chartControlsManager.d.ts +50 -0
- package/dist/components/chartControlsManager.d.ts.map +1 -0
- package/dist/components/chartHelpers.d.ts +51 -0
- package/dist/components/chartHelpers.d.ts.map +1 -0
- package/dist/components/chartOperationsManager.d.ts +10 -0
- package/dist/components/chartOperationsManager.d.ts.map +1 -0
- package/dist/components/chartRenderManager.d.ts +26 -0
- package/dist/components/chartRenderManager.d.ts.map +1 -0
- package/dist/components/community/AddStoreModal.vue.d.ts +35 -0
- package/dist/components/community/AddStoreModal.vue.d.ts.map +1 -0
- package/dist/components/community/CommunityModelCard.vue.d.ts +33 -0
- package/dist/components/community/CommunityModelCard.vue.d.ts.map +1 -0
- package/dist/components/community/CommunityModelHeader.vue.d.ts +22 -0
- package/dist/components/community/CommunityModelHeader.vue.d.ts.map +1 -0
- package/dist/components/community/CommunityModels.vue.d.ts +19 -0
- package/dist/components/community/CommunityModels.vue.d.ts.map +1 -0
- package/dist/components/community/CommunityRemote.vue.d.ts +33 -0
- package/dist/components/community/CommunityRemote.vue.d.ts.map +1 -0
- package/dist/components/connection/ConnectionDatabase.vue.d.ts +153 -0
- package/dist/components/connection/ConnectionDatabase.vue.d.ts.map +1 -0
- package/dist/components/connection/ConnectionHistory.vue.d.ts +13 -0
- package/dist/components/connection/ConnectionHistory.vue.d.ts.map +1 -0
- package/dist/components/connection/ConnectionSchema.vue.d.ts +35 -0
- package/dist/components/connection/ConnectionSchema.vue.d.ts.map +1 -0
- package/dist/components/connection/ConnectionTable.vue.d.ts +251 -0
- package/dist/components/connection/ConnectionTable.vue.d.ts.map +1 -0
- package/dist/components/connection/DatasourceTable.vue.d.ts +16 -0
- package/dist/components/connection/DatasourceTable.vue.d.ts.map +1 -0
- package/dist/components/dashboard/Dashboard.vue.d.ts +13 -0
- package/dist/components/dashboard/Dashboard.vue.d.ts.map +1 -0
- package/dist/components/dashboard/DashboardAddItemModal.vue.d.ts +13 -0
- package/dist/components/dashboard/DashboardAddItemModal.vue.d.ts.map +1 -0
- package/dist/components/dashboard/DashboardCTA.vue.d.ts +12 -0
- package/dist/components/dashboard/DashboardCTA.vue.d.ts.map +1 -0
- package/dist/components/dashboard/DashboardChart.vue.d.ts +427 -0
- package/dist/components/dashboard/DashboardChart.vue.d.ts.map +1 -0
- package/dist/components/dashboard/DashboardChartEditor.vue.d.ts +325 -0
- package/dist/components/dashboard/DashboardChartEditor.vue.d.ts.map +1 -0
- package/dist/components/dashboard/DashboardCreatorIcon.vue.d.ts +52 -0
- package/dist/components/dashboard/DashboardCreatorIcon.vue.d.ts.map +1 -0
- package/dist/components/dashboard/DashboardCreatorInline.vue.d.ts +36 -0
- package/dist/components/dashboard/DashboardCreatorInline.vue.d.ts.map +1 -0
- package/dist/components/dashboard/DashboardDataSelector.vue.d.ts +221 -0
- package/dist/components/dashboard/DashboardDataSelector.vue.d.ts.map +1 -0
- package/dist/components/dashboard/DashboardFilter.vue.d.ts +346 -0
- package/dist/components/dashboard/DashboardFilter.vue.d.ts.map +1 -0
- package/dist/components/dashboard/DashboardFilterAutocomplete.vue.d.ts +38 -0
- package/dist/components/dashboard/DashboardFilterAutocomplete.vue.d.ts.map +1 -0
- package/dist/components/dashboard/DashboardGridItem.vue.d.ts +31 -0
- package/dist/components/dashboard/DashboardGridItem.vue.d.ts.map +1 -0
- package/dist/components/dashboard/DashboardHeader.vue.d.ts +71 -0
- package/dist/components/dashboard/DashboardHeader.vue.d.ts.map +1 -0
- package/dist/components/dashboard/DashboardHeaderFilterInput.vue.d.ts +50 -0
- package/dist/components/dashboard/DashboardHeaderFilterInput.vue.d.ts.map +1 -0
- package/dist/components/dashboard/DashboardImportPopup.vue.d.ts +12 -0
- package/dist/components/dashboard/DashboardImportPopup.vue.d.ts.map +1 -0
- package/dist/components/dashboard/DashboardImportSelector.vue.d.ts +14 -0
- package/dist/components/dashboard/DashboardImportSelector.vue.d.ts.map +1 -0
- package/dist/components/dashboard/DashboardMarkdown.vue.d.ts +175 -0
- package/dist/components/dashboard/DashboardMarkdown.vue.d.ts.map +1 -0
- package/dist/components/dashboard/DashboardMarkdownEditor.vue.d.ts +325 -0
- package/dist/components/dashboard/DashboardMarkdownEditor.vue.d.ts.map +1 -0
- package/dist/components/dashboard/DashboardMobile.vue.d.ts +8 -0
- package/dist/components/dashboard/DashboardMobile.vue.d.ts.map +1 -0
- package/dist/components/dashboard/DashboardSharePopup.vue.d.ts +14 -0
- package/dist/components/dashboard/DashboardSharePopup.vue.d.ts.map +1 -0
- package/dist/components/dashboard/DashboardTable.vue.d.ts +332 -0
- package/dist/components/dashboard/DashboardTable.vue.d.ts.map +1 -0
- package/dist/components/dashboard/useDashboard.d.ts +96 -0
- package/dist/components/dashboard/useDashboard.d.ts.map +1 -0
- package/dist/components/editor/Editor.vue.d.ts +816 -0
- package/dist/components/editor/Editor.vue.d.ts.map +1 -0
- package/dist/components/editor/EditorCode.vue.d.ts +49 -0
- package/dist/components/editor/EditorCode.vue.d.ts.map +1 -0
- package/dist/components/editor/EditorCreatorIcon.vue.d.ts +61 -0
- package/dist/components/editor/EditorCreatorIcon.vue.d.ts.map +1 -0
- package/dist/components/editor/EditorCreatorInline.vue.d.ts +95 -0
- package/dist/components/editor/EditorCreatorInline.vue.d.ts.map +1 -0
- package/dist/components/editor/EditorHeader.vue.d.ts +185 -0
- package/dist/components/editor/EditorHeader.vue.d.ts.map +1 -0
- package/dist/components/editor/ResultComponent.vue.d.ts +1095 -0
- package/dist/components/editor/ResultComponent.vue.d.ts.map +1 -0
- package/dist/components/editor/Results.vue.d.ts +755 -0
- package/dist/components/editor/Results.vue.d.ts.map +1 -0
- package/dist/components/editor/editorHelpers.d.ts +45 -0
- package/dist/components/editor/editorHelpers.d.ts.map +1 -0
- package/dist/components/editor/events.d.ts +4 -0
- package/dist/components/editor/events.d.ts.map +1 -0
- package/dist/components/index.d.ts +2 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/layout/MobileSidebarLayout.vue.d.ts +48 -0
- package/dist/components/layout/MobileSidebarLayout.vue.d.ts.map +1 -0
- package/dist/components/layout/SidebarLayout.vue.d.ts +20 -0
- package/dist/components/layout/SidebarLayout.vue.d.ts.map +1 -0
- package/dist/components/layout/TabDropdownItem.vue.d.ts +73 -0
- package/dist/components/layout/TabDropdownItem.vue.d.ts.map +1 -0
- package/dist/components/layout/TabbedBrowser.vue.d.ts +42 -0
- package/dist/components/layout/TabbedBrowser.vue.d.ts.map +1 -0
- package/dist/components/layout/TabbedLayout.vue.d.ts +5 -0
- package/dist/components/layout/TabbedLayout.vue.d.ts.map +1 -0
- package/dist/components/layout/VerticalSplitLayout.vue.d.ts +13 -0
- package/dist/components/layout/VerticalSplitLayout.vue.d.ts.map +1 -0
- package/dist/components/llm/ChatArtifact.vue.d.ts +470 -0
- package/dist/components/llm/ChatArtifact.vue.d.ts.map +1 -0
- package/dist/components/llm/ChatCreatorModal.vue.d.ts +87 -0
- package/dist/components/llm/ChatCreatorModal.vue.d.ts.map +1 -0
- package/dist/components/llm/LLMChat.vue.d.ts +260 -0
- package/dist/components/llm/LLMChat.vue.d.ts.map +1 -0
- package/dist/components/llm/LLMChatRefinement.vue.d.ts +135 -0
- package/dist/components/llm/LLMChatRefinement.vue.d.ts.map +1 -0
- package/dist/components/llm/LLMChatSplitView.vue.d.ts +2029 -0
- package/dist/components/llm/LLMChatSplitView.vue.d.ts.map +1 -0
- package/dist/components/llm/LLMValidationView.vue.d.ts +106 -0
- package/dist/components/llm/LLMValidationView.vue.d.ts.map +1 -0
- package/dist/components/llm/index.d.ts +6 -0
- package/dist/components/llm/index.d.ts.map +1 -0
- package/dist/components/model/ModelCard.vue.d.ts +1113 -0
- package/dist/components/model/ModelCard.vue.d.ts.map +1 -0
- package/dist/components/model/ModelConcept.vue.d.ts +14 -0
- package/dist/components/model/ModelConcept.vue.d.ts.map +1 -0
- package/dist/components/model/ModelCreator.vue.d.ts +241 -0
- package/dist/components/model/ModelCreator.vue.d.ts.map +1 -0
- package/dist/components/model/ModelSelector.vue.d.ts +9 -0
- package/dist/components/model/ModelSelector.vue.d.ts.map +1 -0
- package/dist/components/sidebar/CommunityModelListItem.vue.d.ts +26 -0
- package/dist/components/sidebar/CommunityModelListItem.vue.d.ts.map +1 -0
- package/dist/components/sidebar/ConnectionCreatorInline.vue.d.ts +68 -0
- package/dist/components/sidebar/ConnectionCreatorInline.vue.d.ts.map +1 -0
- package/dist/components/sidebar/ConnectionIcon.vue.d.ts +6 -0
- package/dist/components/sidebar/ConnectionIcon.vue.d.ts.map +1 -0
- package/dist/components/sidebar/ConnectionList.vue.d.ts +714 -0
- package/dist/components/sidebar/ConnectionList.vue.d.ts.map +1 -0
- package/dist/components/sidebar/ConnectionListItem.vue.d.ts +317 -0
- package/dist/components/sidebar/ConnectionListItem.vue.d.ts.map +1 -0
- package/dist/components/sidebar/ConnectionRefresh.vue.d.ts +15 -0
- package/dist/components/sidebar/ConnectionRefresh.vue.d.ts.map +1 -0
- package/dist/components/sidebar/ConnectionStatusIcon.vue.d.ts +11 -0
- package/dist/components/sidebar/ConnectionStatusIcon.vue.d.ts.map +1 -0
- package/dist/components/sidebar/CreateEditorFromDatasourcePopup.vue.d.ts +15 -0
- package/dist/components/sidebar/CreateEditorFromDatasourcePopup.vue.d.ts.map +1 -0
- package/dist/components/sidebar/DashboardList.vue.d.ts +684 -0
- package/dist/components/sidebar/DashboardList.vue.d.ts.map +1 -0
- package/dist/components/sidebar/DashboardListItem.vue.d.ts +343 -0
- package/dist/components/sidebar/DashboardListItem.vue.d.ts.map +1 -0
- package/dist/components/sidebar/DuckDBImporter.vue.d.ts +24 -0
- package/dist/components/sidebar/DuckDBImporter.vue.d.ts.map +1 -0
- package/dist/components/sidebar/EditorList.vue.d.ts +590 -0
- package/dist/components/sidebar/EditorList.vue.d.ts.map +1 -0
- package/dist/components/sidebar/EditorListItem.vue.d.ts +260 -0
- package/dist/components/sidebar/EditorListItem.vue.d.ts.map +1 -0
- package/dist/components/sidebar/GenericSidebarItem.vue.d.ts +91 -0
- package/dist/components/sidebar/GenericSidebarItem.vue.d.ts.map +1 -0
- package/dist/components/sidebar/LLMConnectionCreator.vue.d.ts +178 -0
- package/dist/components/sidebar/LLMConnectionCreator.vue.d.ts.map +1 -0
- package/dist/components/sidebar/LLMConnectionList.vue.d.ts +978 -0
- package/dist/components/sidebar/LLMConnectionList.vue.d.ts.map +1 -0
- package/dist/components/sidebar/LLMConnectionListItem.vue.d.ts +404 -0
- package/dist/components/sidebar/LLMConnectionListItem.vue.d.ts.map +1 -0
- package/dist/components/sidebar/LLMProviderIcon.vue.d.ts +13 -0
- package/dist/components/sidebar/LLMProviderIcon.vue.d.ts.map +1 -0
- package/dist/components/sidebar/ModelSidebar.vue.d.ts +558 -0
- package/dist/components/sidebar/ModelSidebar.vue.d.ts.map +1 -0
- package/dist/components/sidebar/SidebarList.vue.d.ts +16 -0
- package/dist/components/sidebar/SidebarList.vue.d.ts.map +1 -0
- package/dist/components/sidebar/TutorialSidebar.vue.d.ts +134 -0
- package/dist/components/sidebar/TutorialSidebar.vue.d.ts.map +1 -0
- package/dist/components/tutorial/TutorialFunction.vue.d.ts +38 -0
- package/dist/components/tutorial/TutorialFunction.vue.d.ts.map +1 -0
- package/dist/components/tutorial/TutorialPrompt.vue.d.ts +2002 -0
- package/dist/components/tutorial/TutorialPrompt.vue.d.ts.map +1 -0
- package/dist/components/user/UserProfile.vue.d.ts +11 -0
- package/dist/components/user/UserProfile.vue.d.ts.map +1 -0
- package/dist/components/user/UserSettings.vue.d.ts +129 -0
- package/dist/components/user/UserSettings.vue.d.ts.map +1 -0
- package/dist/composables/ResizeHandles.vue.d.ts +6 -0
- package/dist/composables/ResizeHandles.vue.d.ts.map +1 -0
- package/dist/composables/useChatWithTools.d.ts +62 -0
- package/dist/composables/useChatWithTools.d.ts.map +1 -0
- package/dist/composables/useResizableDialog.d.ts +30 -0
- package/dist/composables/useResizableDialog.d.ts.map +1 -0
- package/dist/composables/useTrilogyChat.d.ts +61 -0
- package/dist/composables/useTrilogyChat.d.ts.map +1 -0
- package/dist/composables/useTrilogyCore.d.ts +51 -0
- package/dist/composables/useTrilogyCore.d.ts.map +1 -0
- package/dist/connections/base.d.ts +86 -0
- package/dist/connections/base.d.ts.map +1 -0
- package/dist/connections/bigquery_oauth.d.ts +35 -0
- package/dist/connections/bigquery_oauth.d.ts.map +1 -0
- package/dist/connections/bigquery_sa.d.ts +2 -0
- package/dist/connections/bigquery_sa.d.ts.map +1 -0
- package/dist/connections/constants.d.ts +2 -0
- package/dist/connections/constants.d.ts.map +1 -0
- package/dist/connections/duckdb.d.ts +43 -0
- package/dist/connections/duckdb.d.ts.map +1 -0
- package/dist/connections/helpers.d.ts +30 -0
- package/dist/connections/helpers.d.ts.map +1 -0
- package/dist/connections/index.d.ts +7 -0
- package/dist/connections/index.d.ts.map +1 -0
- package/dist/connections/motherduck.d.ts +19 -0
- package/dist/connections/motherduck.d.ts.map +1 -0
- package/dist/connections/snowflake.d.ts +94 -0
- package/dist/connections/snowflake.d.ts.map +1 -0
- package/dist/connections/sql_server.d.ts +2 -0
- package/dist/connections/sql_server.d.ts.map +1 -0
- package/dist/cpp-CqOUEpxN.js +395 -0
- package/dist/csharp-DVLiBOZb.js +332 -0
- package/dist/csp-DVFp9bw5.js +59 -0
- package/dist/css-DwARn2R6.js +193 -0
- package/dist/cssMode-Cr0iq_nL.js +1577 -0
- package/dist/cypher-uY0Mffat.js +269 -0
- package/dist/dart-D27H-mX_.js +287 -0
- package/dist/dashboards/barChartSpec.d.ts +28 -0
- package/dist/dashboards/barChartSpec.d.ts.map +1 -0
- package/dist/dashboards/barHChartSpec.d.ts +28 -0
- package/dist/dashboards/barHChartSpec.d.ts.map +1 -0
- package/dist/dashboards/base.d.ts +176 -0
- package/dist/dashboards/base.d.ts.map +1 -0
- package/dist/dashboards/beeSwarmSpec.d.ts +150 -0
- package/dist/dashboards/beeSwarmSpec.d.ts.map +1 -0
- package/dist/dashboards/conditions.d.ts +8 -0
- package/dist/dashboards/conditions.d.ts.map +1 -0
- package/dist/dashboards/conditionsParameters.d.ts +11 -0
- package/dist/dashboards/conditionsParameters.d.ts.map +1 -0
- package/dist/dashboards/constants.d.ts +22 -0
- package/dist/dashboards/constants.d.ts.map +1 -0
- package/dist/dashboards/countryLookup.d.ts +15 -0
- package/dist/dashboards/countryLookup.d.ts.map +1 -0
- package/dist/dashboards/d3utility.d.ts +7 -0
- package/dist/dashboards/d3utility.d.ts.map +1 -0
- package/dist/dashboards/dashboardQueryExecutor.d.ts +142 -0
- package/dist/dashboards/dashboardQueryExecutor.d.ts.map +1 -0
- package/dist/dashboards/donutSpec.d.ts +74 -0
- package/dist/dashboards/donutSpec.d.ts.map +1 -0
- package/dist/dashboards/formatting.d.ts +11 -0
- package/dist/dashboards/formatting.d.ts.map +1 -0
- package/dist/dashboards/headlineSpec.d.ts +23 -0
- package/dist/dashboards/headlineSpec.d.ts.map +1 -0
- package/dist/dashboards/heatmapSpec.d.ts +30 -0
- package/dist/dashboards/heatmapSpec.d.ts.map +1 -0
- package/dist/dashboards/helpers.d.ts +73 -0
- package/dist/dashboards/helpers.d.ts.map +1 -0
- package/dist/dashboards/index.d.ts +3 -0
- package/dist/dashboards/index.d.ts.map +1 -0
- package/dist/dashboards/lineAreaSpec.d.ts +177 -0
- package/dist/dashboards/lineAreaSpec.d.ts.map +1 -0
- package/dist/dashboards/mapSpec.d.ts +431 -0
- package/dist/dashboards/mapSpec.d.ts.map +1 -0
- package/dist/dashboards/pointSpec.d.ts +27 -0
- package/dist/dashboards/pointSpec.d.ts.map +1 -0
- package/dist/dashboards/prompts.d.ts +31 -0
- package/dist/dashboards/prompts.d.ts.map +1 -0
- package/dist/dashboards/spec.d.ts +19 -0
- package/dist/dashboards/spec.d.ts.map +1 -0
- package/dist/dashboards/treeSpec.d.ts +3 -0
- package/dist/dashboards/treeSpec.d.ts.map +1 -0
- package/dist/dashboards/types.d.ts +70 -0
- package/dist/dashboards/types.d.ts.map +1 -0
- package/dist/data/connectionHistoryStorage.d.ts +25 -0
- package/dist/data/connectionHistoryStorage.d.ts.map +1 -0
- package/dist/data/constants.d.ts +4 -0
- package/dist/data/constants.d.ts.map +1 -0
- package/dist/data/credentialHelpers.d.ts +30 -0
- package/dist/data/credentialHelpers.d.ts.map +1 -0
- package/dist/data/credentialService.d.ts +80 -0
- package/dist/data/credentialService.d.ts.map +1 -0
- package/dist/data/githubStorage.d.ts +54 -0
- package/dist/data/githubStorage.d.ts.map +1 -0
- package/dist/data/index.d.ts +3 -0
- package/dist/data/index.d.ts.map +1 -0
- package/dist/data/localStorage.d.ts +48 -0
- package/dist/data/localStorage.d.ts.map +1 -0
- package/dist/data/storage.d.ts +33 -0
- package/dist/data/storage.d.ts.map +1 -0
- package/dist/data/tips.d.ts +12 -0
- package/dist/data/tips.d.ts.map +1 -0
- package/dist/data/tutorial/builtinFunctions.d.ts +3 -0
- package/dist/data/tutorial/builtinFunctions.d.ts.map +1 -0
- package/dist/data/tutorial/dashboardTutorial.d.ts +3 -0
- package/dist/data/tutorial/dashboardTutorial.d.ts.map +1 -0
- package/dist/data/tutorial/demoSetup.d.ts +6 -0
- package/dist/data/tutorial/demoSetup.d.ts.map +1 -0
- package/dist/data/tutorial/docTypes.d.ts +37 -0
- package/dist/data/tutorial/docTypes.d.ts.map +1 -0
- package/dist/data/tutorial/documentation.d.ts +3 -0
- package/dist/data/tutorial/documentation.d.ts.map +1 -0
- package/dist/data/tutorial/functionsReference.d.ts +3 -0
- package/dist/data/tutorial/functionsReference.d.ts.map +1 -0
- package/dist/data/tutorial/introTutorial.d.ts +3 -0
- package/dist/data/tutorial/introTutorial.d.ts.map +1 -0
- package/dist/data/tutorial/llmTutorial.d.ts +3 -0
- package/dist/data/tutorial/llmTutorial.d.ts.map +1 -0
- package/dist/data/tutorial/modelReference.d.ts +3 -0
- package/dist/data/tutorial/modelReference.d.ts.map +1 -0
- package/dist/data/tutorial/modelTutorial.d.ts +3 -0
- package/dist/data/tutorial/modelTutorial.d.ts.map +1 -0
- package/dist/data/tutorial/reference.d.ts +3 -0
- package/dist/data/tutorial/reference.d.ts.map +1 -0
- package/dist/data/tutorial/terms_of_service.d.ts +3 -0
- package/dist/data/tutorial/terms_of_service.d.ts.map +1 -0
- package/dist/data/tutorial/windowFunctionsReference.d.ts +3 -0
- package/dist/data/tutorial/windowFunctionsReference.d.ts.map +1 -0
- package/dist/dockerfile-CmV85WZK.js +136 -0
- package/dist/ecl--fKn7yzB.js +462 -0
- package/dist/editors/editor.d.ts +82 -0
- package/dist/editors/editor.d.ts.map +1 -0
- package/dist/editors/helpers.d.ts +12 -0
- package/dist/editors/helpers.d.ts.map +1 -0
- package/dist/editors/index.d.ts +3 -0
- package/dist/editors/index.d.ts.map +1 -0
- package/dist/editors/results.d.ts +61 -0
- package/dist/editors/results.d.ts.map +1 -0
- package/dist/elixir-DUhH17ON.js +575 -0
- package/dist/events/display.d.ts +9 -0
- package/dist/events/display.d.ts.map +1 -0
- package/dist/flow9-B3Dx2LLe.js +148 -0
- package/dist/freemarker2-de_cA50e.js +995 -0
- package/dist/fsharp-SyqBfUAR.js +223 -0
- package/dist/go-BbMR2tdT.js +224 -0
- package/dist/graphql-DDJE6tIl.js +157 -0
- package/dist/handlebars-C8f44E5O.js +425 -0
- package/dist/hcl-YBvpaUqf.js +189 -0
- package/dist/html-qaggIh0W.js +314 -0
- package/dist/html2canvas.esm-dgT_1dIT.js +4871 -0
- package/dist/htmlMode-xYurYOLw.js +1587 -0
- package/dist/ini-Ct73dBtM.js +77 -0
- package/dist/java-C_jlkwoG.js +238 -0
- package/dist/javascript-DeLkSgQX.js +76 -0
- package/dist/jsonMode-BM-L8w8F.js +2002 -0
- package/dist/julia-D8WE5U1e.js +517 -0
- package/dist/kotlin-Zy9aq5yB.js +259 -0
- package/dist/language/constants.d.ts +6 -0
- package/dist/language/constants.d.ts.map +1 -0
- package/dist/language/index.d.ts +2 -0
- package/dist/language/index.d.ts.map +1 -0
- package/dist/less-sZ0iHtE8.js +168 -0
- package/dist/lexon-CsdNL29A.js +163 -0
- package/dist/liquid-DLNUrc5y.js +246 -0
- package/dist/llm/anthropic.d.ts +13 -0
- package/dist/llm/anthropic.d.ts.map +1 -0
- package/dist/llm/base.d.ts +63 -0
- package/dist/llm/base.d.ts.map +1 -0
- package/dist/llm/chatAgentPrompt.d.ts +166 -0
- package/dist/llm/chatAgentPrompt.d.ts.map +1 -0
- package/dist/llm/chatHelpers.d.ts +23 -0
- package/dist/llm/chatHelpers.d.ts.map +1 -0
- package/dist/llm/chatToolExecutor.d.ts +39 -0
- package/dist/llm/chatToolExecutor.d.ts.map +1 -0
- package/dist/llm/consts.d.ts +3 -0
- package/dist/llm/consts.d.ts.map +1 -0
- package/dist/llm/data/constants.d.ts +5 -0
- package/dist/llm/data/constants.d.ts.map +1 -0
- package/dist/llm/data/models.d.ts +8 -0
- package/dist/llm/data/models.d.ts.map +1 -0
- package/dist/llm/data/prompts.d.ts +7 -0
- package/dist/llm/data/prompts.d.ts.map +1 -0
- package/dist/llm/data/testCases.d.ts +13 -0
- package/dist/llm/data/testCases.d.ts.map +1 -0
- package/dist/llm/googlev2.d.ts +15 -0
- package/dist/llm/googlev2.d.ts.map +1 -0
- package/dist/llm/index.d.ts +11 -0
- package/dist/llm/index.d.ts.map +1 -0
- package/dist/llm/mistral.d.ts +11 -0
- package/dist/llm/mistral.d.ts.map +1 -0
- package/dist/llm/models.d.ts +8 -0
- package/dist/llm/models.d.ts.map +1 -0
- package/dist/llm/openAI.d.ts +13 -0
- package/dist/llm/openAI.d.ts.map +1 -0
- package/dist/llm/utils.d.ts +50 -0
- package/dist/llm/utils.d.ts.map +1 -0
- package/dist/lua-C2YJo0zw.js +168 -0
- package/dist/m3-CPLP40SG.js +216 -0
- package/dist/main-oVvKtGNk.js +203688 -0
- package/dist/main.css +1 -0
- package/dist/main.d.ts +23 -0
- package/dist/main.d.ts.map +1 -0
- package/dist/main.js +22 -0
- package/dist/main.umd.cjs +2885 -0
- package/dist/markdown-B1mf5e0R.js +235 -0
- package/dist/mdx-BmG1effK.js +171 -0
- package/dist/mips-DA33BZX1.js +204 -0
- package/dist/models/helpers.d.ts +59 -0
- package/dist/models/helpers.d.ts.map +1 -0
- package/dist/models/import.d.ts +18 -0
- package/dist/models/import.d.ts.map +1 -0
- package/dist/models/index.d.ts +3 -0
- package/dist/models/index.d.ts.map +1 -0
- package/dist/models/model.d.ts +241 -0
- package/dist/models/model.d.ts.map +1 -0
- package/dist/monaco/editorHelpers.d.ts +32 -0
- package/dist/monaco/editorHelpers.d.ts.map +1 -0
- package/dist/monaco/index.d.ts +2 -0
- package/dist/monaco/index.d.ts.map +1 -0
- package/dist/monaco/setup.d.ts +2 -0
- package/dist/monaco/setup.d.ts.map +1 -0
- package/dist/msdax-CCYFIQsP.js +381 -0
- package/dist/mysql-hjmIjL-D.js +884 -0
- package/dist/objective-c-RRCpEmqC.js +189 -0
- package/dist/pascal-CeV8XfxB.js +257 -0
- package/dist/pascaligo-IEEGVJAJ.js +170 -0
- package/dist/perl-B5-QbHq_.js +632 -0
- package/dist/pgsql-s6kqEJmi.js +857 -0
- package/dist/php-CWWqzOo8.js +506 -0
- package/dist/pla-FSvb_YP_.js +143 -0
- package/dist/postiats-DQdscQXO.js +913 -0
- package/dist/powerquery-CtA5JA1I.js +896 -0
- package/dist/powershell-DglEq96N.js +245 -0
- package/dist/prism-sql-8Y2-THrf.js +33 -0
- package/dist/protobuf-BSepub3e.js +426 -0
- package/dist/pug-B1847F4G.js +408 -0
- package/dist/python-BLXKu9hO.js +307 -0
- package/dist/qsharp-D4i0Nqg9.js +307 -0
- package/dist/r-cdRigKxa.js +249 -0
- package/dist/razor-DSEd6veI.js +556 -0
- package/dist/redis-D9MFxvE8.js +308 -0
- package/dist/redshift-CmCnsvL-.js +815 -0
- package/dist/remotes/constants.d.ts +2 -0
- package/dist/remotes/constants.d.ts.map +1 -0
- package/dist/remotes/displayHelpers.d.ts +67 -0
- package/dist/remotes/displayHelpers.d.ts.map +1 -0
- package/dist/remotes/modelApiService.d.ts +38 -0
- package/dist/remotes/modelApiService.d.ts.map +1 -0
- package/dist/remotes/models.d.ts +48 -0
- package/dist/remotes/models.d.ts.map +1 -0
- package/dist/remotes/storeService.d.ts +42 -0
- package/dist/remotes/storeService.d.ts.map +1 -0
- package/dist/restructuredtext-CWy8J51t.js +180 -0
- package/dist/ruby-WP-c36m5.js +517 -0
- package/dist/rust-Q9FLdYpu.js +349 -0
- package/dist/sb-C54-JBGT.js +121 -0
- package/dist/scala-CzbFImc5.js +376 -0
- package/dist/scheme-BhfDmYN3.js +114 -0
- package/dist/scss-CEmiBXpS.js +268 -0
- package/dist/shell-Bmc1VhG0.js +227 -0
- package/dist/solidity-C9Q2I8Hh.js +1373 -0
- package/dist/sophia-jWa1UyKz.js +205 -0
- package/dist/sparql-CM7jctbc.js +207 -0
- package/dist/sql-WzihTkbg.js +859 -0
- package/dist/st-6y7_3aup.js +422 -0
- package/dist/stores/CredentialManager.vue.d.ts +50 -0
- package/dist/stores/CredentialManager.vue.d.ts.map +1 -0
- package/dist/stores/Manager.vue.d.ts +100 -0
- package/dist/stores/Manager.vue.d.ts.map +1 -0
- package/dist/stores/analyticsStore.d.ts +42 -0
- package/dist/stores/analyticsStore.d.ts.map +1 -0
- package/dist/stores/chatStore.d.ts +153 -0
- package/dist/stores/chatStore.d.ts.map +1 -0
- package/dist/stores/communityApiStore.d.ts +206 -0
- package/dist/stores/communityApiStore.d.ts.map +1 -0
- package/dist/stores/connectionHistoryStore.d.ts +24 -0
- package/dist/stores/connectionHistoryStore.d.ts.map +1 -0
- package/dist/stores/connectionStore.d.ts +31 -0
- package/dist/stores/connectionStore.d.ts.map +1 -0
- package/dist/stores/dashboardStore.d.ts +122 -0
- package/dist/stores/dashboardStore.d.ts.map +1 -0
- package/dist/stores/editorStore.d.ts +44 -0
- package/dist/stores/editorStore.d.ts.map +1 -0
- package/dist/stores/index.d.ts +14 -0
- package/dist/stores/index.d.ts.map +1 -0
- package/dist/stores/llmStore.d.ts +90 -0
- package/dist/stores/llmStore.d.ts.map +1 -0
- package/dist/stores/modelStore.d.ts +29 -0
- package/dist/stores/modelStore.d.ts.map +1 -0
- package/dist/stores/queryExecutionService.d.ts +60 -0
- package/dist/stores/queryExecutionService.d.ts.map +1 -0
- package/dist/stores/resolver.d.ts +91 -0
- package/dist/stores/resolver.d.ts.map +1 -0
- package/dist/stores/urlStore.d.ts +6 -0
- package/dist/stores/urlStore.d.ts.map +1 -0
- package/dist/stores/useScreenNavigation.d.ts +53 -0
- package/dist/stores/useScreenNavigation.d.ts.map +1 -0
- package/dist/stores/userSettingsStore.d.ts +133 -0
- package/dist/stores/userSettingsStore.d.ts.map +1 -0
- package/dist/swift-k-0zxG_D.js +318 -0
- package/dist/systemverilog-Pnr5_rIP.js +582 -0
- package/dist/tcl-fNPXval8.js +238 -0
- package/dist/tsMode-CdypNzs1.js +895 -0
- package/dist/twig-L2MkztkV.js +398 -0
- package/dist/typescript-DZ5G39rT.js +349 -0
- package/dist/typespec-Cqqo-3Pt.js +123 -0
- package/dist/useDashboard-CPI83oAm.js +3352 -0
- package/dist/utility/debounce.d.ts +12 -0
- package/dist/utility/debounce.d.ts.map +1 -0
- package/dist/utility/markdownRenderer.d.ts +34 -0
- package/dist/utility/markdownRenderer.d.ts.map +1 -0
- package/dist/utility/testHelpers.d.ts +2 -0
- package/dist/utility/testHelpers.d.ts.map +1 -0
- package/dist/vb-B5YC2xN9.js +378 -0
- package/dist/views/ConnectionView.vue.d.ts +522 -0
- package/dist/views/ConnectionView.vue.d.ts.map +1 -0
- package/dist/views/CredentialBackgroundPage.vue.d.ts +3 -0
- package/dist/views/CredentialBackgroundPage.vue.d.ts.map +1 -0
- package/dist/views/IDEPlaceholder.vue.d.ts +3 -0
- package/dist/views/IDEPlaceholder.vue.d.ts.map +1 -0
- package/dist/views/LLMView.vue.d.ts +7758 -0
- package/dist/views/LLMView.vue.d.ts.map +1 -0
- package/dist/views/MobileIDEPlaceholder.vue.d.ts +3 -0
- package/dist/views/MobileIDEPlaceholder.vue.d.ts.map +1 -0
- package/dist/views/ModelView.vue.d.ts +2170 -0
- package/dist/views/ModelView.vue.d.ts.map +1 -0
- package/dist/views/ResponsiveIDE.vue.d.ts +3 -0
- package/dist/views/ResponsiveIDE.vue.d.ts.map +1 -0
- package/dist/views/TutorialPage.vue.d.ts +7835 -0
- package/dist/views/TutorialPage.vue.d.ts.map +1 -0
- package/dist/views/WelcomePage.vue.d.ts +13 -0
- package/dist/views/WelcomePage.vue.d.ts.map +1 -0
- package/dist/views/index.d.ts +3 -0
- package/dist/views/index.d.ts.map +1 -0
- package/dist/vite.config.d.ts +3 -0
- package/dist/vite.config.d.ts.map +1 -0
- package/dist/vitest.config.d.ts +3 -0
- package/dist/vitest.config.d.ts.map +1 -0
- package/dist/wgsl-B-_uRex7.js +445 -0
- package/dist/xml-DsUsyRQY.js +101 -0
- package/dist/yaml-BpA1BNpS.js +212 -0
- package/package.json +55 -0
|
@@ -0,0 +1,4692 @@
|
|
|
1
|
+
var _e = Object.defineProperty;
|
|
2
|
+
var Ne = (t, e, o) => e in t ? _e(t, e, { enumerable: !0, configurable: !0, writable: !0, value: o }) : t[e] = o;
|
|
3
|
+
var ne = (t, e, o) => Ne(t, typeof e != "symbol" ? e + "" : e, o);
|
|
4
|
+
import { defineComponent as ae, ref as C, inject as Y, createElementBlock as l, createCommentVNode as I, openBlock as r, createElementVNode as s, withModifiers as A, withDirectives as _, vModelText as G, vModelSelect as ve, vModelCheckbox as Ie, Fragment as pe, computed as $, createBlock as z, withCtx as q, unref as qe, normalizeClass as me, toDisplayString as j, createTextVNode as de, renderList as fe, resolveComponent as U, createVNode as x, Transition as be, onMounted as Ae, onUnmounted as Ue, normalizeStyle as Oe, watch as ke, vModelDynamic as xe } from "vue";
|
|
5
|
+
import { K as N, a as X, T as Ee, L as Se, l as Be, m as Ye, n as Fe, o as Pe, S as Re, h as Me, e as Le, A as Ge, O as je, p as Ke, G as Qe, g as Ve } from "./main-oVvKtGNk.js";
|
|
6
|
+
function He(t, e, o, i) {
|
|
7
|
+
const c = [];
|
|
8
|
+
return Object.values(t).sort((a, d) => a.connected && !d.connected ? -1 : !a.connected && d.connected ? 1 : a.name.localeCompare(d.name)).forEach((a) => {
|
|
9
|
+
if (a.deleted)
|
|
10
|
+
return;
|
|
11
|
+
let d = a.databases ? a.databases : [];
|
|
12
|
+
c.push({
|
|
13
|
+
id: a.name,
|
|
14
|
+
name: a.name,
|
|
15
|
+
indent: 0,
|
|
16
|
+
count: d.length,
|
|
17
|
+
type: "connection",
|
|
18
|
+
searchPath: a.name,
|
|
19
|
+
connection: a
|
|
20
|
+
}), e[a.name] === !1 && (["duckdb"].includes(a.type) && c.push({
|
|
21
|
+
id: `${a.name}-upload`,
|
|
22
|
+
name: "Upload",
|
|
23
|
+
indent: 1,
|
|
24
|
+
count: 0,
|
|
25
|
+
type: "duckdb-upload",
|
|
26
|
+
searchPath: a.name,
|
|
27
|
+
connection: a
|
|
28
|
+
}), c.push({
|
|
29
|
+
id: `${a.name}-model`,
|
|
30
|
+
name: "Model",
|
|
31
|
+
indent: 1,
|
|
32
|
+
count: 0,
|
|
33
|
+
type: "model",
|
|
34
|
+
searchPath: a.name,
|
|
35
|
+
connection: a
|
|
36
|
+
}), a.type === "motherduck" && c.push({
|
|
37
|
+
id: `${a.name}-md-token`,
|
|
38
|
+
name: "MotherDuck Token",
|
|
39
|
+
indent: 1,
|
|
40
|
+
count: 0,
|
|
41
|
+
type: "motherduck-token",
|
|
42
|
+
searchPath: a.name,
|
|
43
|
+
connection: a
|
|
44
|
+
}), a.type === "bigquery-oauth" && (c.push({
|
|
45
|
+
id: `${a.name}-billing-project`,
|
|
46
|
+
name: "Billing Project",
|
|
47
|
+
indent: 1,
|
|
48
|
+
count: 0,
|
|
49
|
+
type: "bigquery-project",
|
|
50
|
+
searchPath: a.name,
|
|
51
|
+
connection: a
|
|
52
|
+
}), c.push({
|
|
53
|
+
id: `${a.name}-browsing-project`,
|
|
54
|
+
name: "Browsing Project",
|
|
55
|
+
indent: 1,
|
|
56
|
+
count: 0,
|
|
57
|
+
type: "bigquery-browsing-project",
|
|
58
|
+
searchPath: a.name,
|
|
59
|
+
connection: a
|
|
60
|
+
})), a.type === "snowflake" && (c.push({
|
|
61
|
+
id: `${a.name}-account`,
|
|
62
|
+
name: "Account",
|
|
63
|
+
indent: 1,
|
|
64
|
+
count: 0,
|
|
65
|
+
type: "snowflake-account",
|
|
66
|
+
searchPath: a.name,
|
|
67
|
+
connection: a
|
|
68
|
+
}), c.push({
|
|
69
|
+
id: `${a.name}-username`,
|
|
70
|
+
name: "Username",
|
|
71
|
+
indent: 1,
|
|
72
|
+
count: 0,
|
|
73
|
+
type: "snowflake-username",
|
|
74
|
+
searchPath: a.name,
|
|
75
|
+
connection: a
|
|
76
|
+
}), c.push({
|
|
77
|
+
id: `${a.name}-private-key`,
|
|
78
|
+
name: "Private Key",
|
|
79
|
+
indent: 1,
|
|
80
|
+
count: 0,
|
|
81
|
+
type: "snowflake-private-key",
|
|
82
|
+
searchPath: a.name,
|
|
83
|
+
connection: a
|
|
84
|
+
})), ["snowflake", "motherduck"].includes(a.type) && c.push({
|
|
85
|
+
id: `${a.name}-toggle-save-credential`,
|
|
86
|
+
name: "Toggle Credential Saving",
|
|
87
|
+
indent: 1,
|
|
88
|
+
count: 0,
|
|
89
|
+
type: "toggle-save-credential",
|
|
90
|
+
searchPath: a.name,
|
|
91
|
+
connection: a
|
|
92
|
+
}), o[a.name] && c.push({
|
|
93
|
+
id: `${a.name}-loading`,
|
|
94
|
+
name: "Loading...",
|
|
95
|
+
indent: 1,
|
|
96
|
+
count: 0,
|
|
97
|
+
type: "loading",
|
|
98
|
+
searchPath: a.name,
|
|
99
|
+
connection: a
|
|
100
|
+
}), i[a.name] && c.push({
|
|
101
|
+
id: `${a.name}-error`,
|
|
102
|
+
name: i[a.name],
|
|
103
|
+
indent: 1,
|
|
104
|
+
count: 0,
|
|
105
|
+
type: "error",
|
|
106
|
+
searchPath: a.name,
|
|
107
|
+
connection: a
|
|
108
|
+
}), d.forEach((w) => {
|
|
109
|
+
const h = `${a.name}${N}${w.name}`;
|
|
110
|
+
c.push({
|
|
111
|
+
id: h,
|
|
112
|
+
name: w.name,
|
|
113
|
+
indent: 1,
|
|
114
|
+
count: w.schemas.length,
|
|
115
|
+
type: "database",
|
|
116
|
+
searchPath: `${w.name}`,
|
|
117
|
+
connection: a
|
|
118
|
+
}), e[h] || (o[h] && c.push({
|
|
119
|
+
id: `${h}-loading`,
|
|
120
|
+
name: "Loading...",
|
|
121
|
+
indent: 1,
|
|
122
|
+
count: 0,
|
|
123
|
+
type: "loading",
|
|
124
|
+
searchPath: `${w.name}`,
|
|
125
|
+
connection: a
|
|
126
|
+
}), w.schemas.forEach((P) => {
|
|
127
|
+
const E = `${h}${N}${P.name}`;
|
|
128
|
+
c.push({
|
|
129
|
+
id: E,
|
|
130
|
+
name: P.name,
|
|
131
|
+
indent: 2,
|
|
132
|
+
count: P.tables.length,
|
|
133
|
+
type: "schema",
|
|
134
|
+
searchPath: `${w.name}.${P.name}`,
|
|
135
|
+
connection: a
|
|
136
|
+
}), e[E] || (o[E] && c.push({
|
|
137
|
+
id: `${E}-loading`,
|
|
138
|
+
name: "Loading...",
|
|
139
|
+
indent: 2,
|
|
140
|
+
count: 0,
|
|
141
|
+
type: "loading",
|
|
142
|
+
searchPath: `${w.name}.${P.name}`,
|
|
143
|
+
connection: a
|
|
144
|
+
}), P.tables.forEach((b) => {
|
|
145
|
+
const m = `${h}${N}${P.name}${N}${b.name}`;
|
|
146
|
+
c.push({
|
|
147
|
+
id: m,
|
|
148
|
+
name: b.name,
|
|
149
|
+
indent: 3,
|
|
150
|
+
count: 0,
|
|
151
|
+
type: "table",
|
|
152
|
+
searchPath: `${w.name}.${P.name}.${b.name}`,
|
|
153
|
+
connection: a,
|
|
154
|
+
object: b
|
|
155
|
+
});
|
|
156
|
+
}));
|
|
157
|
+
}));
|
|
158
|
+
}));
|
|
159
|
+
}), c;
|
|
160
|
+
}
|
|
161
|
+
function We(t, e) {
|
|
162
|
+
if (!e || e.trim() === "")
|
|
163
|
+
return t;
|
|
164
|
+
const o = e.toLowerCase().trim(), i = /* @__PURE__ */ new Set();
|
|
165
|
+
t.forEach((d) => {
|
|
166
|
+
(d.type === "view-queries" || d.searchPath.toLowerCase().includes(o)) && i.add(d.id);
|
|
167
|
+
});
|
|
168
|
+
const c = /* @__PURE__ */ new Map();
|
|
169
|
+
for (let d = 0; d < t.length; d++) {
|
|
170
|
+
const w = t[d];
|
|
171
|
+
let h = null;
|
|
172
|
+
for (let P = d - 1; P >= 0; P--) {
|
|
173
|
+
const E = t[P];
|
|
174
|
+
if (E.indent < w.indent) {
|
|
175
|
+
h = E.id;
|
|
176
|
+
break;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
h && (c.has(w.id) || c.set(w.id, /* @__PURE__ */ new Set()), c.get(w.id).add(h));
|
|
180
|
+
}
|
|
181
|
+
const p = new Set(i), a = (d) => {
|
|
182
|
+
const w = c.get(d);
|
|
183
|
+
if (w)
|
|
184
|
+
for (const h of w)
|
|
185
|
+
p.has(h) || (p.add(h), a(h));
|
|
186
|
+
};
|
|
187
|
+
return i.forEach((d) => {
|
|
188
|
+
a(d);
|
|
189
|
+
}), t.filter((d) => p.has(d.id));
|
|
190
|
+
}
|
|
191
|
+
const ze = ae({
|
|
192
|
+
name: "ConnectionCreator",
|
|
193
|
+
props: {
|
|
194
|
+
visible: {
|
|
195
|
+
type: Boolean,
|
|
196
|
+
required: !0
|
|
197
|
+
},
|
|
198
|
+
testTag: {
|
|
199
|
+
type: String,
|
|
200
|
+
required: !1,
|
|
201
|
+
default: ""
|
|
202
|
+
}
|
|
203
|
+
},
|
|
204
|
+
methods: {
|
|
205
|
+
close() {
|
|
206
|
+
this.$emit("close");
|
|
207
|
+
}
|
|
208
|
+
},
|
|
209
|
+
setup(t, { emit: e }) {
|
|
210
|
+
const o = C({
|
|
211
|
+
name: "",
|
|
212
|
+
type: "duckdb",
|
|
213
|
+
options: {
|
|
214
|
+
mdToken: "",
|
|
215
|
+
account: "",
|
|
216
|
+
projectId: "",
|
|
217
|
+
username: "",
|
|
218
|
+
password: "",
|
|
219
|
+
privateKey: "",
|
|
220
|
+
saveCredential: !1
|
|
221
|
+
}
|
|
222
|
+
}), i = Y("connectionStore"), c = Y("saveConnections"), p = Y("saveAll");
|
|
223
|
+
if (!i || !c || !p)
|
|
224
|
+
throw new Error("must inject connectionStore to ConnectionCreator");
|
|
225
|
+
const a = i.connections;
|
|
226
|
+
return {
|
|
227
|
+
connectionDetails: o,
|
|
228
|
+
connections: a,
|
|
229
|
+
createConnection: () => {
|
|
230
|
+
o.value.name = "", o.value.type = "duckdb", o.value.options = {
|
|
231
|
+
mdToken: "",
|
|
232
|
+
account: "",
|
|
233
|
+
projectId: "",
|
|
234
|
+
username: "",
|
|
235
|
+
password: "",
|
|
236
|
+
privateKey: "",
|
|
237
|
+
saveCredential: !1
|
|
238
|
+
};
|
|
239
|
+
},
|
|
240
|
+
submitConnectionCreation: async () => {
|
|
241
|
+
o.value.name && o.value.type && (await i.newConnection(
|
|
242
|
+
o.value.name,
|
|
243
|
+
o.value.type,
|
|
244
|
+
o.value.options
|
|
245
|
+
), await p(), e("close"));
|
|
246
|
+
}
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
}), Xe = {
|
|
250
|
+
key: 0,
|
|
251
|
+
class: "creator-container"
|
|
252
|
+
}, Je = { class: "form-row" }, Ze = { class: "form-row" }, $e = {
|
|
253
|
+
key: 0,
|
|
254
|
+
class: "form-row"
|
|
255
|
+
}, et = {
|
|
256
|
+
key: 1,
|
|
257
|
+
class: "form-row"
|
|
258
|
+
}, tt = {
|
|
259
|
+
key: 2,
|
|
260
|
+
class: "form-row"
|
|
261
|
+
}, nt = { class: "form-row" }, ot = { class: "form-row" }, it = { class: "form-row" }, at = { class: "button-row" };
|
|
262
|
+
function st(t, e, o, i, c, p) {
|
|
263
|
+
return t.visible ? (r(), l("div", Xe, [
|
|
264
|
+
s("form", {
|
|
265
|
+
onSubmit: e[11] || (e[11] = A((...a) => t.submitConnectionCreation && t.submitConnectionCreation(...a), ["prevent"]))
|
|
266
|
+
}, [
|
|
267
|
+
s("div", Je, [
|
|
268
|
+
e[12] || (e[12] = s("label", { for: "connection-name" }, "Name", -1)),
|
|
269
|
+
_(s("input", {
|
|
270
|
+
"data-testid": "connection-creator-name",
|
|
271
|
+
type: "text",
|
|
272
|
+
"onUpdate:modelValue": e[0] || (e[0] = (a) => t.connectionDetails.name = a),
|
|
273
|
+
id: "connection-name",
|
|
274
|
+
required: ""
|
|
275
|
+
}, null, 512), [
|
|
276
|
+
[G, t.connectionDetails.name]
|
|
277
|
+
])
|
|
278
|
+
]),
|
|
279
|
+
s("div", Ze, [
|
|
280
|
+
e[14] || (e[14] = s("label", { for: "connection-type" }, "Type", -1)),
|
|
281
|
+
_(s("select", {
|
|
282
|
+
"onUpdate:modelValue": e[1] || (e[1] = (a) => t.connectionDetails.type = a),
|
|
283
|
+
id: "connection-type",
|
|
284
|
+
required: ""
|
|
285
|
+
}, [...e[13] || (e[13] = [
|
|
286
|
+
s("option", { value: "duckdb" }, "DuckDB", -1),
|
|
287
|
+
s("option", { value: "bigquery" }, "Bigquery Oauth", -1),
|
|
288
|
+
s("option", { value: "snowflake" }, "Snowflake", -1)
|
|
289
|
+
])], 512), [
|
|
290
|
+
[ve, t.connectionDetails.type]
|
|
291
|
+
])
|
|
292
|
+
]),
|
|
293
|
+
t.connectionDetails.type === "motherduck" ? (r(), l("div", $e, [
|
|
294
|
+
e[15] || (e[15] = s("label", { for: "md-token" }, "MotherDuck Token", -1)),
|
|
295
|
+
_(s("input", {
|
|
296
|
+
type: "password",
|
|
297
|
+
"onUpdate:modelValue": e[2] || (e[2] = (a) => t.connectionDetails.options.mdToken = a),
|
|
298
|
+
id: "md-token",
|
|
299
|
+
placeholder: "MotherDuck Token",
|
|
300
|
+
required: ""
|
|
301
|
+
}, null, 512), [
|
|
302
|
+
[G, t.connectionDetails.options.mdToken]
|
|
303
|
+
]),
|
|
304
|
+
e[16] || (e[16] = s("label", { for: "save-credential" }, "Save Credential?", -1)),
|
|
305
|
+
_(s("input", {
|
|
306
|
+
type: "checkbox",
|
|
307
|
+
id: "save-credential",
|
|
308
|
+
"onUpdate:modelValue": e[3] || (e[3] = (a) => t.connectionDetails.options.saveCredential = a),
|
|
309
|
+
label: "Save Credential?"
|
|
310
|
+
}, null, 512), [
|
|
311
|
+
[Ie, t.connectionDetails.options.saveCredential]
|
|
312
|
+
])
|
|
313
|
+
])) : I("", !0),
|
|
314
|
+
t.connectionDetails.type === "bigquery" ? (r(), l("div", et, [
|
|
315
|
+
e[17] || (e[17] = s("label", { for: "project-id" }, "BigQuery Project ID", -1)),
|
|
316
|
+
_(s("input", {
|
|
317
|
+
type: "text",
|
|
318
|
+
"onUpdate:modelValue": e[4] || (e[4] = (a) => t.connectionDetails.options.projectId = a),
|
|
319
|
+
id: "project-id",
|
|
320
|
+
placeholder: "Billing Project ID",
|
|
321
|
+
required: ""
|
|
322
|
+
}, null, 512), [
|
|
323
|
+
[G, t.connectionDetails.options.projectId]
|
|
324
|
+
])
|
|
325
|
+
])) : I("", !0),
|
|
326
|
+
t.connectionDetails.type === "sqlserver" ? (r(), l("div", tt, [
|
|
327
|
+
e[18] || (e[18] = s("label", { for: "username" }, "Username", -1)),
|
|
328
|
+
_(s("input", {
|
|
329
|
+
type: "text",
|
|
330
|
+
"onUpdate:modelValue": e[5] || (e[5] = (a) => t.connectionDetails.options.username = a),
|
|
331
|
+
id: "username",
|
|
332
|
+
required: ""
|
|
333
|
+
}, null, 512), [
|
|
334
|
+
[G, t.connectionDetails.options.username]
|
|
335
|
+
]),
|
|
336
|
+
e[19] || (e[19] = s("label", { for: "password" }, "Password", -1)),
|
|
337
|
+
_(s("input", {
|
|
338
|
+
type: "password",
|
|
339
|
+
"onUpdate:modelValue": e[6] || (e[6] = (a) => t.connectionDetails.options.password = a),
|
|
340
|
+
id: "username",
|
|
341
|
+
required: ""
|
|
342
|
+
}, null, 512), [
|
|
343
|
+
[G, t.connectionDetails.options.password]
|
|
344
|
+
])
|
|
345
|
+
])) : I("", !0),
|
|
346
|
+
t.connectionDetails.type === "snowflake" ? (r(), l(pe, { key: 3 }, [
|
|
347
|
+
s("div", nt, [
|
|
348
|
+
e[20] || (e[20] = s("label", { for: "account" }, "Account", -1)),
|
|
349
|
+
_(s("input", {
|
|
350
|
+
type: "text",
|
|
351
|
+
"onUpdate:modelValue": e[7] || (e[7] = (a) => t.connectionDetails.options.account = a),
|
|
352
|
+
id: "account",
|
|
353
|
+
required: ""
|
|
354
|
+
}, null, 512), [
|
|
355
|
+
[G, t.connectionDetails.options.account]
|
|
356
|
+
])
|
|
357
|
+
]),
|
|
358
|
+
s("div", ot, [
|
|
359
|
+
e[21] || (e[21] = s("label", { for: "username" }, "Username", -1)),
|
|
360
|
+
_(s("input", {
|
|
361
|
+
type: "text",
|
|
362
|
+
"onUpdate:modelValue": e[8] || (e[8] = (a) => t.connectionDetails.options.username = a),
|
|
363
|
+
id: "username",
|
|
364
|
+
required: ""
|
|
365
|
+
}, null, 512), [
|
|
366
|
+
[G, t.connectionDetails.options.username]
|
|
367
|
+
])
|
|
368
|
+
]),
|
|
369
|
+
s("div", it, [
|
|
370
|
+
e[22] || (e[22] = s("label", { for: "privateKey" }, "Private Key", -1)),
|
|
371
|
+
_(s("input", {
|
|
372
|
+
type: "password",
|
|
373
|
+
"onUpdate:modelValue": e[9] || (e[9] = (a) => t.connectionDetails.options.privateKey = a),
|
|
374
|
+
id: "privateKey",
|
|
375
|
+
required: ""
|
|
376
|
+
}, null, 512), [
|
|
377
|
+
[G, t.connectionDetails.options.privateKey]
|
|
378
|
+
])
|
|
379
|
+
])
|
|
380
|
+
], 64)) : I("", !0),
|
|
381
|
+
s("div", at, [
|
|
382
|
+
e[23] || (e[23] = s("button", {
|
|
383
|
+
"data-testid": "connection-creator-submit",
|
|
384
|
+
type: "submit"
|
|
385
|
+
}, "Submit", -1)),
|
|
386
|
+
s("button", {
|
|
387
|
+
type: "button",
|
|
388
|
+
onClick: e[10] || (e[10] = (a) => t.close())
|
|
389
|
+
}, "Cancel")
|
|
390
|
+
])
|
|
391
|
+
], 32)
|
|
392
|
+
])) : I("", !0);
|
|
393
|
+
}
|
|
394
|
+
const rt = /* @__PURE__ */ X(ze, [["render", st], ["__scopeId", "data-v-bd6e19a1"]]), lt = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFgAAABYCAIAAAD+96djAAAAIGNIUk0AAHomAACAhAAA+gAAAIDoAAB1MAAA6mAAADqYAAAXcJy6UTwAAAAGYktHRAD/AP8A/6C9p5MAAAAHdElNRQfnBRMXJzJGoqCLAAANmElEQVR42u2be4xdxX3HPzNzzn3u3r3s2qy9rLFZxS4E7CA1dVDjBnDclAANbXEgaUpbVIFSqa2UqK1UqfmnaVPURmlUqSRqJKIIQwg1hEDlypaJISIBnFiE+IEfGLxmvX7tw/f9OOfM9I8z997dZV93927vUu1Pd6XV3bNzZj5n5vt7zBxxyy23sGIg292B5WIrIKytgLC2AsLaCghrKyCsrYCw5rS7A4syY3+sCfEBB2HM1G/mM6Twv4RACgBtMAYBLAjHsgABSIESINCaIBzSrOMJL3AElYC8j4CEiyPxNcz1v9N3oL3jNwZjcCSVgAtFzufJezgSIaaZJlMoAOfyGPhwDxu7KfpcLKCkvaBZa/+MUJILBfo6+PR1xBxeHeatUdYkQUw/L+pfjhT50kf54s24cYBsjkde4wcnWJMk0M13o7+/vy3jDx+aI7lY4PM38Pg9bL+eTwzwhc1ENHvPkI5hZni2UcVgln+9jQdvRXrgQUAsxic3U8rxkyHSUYKagix3ECGFsTLbruGbvw9V/BK6Cpqt15PP8j/v0JucdL0QKElUcWqc+6/nS7fjjyNqEyTwkR7bNvDccXIersQ0A6I9GlF/zBWfB7aAj+fhKBwFBnOFv9/Ow1s4OUa2YpE5EiBX5cQYOzfxjTuggJJIiRAIgaPwfYjy8XXkKqgm9bJNGmGsHDqSVQkIrAs0BikwBlPmq3ew/Vr+/Q1OjlEOAKKKgS6+9lvcvRnKGG0bmfTYDd1RtGnaibYJhMAYpMTTnL3CTdc0ggJTY6Tz3H4Dt2/iwhiDWbRhXSf9PeCiCwimowDA6jj6g+I1BBgw4EheHOTOmxrjqQ9PgF9ACdZcxZpVAAQYj6CMktNTEAJ8PtaHI5tm0c44Qhs6Ixw8T1BEqYaDsMMTVhd0haCIXySogMFR9oL3zwUpMBU29fEbaxktEam1aYx1QO//LBcQcYfhHL+4ANHpn6EQSImSONJOhFlMCLQBzT/fRqDJe0RU7W+1pedIXIWrpoZebQMx8am+eAbUQsLBqWZQkqDE+qt54jOUPIbzVpJdiSMxhtESQzmGcmQqk0LYdsYRYHOkKxW+cAOSuVOMOZsLNTiosu5q7t/I+RynrjBaIlslVwXYdg0P3Mit6yh4HB+jw62FsG0s59dFcazMCzvZeLUVwkW1CcKAINCoKLhkxjg8wniZVISbVtHTAxIMSL7zCo8ctCF5O3MNG0ooKj4vnWXjNZjSotsEI2prpAIVupJsS9cclY8uoA0GlOShT/DGJX58llXxdmefgDYkXA4MQoCSLVCKMMQIWSiJ9vGL+Hn8ItqzMair0Bqq3P9hvADanoaHIDoiHB3h8jjCZfGK2eABgBQ4EkfhSKSYFLCg6UngyHChtNcExhBRZCu8MgQRdPMZdLMWTrpAQ4QTo3gaKdoNQtR6FlXsHwRs0rGkFITAD4jEocS3DpGKEuh2gwhNGzqiHDpPJYd0FpIpzAvBBApOAt/j3t0M5elw0aYdIBoR7gQQMcWlIq+fh8iSgAjrupZCB2NZfvv7HB5hdQJfIxa5NEzz1cF6lhkKez2CCovR+8+Aaq7B+VIQAH6Ak+LtYXZ8n0sl1iTxAvunBYKwGYtp/D4fIMbYrCEsvbvKVh+AQNMZ4WfnoITTknB7MgVj8AOcNK+e5M7dGOiOUQ0aTmQhIMKmXWULR+F45iQRxvz5KsN5fE3RYyiLp20pyUDCZTDD4UutXB2N6obBSfPDX/C5F0hHSbqNuRBa05Fl+FR9zXAOBAICTTpG0rWLbRYKY2Wu7eTbn+KmVVQC9g/yL69T1CQcgjBHMPx4kM3rWzMjQgpag0R18ujL/NNrrE8hmKarzeUaIYV8FQN/ciPb+okojlzmscMM57k6ORXzRAq5Kr0J9n0e4lAGAUnOvsc9z9ikWAqyFTZ28+x9UGmu9DoThUCjHIjylb08doTrumbcPWoi+zQGJSj4pCLsuZcdW+jvYm0XH1nPn97IG+f51WVWxe2dJt1DAlzI893fZU03lQwSjKaap2ctXokDg3TFCAwRxXCOzwzQ1YHxFw7CUghQMZA89By7TzGQxp95D22+GmEXGxSr/MfvsLqX6jh+kaCEdwXgsXv4aC+nxpGCSF0+JBFF2ef0OF+7lZuvxc8TdZECKXAUlNnaZ5dxOHGKHi+/B+4CZSLcFg7dpEpQqXLPU7x4loEuqsFsaX4TYhlO3a19bFlHkCXi2KqR6xBUQfNfO/mzzVwq8F6OyyVGS1woMpjFley6mwe2ovM2sG90WlD1GzPIGOIOLw6CaTiU5iYCEAYLnVwcZ8eTHB+nv5NKUPPZM1gTYikF5YCN3SAmuYhQOLSHUPzDHTz8EV44zVujlHxWxfnNPu7aiIwT5Ow2L/VauwHJ0RF0TQ4CQ0eUNy+SydAVR/tNFOXrDiLQOF0cO8PnnsdAb2KSm2wBiHDKVX2YvGkganUhrdE5+nv487WgaeR0ZYIJ27OT8j84Nkqkln2HScflAq8McdeN6CpyfvFVg4LBSXPgCA/tJRUl6cyLAguII8KlO2XOWhbClkP8LEEBHVYBcpgAJRvl03rXlYQqb48TcyatDlex/wyI+YqldZMGDU4XT77GH++hJ07cwdPzbaSZGSHwAwbSTENiwgjrtTZjcCbNnMm9B6EYz3M+T8yhnnxrQyrCwfP4BRwHM9fzrAcLQiETfH0//3aIDV12jSzJ3qc2KMnt62F+jm3OAeBw+gq5qq0v1+8Sczif5/VhiNhN7dkpBAHSRUT58vN88xADabRBN1kHboCYaQsk/MQchvN86jo+1Icut6BqYAwojo0SaNtaXdXDBGzfGVAzRu4Tc2oVB8MfPs0zpxhI483qJmcyZ2Lb4SIPexlWOEVtU+Rcnr4kX98OlSZW7yxmlXIE932jDROwnw41ErApt7Pf1HLqTIadP+TdDBtSVIJG4wsBEQYzJZ9MEW2IKhIuSqANJZ9MhV/v5bt3k4ijy0i52A2IMEjF5+Q4McWU6lxYzj2T4ZeXuPkadAk1wenaWxt8jZPinXPc9yOKPn0dNlhYmDl1CpeLrEnyB5vodDkywrFRSj5Rxa9189lN/N5mMK2hQDgoh0KBoSzRySUpu7sLSvC9N7l5AFNEm8ZitA7C4KT52XEe3EPcpSc+Xzc5I4iQwqUiO9bz6KchBkCAKZGrknRQSZCYIka3hgI1gXg3w5UKqxPTRNO+ZlWCH73Ntp9z78cwGXx/QqddZJKnD/I3L9GbJKKmT/aaAyEFBY91HTx6Jwi8jNUqqUglwKBLaG3PprSEAjWXcXwUL0CKqX6uXkHoTfK3LzGc4y+34qRqUiKgyFf38p9vsq7TUlt8rxwlyVZ4cAtE8TK4ju2o0Rht7+vUwruWULCNwtGRGTf46scfepN84xC7T7JjAx9Kow0nxtg/yMUi61PzOpE5XxCAgb5O0Ihat6wba9Gop5hVyoDjY8TUjFmm3acW9HeS8/jeERtTKEE6Sl8STze62hoQUnB6HBxbzFlqMyAVXomz2UnB9UwsvICYIplspGqBaSJ2nqfJQHNVjN1vMT5KJIXnN/KfpQJhwGEwWzvUMuvFonbO2tN4AV6ApxdyVmxuENoQUZQDdj7L8EXcMD6tHVhbKhCK46NUAlRt/s/OYppPq3slw8JeV5TLJW57iqd/jupEugQ1h7QkOCRHR5BYBEu8yzfPHoX7P5pUhO4YXz7AF5+l6qE68YNGnt8qCysXBLw1StRZwgW4EBB1FkIwkGb/IB/fxeuncNIY2VwyO69bSijzbobYkm1zLhwENYmuBqztQBs++zyP7EO6qLidGrRimWgDDmezXC4SnUsp2wOCmix5AVHFtSm+9SZ3PcnQCE5XyxTUAA4nxij5OPNQyvaAqOPQBl+zPsVglu1P8dRBVCcygr94Ba0VbOvvHC0PDjPET+HUqAako3TH+OuXePgZyhWcxSloWNdEc2yUaEt3epcKRB1HXUEPnGXbLl49uVgFlQoqnL6yvJSSOSPquoKu6cDAfS/wj3uRzgIVNAylhnNcLCwvpZwbBJMVdH2K7/yKO55g8BJOF5rmFFQDDifHKHqTCrbLweabY01U0HN5PvkDHn8NlWxSQQ0ojly2DdLCvP7/DAQTFLQryuoEf/cTHtxNoYyTwg9s+Xy2dxSxSnlkpPECwfKxprPuUEGBgTQ/Pce2Xbx8DKcLIRvpyfSr31ilfHuc+DJTyoWAYIKC9iZRgj/aw1f2ICQqWVPQ6aZGqJRDObu1tcw4LLQOU1fQiGJDil3H2P4EJ87hpNFieufqa4iz711Kfk0pl41AsMj3NepV1u4442UeO0zUY+t1SIVftRsRBrQhCIh0MjrGX+0jGamdDfh/A4La1Ag0MYcOl/9+h1cHua2PzlXIcKNMIl1UJ2Mj3Pcc2SpJl6BFFddlBKKOIyyf9cQ5k+Hxo5gKfQniCq0ZzvDkL/mL/RQ8uqKtqb633Fr5Bk94fsmReJpLRWKK7jgYxsqUA1bHcVXrqxutsla+wWPPL2mkoL+TQFPxAa6K2aOZy5ZCi0FYHLUavBD2bUODfUtm2VJYEhD1AU88oL2cESwhiA/K4CfasnhxZTnYCghrKyCsrYCwtgLC2goIaysgrK2AsLYCwtoKCGv/C38vfvTP3ug8AAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDIzLTA1LTE5VDIzOjM5OjQ5KzAwOjAweTItFAAAACV0RVh0ZGF0ZTptb2RpZnkAMjAyMy0wNS0xOVQyMzozOTo0OSswMDowMAhvlagAAAAodEVYdGRhdGU6dGltZXN0YW1wADE5NzAtMDEtMDFUMDA6MDA6MDArMDA6MDCutErVAAAAAElFTkSuQmCC", ct = {
|
|
395
|
+
key: 0,
|
|
396
|
+
class: "mdi mdi-duck"
|
|
397
|
+
}, ut = ["src"], dt = {
|
|
398
|
+
key: 2,
|
|
399
|
+
class: "mdi mdi-google"
|
|
400
|
+
}, pt = {
|
|
401
|
+
key: 3,
|
|
402
|
+
class: "mdi mdi-google"
|
|
403
|
+
}, mt = {
|
|
404
|
+
key: 4,
|
|
405
|
+
class: "mdi mdi-database"
|
|
406
|
+
}, ht = /* @__PURE__ */ ae({
|
|
407
|
+
__name: "ConnectionIcon",
|
|
408
|
+
props: {
|
|
409
|
+
connectionType: {}
|
|
410
|
+
},
|
|
411
|
+
setup(t) {
|
|
412
|
+
const e = t, o = $(() => ({
|
|
413
|
+
duckdb: "DuckDB",
|
|
414
|
+
motherduck: "MotherDuck",
|
|
415
|
+
"bigquery-oauth": "BigQuery",
|
|
416
|
+
snowflake: "Snowflake",
|
|
417
|
+
default: "Database Connection"
|
|
418
|
+
})[e.connectionType || "default"] || e.connectionType || "");
|
|
419
|
+
return (i, c) => (r(), z(Ee, { content: o.value }, {
|
|
420
|
+
default: q(() => [
|
|
421
|
+
t.connectionType === "duckdb" ? (r(), l("i", ct)) : t.connectionType === "motherduck" ? (r(), l("img", {
|
|
422
|
+
key: 1,
|
|
423
|
+
src: qe(lt),
|
|
424
|
+
class: "motherduck-icon",
|
|
425
|
+
alt: "MotherDuck"
|
|
426
|
+
}, null, 8, ut)) : t.connectionType === "bigquery-oauth" ? (r(), l("i", dt)) : t.connectionType === "bigquery" ? (r(), l("i", pt)) : (r(), l("i", mt))
|
|
427
|
+
]),
|
|
428
|
+
_: 1
|
|
429
|
+
}, 8, ["content"]));
|
|
430
|
+
}
|
|
431
|
+
}), yt = /* @__PURE__ */ X(ht, [["__scopeId", "data-v-8b4a0eaf"]]), ft = /* @__PURE__ */ ae({
|
|
432
|
+
__name: "ConnectionRefresh",
|
|
433
|
+
props: {
|
|
434
|
+
connection: {},
|
|
435
|
+
type: {},
|
|
436
|
+
isConnected: { type: Boolean }
|
|
437
|
+
},
|
|
438
|
+
emits: ["refresh"],
|
|
439
|
+
setup(t, { emit: e }) {
|
|
440
|
+
const o = t, i = e;
|
|
441
|
+
let c;
|
|
442
|
+
if (o.type === "llm" ? c = Y("llmConnectionStore") : c = Y("connectionStore"), !c)
|
|
443
|
+
throw new Error("Connection store is not provided!");
|
|
444
|
+
const p = $(
|
|
445
|
+
() => o.connection.connected ? "mdi mdi-refresh" : "mdi mdi-connection"
|
|
446
|
+
), a = async () => {
|
|
447
|
+
try {
|
|
448
|
+
await c.resetConnection(o.connection.name), i("refresh", o.connection.name);
|
|
449
|
+
} catch (d) {
|
|
450
|
+
throw console.error("Refresh failed:", d), d;
|
|
451
|
+
}
|
|
452
|
+
};
|
|
453
|
+
return (d, w) => (r(), z(Se, {
|
|
454
|
+
class: "refresh-button",
|
|
455
|
+
action: a,
|
|
456
|
+
"data-testid": `refresh-connection-${t.connection.name}`,
|
|
457
|
+
useDefaultStyle: !1,
|
|
458
|
+
testId: `refresh-connection-${t.connection.name}`,
|
|
459
|
+
onClick: w[0] || (w[0] = A(() => {
|
|
460
|
+
}, ["stop"]))
|
|
461
|
+
}, {
|
|
462
|
+
default: q(() => [
|
|
463
|
+
s("i", {
|
|
464
|
+
class: me([p.value, "refresh-icon"])
|
|
465
|
+
}, null, 2)
|
|
466
|
+
]),
|
|
467
|
+
_: 1
|
|
468
|
+
}, 8, ["data-testid", "testId"]));
|
|
469
|
+
}
|
|
470
|
+
}), De = /* @__PURE__ */ X(ft, [["__scopeId", "data-v-a2ead502"]]), gt = ae({
|
|
471
|
+
name: "FileUpload",
|
|
472
|
+
props: {
|
|
473
|
+
connection: {
|
|
474
|
+
type: Object,
|
|
475
|
+
required: !0
|
|
476
|
+
}
|
|
477
|
+
},
|
|
478
|
+
setup(t) {
|
|
479
|
+
const e = C(!1), o = C(!1), i = C("Processing file..."), c = C(""), p = C(null), a = () => {
|
|
480
|
+
e.value = !0;
|
|
481
|
+
}, d = () => {
|
|
482
|
+
e.value = !1;
|
|
483
|
+
}, w = async (b) => {
|
|
484
|
+
const m = b.target;
|
|
485
|
+
m.files && m.files.length > 0 && await E(m.files[0]);
|
|
486
|
+
}, h = async (b) => {
|
|
487
|
+
var m;
|
|
488
|
+
if (e.value = !1, (m = b.dataTransfer) != null && m.files && b.dataTransfer.files.length > 0) {
|
|
489
|
+
const F = b.dataTransfer.files[0];
|
|
490
|
+
P(F) ? await E(F) : alert("Please drop a CSV, Parquet, or DuckDB file");
|
|
491
|
+
}
|
|
492
|
+
}, P = (b) => b.type === "text/csv" || b.name.endsWith(".csv") || b.type === "application/octet-stream" || b.name.endsWith(".parquet") || b.name.endsWith(".db"), E = async (b) => {
|
|
493
|
+
try {
|
|
494
|
+
o.value = !0, i.value = `Processing ${b.name}...`;
|
|
495
|
+
const m = await t.connection.importFile(b, (F) => {
|
|
496
|
+
i.value = F;
|
|
497
|
+
});
|
|
498
|
+
m.type === "database" ? c.value = `Successfully attached database ${m.name}` : c.value = `Successfully imported ${m.name}`, o.value = !1, setTimeout(() => {
|
|
499
|
+
c.value = "";
|
|
500
|
+
}, 5e3), p.value && (p.value.value = "");
|
|
501
|
+
} catch (m) {
|
|
502
|
+
o.value = !1, console.error(`Error processing ${b.name}:`, m), alert(
|
|
503
|
+
`Error processing ${b.name}: ${m instanceof Error ? m.message : "Unknown error"}`
|
|
504
|
+
);
|
|
505
|
+
}
|
|
506
|
+
};
|
|
507
|
+
return {
|
|
508
|
+
isDragging: e,
|
|
509
|
+
isLoading: o,
|
|
510
|
+
loadingMessage: i,
|
|
511
|
+
successMessage: c,
|
|
512
|
+
fileInput: p,
|
|
513
|
+
handleDragOver: a,
|
|
514
|
+
handleDragLeave: d,
|
|
515
|
+
handleDrop: h,
|
|
516
|
+
handleFileInput: w
|
|
517
|
+
};
|
|
518
|
+
}
|
|
519
|
+
}), wt = { class: "upload-area" }, Tt = {
|
|
520
|
+
key: 0,
|
|
521
|
+
class: "success-message"
|
|
522
|
+
}, bt = { key: 1 }, vt = { class: "truncate-text" }, Et = { class: "file-input-label" }, St = {
|
|
523
|
+
key: 2,
|
|
524
|
+
class: "loading-container"
|
|
525
|
+
};
|
|
526
|
+
function Ct(t, e, o, i, c, p) {
|
|
527
|
+
return r(), l("div", {
|
|
528
|
+
class: me(["file-upload-container", { "drag-active": t.isDragging }]),
|
|
529
|
+
onDragover: e[1] || (e[1] = A((...a) => t.handleDragOver && t.handleDragOver(...a), ["prevent"])),
|
|
530
|
+
onDragleave: e[2] || (e[2] = A((...a) => t.handleDragLeave && t.handleDragLeave(...a), ["prevent"])),
|
|
531
|
+
onDrop: e[3] || (e[3] = A((...a) => t.handleDrop && t.handleDrop(...a), ["prevent"]))
|
|
532
|
+
}, [
|
|
533
|
+
s("div", wt, [
|
|
534
|
+
t.successMessage && !t.isLoading ? (r(), l("div", Tt, [
|
|
535
|
+
s("span", null, j(t.successMessage), 1)
|
|
536
|
+
])) : t.isLoading ? (r(), l("div", St, [
|
|
537
|
+
e[7] || (e[7] = s("span", { class: "spinner" }, null, -1)),
|
|
538
|
+
s("span", null, j(t.loadingMessage), 1)
|
|
539
|
+
])) : (r(), l("div", bt, [
|
|
540
|
+
s("div", vt, [
|
|
541
|
+
e[5] || (e[5] = de(" Drag or", -1)),
|
|
542
|
+
s("label", Et, [
|
|
543
|
+
e[4] || (e[4] = de(" select ", -1)),
|
|
544
|
+
s("input", {
|
|
545
|
+
type: "file",
|
|
546
|
+
accept: ".csv,.parquet,.db",
|
|
547
|
+
onChange: e[0] || (e[0] = (...a) => t.handleFileInput && t.handleFileInput(...a)),
|
|
548
|
+
ref: "fileInput",
|
|
549
|
+
class: "hidden-input"
|
|
550
|
+
}, null, 544)
|
|
551
|
+
]),
|
|
552
|
+
e[6] || (e[6] = de(" CSV/Parquet or DuckDB DB ", -1))
|
|
553
|
+
])
|
|
554
|
+
]))
|
|
555
|
+
])
|
|
556
|
+
], 34);
|
|
557
|
+
}
|
|
558
|
+
const kt = /* @__PURE__ */ X(gt, [["render", Ct], ["__scopeId", "data-v-d7832089"]]), At = { class: "model-anchor" }, It = {
|
|
559
|
+
key: 0,
|
|
560
|
+
class: "model-form"
|
|
561
|
+
}, Pt = ["value"], Rt = /* @__PURE__ */ ae({
|
|
562
|
+
__name: "ModelSelector",
|
|
563
|
+
props: {
|
|
564
|
+
connection: {}
|
|
565
|
+
},
|
|
566
|
+
setup(t) {
|
|
567
|
+
const e = t, o = Y("modelStore"), i = Y("connectionStore"), c = Y("saveConnections", () => {
|
|
568
|
+
}), p = C(!1), a = C(e.connection.model || ""), d = $(() => o ? Object.keys(o.models) : []), w = () => {
|
|
569
|
+
p.value = !p.value;
|
|
570
|
+
}, h = () => {
|
|
571
|
+
p.value = !1;
|
|
572
|
+
}, P = async () => {
|
|
573
|
+
if (a.value && i) {
|
|
574
|
+
let E = a.value;
|
|
575
|
+
E === "~new-model" && (E = e.connection.name, await (o == null ? void 0 : o.addModelConfig(
|
|
576
|
+
new Be({
|
|
577
|
+
name: e.connection.name,
|
|
578
|
+
sources: [],
|
|
579
|
+
storage: "local",
|
|
580
|
+
description: ""
|
|
581
|
+
})
|
|
582
|
+
))), i.connections[e.connection.name].model = E;
|
|
583
|
+
}
|
|
584
|
+
c(), p.value = !1;
|
|
585
|
+
};
|
|
586
|
+
return (E, b) => (r(), l("div", At, [
|
|
587
|
+
s("button", {
|
|
588
|
+
class: "button truncate-text",
|
|
589
|
+
onClick: w
|
|
590
|
+
}, j(t.connection.model || "Set Model"), 1),
|
|
591
|
+
p.value ? (r(), l("div", It, [
|
|
592
|
+
s("form", {
|
|
593
|
+
onSubmit: A(P, ["prevent"])
|
|
594
|
+
}, [
|
|
595
|
+
_(s("select", {
|
|
596
|
+
"onUpdate:modelValue": b[0] || (b[0] = (m) => a.value = m),
|
|
597
|
+
class: "model-select",
|
|
598
|
+
required: ""
|
|
599
|
+
}, [
|
|
600
|
+
(r(!0), l(pe, null, fe(d.value, (m) => (r(), l("option", {
|
|
601
|
+
key: m,
|
|
602
|
+
value: m,
|
|
603
|
+
class: "model-select-item"
|
|
604
|
+
}, j(m), 9, Pt))), 128)),
|
|
605
|
+
b[1] || (b[1] = s("option", {
|
|
606
|
+
key: "~new-model",
|
|
607
|
+
value: "~new-model",
|
|
608
|
+
class: "model-select-item"
|
|
609
|
+
}, " Create New Model ", -1))
|
|
610
|
+
], 512), [
|
|
611
|
+
[ve, a.value]
|
|
612
|
+
]),
|
|
613
|
+
s("div", { class: "model-form-actions" }, [
|
|
614
|
+
b[2] || (b[2] = s("button", { type: "submit" }, "Submit", -1)),
|
|
615
|
+
s("button", {
|
|
616
|
+
type: "button",
|
|
617
|
+
onClick: h
|
|
618
|
+
}, "Close")
|
|
619
|
+
])
|
|
620
|
+
], 32)
|
|
621
|
+
])) : I("", !0)
|
|
622
|
+
]));
|
|
623
|
+
}
|
|
624
|
+
}), Mt = /* @__PURE__ */ X(Rt, [["__scopeId", "data-v-11ffb5f2"]]), Lt = {
|
|
625
|
+
name: "ConnectionListItem",
|
|
626
|
+
components: {
|
|
627
|
+
SidebarItem: Re,
|
|
628
|
+
ConnectionIcon: yt,
|
|
629
|
+
ConnectionRefresh: De,
|
|
630
|
+
ConnectionStatusIcon: Pe,
|
|
631
|
+
EditorCreatorIcon: Fe,
|
|
632
|
+
CreateEditorFromDatasourcePopup: Ye,
|
|
633
|
+
DuckDBImporter: kt,
|
|
634
|
+
ModelSelector: Mt,
|
|
635
|
+
Tooltip: Ee
|
|
636
|
+
},
|
|
637
|
+
props: {
|
|
638
|
+
item: {
|
|
639
|
+
type: Object,
|
|
640
|
+
required: !0
|
|
641
|
+
},
|
|
642
|
+
isCollapsed: {
|
|
643
|
+
type: Boolean,
|
|
644
|
+
default: !0
|
|
645
|
+
},
|
|
646
|
+
isSelected: {
|
|
647
|
+
type: Boolean,
|
|
648
|
+
default: !1
|
|
649
|
+
},
|
|
650
|
+
testTag: {
|
|
651
|
+
type: String,
|
|
652
|
+
default: ""
|
|
653
|
+
}
|
|
654
|
+
},
|
|
655
|
+
emits: [
|
|
656
|
+
"toggle",
|
|
657
|
+
"click",
|
|
658
|
+
"refresh",
|
|
659
|
+
"updateBigqueryProject",
|
|
660
|
+
"updateBigqueryBrowsingProject",
|
|
661
|
+
"updateMotherDuckToken",
|
|
662
|
+
"updateSnowflakePrivateKey",
|
|
663
|
+
"updateSnowflakeAccount",
|
|
664
|
+
"updateSnowflakeUsername",
|
|
665
|
+
"toggleSaveCredential",
|
|
666
|
+
"deleteConnection",
|
|
667
|
+
"toggleMobileMenu"
|
|
668
|
+
],
|
|
669
|
+
setup(t, { emit: e }) {
|
|
670
|
+
var re, H, ge;
|
|
671
|
+
const o = Y("isMobile", !1), i = $(
|
|
672
|
+
() => ["connection", "database", "schema"].includes(t.item.type)
|
|
673
|
+
), c = $(
|
|
674
|
+
() => ["connection", "database", "schema", "table", "schema"].includes(t.item.type)
|
|
675
|
+
), p = () => [
|
|
676
|
+
"refresh-connection",
|
|
677
|
+
"refresh-database",
|
|
678
|
+
"refresh-schema",
|
|
679
|
+
"duckdb-upload",
|
|
680
|
+
"model",
|
|
681
|
+
"bigquery-project",
|
|
682
|
+
"bigquery-browsing-project",
|
|
683
|
+
"motherduck-token",
|
|
684
|
+
"snowflake-private-key",
|
|
685
|
+
"snowflake-account",
|
|
686
|
+
"snowflake-username",
|
|
687
|
+
"toggle-save-credential"
|
|
688
|
+
].includes(t.item.type) ? "" : t.item.name, a = () => {
|
|
689
|
+
var R;
|
|
690
|
+
c.value && e("click", t.item.id, ((R = t.item.connection) == null ? void 0 : R.name) || "", t.item.type);
|
|
691
|
+
}, d = () => {
|
|
692
|
+
var R;
|
|
693
|
+
c.value && e("toggle", t.item.id, ((R = t.item.connection) == null ? void 0 : R.name) || "", t.item.type);
|
|
694
|
+
}, w = () => {
|
|
695
|
+
e("toggleMobileMenu");
|
|
696
|
+
}, h = () => {
|
|
697
|
+
var R, ie;
|
|
698
|
+
e("refresh", (R = t.item.connection) == null ? void 0 : R.name, ((ie = t.item.connection) == null ? void 0 : ie.name) || "", "connection");
|
|
699
|
+
}, P = () => {
|
|
700
|
+
var R;
|
|
701
|
+
e("refresh", t.item.id, ((R = t.item.connection) == null ? void 0 : R.name) || "", "database");
|
|
702
|
+
}, E = () => {
|
|
703
|
+
var R;
|
|
704
|
+
e("refresh", t.item.id, ((R = t.item.connection) == null ? void 0 : R.name) || "", "schema");
|
|
705
|
+
}, b = (R) => {
|
|
706
|
+
e("deleteConnection", R);
|
|
707
|
+
}, m = C(
|
|
708
|
+
t.item.connection.projectId || ""
|
|
709
|
+
), F = C(
|
|
710
|
+
t.item.connection.browsingProjectId || ""
|
|
711
|
+
), g = C(t.item.connection.mdToken || ""), le = C(
|
|
712
|
+
((re = t.item.connection.config) == null ? void 0 : re.privateKey) || ""
|
|
713
|
+
), f = C(
|
|
714
|
+
((H = t.item.connection.config) == null ? void 0 : H.account) || ""
|
|
715
|
+
), k = C(
|
|
716
|
+
((ge = t.item.connection.config) == null ? void 0 : ge.username) || ""
|
|
717
|
+
), v = C(!1), L = C(!1), T = C(!1), V = C(!1), J = C(!1), Q = (R) => {
|
|
718
|
+
R.value = !0, setTimeout(() => {
|
|
719
|
+
R.value = !1;
|
|
720
|
+
}, 1500);
|
|
721
|
+
}, K = (R, ie) => {
|
|
722
|
+
let we;
|
|
723
|
+
return (...ce) => {
|
|
724
|
+
clearTimeout(we), we = setTimeout(() => R(...ce), ie);
|
|
725
|
+
};
|
|
726
|
+
}, y = () => {
|
|
727
|
+
e("updateBigqueryProject", t.item.connection, m.value), Q(v);
|
|
728
|
+
}, D = () => {
|
|
729
|
+
e("updateBigqueryBrowsingProject", t.item.connection, F.value), Q(L);
|
|
730
|
+
}, u = () => {
|
|
731
|
+
e("updateSnowflakePrivateKey", t.item.connection, le.value), Q(T);
|
|
732
|
+
}, S = () => {
|
|
733
|
+
e("updateSnowflakeAccount", t.item.connection, f.value), Q(V);
|
|
734
|
+
}, B = () => {
|
|
735
|
+
e("updateSnowflakeUsername", t.item.connection, k.value), Q(J);
|
|
736
|
+
}, ee = K(y, 500), Z = K(
|
|
737
|
+
D,
|
|
738
|
+
500
|
|
739
|
+
), te = K(u, 500), oe = K(S, 500), O = K(B, 500);
|
|
740
|
+
return {
|
|
741
|
+
isMobile: o,
|
|
742
|
+
isExpandable: i,
|
|
743
|
+
getItemName: p,
|
|
744
|
+
handleItemClick: a,
|
|
745
|
+
handleToggle: d,
|
|
746
|
+
toggleMobileMenu: w,
|
|
747
|
+
handleRefreshConnectionClick: h,
|
|
748
|
+
handleRefreshDatabaseClick: P,
|
|
749
|
+
handleRefreshSchemaClick: E,
|
|
750
|
+
deleteConnection: b,
|
|
751
|
+
// Config variables
|
|
752
|
+
bigqueryProject: m,
|
|
753
|
+
bigqueryBrowsingProject: F,
|
|
754
|
+
mdToken: g,
|
|
755
|
+
snowflakePrivateKey: le,
|
|
756
|
+
snowflakeAccount: f,
|
|
757
|
+
snowflakeUsername: k,
|
|
758
|
+
// Success indicators
|
|
759
|
+
showBillingSuccess: v,
|
|
760
|
+
showBrowsingSuccess: L,
|
|
761
|
+
showPrivateKeySuccess: T,
|
|
762
|
+
showAccountSuccess: V,
|
|
763
|
+
showUsernameSuccess: J,
|
|
764
|
+
// Update functions
|
|
765
|
+
debouncedUpdateBigqueryProject: ee,
|
|
766
|
+
debouncedUpdateBigqueryBrowsingProject: Z,
|
|
767
|
+
debouncedUpdateSnowflakePrivateKey: te,
|
|
768
|
+
debouncedUpdateSnowflakeAccount: oe,
|
|
769
|
+
debouncedUpdateSnowflakeUsername: O,
|
|
770
|
+
updateMotherDuckToken: (R, ie) => {
|
|
771
|
+
e("updateMotherDuckToken", R, ie);
|
|
772
|
+
},
|
|
773
|
+
toggleSaveCredential: (R) => {
|
|
774
|
+
e("toggleSaveCredential", R);
|
|
775
|
+
}
|
|
776
|
+
};
|
|
777
|
+
}
|
|
778
|
+
}, Dt = {
|
|
779
|
+
key: 1,
|
|
780
|
+
class: "mdi mdi-database node-icon"
|
|
781
|
+
}, _t = {
|
|
782
|
+
key: 2,
|
|
783
|
+
class: "mdi mdi-folder-outline node-icon"
|
|
784
|
+
}, Nt = {
|
|
785
|
+
key: 3,
|
|
786
|
+
class: "mdi mdi-table node-icon"
|
|
787
|
+
}, qt = {
|
|
788
|
+
key: 4,
|
|
789
|
+
class: "mdi mdi-alert-circle node-icon"
|
|
790
|
+
}, Ut = {
|
|
791
|
+
key: 5,
|
|
792
|
+
class: "mdi mdi-loading mdi-spin node-icon"
|
|
793
|
+
}, Ot = {
|
|
794
|
+
key: 6,
|
|
795
|
+
class: "mdi mdi-table-column node-icon"
|
|
796
|
+
}, xt = {
|
|
797
|
+
key: 0,
|
|
798
|
+
class: "mdi mdi-check-circle success-icon"
|
|
799
|
+
}, Bt = {
|
|
800
|
+
key: 0,
|
|
801
|
+
class: "mdi mdi-check-circle success-icon"
|
|
802
|
+
}, Yt = {
|
|
803
|
+
key: 0,
|
|
804
|
+
class: "mdi mdi-check-circle success-icon"
|
|
805
|
+
}, Ft = {
|
|
806
|
+
key: 0,
|
|
807
|
+
class: "mdi mdi-check-circle success-icon"
|
|
808
|
+
}, Gt = {
|
|
809
|
+
key: 0,
|
|
810
|
+
class: "mdi mdi-check-circle success-icon"
|
|
811
|
+
}, jt = { class: "save-credential-toggle" }, Kt = ["checked"], Qt = { key: 0 }, Vt = {
|
|
812
|
+
key: 0,
|
|
813
|
+
class: "connection-actions"
|
|
814
|
+
}, Ht = {
|
|
815
|
+
key: 1,
|
|
816
|
+
class: "connection-actions"
|
|
817
|
+
}, Wt = ["data-testid"];
|
|
818
|
+
function zt(t, e, o, i, c, p) {
|
|
819
|
+
const a = U("connection-icon"), d = U("DuckDBImporter"), w = U("model-selector"), h = U("CreateEditorFromDatasourcePopup"), P = U("editor-creator-icon"), E = U("connection-refresh"), b = U("tooltip"), m = U("connection-status-icon"), F = U("sidebar-item");
|
|
820
|
+
return r(), l("div", null, [
|
|
821
|
+
x(F, {
|
|
822
|
+
"item-id": o.item.id,
|
|
823
|
+
name: i.getItemName(),
|
|
824
|
+
indent: o.item.indent,
|
|
825
|
+
"is-selected": o.isSelected,
|
|
826
|
+
"is-collapsible": i.isExpandable,
|
|
827
|
+
"is-collapsed": o.isCollapsed,
|
|
828
|
+
itemType: o.testTag ? o.testTag : "connection",
|
|
829
|
+
onClick: i.handleItemClick,
|
|
830
|
+
onToggle: i.handleToggle
|
|
831
|
+
}, {
|
|
832
|
+
icon: q(() => {
|
|
833
|
+
var g;
|
|
834
|
+
return [
|
|
835
|
+
o.item.type === "connection" ? (r(), z(a, {
|
|
836
|
+
key: 0,
|
|
837
|
+
"connection-type": (g = o.item.connection) == null ? void 0 : g.type
|
|
838
|
+
}, null, 8, ["connection-type"])) : o.item.type === "database" ? (r(), l("i", Dt)) : o.item.type === "schema" ? (r(), l("i", _t)) : o.item.type === "table" ? (r(), l("i", Nt)) : o.item.type === "error" ? (r(), l("i", qt)) : o.item.type === "loading" ? (r(), l("i", Ut)) : o.item.type === "column" ? (r(), l("i", Ot)) : I("", !0)
|
|
839
|
+
];
|
|
840
|
+
}),
|
|
841
|
+
name: q(() => [
|
|
842
|
+
o.item.type === "refresh-connection" ? (r(), l("div", {
|
|
843
|
+
key: 0,
|
|
844
|
+
class: "refresh title-pad-left truncate-text sidebar-sub-item",
|
|
845
|
+
onClick: e[0] || (e[0] = (...g) => i.handleRefreshConnectionClick && i.handleRefreshConnectionClick(...g))
|
|
846
|
+
}, j(o.item.name), 1)) : o.item.type === "refresh-database" ? (r(), l("div", {
|
|
847
|
+
key: 1,
|
|
848
|
+
class: "refresh title-pad-left truncate-text sidebar-sub-item",
|
|
849
|
+
onClick: e[1] || (e[1] = (...g) => i.handleRefreshDatabaseClick && i.handleRefreshDatabaseClick(...g))
|
|
850
|
+
}, j(o.item.name), 1)) : o.item.type === "refresh-schema" ? (r(), l("div", {
|
|
851
|
+
key: 2,
|
|
852
|
+
class: "refresh title-pad-left truncate-text sidebar-sub-item",
|
|
853
|
+
onClick: e[2] || (e[2] = (...g) => i.handleRefreshSchemaClick && i.handleRefreshSchemaClick(...g))
|
|
854
|
+
}, j(o.item.name), 1)) : o.item.type === "duckdb-upload" ? (r(), z(d, {
|
|
855
|
+
key: 3,
|
|
856
|
+
db: o.item.connection.db,
|
|
857
|
+
connection: o.item.connection
|
|
858
|
+
}, null, 8, ["db", "connection"])) : o.item.type === "model" ? (r(), l("div", {
|
|
859
|
+
key: 4,
|
|
860
|
+
class: "bq-project-container",
|
|
861
|
+
onClick: e[3] || (e[3] = A(() => {
|
|
862
|
+
}, ["stop"]))
|
|
863
|
+
}, [
|
|
864
|
+
e[29] || (e[29] = s("label", { class: "input-label" }, "Model", -1)),
|
|
865
|
+
x(w, {
|
|
866
|
+
connection: o.item.connection
|
|
867
|
+
}, null, 8, ["connection"])
|
|
868
|
+
])) : o.item.type === "bigquery-project" ? (r(), l("div", {
|
|
869
|
+
key: 5,
|
|
870
|
+
class: "bq-project-container",
|
|
871
|
+
onClick: e[6] || (e[6] = A(() => {
|
|
872
|
+
}, ["stop"]))
|
|
873
|
+
}, [
|
|
874
|
+
e[30] || (e[30] = s("label", { class: "input-label" }, "Billing", -1)),
|
|
875
|
+
s("span", null, [
|
|
876
|
+
x(be, { name: "fade" }, {
|
|
877
|
+
default: q(() => [
|
|
878
|
+
i.showBillingSuccess ? (r(), l("i", xt)) : I("", !0)
|
|
879
|
+
]),
|
|
880
|
+
_: 1
|
|
881
|
+
}),
|
|
882
|
+
_(s("input", {
|
|
883
|
+
type: "text",
|
|
884
|
+
"onUpdate:modelValue": e[4] || (e[4] = (g) => i.bigqueryProject = g),
|
|
885
|
+
placeholder: "Billing Project",
|
|
886
|
+
class: "bq-project-input",
|
|
887
|
+
onInput: e[5] || (e[5] = (...g) => i.debouncedUpdateBigqueryProject && i.debouncedUpdateBigqueryProject(...g))
|
|
888
|
+
}, null, 544), [
|
|
889
|
+
[G, i.bigqueryProject]
|
|
890
|
+
])
|
|
891
|
+
])
|
|
892
|
+
])) : o.item.type === "bigquery-browsing-project" ? (r(), l("div", {
|
|
893
|
+
key: 6,
|
|
894
|
+
class: "bq-project-container",
|
|
895
|
+
onClick: e[9] || (e[9] = A(() => {
|
|
896
|
+
}, ["stop"]))
|
|
897
|
+
}, [
|
|
898
|
+
e[31] || (e[31] = s("label", { class: "input-label" }, "Browsing", -1)),
|
|
899
|
+
s("span", null, [
|
|
900
|
+
x(be, { name: "fade" }, {
|
|
901
|
+
default: q(() => [
|
|
902
|
+
i.showBrowsingSuccess ? (r(), l("i", Bt)) : I("", !0)
|
|
903
|
+
]),
|
|
904
|
+
_: 1
|
|
905
|
+
}),
|
|
906
|
+
_(s("input", {
|
|
907
|
+
type: "text",
|
|
908
|
+
"onUpdate:modelValue": e[7] || (e[7] = (g) => i.bigqueryBrowsingProject = g),
|
|
909
|
+
placeholder: "Browsing Project",
|
|
910
|
+
class: "bq-project-input",
|
|
911
|
+
onInput: e[8] || (e[8] = (...g) => i.debouncedUpdateBigqueryBrowsingProject && i.debouncedUpdateBigqueryBrowsingProject(...g))
|
|
912
|
+
}, null, 544), [
|
|
913
|
+
[G, i.bigqueryBrowsingProject]
|
|
914
|
+
])
|
|
915
|
+
])
|
|
916
|
+
])) : o.item.type === "motherduck-token" ? (r(), l("div", {
|
|
917
|
+
key: 7,
|
|
918
|
+
class: "md-token-container",
|
|
919
|
+
onClick: e[12] || (e[12] = A(() => {
|
|
920
|
+
}, ["stop"]))
|
|
921
|
+
}, [
|
|
922
|
+
s("form", {
|
|
923
|
+
onSubmit: e[11] || (e[11] = A((g) => i.updateMotherDuckToken(o.item.connection, i.mdToken), ["prevent"]))
|
|
924
|
+
}, [
|
|
925
|
+
e[32] || (e[32] = s("button", {
|
|
926
|
+
type: "submit",
|
|
927
|
+
class: "customize-button"
|
|
928
|
+
}, "Update Token", -1)),
|
|
929
|
+
_(s("input", {
|
|
930
|
+
type: "password",
|
|
931
|
+
"onUpdate:modelValue": e[10] || (e[10] = (g) => i.mdToken = g),
|
|
932
|
+
placeholder: "mdToken",
|
|
933
|
+
class: "connection-customize"
|
|
934
|
+
}, null, 512), [
|
|
935
|
+
[G, i.mdToken]
|
|
936
|
+
])
|
|
937
|
+
], 32)
|
|
938
|
+
])) : o.item.type === "snowflake-private-key" ? (r(), l("div", {
|
|
939
|
+
key: 8,
|
|
940
|
+
class: "bq-project-container",
|
|
941
|
+
onClick: e[15] || (e[15] = A(() => {
|
|
942
|
+
}, ["stop"]))
|
|
943
|
+
}, [
|
|
944
|
+
e[33] || (e[33] = s("label", { class: "input-label" }, "Private Key", -1)),
|
|
945
|
+
s("span", null, [
|
|
946
|
+
x(be, { name: "fade" }, {
|
|
947
|
+
default: q(() => [
|
|
948
|
+
i.showPrivateKeySuccess ? (r(), l("i", Yt)) : I("", !0)
|
|
949
|
+
]),
|
|
950
|
+
_: 1
|
|
951
|
+
}),
|
|
952
|
+
_(s("input", {
|
|
953
|
+
type: "password",
|
|
954
|
+
"onUpdate:modelValue": e[13] || (e[13] = (g) => i.snowflakePrivateKey = g),
|
|
955
|
+
placeholder: "Private Key",
|
|
956
|
+
class: "bq-project-input",
|
|
957
|
+
onInput: e[14] || (e[14] = (...g) => i.debouncedUpdateSnowflakePrivateKey && i.debouncedUpdateSnowflakePrivateKey(...g))
|
|
958
|
+
}, null, 544), [
|
|
959
|
+
[G, i.snowflakePrivateKey]
|
|
960
|
+
])
|
|
961
|
+
])
|
|
962
|
+
])) : o.item.type === "snowflake-account" ? (r(), l("div", {
|
|
963
|
+
key: 9,
|
|
964
|
+
class: "bq-project-container",
|
|
965
|
+
onClick: e[18] || (e[18] = A(() => {
|
|
966
|
+
}, ["stop"]))
|
|
967
|
+
}, [
|
|
968
|
+
e[34] || (e[34] = s("label", { class: "input-label" }, "Account", -1)),
|
|
969
|
+
s("span", null, [
|
|
970
|
+
x(be, { name: "fade" }, {
|
|
971
|
+
default: q(() => [
|
|
972
|
+
i.showAccountSuccess ? (r(), l("i", Ft)) : I("", !0)
|
|
973
|
+
]),
|
|
974
|
+
_: 1
|
|
975
|
+
}),
|
|
976
|
+
_(s("input", {
|
|
977
|
+
type: "text",
|
|
978
|
+
"onUpdate:modelValue": e[16] || (e[16] = (g) => i.snowflakeAccount = g),
|
|
979
|
+
placeholder: "Account",
|
|
980
|
+
class: "bq-project-input",
|
|
981
|
+
onInput: e[17] || (e[17] = (...g) => i.debouncedUpdateSnowflakeAccount && i.debouncedUpdateSnowflakeAccount(...g))
|
|
982
|
+
}, null, 544), [
|
|
983
|
+
[G, i.snowflakeAccount]
|
|
984
|
+
])
|
|
985
|
+
])
|
|
986
|
+
])) : o.item.type === "snowflake-username" ? (r(), l("div", {
|
|
987
|
+
key: 10,
|
|
988
|
+
class: "bq-project-container",
|
|
989
|
+
onClick: e[21] || (e[21] = A(() => {
|
|
990
|
+
}, ["stop"]))
|
|
991
|
+
}, [
|
|
992
|
+
e[35] || (e[35] = s("label", { class: "input-label" }, "Username", -1)),
|
|
993
|
+
s("span", null, [
|
|
994
|
+
x(be, { name: "fade" }, {
|
|
995
|
+
default: q(() => [
|
|
996
|
+
i.showUsernameSuccess ? (r(), l("i", Gt)) : I("", !0)
|
|
997
|
+
]),
|
|
998
|
+
_: 1
|
|
999
|
+
}),
|
|
1000
|
+
_(s("input", {
|
|
1001
|
+
type: "text",
|
|
1002
|
+
"onUpdate:modelValue": e[19] || (e[19] = (g) => i.snowflakeUsername = g),
|
|
1003
|
+
placeholder: "Username",
|
|
1004
|
+
class: "bq-project-input",
|
|
1005
|
+
onInput: e[20] || (e[20] = (...g) => i.debouncedUpdateSnowflakeUsername && i.debouncedUpdateSnowflakeUsername(...g))
|
|
1006
|
+
}, null, 544), [
|
|
1007
|
+
[G, i.snowflakeUsername]
|
|
1008
|
+
])
|
|
1009
|
+
])
|
|
1010
|
+
])) : o.item.type === "toggle-save-credential" ? (r(), l("div", {
|
|
1011
|
+
key: 11,
|
|
1012
|
+
class: "md-token-container",
|
|
1013
|
+
onClick: e[23] || (e[23] = A(() => {
|
|
1014
|
+
}, ["stop"]))
|
|
1015
|
+
}, [
|
|
1016
|
+
s("label", jt, [
|
|
1017
|
+
s("input", {
|
|
1018
|
+
type: "checkbox",
|
|
1019
|
+
checked: o.item.connection.saveCredential,
|
|
1020
|
+
onChange: e[22] || (e[22] = (g) => i.toggleSaveCredential(o.item.connection))
|
|
1021
|
+
}, null, 40, Kt),
|
|
1022
|
+
e[36] || (e[36] = s("span", { class: "checkbox-label" }, "Save Credentials", -1))
|
|
1023
|
+
])
|
|
1024
|
+
])) : (r(), l("span", {
|
|
1025
|
+
key: 12,
|
|
1026
|
+
class: me(["title-pad-left truncate-text", { "error-indicator": o.item.type === "error" }])
|
|
1027
|
+
}, [
|
|
1028
|
+
de(j(o.item.name) + " ", 1),
|
|
1029
|
+
o.item.count !== void 0 && o.item.count > 0 ? (r(), l("span", Qt, " (" + j(o.item.count) + ") ", 1)) : I("", !0),
|
|
1030
|
+
o.item.type === "connection" ? (r(), l("span", {
|
|
1031
|
+
key: 1,
|
|
1032
|
+
class: "hover-icon",
|
|
1033
|
+
onClick: e[24] || (e[24] = A((...g) => i.handleRefreshConnectionClick && i.handleRefreshConnectionClick(...g), ["stop"]))
|
|
1034
|
+
}, [...e[37] || (e[37] = [
|
|
1035
|
+
s("i", { class: "mdi mdi-refresh" }, null, -1)
|
|
1036
|
+
])])) : I("", !0),
|
|
1037
|
+
o.item.type === "database" ? (r(), l("span", {
|
|
1038
|
+
key: 2,
|
|
1039
|
+
class: "hover-icon",
|
|
1040
|
+
onClick: e[25] || (e[25] = A((...g) => i.handleRefreshDatabaseClick && i.handleRefreshDatabaseClick(...g), ["stop"]))
|
|
1041
|
+
}, [...e[38] || (e[38] = [
|
|
1042
|
+
s("i", { class: "mdi mdi-refresh" }, null, -1)
|
|
1043
|
+
])])) : I("", !0),
|
|
1044
|
+
o.item.type === "schema" ? (r(), l("span", {
|
|
1045
|
+
key: 3,
|
|
1046
|
+
class: "hover-icon",
|
|
1047
|
+
onClick: e[26] || (e[26] = A((...g) => i.handleRefreshSchemaClick && i.handleRefreshSchemaClick(...g), ["stop"]))
|
|
1048
|
+
}, [...e[39] || (e[39] = [
|
|
1049
|
+
s("i", { class: "mdi mdi-refresh" }, null, -1)
|
|
1050
|
+
])])) : I("", !0)
|
|
1051
|
+
], 2))
|
|
1052
|
+
]),
|
|
1053
|
+
"extra-content": q(() => [
|
|
1054
|
+
o.item.type === "table" ? (r(), l("div", Vt, [
|
|
1055
|
+
x(h, {
|
|
1056
|
+
class: "hover-icon",
|
|
1057
|
+
connection: o.item.connection,
|
|
1058
|
+
table: o.item.object,
|
|
1059
|
+
mode: "icon"
|
|
1060
|
+
}, null, 8, ["connection", "table"])
|
|
1061
|
+
])) : o.item.type === "connection" ? (r(), l("div", Ht, [
|
|
1062
|
+
i.isMobile ? (r(), l("i", {
|
|
1063
|
+
key: 0,
|
|
1064
|
+
"data-testid": `toggle-history-${o.item.connection.name}`,
|
|
1065
|
+
class: "mdi mdi-history hover-icon",
|
|
1066
|
+
title: "Query History",
|
|
1067
|
+
onClick: e[27] || (e[27] = A((...g) => i.toggleMobileMenu && i.toggleMobileMenu(...g), ["stop"]))
|
|
1068
|
+
}, null, 8, Wt)) : I("", !0),
|
|
1069
|
+
x(P, {
|
|
1070
|
+
class: "tacticle-button hover-icon",
|
|
1071
|
+
connection: o.item.connection.name,
|
|
1072
|
+
type: "sql",
|
|
1073
|
+
title: "New SQL Editor",
|
|
1074
|
+
"data-testid": o.testTag ? `new-sql-editor-${o.item.connection.name}-${o.testTag}` : `new-sql-editor-${o.item.connection.name}`
|
|
1075
|
+
}, null, 8, ["connection", "data-testid"]),
|
|
1076
|
+
x(P, {
|
|
1077
|
+
class: "tacticle-button hover-icon",
|
|
1078
|
+
connection: o.item.connection.name,
|
|
1079
|
+
title: "New Trilogy Editor",
|
|
1080
|
+
"data-testid": o.testTag ? `new-trilogy-editor-${o.item.connection.name}-${o.testTag}` : `new-trilogy-editor-${o.item.connection.name}`
|
|
1081
|
+
}, null, 8, ["connection", "data-testid"]),
|
|
1082
|
+
x(E, {
|
|
1083
|
+
class: "tacticle-button hover-icon",
|
|
1084
|
+
connection: o.item.connection,
|
|
1085
|
+
"is-connected": o.item.connection.connected
|
|
1086
|
+
}, null, 8, ["connection", "is-connected"]),
|
|
1087
|
+
x(b, {
|
|
1088
|
+
class: "tacticle-button hover-icon",
|
|
1089
|
+
content: "Delete Connection",
|
|
1090
|
+
position: "left"
|
|
1091
|
+
}, {
|
|
1092
|
+
default: q(() => [
|
|
1093
|
+
s("span", {
|
|
1094
|
+
class: "remove-btn",
|
|
1095
|
+
onClick: e[28] || (e[28] = A((g) => i.deleteConnection(o.item.connection), ["stop"]))
|
|
1096
|
+
}, [...e[40] || (e[40] = [
|
|
1097
|
+
s("i", { class: "mdi mdi-trash-can-outline" }, null, -1)
|
|
1098
|
+
])])
|
|
1099
|
+
]),
|
|
1100
|
+
_: 1
|
|
1101
|
+
}),
|
|
1102
|
+
x(m, {
|
|
1103
|
+
connection: o.item.connection
|
|
1104
|
+
}, null, 8, ["connection"])
|
|
1105
|
+
])) : I("", !0)
|
|
1106
|
+
]),
|
|
1107
|
+
_: 1
|
|
1108
|
+
}, 8, ["item-id", "name", "indent", "is-selected", "is-collapsible", "is-collapsed", "itemType", "onClick", "onToggle"])
|
|
1109
|
+
]);
|
|
1110
|
+
}
|
|
1111
|
+
const Xt = /* @__PURE__ */ X(Lt, [["render", zt], ["__scopeId", "data-v-fce665fc"]]), Jt = {
|
|
1112
|
+
name: "ConnectionList",
|
|
1113
|
+
props: {
|
|
1114
|
+
activeConnectionKey: {
|
|
1115
|
+
type: String,
|
|
1116
|
+
default: "",
|
|
1117
|
+
optional: !0
|
|
1118
|
+
},
|
|
1119
|
+
testTag: {
|
|
1120
|
+
type: String,
|
|
1121
|
+
default: ""
|
|
1122
|
+
}
|
|
1123
|
+
},
|
|
1124
|
+
data() {
|
|
1125
|
+
return {
|
|
1126
|
+
showDeleteConfirmationState: !1,
|
|
1127
|
+
connectionToDelete: ""
|
|
1128
|
+
};
|
|
1129
|
+
},
|
|
1130
|
+
setup(t, { emit: e }) {
|
|
1131
|
+
const o = Y("connectionStore"), i = Y("saveConnections"), c = Y("modelStore"), p = Y("editorStore"), a = Y("isMobile", C(!1));
|
|
1132
|
+
if (!o || !i || !c || !p)
|
|
1133
|
+
throw new Error("Connection store is not provided!");
|
|
1134
|
+
const d = C({}), w = C({}), h = C({}), P = C(!1), E = C(""), b = () => {
|
|
1135
|
+
E.value = "";
|
|
1136
|
+
}, m = (u, S) => {
|
|
1137
|
+
u.type === "motherduck" && (u.setAttribute("mdToken", S), o.resetConnection(u.name));
|
|
1138
|
+
}, F = async (u, S) => {
|
|
1139
|
+
u.type === "snowflake" && (u.setPrivateKey(S), await i(), await o.resetConnection(u.name));
|
|
1140
|
+
}, g = async (u, S) => {
|
|
1141
|
+
u.type === "snowflake" && (u.setAccount(S), await i(), o.resetConnection(u.name));
|
|
1142
|
+
}, le = async (u, S) => {
|
|
1143
|
+
u.type === "snowflake" && (u.setUsername(S), await i(), o.resetConnection(u.name));
|
|
1144
|
+
}, f = async (u, S) => {
|
|
1145
|
+
u.type === "bigquery-oauth" && (u.setAttribute("projectId", S), await i(), o.resetConnection(u.name));
|
|
1146
|
+
}, k = async (u, S) => {
|
|
1147
|
+
u.type === "bigquery-oauth" && (u.setAttribute("browsingProjectId", S), await i(), u.databases = [], await u.getDatabases());
|
|
1148
|
+
}, v = (u) => {
|
|
1149
|
+
u.saveCredential = !u.saveCredential, o.resetConnection(u.name);
|
|
1150
|
+
}, L = () => {
|
|
1151
|
+
e("toggle-mobile-menu");
|
|
1152
|
+
}, T = C({}), V = async (u, S, B) => {
|
|
1153
|
+
var ee, Z, te, oe;
|
|
1154
|
+
try {
|
|
1155
|
+
if (w.value[u] = !0, (ee = o.connections[S]) != null && ee.connected || await o.resetConnection(S), B === "connection") {
|
|
1156
|
+
console.log("getting databases");
|
|
1157
|
+
let O = await o.connections[S].getDatabases();
|
|
1158
|
+
for (let W of O) {
|
|
1159
|
+
let se = `${S}${N}${W.name}`;
|
|
1160
|
+
T.value[se] = !0;
|
|
1161
|
+
}
|
|
1162
|
+
}
|
|
1163
|
+
if (B === "database") {
|
|
1164
|
+
console.log("getting schemas");
|
|
1165
|
+
let O = u.split(N)[1];
|
|
1166
|
+
await o.connections[S].refreshDatabase(O);
|
|
1167
|
+
}
|
|
1168
|
+
if (B === "schema") {
|
|
1169
|
+
let O = u.split(N)[1], W = u.split(N)[2];
|
|
1170
|
+
await o.connections[S].refreshSchema(O, W);
|
|
1171
|
+
}
|
|
1172
|
+
if (B === "table") {
|
|
1173
|
+
let O = u.split(N)[1], W = u.split(N)[2], se = u.split(N)[3], re = (oe = (te = (Z = o.connections[S].databases) == null ? void 0 : Z.find((H) => H.name === O)) == null ? void 0 : te.schemas.find((H) => H.name === W)) == null ? void 0 : oe.tables.find((H) => H.name === se);
|
|
1174
|
+
if (re) {
|
|
1175
|
+
let H = await o.connections[S].getColumns(
|
|
1176
|
+
O,
|
|
1177
|
+
W,
|
|
1178
|
+
se
|
|
1179
|
+
);
|
|
1180
|
+
re.columns = H;
|
|
1181
|
+
}
|
|
1182
|
+
}
|
|
1183
|
+
delete h.value[u];
|
|
1184
|
+
} catch (O) {
|
|
1185
|
+
console.error(O), O instanceof Error ? h.value[u] = O.message : h.value[u] = "An error occurred";
|
|
1186
|
+
}
|
|
1187
|
+
delete w.value[u];
|
|
1188
|
+
}, J = async (u, S, B) => {
|
|
1189
|
+
console.log("emitting connection key selected:", u), e("connection-key-selected", u);
|
|
1190
|
+
}, Q = async (u, S, B) => {
|
|
1191
|
+
var ee, Z, te, oe, O, W, se, re, H, ge, R, ie, we;
|
|
1192
|
+
if (B === "connection" && (T.value[u] === void 0 || T.value[u] === !0))
|
|
1193
|
+
T.value[u] = !1, (((ee = o.connections[S].databases) == null ? void 0 : ee.length) === 0 || ((Z = o.connections[S].databases) == null ? void 0 : Z.length) === void 0) && await V(u, S, B);
|
|
1194
|
+
else if (B === "database" && T.value[u] !== !1) {
|
|
1195
|
+
T.value[u] = !1;
|
|
1196
|
+
let ce = u.split(N)[1], he = (te = o.connections[S].databases) == null ? void 0 : te.find((ue) => ue.name === ce);
|
|
1197
|
+
he && ((oe = he.schemas) == null ? void 0 : oe.length) === 0 && await V(u, S, B);
|
|
1198
|
+
} else if (B === "schema" && T.value[u] !== !1) {
|
|
1199
|
+
T.value[u] = !1;
|
|
1200
|
+
let ce = u.split(N)[1], he = u.split(N)[2], ue = (se = (W = (O = o.connections[S].databases) == null ? void 0 : O.find((ye) => ye.name === ce)) == null ? void 0 : W.schemas) == null ? void 0 : se.find((ye) => ye.name === he);
|
|
1201
|
+
ue && ((re = ue.tables) == null ? void 0 : re.length) === 0 && await V(u, S, B);
|
|
1202
|
+
} else if (B === "table" && T.value[u] !== !1) {
|
|
1203
|
+
let ce = u.split(N)[1], he = u.split(N)[3], ue = u.split(N)[2];
|
|
1204
|
+
if (ue) {
|
|
1205
|
+
let ye = await ((we = (ie = (R = (ge = (H = o.connections[S].databases) == null ? void 0 : H.find((Te) => Te.name === ce)) == null ? void 0 : ge.schemas) == null ? void 0 : R.find((Te) => Te.name === ue)) == null ? void 0 : ie.tables) == null ? void 0 : we.find((Te) => Te.name === he));
|
|
1206
|
+
if (ye && ye.columns.length === 0) {
|
|
1207
|
+
await V(u, S, B);
|
|
1208
|
+
return;
|
|
1209
|
+
}
|
|
1210
|
+
}
|
|
1211
|
+
} else T.value[u] === void 0 ? T.value[u] = !1 : T.value[u] = !T.value[u];
|
|
1212
|
+
};
|
|
1213
|
+
Object.values(o.connections).forEach((u) => {
|
|
1214
|
+
var B;
|
|
1215
|
+
let S = `${u.name}`;
|
|
1216
|
+
T.value[S] = !0, (B = u.databases) == null || B.forEach((ee) => {
|
|
1217
|
+
let Z = `${S}${N}${ee.name}`;
|
|
1218
|
+
T.value[Z] = !0, ee.schemas.forEach((te) => {
|
|
1219
|
+
let oe = `${Z}${N}${te.name}`;
|
|
1220
|
+
T.value[oe] = !0;
|
|
1221
|
+
for (let O of te.tables) {
|
|
1222
|
+
let W = `${Z}${N}${O.schema}${N}${O.name}`;
|
|
1223
|
+
T.value[W] = !0;
|
|
1224
|
+
}
|
|
1225
|
+
});
|
|
1226
|
+
});
|
|
1227
|
+
});
|
|
1228
|
+
const K = $(() => He(
|
|
1229
|
+
Object.values(o.connections),
|
|
1230
|
+
T.value,
|
|
1231
|
+
w.value,
|
|
1232
|
+
h.value
|
|
1233
|
+
)), y = $(() => We(K.value, E.value));
|
|
1234
|
+
return {
|
|
1235
|
+
connectionStore: o,
|
|
1236
|
+
editorStore: p,
|
|
1237
|
+
contentList: K,
|
|
1238
|
+
filteredContentList: y,
|
|
1239
|
+
toggleCollapse: Q,
|
|
1240
|
+
handleItemClick: J,
|
|
1241
|
+
toggleMobileMenu: L,
|
|
1242
|
+
collapsed: T,
|
|
1243
|
+
saveConnections: i,
|
|
1244
|
+
modelStore: c,
|
|
1245
|
+
connectionModelVisible: d,
|
|
1246
|
+
updateMotherDuckToken: m,
|
|
1247
|
+
updateSnowflakePrivateKey: F,
|
|
1248
|
+
updateSnowflakeAccount: g,
|
|
1249
|
+
updateSnowflakeUsername: le,
|
|
1250
|
+
toggleSaveCredential: v,
|
|
1251
|
+
updateBigqueryProject: f,
|
|
1252
|
+
updateBigqueryBrowsingProject: k,
|
|
1253
|
+
refreshId: V,
|
|
1254
|
+
rightSplit: (u) => {
|
|
1255
|
+
const S = u.lastIndexOf(N);
|
|
1256
|
+
return S !== -1 ? u.substring(0, S) : u;
|
|
1257
|
+
},
|
|
1258
|
+
creatorVisible: P,
|
|
1259
|
+
isMobile: a,
|
|
1260
|
+
searchTerm: E,
|
|
1261
|
+
clearSearch: b
|
|
1262
|
+
};
|
|
1263
|
+
},
|
|
1264
|
+
components: {
|
|
1265
|
+
SidebarList: Le,
|
|
1266
|
+
ConnectionCreatorInline: rt,
|
|
1267
|
+
LoadingButton: Se,
|
|
1268
|
+
StatusIcon: Me,
|
|
1269
|
+
Tooltip: Ee,
|
|
1270
|
+
ConnectionListItem: Xt
|
|
1271
|
+
},
|
|
1272
|
+
methods: {
|
|
1273
|
+
resetConnection(t) {
|
|
1274
|
+
return this.connectionStore.resetConnection(t.name);
|
|
1275
|
+
},
|
|
1276
|
+
showDeleteConfirmation(t) {
|
|
1277
|
+
this.connectionToDelete = t.name, this.showDeleteConfirmationState = !0;
|
|
1278
|
+
},
|
|
1279
|
+
cancelDelete() {
|
|
1280
|
+
this.showDeleteConfirmationState = !1, this.connectionToDelete = "";
|
|
1281
|
+
},
|
|
1282
|
+
confirmDelete() {
|
|
1283
|
+
if (this.connectionToDelete) {
|
|
1284
|
+
for (const t of Object.values(this.editorStore.editors))
|
|
1285
|
+
t.connection === this.connectionToDelete && t.delete();
|
|
1286
|
+
this.connectionStore.deleteConnection(this.connectionToDelete);
|
|
1287
|
+
}
|
|
1288
|
+
this.showDeleteConfirmationState = !1, this.connectionToDelete = "";
|
|
1289
|
+
},
|
|
1290
|
+
// @ts-ignore
|
|
1291
|
+
deleteConnection(t) {
|
|
1292
|
+
this.showDeleteConfirmation(t);
|
|
1293
|
+
}
|
|
1294
|
+
},
|
|
1295
|
+
computed: {
|
|
1296
|
+
connections() {
|
|
1297
|
+
return Object.values(this.connectionStore.connections);
|
|
1298
|
+
},
|
|
1299
|
+
modelList() {
|
|
1300
|
+
return Object.keys(this.modelStore.models);
|
|
1301
|
+
}
|
|
1302
|
+
}
|
|
1303
|
+
}, Zt = { class: "button-container" }, $t = ["data-testid"], en = {
|
|
1304
|
+
key: 0,
|
|
1305
|
+
class: "mdi mdi-plus icon"
|
|
1306
|
+
}, tn = { class: "search-container" }, nn = ["data-testid"], on = ["data-testid"], an = { class: "confirmation-dialog" }, sn = { class: "dialog-actions" };
|
|
1307
|
+
function rn(t, e, o, i, c, p) {
|
|
1308
|
+
const a = U("connection-creator-inline"), d = U("connection-list-item"), w = U("sidebar-list");
|
|
1309
|
+
return r(), z(w, { title: "Connections" }, {
|
|
1310
|
+
actions: q(() => [
|
|
1311
|
+
s("div", Zt, [
|
|
1312
|
+
s("button", {
|
|
1313
|
+
onClick: e[0] || (e[0] = (h) => i.creatorVisible = !i.creatorVisible),
|
|
1314
|
+
"data-testid": o.testTag ? `connection-creator-add-${o.testTag}` : "connection-creator-add"
|
|
1315
|
+
}, [
|
|
1316
|
+
i.creatorVisible ? (r(), l("i", en)) : I("", !0),
|
|
1317
|
+
de(" " + j(i.creatorVisible ? "Hide" : "New"), 1)
|
|
1318
|
+
], 8, $t)
|
|
1319
|
+
]),
|
|
1320
|
+
x(a, {
|
|
1321
|
+
visible: i.creatorVisible,
|
|
1322
|
+
onClose: e[1] || (e[1] = (h) => i.creatorVisible = !i.creatorVisible)
|
|
1323
|
+
}, null, 8, ["visible"]),
|
|
1324
|
+
s("div", tn, [
|
|
1325
|
+
_(s("input", {
|
|
1326
|
+
type: "text",
|
|
1327
|
+
"onUpdate:modelValue": e[2] || (e[2] = (h) => i.searchTerm = h),
|
|
1328
|
+
placeholder: "Search objects...",
|
|
1329
|
+
class: "search-input",
|
|
1330
|
+
"data-testid": o.testTag ? `connection-search-${o.testTag}` : "connection-search"
|
|
1331
|
+
}, null, 8, nn), [
|
|
1332
|
+
[G, i.searchTerm]
|
|
1333
|
+
]),
|
|
1334
|
+
i.searchTerm ? (r(), l("button", {
|
|
1335
|
+
key: 0,
|
|
1336
|
+
onClick: e[3] || (e[3] = (...h) => i.clearSearch && i.clearSearch(...h)),
|
|
1337
|
+
class: "clear-search-btn",
|
|
1338
|
+
"data-testid": o.testTag ? `connection-search-clear-${o.testTag}` : "connection-search-clear"
|
|
1339
|
+
}, " ✕ ", 8, on)) : I("", !0)
|
|
1340
|
+
])
|
|
1341
|
+
]),
|
|
1342
|
+
default: q(() => [
|
|
1343
|
+
(r(!0), l(pe, null, fe(i.filteredContentList, (h) => (r(), z(d, {
|
|
1344
|
+
key: h.id,
|
|
1345
|
+
item: h,
|
|
1346
|
+
"is-collapsed": i.collapsed[h.id],
|
|
1347
|
+
isSelected: h.id === o.activeConnectionKey,
|
|
1348
|
+
isMobile: i.isMobile,
|
|
1349
|
+
testTag: o.testTag,
|
|
1350
|
+
onToggle: i.toggleCollapse,
|
|
1351
|
+
onClick: i.handleItemClick,
|
|
1352
|
+
onRefresh: i.refreshId,
|
|
1353
|
+
onUpdateMotherduckToken: i.updateMotherDuckToken,
|
|
1354
|
+
onUpdateBigqueryProject: i.updateBigqueryProject,
|
|
1355
|
+
onUpdateBigqueryBrowsingProject: i.updateBigqueryBrowsingProject,
|
|
1356
|
+
onUpdateSnowflakePrivateKey: i.updateSnowflakePrivateKey,
|
|
1357
|
+
onUpdateSnowflakeAccount: i.updateSnowflakeAccount,
|
|
1358
|
+
onUpdateSnowflakeUsername: i.updateSnowflakeUsername,
|
|
1359
|
+
onToggleSaveCredential: i.toggleSaveCredential,
|
|
1360
|
+
onToggleMobileMenu: i.toggleMobileMenu,
|
|
1361
|
+
"delete-connection": p.deleteConnection
|
|
1362
|
+
}, null, 8, ["item", "is-collapsed", "isSelected", "isMobile", "testTag", "onToggle", "onClick", "onRefresh", "onUpdateMotherduckToken", "onUpdateBigqueryProject", "onUpdateBigqueryBrowsingProject", "onUpdateSnowflakePrivateKey", "onUpdateSnowflakeAccount", "onUpdateSnowflakeUsername", "onToggleSaveCredential", "onToggleMobileMenu", "delete-connection"]))), 128)),
|
|
1363
|
+
c.showDeleteConfirmationState ? (r(), l("div", {
|
|
1364
|
+
key: 0,
|
|
1365
|
+
class: "confirmation-overlay",
|
|
1366
|
+
onClick: e[6] || (e[6] = A((...h) => p.cancelDelete && p.cancelDelete(...h), ["self"]))
|
|
1367
|
+
}, [
|
|
1368
|
+
s("div", an, [
|
|
1369
|
+
e[7] || (e[7] = s("h3", null, "Confirm Deletion", -1)),
|
|
1370
|
+
e[8] || (e[8] = s("p", null, " Are you sure you want to delete this connection? All associated editors will be deleted. ", -1)),
|
|
1371
|
+
s("div", sn, [
|
|
1372
|
+
s("button", {
|
|
1373
|
+
class: "cancel-btn",
|
|
1374
|
+
onClick: e[4] || (e[4] = (...h) => p.cancelDelete && p.cancelDelete(...h))
|
|
1375
|
+
}, "Cancel"),
|
|
1376
|
+
s("button", {
|
|
1377
|
+
class: "confirm-btn",
|
|
1378
|
+
onClick: e[5] || (e[5] = (...h) => p.confirmDelete && p.confirmDelete(...h))
|
|
1379
|
+
}, "Delete")
|
|
1380
|
+
])
|
|
1381
|
+
])
|
|
1382
|
+
])) : I("", !0)
|
|
1383
|
+
]),
|
|
1384
|
+
_: 1
|
|
1385
|
+
});
|
|
1386
|
+
}
|
|
1387
|
+
const To = /* @__PURE__ */ X(Jt, [["render", rn], ["__scopeId", "data-v-e9246856"]]);
|
|
1388
|
+
class n {
|
|
1389
|
+
constructor(e, o, i = null, c = null) {
|
|
1390
|
+
ne(this, "title");
|
|
1391
|
+
ne(this, "content");
|
|
1392
|
+
ne(this, "type");
|
|
1393
|
+
ne(this, "data");
|
|
1394
|
+
this.title = e, this.content = o, this.type = i, this.data = c || {};
|
|
1395
|
+
}
|
|
1396
|
+
}
|
|
1397
|
+
class M {
|
|
1398
|
+
constructor(e, o, i = void 0) {
|
|
1399
|
+
ne(this, "title");
|
|
1400
|
+
ne(this, "paragraphs");
|
|
1401
|
+
ne(this, "displayName");
|
|
1402
|
+
this.title = e, this.paragraphs = o, this.displayName = i;
|
|
1403
|
+
}
|
|
1404
|
+
}
|
|
1405
|
+
class Ce {
|
|
1406
|
+
constructor(e, o) {
|
|
1407
|
+
ne(this, "title");
|
|
1408
|
+
ne(this, "articles");
|
|
1409
|
+
this.title = e, this.articles = o;
|
|
1410
|
+
}
|
|
1411
|
+
}
|
|
1412
|
+
const ln = new M(
|
|
1413
|
+
"Dashboards",
|
|
1414
|
+
[
|
|
1415
|
+
new n(
|
|
1416
|
+
"Purpose",
|
|
1417
|
+
"Trilogy is designed as a data consumption language, and one of the fastest ways to expore data is through visualization. The dashboarding system in Trilogy Studio is designed to be streamlined but powerful. The semantic model means that default selections can be tailored and rich."
|
|
1418
|
+
),
|
|
1419
|
+
new n(
|
|
1420
|
+
"Purpose",
|
|
1421
|
+
"It aspires to be good out of the box, with progressive disclosure of capability. It is designed to be extensible and feature requests are welcome."
|
|
1422
|
+
),
|
|
1423
|
+
new n(
|
|
1424
|
+
"Purpose",
|
|
1425
|
+
"We`ll use the demo model you set up in the first tutorial. If you haven`t done that yet, go back and run through the imports. Make sure you have a model and connection read to go below."
|
|
1426
|
+
),
|
|
1427
|
+
new n("ModelList", "", "model-validator"),
|
|
1428
|
+
new n("ConnectionList", "", "connection-validator"),
|
|
1429
|
+
new n(
|
|
1430
|
+
"Purpose",
|
|
1431
|
+
"Now that you have a connection and model set up, lets get charting! Dashboards are accessed through the dashboard icon the left nav, but we'll drop one in right below. The demo model comes with a default example. "
|
|
1432
|
+
),
|
|
1433
|
+
new n(
|
|
1434
|
+
"Purpose",
|
|
1435
|
+
`Dashboards are SQL centric - so mostly, you'll just be writing queries. The one special thing on a dashboard is the global where clause. The filter bar at the top defines this; it will be concatenated to the where clause of every query on the dashboard. This is a great way to filter all of your charts at once.
|
|
1436
|
+
You can also cross-filter by clicking on any element in the chart. This will be automatically enabled; you can toggle off cross-filtering behavior on a per-chart basis on the header. (Make it only filter otherse, or not filterable at all.)`
|
|
1437
|
+
),
|
|
1438
|
+
new n(
|
|
1439
|
+
"Purpose",
|
|
1440
|
+
"In the below dashboard, try the following: <br>-Click on a manufacturer to filter other views. <br>-Go to edit mode and update the markdown on the top. <br>-Add a new chart. <br>-Change the horizontal bar chart to a vertical."
|
|
1441
|
+
),
|
|
1442
|
+
new n("Purpose", "", "dashboard"),
|
|
1443
|
+
new n(
|
|
1444
|
+
"Purpose",
|
|
1445
|
+
"When starting a new dashboard, you can either create a blank one or use a template. The templates are designed to be a good starting point for common use cases. You can also import dashboards from other users. Some of the public models will come with default dashboards."
|
|
1446
|
+
),
|
|
1447
|
+
new n(
|
|
1448
|
+
"Purpose",
|
|
1449
|
+
"Each chart can have their own query, so it's easy to define metrics in place. For dimensions, it's best to define them in the model so that automatic cross-filtering can be applied; if they are local to a chart, they cannot be applied to other views."
|
|
1450
|
+
),
|
|
1451
|
+
new n(
|
|
1452
|
+
"Purpose",
|
|
1453
|
+
"If you have an active LLM configured, the top search bar can be used for natural language filtering with the LLM - use ctrl+shift+enter."
|
|
1454
|
+
),
|
|
1455
|
+
new n(
|
|
1456
|
+
"Purpose",
|
|
1457
|
+
"You can only crossfilter if fields exist on all charts. It's best to define anything you want to filter on in the base dashboard file, and avoid aliasing base fields.",
|
|
1458
|
+
"tip"
|
|
1459
|
+
),
|
|
1460
|
+
new n(
|
|
1461
|
+
"Purpose",
|
|
1462
|
+
"To fix the formatting of fields, ensure they have the appropriate types and traits in the model. For example, marking a year as a year type will make line charts eligible. See the model tutorial for more details. ",
|
|
1463
|
+
"tip"
|
|
1464
|
+
),
|
|
1465
|
+
new n(
|
|
1466
|
+
"Purpose",
|
|
1467
|
+
'For missing features [such as chart types] or other issues, please open an issue on the <a href="https://github.com/trilogy-data/trilogy-studio-core/issues" target="_blank">studio GitHub repo</a>.'
|
|
1468
|
+
)
|
|
1469
|
+
],
|
|
1470
|
+
"Dashboard Tutorial"
|
|
1471
|
+
), cn = new M(
|
|
1472
|
+
"Model Tutorial",
|
|
1473
|
+
[
|
|
1474
|
+
new n(
|
|
1475
|
+
"Purpose",
|
|
1476
|
+
"The prior two tutorials cover how to query data and create dashboards. Both of those rely on the foundational concept of Trilogy - the model."
|
|
1477
|
+
),
|
|
1478
|
+
new n(
|
|
1479
|
+
"Purpose",
|
|
1480
|
+
"A model is simply a collection of editors that have been marked as sources. Any source can be imported by name into another editor, or multiple times under different aliases. Composition of models is how more complex models are built."
|
|
1481
|
+
),
|
|
1482
|
+
new n(
|
|
1483
|
+
"Purpose",
|
|
1484
|
+
"The core aspects of models are concepts and datasources. Concepts represent the abstract logical model of the data, while datasources represent physical instantiations of it."
|
|
1485
|
+
),
|
|
1486
|
+
new n(
|
|
1487
|
+
"Purpose",
|
|
1488
|
+
"These are loosely coupled, meaning that you can evolve or change your underlying database schema and simply update the datasources to point to the new tables and column names. Critically, queries operate on concepts so do not need to change."
|
|
1489
|
+
),
|
|
1490
|
+
new n(
|
|
1491
|
+
"Purpose",
|
|
1492
|
+
"Let's set one up. If you haven't already done the first tutorial, go back and create `my-first-editor` using that. We'll use that as a base."
|
|
1493
|
+
),
|
|
1494
|
+
new n("Purpose", "", "editor-validator"),
|
|
1495
|
+
new n("Tutorial Queries", "bsb", "tutorial-prompts", {
|
|
1496
|
+
context: "model-tutorial",
|
|
1497
|
+
editorId: "sql-basic-editor",
|
|
1498
|
+
prompts: [
|
|
1499
|
+
{
|
|
1500
|
+
title: "Declaring a Constant",
|
|
1501
|
+
description: "In the editor below, we will define pi and select it. A constant is the simplest possible concept; it does not require a datasource to resolve. Constants are useful for variables in scripts. Run and confirm you see 3.14.",
|
|
1502
|
+
example: "const pi <- 3.14; select pi;",
|
|
1503
|
+
hints: ["Don't forget the semicolon at the end!"],
|
|
1504
|
+
validationFn: (t) => {
|
|
1505
|
+
var e, o;
|
|
1506
|
+
return ((o = (e = t.data) == null ? void 0 : e[0]) == null ? void 0 : o.pi) === 3.14;
|
|
1507
|
+
}
|
|
1508
|
+
},
|
|
1509
|
+
{
|
|
1510
|
+
title: "Typing",
|
|
1511
|
+
description: "Trilogy has a core type system and a metadata based trait system. Let's try it. In the below definition, `list` and `string` are core types, while us_state_short is a `trait`. Any number of traits can modify a base type. Traits are metadata signals that can be used for typechecking of custom functions or by other systems; for example, here, if you click visualize, you will have a default state map as the studio can make intelligent default choices based on standard lib traits.",
|
|
1512
|
+
example: `import std.geography;
|
|
1513
|
+
auto states <- ['NY', 'CA', 'TX']::list<string::us_state_short>;
|
|
1514
|
+
|
|
1515
|
+
select
|
|
1516
|
+
unnest(states) as state,
|
|
1517
|
+
random(state)*100 as rank
|
|
1518
|
+
order by
|
|
1519
|
+
state asc;`,
|
|
1520
|
+
hints: [
|
|
1521
|
+
"Don't forget the import statement. Importing without a name puts all values in the base namespace.",
|
|
1522
|
+
"Make sure the state output is named state and you've ordered properly."
|
|
1523
|
+
],
|
|
1524
|
+
validationFn: (t) => {
|
|
1525
|
+
var e, o, i, c, p, a, d;
|
|
1526
|
+
return ((e = t.data) == null ? void 0 : e.length) === 3 && ((i = (o = t.data) == null ? void 0 : o[0]) == null ? void 0 : i.state) === "CA" && ((p = (c = t.data) == null ? void 0 : c[1]) == null ? void 0 : p.state) === "NY" && ((d = (a = t.data) == null ? void 0 : a[2]) == null ? void 0 : d.state) === "TX";
|
|
1527
|
+
}
|
|
1528
|
+
},
|
|
1529
|
+
{
|
|
1530
|
+
title: "Typing",
|
|
1531
|
+
description: "In the last question, we imported from the standard library (under std) which is always available. Most of the time, you will be importing from your own model. Add an import from lineitem - the row level of orders in the demo model - and see if you can get the count of orders, aliased as order_count.",
|
|
1532
|
+
example: `import lineitem;
|
|
1533
|
+
... your query here`,
|
|
1534
|
+
hints: ["select count(order.id) as order_count;"],
|
|
1535
|
+
validationFn: (t) => {
|
|
1536
|
+
var e, o, i;
|
|
1537
|
+
return ((e = t.data) == null ? void 0 : e.length) === 1 && ((i = (o = t.data) == null ? void 0 : o[0]) == null ? void 0 : i.order_count) === 3e4;
|
|
1538
|
+
}
|
|
1539
|
+
},
|
|
1540
|
+
{
|
|
1541
|
+
title: "Typing",
|
|
1542
|
+
description: "Now, let's try a datasouce. Datasources bind concepts to physical resources. We can extend our demo model by adding a new concept defining our HQ locations, and a mapping to regions. Then write a query to fetch total sales by headquarters.",
|
|
1543
|
+
example: `import lineitem;
|
|
1544
|
+
|
|
1545
|
+
|
|
1546
|
+
property order.customer.nation.region.id.headquarters string;
|
|
1547
|
+
|
|
1548
|
+
datasource region_headquarters (
|
|
1549
|
+
region_id: ?order.customer.nation.region.id,
|
|
1550
|
+
headquarters: order.customer.nation.region.headquarters,)
|
|
1551
|
+
grain (order.customer.nation.region.id)
|
|
1552
|
+
query '''
|
|
1553
|
+
select 1 as region_id, 'HQ1' as headquarters
|
|
1554
|
+
union all
|
|
1555
|
+
select 2 as region_id, 'HQ2' as headquarters
|
|
1556
|
+
union all
|
|
1557
|
+
select 3 as region_id, 'HQ3' as headquarters
|
|
1558
|
+
union all
|
|
1559
|
+
select 4 as region_id, 'HQ4' as headquarters
|
|
1560
|
+
''';
|
|
1561
|
+
`,
|
|
1562
|
+
hints: [
|
|
1563
|
+
`select
|
|
1564
|
+
order.customer.nation.region.headquarters,
|
|
1565
|
+
total_revenue
|
|
1566
|
+
order by total_revenue desc;`
|
|
1567
|
+
],
|
|
1568
|
+
validationFn: (t) => {
|
|
1569
|
+
var e;
|
|
1570
|
+
return ((e = t.data) == null ? void 0 : e.some(
|
|
1571
|
+
(o) => o.order_customer_nation_region_headquarters === "HQ4" && Math.round(o.total_revenue) === 72212597826928
|
|
1572
|
+
)) ?? !1;
|
|
1573
|
+
}
|
|
1574
|
+
}
|
|
1575
|
+
// More prompts...
|
|
1576
|
+
]
|
|
1577
|
+
}),
|
|
1578
|
+
new n("Purpose", "Review the standard library doc for always available traits.", "tip"),
|
|
1579
|
+
new n(
|
|
1580
|
+
"Purpose",
|
|
1581
|
+
`We've defined all the key parts of a model - a key, some properties, and a datasource to fetch. In a real database, you'll usually be working off an actual table. Let's try that out. Follow these steps:
|
|
1582
|
+
<ul>
|
|
1583
|
+
<li>1. Create a new duckdb connection called 'iris-data' using the connection list below.</li>
|
|
1584
|
+
<li>2. Copy the SQL command to create the table.</li>
|
|
1585
|
+
<li>3. Click the black doc icon to create a new SQL editor. This will take you to the editor!</li>
|
|
1586
|
+
<li>4. Paste in the code and run it.</li>
|
|
1587
|
+
<li>5. Click 'set editor as startup script' in the top right.</li>
|
|
1588
|
+
<li>6. Come back into this tutorial tab.</li>
|
|
1589
|
+
</ul>
|
|
1590
|
+
`
|
|
1591
|
+
),
|
|
1592
|
+
new n(
|
|
1593
|
+
"Purpose",
|
|
1594
|
+
"It's important to not miss step 5 - that way every time you connect, the table will be automatically populated!.",
|
|
1595
|
+
"tip"
|
|
1596
|
+
),
|
|
1597
|
+
new n(
|
|
1598
|
+
"Purpose",
|
|
1599
|
+
"DuckDB WASM CSV import of this file don't appear to work properly on Firefox or Safari as of early 2025. On those browsers, consider download the csv directly and importing it into duckdb using the drag box rather than using the read_csv SQL below.",
|
|
1600
|
+
"warning"
|
|
1601
|
+
),
|
|
1602
|
+
new n(
|
|
1603
|
+
"Purpose",
|
|
1604
|
+
"CREATE OR REPLACE TABLE iris_data AS select *, row_number() over () as pk FROM read_csv('https://raw.githubusercontent.com/mwaskom/seaborn-data/master/iris.csv');",
|
|
1605
|
+
"code"
|
|
1606
|
+
),
|
|
1607
|
+
new n("Purpose", "", "connections"),
|
|
1608
|
+
new n(
|
|
1609
|
+
"Purpose",
|
|
1610
|
+
`Now we're ready to create a new model. The steps below will again take you out of this tutorial, but you can always come back here by clicking the 'documentation' icon on the left.
|
|
1611
|
+
<ul>
|
|
1612
|
+
<li>1. Click on the connection you have, and expand the memory database.</li>
|
|
1613
|
+
<li>2. Hit refresh if needed. On the row with the iris table, click the database icon to generate a new raw datasource file.</li>
|
|
1614
|
+
<li>3. In the open file, change pk to be a "key" instead of "property" and replace the placeholder tags with pk. (example: property pk.species string;)</li>
|
|
1615
|
+
<li>4. In the open file, add a grain clause below the field mapping - grain(pk)</li>
|
|
1616
|
+
<li>5. Click the 'set as source' in top right to make this importable by other files.</li>
|
|
1617
|
+
<li>6. Rename the file to 'iris'.</li>
|
|
1618
|
+
</ul>
|
|
1619
|
+
`
|
|
1620
|
+
),
|
|
1621
|
+
new n(
|
|
1622
|
+
"Purpose",
|
|
1623
|
+
`The grain clause defines the primary key of your datasource. In this case, we've added a surrogate key called pk. Grains are used to understand when information needs to be grouped, and by what. The property tag is used similarly. A datasource can have no grain, in which case it is a heap and most operations on it will require an extra group to deduplicate.
|
|
1624
|
+
`,
|
|
1625
|
+
"tip"
|
|
1626
|
+
),
|
|
1627
|
+
new n(
|
|
1628
|
+
"Purpose",
|
|
1629
|
+
`
|
|
1630
|
+
key pk int; # surrogate primary key for the dataset
|
|
1631
|
+
property pk.sepal_length float;
|
|
1632
|
+
property pk.sepal_width float;
|
|
1633
|
+
property pk.petal_length float;
|
|
1634
|
+
property pk.petal_width float;
|
|
1635
|
+
property pk.species string;
|
|
1636
|
+
|
|
1637
|
+
datasource iris_data (
|
|
1638
|
+
sepal_length:sepal_length,
|
|
1639
|
+
sepal_width:sepal_width,
|
|
1640
|
+
petal_length:petal_length,
|
|
1641
|
+
petal_width:petal_width,
|
|
1642
|
+
species:species,
|
|
1643
|
+
pk:pk,
|
|
1644
|
+
)
|
|
1645
|
+
grain (pk)
|
|
1646
|
+
address iris_data;
|
|
1647
|
+
`,
|
|
1648
|
+
"code"
|
|
1649
|
+
),
|
|
1650
|
+
new n(
|
|
1651
|
+
"Purpose",
|
|
1652
|
+
`Make sure your file looks like the above. Now create a new trilogy editor by clicking the orange document icon by your connection. Copy the below code and run it!
|
|
1653
|
+
`
|
|
1654
|
+
),
|
|
1655
|
+
new n(
|
|
1656
|
+
"Purpose",
|
|
1657
|
+
`import iris;
|
|
1658
|
+
select
|
|
1659
|
+
species,
|
|
1660
|
+
avg(petal_length) as avg_petal_length,
|
|
1661
|
+
avg(petal_width) as avg_petal_width
|
|
1662
|
+
;
|
|
1663
|
+
`,
|
|
1664
|
+
"code"
|
|
1665
|
+
),
|
|
1666
|
+
new n(
|
|
1667
|
+
"Purpose",
|
|
1668
|
+
`If you get any errors, double check names and that you have set the iris file as a source. If you get a "no such table" error, make sure you have run the startup script to create the table.
|
|
1669
|
+
`,
|
|
1670
|
+
"tip"
|
|
1671
|
+
),
|
|
1672
|
+
new n(
|
|
1673
|
+
"Purpose",
|
|
1674
|
+
`Make sure your file looks like the above. Now create a new trilogy editor by clicking the orange document icon by your connection. Copy the below code and run it!
|
|
1675
|
+
`
|
|
1676
|
+
),
|
|
1677
|
+
new n(
|
|
1678
|
+
"Further Reading",
|
|
1679
|
+
`Go to the model page under the trilogy reference section.
|
|
1680
|
+
`
|
|
1681
|
+
)
|
|
1682
|
+
],
|
|
1683
|
+
"Model Tutorial"
|
|
1684
|
+
), un = new M(
|
|
1685
|
+
"Welcome",
|
|
1686
|
+
[
|
|
1687
|
+
new n(
|
|
1688
|
+
"Purpose",
|
|
1689
|
+
"Trilogy is a semantic-powered SQL - familiar SQL syntax that operates on a typed semantic layer, instead of tables. It should feel like SQL, but faster and more expressive. You can read more about the language in the Trilogy reference section."
|
|
1690
|
+
),
|
|
1691
|
+
new n(
|
|
1692
|
+
"Purpose",
|
|
1693
|
+
"Trilogy Studio is intended as an accessible demonstration of core language features, which would otherwise have a high barrier to experimentation. It is open source and feature requests and contributions are welcome."
|
|
1694
|
+
),
|
|
1695
|
+
new n(
|
|
1696
|
+
"Purpose",
|
|
1697
|
+
"In the rest of this tutorial, we will walk you through a demo-model - based on the TPC-H dataset - to get started. This will give you a feel for how Trilogy works and how you can use it to query data."
|
|
1698
|
+
),
|
|
1699
|
+
new n(
|
|
1700
|
+
"Purpose",
|
|
1701
|
+
'A "model" is a collection of associated Trilogy files that define a specific semantic layer. Models can be imported and exported, and are the primary way to share and reuse Trilogy code. In Trilogy Studio, a model will always be associated with a connection, representing a database backend. You can assign the same model to multiple connections for reuse. ',
|
|
1702
|
+
"tip"
|
|
1703
|
+
),
|
|
1704
|
+
new n(
|
|
1705
|
+
"Purpose",
|
|
1706
|
+
`Trilogy Studio has a built in model "store", containing a set of public models hosted on github. The demo model is one of those options. Let's get started! Search below for the demo-model, and click the import button to add it. You want to import it to a duckdb connection. Select new duckdb connection and name it demo-connection.`
|
|
1707
|
+
),
|
|
1708
|
+
new n("Purpose", "<PLACEHOLDER>", "community-models"),
|
|
1709
|
+
new n("ModelList", "", "model-validator"),
|
|
1710
|
+
new n(
|
|
1711
|
+
"Purpose",
|
|
1712
|
+
"Now that you have the model imported and associated with a connection, we just need to click the plug icon to connect to it."
|
|
1713
|
+
),
|
|
1714
|
+
new n(
|
|
1715
|
+
"Purpose",
|
|
1716
|
+
'If you had set up the connection first, you could click the connection name to toggle details, and click the model dropdown and select the "demo-model".',
|
|
1717
|
+
"tip"
|
|
1718
|
+
),
|
|
1719
|
+
new n(
|
|
1720
|
+
"Purpose",
|
|
1721
|
+
"You can also run normal SQL against a connection, using a 'sql' typed editor. This is a good way to debug or test queries that you are not sure how to write in Trilogy, or to manage databases.",
|
|
1722
|
+
"tip"
|
|
1723
|
+
),
|
|
1724
|
+
new n("ConnectionList", "", "connections"),
|
|
1725
|
+
new n("ConnectionList", "", "connection-validator"),
|
|
1726
|
+
new n(
|
|
1727
|
+
"Purpose",
|
|
1728
|
+
"When the above indicator is green, you are good to move on! Note that normally, you will manage connections through the connection panel available on the sidebar - this component is just embedded here as well for the tutorial.",
|
|
1729
|
+
"tip"
|
|
1730
|
+
),
|
|
1731
|
+
new n(
|
|
1732
|
+
"Purpose",
|
|
1733
|
+
'Now that you have a connection and model set up, you can start querying in an editor. Editors are grouped by their storage, then by connection. `Local` represents local storage in your browser. [Other storage, like Github, will be available in the future] Your imported model will have populated some default editors, but lets start with a new one. Click the new button and create a Trilogy editor named "my-first-editor" associated with the demo connection.'
|
|
1734
|
+
),
|
|
1735
|
+
new n("Purpose", "", "editors"),
|
|
1736
|
+
new n("Purpose", "", "editor-validator"),
|
|
1737
|
+
new n(
|
|
1738
|
+
"Purpose",
|
|
1739
|
+
"When the above indicator is green, you are good to move on! Note again that normally editors are managed through the sidebar. You will also see that some editors are marked as sources - these are importable by other editors on the model. As these often are metadata only, you can use the toggle at the top to hide these if desired. Any editor can be made a source by toggling a button in the editor.",
|
|
1740
|
+
"tip"
|
|
1741
|
+
),
|
|
1742
|
+
new n(
|
|
1743
|
+
"Purpose",
|
|
1744
|
+
"Editors are your interactive SQL experience. They let you write Trilogy, validate it, run it, and look at the results. Running (ctrl-enter) will either execute the full editor or the highlighted chunk of code (with any imports). In the below tutorial editor, we'll run through a few queries and validate your results."
|
|
1745
|
+
),
|
|
1746
|
+
new n("Tutorial Queries", "bsb", "tutorial-prompts", {
|
|
1747
|
+
context: "sql-tutorial",
|
|
1748
|
+
editorId: "sql-basic-editor",
|
|
1749
|
+
prompts: [
|
|
1750
|
+
{
|
|
1751
|
+
title: "Hello World",
|
|
1752
|
+
description: `Just like SQL, you can select constant values without any sources. Let's try saying hello world. You have two options; define it in a select directly, or define a constant and then select it. Before running, click the "validate" button to check your syntax - if its correct, you'll see your extract concept visible on the right. Note that when you define the concept first, you are able to add a description via the comment.`,
|
|
1753
|
+
example: `select 'Hello World' as greeting;
|
|
1754
|
+
const greeting <- 'Hello World'; # A friendly greeting
|
|
1755
|
+
select greeting;`,
|
|
1756
|
+
hints: ["Don't forget the closing semicolon or as!", "Select 'Hello World' as greeting;"],
|
|
1757
|
+
validationFn: (t) => {
|
|
1758
|
+
var e, o, i;
|
|
1759
|
+
return ((i = (o = (e = t.data) == null ? void 0 : e[0]) == null ? void 0 : o.greeting) == null ? void 0 : i.toLowerCase()) === "hello world";
|
|
1760
|
+
}
|
|
1761
|
+
},
|
|
1762
|
+
{
|
|
1763
|
+
title: "Multiple Rows",
|
|
1764
|
+
description: "Now, let's try a few different rows. We can unnest an array constant - this is a handy way to get test data.",
|
|
1765
|
+
example: "SELECT unnest([1,2,3,4]) as constant order by constant asc;",
|
|
1766
|
+
hints: ["Don't forget the semicolon at the end!"],
|
|
1767
|
+
validationFn: (t) => {
|
|
1768
|
+
var e, o, i, c;
|
|
1769
|
+
return ((o = (e = t.data) == null ? void 0 : e[0]) == null ? void 0 : o.constant) == 1 && ((c = (i = t.data) == null ? void 0 : i[3]) == null ? void 0 : c.constant) === 4;
|
|
1770
|
+
}
|
|
1771
|
+
},
|
|
1772
|
+
{
|
|
1773
|
+
title: "Typing",
|
|
1774
|
+
description: "But let's get to the good stuff. Other tutorials will cover syntax in more depth, but let's import a model and see what we can do. The demo model has an available called lineitem, which is the row level of orders. Let's pull it in and aggregate our sales by nation.",
|
|
1775
|
+
example: `import lineitem as lineitem;
|
|
1776
|
+
SELECT
|
|
1777
|
+
sum(lineitem.extended_price)->sales,
|
|
1778
|
+
lineitem.supplier.nation.name,
|
|
1779
|
+
order by
|
|
1780
|
+
sales desc;`,
|
|
1781
|
+
hints: [],
|
|
1782
|
+
validationFn: (t) => {
|
|
1783
|
+
var e, o, i, c;
|
|
1784
|
+
return ((o = (e = t.data) == null ? void 0 : e[0]) == null ? void 0 : o.lineitem_supplier_nation_name) === "CHINA" || ((c = (i = t.data) == null ? void 0 : i[0]) == null ? void 0 : c.lineitem_supplier_nation_name) === "UNITED STATES";
|
|
1785
|
+
}
|
|
1786
|
+
}
|
|
1787
|
+
]
|
|
1788
|
+
}),
|
|
1789
|
+
new n(
|
|
1790
|
+
"Purpose",
|
|
1791
|
+
"Thats the basics! You know how to run queries in an editor, how to import a model, and how to connect to a datasource.",
|
|
1792
|
+
"tip"
|
|
1793
|
+
),
|
|
1794
|
+
new n(
|
|
1795
|
+
"Purpose",
|
|
1796
|
+
"For the last query, could you figure out how to visualize the data? Editors support inline visualization for rapid introspection; to create more complicated visuals, check out the dashboarding tutorial up next.",
|
|
1797
|
+
"tip"
|
|
1798
|
+
),
|
|
1799
|
+
new n(
|
|
1800
|
+
"Purpose",
|
|
1801
|
+
"Feel free to explore from here. A good place to start is clicking on the editors icon in the left nav and exploring the pre-populated demo editors, which show more functionality. Alternatively, poke more around the docs!"
|
|
1802
|
+
)
|
|
1803
|
+
],
|
|
1804
|
+
"Welcome and Query Tutorial"
|
|
1805
|
+
), dn = new M("LLM Tutorial", [
|
|
1806
|
+
new n(
|
|
1807
|
+
"Connections",
|
|
1808
|
+
"LLMs can optionally be used to enhance the studio experience. The LLM screen is accessible on the left-hand nav and provides some basic validation that your LLM will work. LLMs is not required, but we aim to make the best use of them when available."
|
|
1809
|
+
),
|
|
1810
|
+
new n(
|
|
1811
|
+
"Connections",
|
|
1812
|
+
"Gemini has had some of the best results, but any lightweight fast model works well to build scaffolding quickly. You will need to QA answers.",
|
|
1813
|
+
"tip"
|
|
1814
|
+
),
|
|
1815
|
+
new n(
|
|
1816
|
+
"Connections",
|
|
1817
|
+
"Core LLM use cases are -query generation from natural language, dashboard generation from natural language, dashboard filtering with natural language, Feature requests welcome! To add an LLM, you will need an appropriate API key. Currently, we support OpenAI, Anthropic, and Google, but adding more is straightforward."
|
|
1818
|
+
),
|
|
1819
|
+
new n(
|
|
1820
|
+
"Connections",
|
|
1821
|
+
"To improve LLM performance, the first place to start is your model, as concept definitions are provided as primary context. Adding more specific concepts and - especially - descriptions to fields will help the model understand better. For complex calculations, consider pre-defining them so they can be easily selected by the model."
|
|
1822
|
+
),
|
|
1823
|
+
new n(
|
|
1824
|
+
"Connections",
|
|
1825
|
+
"Make sure to update the model to your favorite! Do this by selecting one from the dropdown and explicitly clicking update model - after first setting up an LLM. We don't know what models are available until you first connect.",
|
|
1826
|
+
"tip"
|
|
1827
|
+
),
|
|
1828
|
+
new n(
|
|
1829
|
+
"Managing Connections",
|
|
1830
|
+
"You can view current LLM connections below. Only one LLM connection can be the default at a time. You can set a default by clicking the star icon. The default LLM will be used for all LLM functionality. Try setting one up, confirm you can connect, select an appropriate model, and save. Then head to an editor or a dashboard to try it out!"
|
|
1831
|
+
),
|
|
1832
|
+
new n("LLMList", "", "llm-connections"),
|
|
1833
|
+
new n("LLMList", "The LLM experience is not tested on mobile.", "warning"),
|
|
1834
|
+
new n("Purpose", "", "editor-validator"),
|
|
1835
|
+
new n(
|
|
1836
|
+
"Tutorial Queries",
|
|
1837
|
+
"There should be an edito here! Make sure you've completed the first tutorial!",
|
|
1838
|
+
"tutorial-prompts",
|
|
1839
|
+
{
|
|
1840
|
+
context: "sql-tutorial",
|
|
1841
|
+
editorId: "sql-basic-editor",
|
|
1842
|
+
prompts: [
|
|
1843
|
+
{
|
|
1844
|
+
title: "Try it out!",
|
|
1845
|
+
description: "Copy the below input, and hit generate [ctrl-shift-enter]. You can either refine the query or hit [ctrl-shift-enter] again to accept and run.",
|
|
1846
|
+
example: `import std.geography;
|
|
1847
|
+
auto state_source <- ['NY', 'CA', 'TX']::list<string::us_state_short>;
|
|
1848
|
+
auto state <- unnest(state_source);
|
|
1849
|
+
auto state.population <- random(state)*10000;
|
|
1850
|
+
|
|
1851
|
+
# what states have the most people?`,
|
|
1852
|
+
hints: [
|
|
1853
|
+
"Don't forget the import statement. Importing without a name puts all values in the base namespace.",
|
|
1854
|
+
"Make sure the state output is named state and you've ordered properly."
|
|
1855
|
+
],
|
|
1856
|
+
validationFn: (t) => t.data != null
|
|
1857
|
+
},
|
|
1858
|
+
{
|
|
1859
|
+
title: "Typing",
|
|
1860
|
+
description: "LLMs will have access to all imports and the selected context at submission time. If you define new context in the editor, make sure it's selected and syntactically valid. Copy in the below and click the generate button without any selection; if you try with just the comment selected the LLM will not be aware of the new concept you defined.",
|
|
1861
|
+
example: `import lineitem;
|
|
1862
|
+
|
|
1863
|
+
property order.customer.nation.region.id.headquarters string;
|
|
1864
|
+
|
|
1865
|
+
datasource region_headquarters (
|
|
1866
|
+
region_id: ?order.customer.nation.region.id,
|
|
1867
|
+
headquarters: order.customer.nation.region.headquarters,)
|
|
1868
|
+
grain (order.customer.nation.region.id)
|
|
1869
|
+
query '''
|
|
1870
|
+
select 0 as region_id, 'HQ0' as headquarters
|
|
1871
|
+
union all
|
|
1872
|
+
select 1 as region_id, 'HQ1' as headquarters
|
|
1873
|
+
union all
|
|
1874
|
+
select 2 as region_id, 'HQ2' as headquarters
|
|
1875
|
+
union all
|
|
1876
|
+
select 3 as region_id, 'HQ3' as headquarters
|
|
1877
|
+
union all
|
|
1878
|
+
select 4 as region_id, 'HQ4' as headquarters
|
|
1879
|
+
''';
|
|
1880
|
+
|
|
1881
|
+
# what is the total revenue for each headquarter?
|
|
1882
|
+
`,
|
|
1883
|
+
hints: [
|
|
1884
|
+
`select
|
|
1885
|
+
order.customer.nation.region.headquarters,
|
|
1886
|
+
total_revenue
|
|
1887
|
+
order by total_revenue desc;`
|
|
1888
|
+
],
|
|
1889
|
+
validationFn: (t) => {
|
|
1890
|
+
var e;
|
|
1891
|
+
return ((e = t.data) == null ? void 0 : e.some(
|
|
1892
|
+
(o) => o.order_customer_nation_region_headquarters === "HQ4" && Math.round(o.total_revenue) === 451328736
|
|
1893
|
+
)) ?? !1;
|
|
1894
|
+
}
|
|
1895
|
+
}
|
|
1896
|
+
// More prompts...
|
|
1897
|
+
]
|
|
1898
|
+
}
|
|
1899
|
+
),
|
|
1900
|
+
new n(
|
|
1901
|
+
"Connections",
|
|
1902
|
+
"LLMs operate on the imported concept context. Make sure you have a datasource selected on a dashboard, or add imports to an editor before typing your comment. Ctrl-shift-enter is the default LLM activation shortcut; typically you will highlight text and then run this.",
|
|
1903
|
+
"tip"
|
|
1904
|
+
)
|
|
1905
|
+
]), pn = new M("Functions", [
|
|
1906
|
+
new n(
|
|
1907
|
+
"Trilogy Built-in Functions",
|
|
1908
|
+
"Trilogy provides a comprehensive set of built-in functions that closely map to standard SQL functions. These functions enable data transformation, aggregation, and manipulation within your queries. They are categorized into aggregate, date/time, string, numeric, collection, and utility functions."
|
|
1909
|
+
),
|
|
1910
|
+
new n(
|
|
1911
|
+
"Function Usage & Concepts",
|
|
1912
|
+
`Each function definition includes its input requirements and output characteristics. Key information includes:
|
|
1913
|
+
<ul>
|
|
1914
|
+
<li><b>Input Types:</b> The allowed data types for each argument.</li>
|
|
1915
|
+
<li><b>Output Type:</b> The data type of the value returned by the function.</li>
|
|
1916
|
+
<li><b>Output Purpose:</b> Describes the conceptual role of the output.
|
|
1917
|
+
<ul>
|
|
1918
|
+
<li><b>PROPERTY:</b> Represents an attribute derived from existing data, typically associated with the grain of the input(s). Example: <code>UPPER(name)</code>.</li>
|
|
1919
|
+
<li><b>METRIC:</b> Represents a calculated value that summarizes data across rows, respecting the query's grouping. Example: <code>SUM(revenue)</code>.</li>
|
|
1920
|
+
<li><b>KEY:</b> Represents an identifier or a dimension used for joining or grouping, often changing the grain of the data. Example: <code>UNNEST(tags)</code>.</li>
|
|
1921
|
+
<li><b>CONSTANT:</b> Represents a fixed value, independent of the input data rows. Example: <code>CURRENT_DATE()</code>.</li>
|
|
1922
|
+
</ul>
|
|
1923
|
+
</li>
|
|
1924
|
+
</ul>`
|
|
1925
|
+
),
|
|
1926
|
+
// AGGREGATE FUNCTIONS
|
|
1927
|
+
new n(
|
|
1928
|
+
"Aggregate Functions",
|
|
1929
|
+
"Aggregate functions perform calculations across a set of input rows and return a single summary value for each group."
|
|
1930
|
+
),
|
|
1931
|
+
new n(
|
|
1932
|
+
"SUM",
|
|
1933
|
+
"Computes the sum of non-null numeric values within each group. Returns NULL if the group is empty or contains only NULL values.",
|
|
1934
|
+
"function",
|
|
1935
|
+
{
|
|
1936
|
+
function: {
|
|
1937
|
+
inputTypes: ["INTEGER", "FLOAT", "NUMBER", "NUMERIC"],
|
|
1938
|
+
outputType: "Same as input (or promoted numeric type)",
|
|
1939
|
+
outputPurpose: "METRIC",
|
|
1940
|
+
example: "SELECT SUM(order_total) AS total_revenue BY customer_id;"
|
|
1941
|
+
}
|
|
1942
|
+
}
|
|
1943
|
+
),
|
|
1944
|
+
new n(
|
|
1945
|
+
"COUNT",
|
|
1946
|
+
"Counts the number of non-null input rows within each group. Takes a single argument of any type.",
|
|
1947
|
+
"function",
|
|
1948
|
+
{
|
|
1949
|
+
function: {
|
|
1950
|
+
inputTypes: ["Any"],
|
|
1951
|
+
outputType: "INTEGER",
|
|
1952
|
+
outputPurpose: "METRIC",
|
|
1953
|
+
example: "SELECT COUNT(order_id) AS num_orders BY product_category;"
|
|
1954
|
+
}
|
|
1955
|
+
}
|
|
1956
|
+
),
|
|
1957
|
+
new n(
|
|
1958
|
+
"COUNT_DISTINCT",
|
|
1959
|
+
"Counts the number of distinct non-null input values within each group. Takes a single argument of any type.",
|
|
1960
|
+
"function",
|
|
1961
|
+
{
|
|
1962
|
+
function: {
|
|
1963
|
+
inputTypes: ["Any"],
|
|
1964
|
+
outputType: "INTEGER",
|
|
1965
|
+
outputPurpose: "METRIC",
|
|
1966
|
+
example: "SELECT COUNT_DISTINCT(customer_id) AS unique_customers BY month;"
|
|
1967
|
+
}
|
|
1968
|
+
}
|
|
1969
|
+
),
|
|
1970
|
+
new n(
|
|
1971
|
+
"MAX",
|
|
1972
|
+
"Returns the maximum non-null value across all input rows within each group. Comparison follows standard data type rules.",
|
|
1973
|
+
"function",
|
|
1974
|
+
{
|
|
1975
|
+
function: {
|
|
1976
|
+
inputTypes: [
|
|
1977
|
+
"INTEGER",
|
|
1978
|
+
"FLOAT",
|
|
1979
|
+
"NUMBER",
|
|
1980
|
+
"DATE",
|
|
1981
|
+
"DATETIME",
|
|
1982
|
+
"TIMESTAMP",
|
|
1983
|
+
"BOOL",
|
|
1984
|
+
"STRING"
|
|
1985
|
+
],
|
|
1986
|
+
// Added STRING based on common SQL
|
|
1987
|
+
outputType: "Same as input type",
|
|
1988
|
+
outputPurpose: "METRIC",
|
|
1989
|
+
example: "SELECT MAX(order_date) AS latest_order_date BY customer_id;"
|
|
1990
|
+
}
|
|
1991
|
+
}
|
|
1992
|
+
),
|
|
1993
|
+
new n(
|
|
1994
|
+
"MIN",
|
|
1995
|
+
"Returns the minimum non-null value across all input rows within each group. Comparison follows standard data type rules.",
|
|
1996
|
+
"function",
|
|
1997
|
+
{
|
|
1998
|
+
function: {
|
|
1999
|
+
inputTypes: ["INTEGER", "FLOAT", "NUMBER", "DATE", "DATETIME", "TIMESTAMP", "STRING"],
|
|
2000
|
+
// Added STRING based on common SQL, removed BOOL
|
|
2001
|
+
outputType: "Same as input type",
|
|
2002
|
+
outputPurpose: "METRIC",
|
|
2003
|
+
example: "SELECT MIN(order_date) AS first_order_date BY customer_id;"
|
|
2004
|
+
}
|
|
2005
|
+
}
|
|
2006
|
+
),
|
|
2007
|
+
new n(
|
|
2008
|
+
"AVG",
|
|
2009
|
+
"Computes the average (arithmetic mean) of non-null numeric values within each group. Returns NULL if the group is empty or contains only NULL values. The result is typically a FLOAT or NUMBER.",
|
|
2010
|
+
"function",
|
|
2011
|
+
{
|
|
2012
|
+
function: {
|
|
2013
|
+
inputTypes: ["INTEGER", "FLOAT", "NUMBER", "NUMERIC"],
|
|
2014
|
+
outputType: "FLOAT or NUMBER",
|
|
2015
|
+
// AVG often results in non-integer types
|
|
2016
|
+
outputPurpose: "METRIC",
|
|
2017
|
+
example: "SELECT AVG(product_price) AS avg_price BY category;"
|
|
2018
|
+
}
|
|
2019
|
+
}
|
|
2020
|
+
),
|
|
2021
|
+
// DATE/TIME FUNCTIONS
|
|
2022
|
+
new n(
|
|
2023
|
+
"Date/Time Functions",
|
|
2024
|
+
"Functions for manipulating and extracting information from date and time values."
|
|
2025
|
+
),
|
|
2026
|
+
new n(
|
|
2027
|
+
"CURRENT_DATE",
|
|
2028
|
+
"Returns the current date when the query begins execution. This value remains constant throughout the query.",
|
|
2029
|
+
"function",
|
|
2030
|
+
{
|
|
2031
|
+
function: {
|
|
2032
|
+
inputTypes: [],
|
|
2033
|
+
outputType: "DATE",
|
|
2034
|
+
outputPurpose: "CONSTANT",
|
|
2035
|
+
example: "SELECT order_id WHERE order_date = CURRENT_DATE();"
|
|
2036
|
+
}
|
|
2037
|
+
}
|
|
2038
|
+
),
|
|
2039
|
+
new n(
|
|
2040
|
+
"CURRENT_DATETIME",
|
|
2041
|
+
"Returns the current date and time (timestamp) when the query begins execution. This value remains constant throughout the query.",
|
|
2042
|
+
"function",
|
|
2043
|
+
{
|
|
2044
|
+
function: {
|
|
2045
|
+
inputTypes: [],
|
|
2046
|
+
// Assuming Python `DataType.DATE` was a typo and should be DATETIME/TIMESTAMP
|
|
2047
|
+
outputType: "DATETIME",
|
|
2048
|
+
outputPurpose: "CONSTANT",
|
|
2049
|
+
example: "SELECT event_id, CURRENT_DATETIME() AS processing_time;"
|
|
2050
|
+
}
|
|
2051
|
+
}
|
|
2052
|
+
),
|
|
2053
|
+
new n(
|
|
2054
|
+
"DATE",
|
|
2055
|
+
"Extracts the date part from a timestamp, datetime, or string, or casts a value to the DATE type. If the input is already a DATE, it is returned unchanged.",
|
|
2056
|
+
"function",
|
|
2057
|
+
{
|
|
2058
|
+
function: {
|
|
2059
|
+
inputTypes: ["DATE", "TIMESTAMP", "DATETIME", "STRING"],
|
|
2060
|
+
outputType: "DATE",
|
|
2061
|
+
outputPurpose: "PROPERTY",
|
|
2062
|
+
example: "SELECT DATE(user_signup_timestamp) AS signup_date;"
|
|
2063
|
+
}
|
|
2064
|
+
}
|
|
2065
|
+
),
|
|
2066
|
+
new n(
|
|
2067
|
+
"DATETIME",
|
|
2068
|
+
"Casts the input value (date, timestamp, or string) to the DATETIME type.",
|
|
2069
|
+
"function",
|
|
2070
|
+
{
|
|
2071
|
+
function: {
|
|
2072
|
+
inputTypes: ["DATE", "TIMESTAMP", "DATETIME", "STRING"],
|
|
2073
|
+
outputType: "DATETIME",
|
|
2074
|
+
outputPurpose: "PROPERTY",
|
|
2075
|
+
example: "SELECT DATETIME(event_date) AS event_datetime;"
|
|
2076
|
+
}
|
|
2077
|
+
}
|
|
2078
|
+
),
|
|
2079
|
+
new n(
|
|
2080
|
+
"TIMESTAMP",
|
|
2081
|
+
"Casts the input value (date, datetime, or string) to the TIMESTAMP type.",
|
|
2082
|
+
"function",
|
|
2083
|
+
{
|
|
2084
|
+
function: {
|
|
2085
|
+
inputTypes: ["DATE", "TIMESTAMP", "DATETIME", "STRING"],
|
|
2086
|
+
outputType: "TIMESTAMP",
|
|
2087
|
+
outputPurpose: "PROPERTY",
|
|
2088
|
+
example: "SELECT TIMESTAMP(log_entry_string) AS log_timestamp;"
|
|
2089
|
+
}
|
|
2090
|
+
}
|
|
2091
|
+
),
|
|
2092
|
+
new n(
|
|
2093
|
+
"DATE_TRUNCATE",
|
|
2094
|
+
"Truncates a date/time value to the specified precision ('year', 'month', 'day', etc.). Returns a value of the same type as the input (or DATE if truncating to day or higher from a timestamp/datetime).",
|
|
2095
|
+
"function",
|
|
2096
|
+
{
|
|
2097
|
+
function: {
|
|
2098
|
+
inputTypes: ["DATE/TIMESTAMP/DATETIME/STRING", "DATE_PART"],
|
|
2099
|
+
outputType: "Same as input type (usually DATE or DATETIME/TIMESTAMP)",
|
|
2100
|
+
// Reflects get_date_trunc_output logic
|
|
2101
|
+
outputPurpose: "PROPERTY",
|
|
2102
|
+
example: "SELECT DATE_TRUNCATE(created_at, month) AS creation_month;"
|
|
2103
|
+
}
|
|
2104
|
+
}
|
|
2105
|
+
),
|
|
2106
|
+
new n(
|
|
2107
|
+
"DATE_PART",
|
|
2108
|
+
"Extracts a specific subfield (e.g., 'year', 'month', 'day', 'hour', 'dow' for day of week) from a date/time value as an integer.",
|
|
2109
|
+
"function",
|
|
2110
|
+
{
|
|
2111
|
+
function: {
|
|
2112
|
+
inputTypes: ["DATE/TIMESTAMP/DATETIME/STRING", "DATE_PART"],
|
|
2113
|
+
outputType: "INTEGER (with potential trait)",
|
|
2114
|
+
// Reflects get_date_part_output
|
|
2115
|
+
outputPurpose: "PROPERTY",
|
|
2116
|
+
example: "SELECT DATE_PART(order_timestamp, hour) AS hour_of_order;"
|
|
2117
|
+
}
|
|
2118
|
+
}
|
|
2119
|
+
),
|
|
2120
|
+
new n(
|
|
2121
|
+
"DATE_ADD",
|
|
2122
|
+
"Adds a specified integer interval to a date/time value. The unit of the interval is specified by the date part argument (e.g., day, month, year).",
|
|
2123
|
+
"function",
|
|
2124
|
+
{
|
|
2125
|
+
function: {
|
|
2126
|
+
inputTypes: ["DATE/TIMESTAMP/DATETIME/STRING", "DATE_PART", "INTEGER"],
|
|
2127
|
+
// Output type might depend on input, Python says DATE, could be DATETIME/TIMESTAMP too
|
|
2128
|
+
outputType: "Same as first input type (usually DATE or DATETIME/TIMESTAMP)",
|
|
2129
|
+
outputPurpose: "PROPERTY",
|
|
2130
|
+
example: "SELECT DATE_ADD(start_date, day, 14) AS end_date;"
|
|
2131
|
+
}
|
|
2132
|
+
}
|
|
2133
|
+
),
|
|
2134
|
+
new n(
|
|
2135
|
+
"DATE_SUB",
|
|
2136
|
+
"Subtracts a specified integer interval from a date/time value. The unit of the interval is specified by the date part argument.",
|
|
2137
|
+
"function",
|
|
2138
|
+
{
|
|
2139
|
+
function: {
|
|
2140
|
+
inputTypes: ["DATE/TIMESTAMP/DATETIME/STRING", "DATE_PART", "INTEGER"],
|
|
2141
|
+
// Output type might depend on input, Python says DATE, could be DATETIME/TIMESTAMP too
|
|
2142
|
+
outputType: "Same as first input type (usually DATE or DATETIME/TIMESTAMP)",
|
|
2143
|
+
outputPurpose: "PROPERTY",
|
|
2144
|
+
example: "SELECT DATE_SUB(event_timestamp, hour, 3) AS reminder_time;"
|
|
2145
|
+
}
|
|
2146
|
+
}
|
|
2147
|
+
),
|
|
2148
|
+
new n(
|
|
2149
|
+
"DATE_DIFF",
|
|
2150
|
+
"Calculates the integer difference between two date/time values, expressed in the units specified by the date part argument.",
|
|
2151
|
+
"function",
|
|
2152
|
+
{
|
|
2153
|
+
function: {
|
|
2154
|
+
inputTypes: [
|
|
2155
|
+
"DATE/TIMESTAMP/DATETIME/STRING",
|
|
2156
|
+
"DATE/TIMESTAMP/DATETIME/STRING",
|
|
2157
|
+
"DATE_PART"
|
|
2158
|
+
],
|
|
2159
|
+
outputType: "INTEGER",
|
|
2160
|
+
outputPurpose: "PROPERTY",
|
|
2161
|
+
example: "SELECT DATE_DIFF(end_date, start_date, day) AS duration_days;"
|
|
2162
|
+
}
|
|
2163
|
+
}
|
|
2164
|
+
),
|
|
2165
|
+
new n(
|
|
2166
|
+
"UNIX_TO_TIMESTAMP",
|
|
2167
|
+
"Converts an integer Unix epoch timestamp (seconds since 1970-01-01 00:00:00 UTC) to a TIMESTAMP value.",
|
|
2168
|
+
"function",
|
|
2169
|
+
{
|
|
2170
|
+
function: {
|
|
2171
|
+
inputTypes: ["INTEGER"],
|
|
2172
|
+
outputType: "TIMESTAMP",
|
|
2173
|
+
outputPurpose: "PROPERTY",
|
|
2174
|
+
example: "SELECT UNIX_TO_TIMESTAMP(log_time_seconds) AS event_time;"
|
|
2175
|
+
}
|
|
2176
|
+
}
|
|
2177
|
+
),
|
|
2178
|
+
new n(
|
|
2179
|
+
"SECOND",
|
|
2180
|
+
"Extracts the second component (0-59) from a date/time value as an integer.",
|
|
2181
|
+
"function",
|
|
2182
|
+
{
|
|
2183
|
+
function: {
|
|
2184
|
+
inputTypes: ["DATE", "TIMESTAMP", "DATETIME", "STRING"],
|
|
2185
|
+
outputType: 'INTEGER with "second" trait',
|
|
2186
|
+
outputPurpose: "PROPERTY",
|
|
2187
|
+
example: "SELECT SECOND(event_time) AS event_second;"
|
|
2188
|
+
}
|
|
2189
|
+
}
|
|
2190
|
+
),
|
|
2191
|
+
new n(
|
|
2192
|
+
"MINUTE",
|
|
2193
|
+
"Extracts the minute component (0-59) from a date/time value as an integer.",
|
|
2194
|
+
"function",
|
|
2195
|
+
{
|
|
2196
|
+
function: {
|
|
2197
|
+
inputTypes: ["DATE", "TIMESTAMP", "DATETIME", "STRING"],
|
|
2198
|
+
outputType: 'INTEGER with "minute" trait',
|
|
2199
|
+
outputPurpose: "PROPERTY",
|
|
2200
|
+
example: "SELECT MINUTE(event_time) AS event_minute;"
|
|
2201
|
+
}
|
|
2202
|
+
}
|
|
2203
|
+
),
|
|
2204
|
+
new n(
|
|
2205
|
+
"HOUR",
|
|
2206
|
+
"Extracts the hour component (0-23) from a date/time value as an integer.",
|
|
2207
|
+
"function",
|
|
2208
|
+
{
|
|
2209
|
+
function: {
|
|
2210
|
+
inputTypes: ["DATE", "TIMESTAMP", "DATETIME", "STRING"],
|
|
2211
|
+
outputType: 'INTEGER with "hour" trait',
|
|
2212
|
+
outputPurpose: "PROPERTY",
|
|
2213
|
+
example: "SELECT HOUR(event_time) AS event_hour;"
|
|
2214
|
+
}
|
|
2215
|
+
}
|
|
2216
|
+
),
|
|
2217
|
+
new n(
|
|
2218
|
+
"DAY",
|
|
2219
|
+
"Extracts the day of the month component (1-31) from a date/time value as an integer.",
|
|
2220
|
+
"function",
|
|
2221
|
+
{
|
|
2222
|
+
function: {
|
|
2223
|
+
inputTypes: ["DATE", "TIMESTAMP", "DATETIME", "STRING"],
|
|
2224
|
+
outputType: 'INTEGER with "day" trait',
|
|
2225
|
+
outputPurpose: "PROPERTY",
|
|
2226
|
+
example: "SELECT DAY(event_date) AS event_day_of_month;"
|
|
2227
|
+
}
|
|
2228
|
+
}
|
|
2229
|
+
),
|
|
2230
|
+
new n(
|
|
2231
|
+
"WEEK",
|
|
2232
|
+
"Extracts the ISO week number (1-53) from a date/time value as an integer.",
|
|
2233
|
+
"function",
|
|
2234
|
+
{
|
|
2235
|
+
function: {
|
|
2236
|
+
inputTypes: ["DATE", "TIMESTAMP", "DATETIME", "STRING"],
|
|
2237
|
+
outputType: 'INTEGER with "week" trait',
|
|
2238
|
+
outputPurpose: "PROPERTY",
|
|
2239
|
+
example: "SELECT WEEK(order_date) AS order_week_iso;"
|
|
2240
|
+
}
|
|
2241
|
+
}
|
|
2242
|
+
),
|
|
2243
|
+
new n(
|
|
2244
|
+
"MONTH",
|
|
2245
|
+
"Extracts the month component (1-12) from a date/time value as an integer.",
|
|
2246
|
+
"function",
|
|
2247
|
+
{
|
|
2248
|
+
function: {
|
|
2249
|
+
inputTypes: ["DATE", "TIMESTAMP", "DATETIME", "STRING"],
|
|
2250
|
+
outputType: 'INTEGER with "month" trait',
|
|
2251
|
+
outputPurpose: "PROPERTY",
|
|
2252
|
+
example: "SELECT MONTH(signup_date) AS signup_month;"
|
|
2253
|
+
}
|
|
2254
|
+
}
|
|
2255
|
+
),
|
|
2256
|
+
new n(
|
|
2257
|
+
"QUARTER",
|
|
2258
|
+
"Extracts the quarter component (1-4) from a date/time value as an integer.",
|
|
2259
|
+
"function",
|
|
2260
|
+
{
|
|
2261
|
+
function: {
|
|
2262
|
+
inputTypes: ["DATE", "TIMESTAMP", "DATETIME", "STRING"],
|
|
2263
|
+
outputType: 'INTEGER with "quarter" trait',
|
|
2264
|
+
outputPurpose: "PROPERTY",
|
|
2265
|
+
example: "SELECT QUARTER(fiscal_date) AS fiscal_quarter;"
|
|
2266
|
+
}
|
|
2267
|
+
}
|
|
2268
|
+
),
|
|
2269
|
+
new n(
|
|
2270
|
+
"YEAR",
|
|
2271
|
+
"Extracts the year component from a date/time value as an integer.",
|
|
2272
|
+
"function",
|
|
2273
|
+
{
|
|
2274
|
+
function: {
|
|
2275
|
+
inputTypes: ["DATE", "TIMESTAMP", "DATETIME", "STRING"],
|
|
2276
|
+
outputType: 'INTEGER with "year" trait',
|
|
2277
|
+
outputPurpose: "PROPERTY",
|
|
2278
|
+
example: "SELECT YEAR(birth_date) AS birth_year;"
|
|
2279
|
+
}
|
|
2280
|
+
}
|
|
2281
|
+
),
|
|
2282
|
+
new n(
|
|
2283
|
+
"DAY_OF_WEEK",
|
|
2284
|
+
"Extracts the day of the week as an integer (e.g., Sunday=0 or 1, Monday=1 or 2, depending on locale/implementation - typically Sunday=0).",
|
|
2285
|
+
"function",
|
|
2286
|
+
{
|
|
2287
|
+
function: {
|
|
2288
|
+
inputTypes: ["DATE", "TIMESTAMP", "DATETIME", "STRING"],
|
|
2289
|
+
outputType: 'INTEGER with "day_of_week" trait',
|
|
2290
|
+
outputPurpose: "PROPERTY",
|
|
2291
|
+
example: "SELECT DAY_OF_WEEK(transaction_date) AS transaction_dow;"
|
|
2292
|
+
}
|
|
2293
|
+
}
|
|
2294
|
+
),
|
|
2295
|
+
// STRING FUNCTIONS
|
|
2296
|
+
new n("String Functions", "Functions for manipulating text strings."),
|
|
2297
|
+
new n(
|
|
2298
|
+
"SPLIT",
|
|
2299
|
+
"Splits the first string argument into an array of strings, using the second string argument as the delimiter.",
|
|
2300
|
+
"function",
|
|
2301
|
+
{
|
|
2302
|
+
function: {
|
|
2303
|
+
inputTypes: ["STRING", "STRING"],
|
|
2304
|
+
outputType: "LIST<STRING>",
|
|
2305
|
+
// Using LIST as per Python
|
|
2306
|
+
outputPurpose: "PROPERTY",
|
|
2307
|
+
example: 'SELECT SPLIT(product_tags, ";") AS tag_list;'
|
|
2308
|
+
}
|
|
2309
|
+
}
|
|
2310
|
+
),
|
|
2311
|
+
new n(
|
|
2312
|
+
"UPPER",
|
|
2313
|
+
"Converts the input string to all uppercase letters according to locale rules.",
|
|
2314
|
+
"function",
|
|
2315
|
+
{
|
|
2316
|
+
function: {
|
|
2317
|
+
inputTypes: ["STRING"],
|
|
2318
|
+
outputType: "STRING",
|
|
2319
|
+
outputPurpose: "PROPERTY",
|
|
2320
|
+
example: "SELECT UPPER(country_code) AS normalized_country;"
|
|
2321
|
+
}
|
|
2322
|
+
}
|
|
2323
|
+
),
|
|
2324
|
+
new n(
|
|
2325
|
+
"LOWER",
|
|
2326
|
+
"Converts the input string to all lowercase letters according to locale rules.",
|
|
2327
|
+
"function",
|
|
2328
|
+
{
|
|
2329
|
+
function: {
|
|
2330
|
+
inputTypes: ["STRING"],
|
|
2331
|
+
outputType: "STRING",
|
|
2332
|
+
outputPurpose: "PROPERTY",
|
|
2333
|
+
example: "SELECT LOWER(email_address) AS normalized_email;"
|
|
2334
|
+
}
|
|
2335
|
+
}
|
|
2336
|
+
),
|
|
2337
|
+
new n(
|
|
2338
|
+
"CONTAINS",
|
|
2339
|
+
"Returns true if the first string contains the second string as a substring, false otherwise. Case-sensitive.",
|
|
2340
|
+
"function",
|
|
2341
|
+
{
|
|
2342
|
+
function: {
|
|
2343
|
+
inputTypes: ["STRING", "STRING"],
|
|
2344
|
+
outputType: "BOOL",
|
|
2345
|
+
outputPurpose: "PROPERTY",
|
|
2346
|
+
example: 'SELECT description WHERE CONTAINS(description, "urgent");'
|
|
2347
|
+
}
|
|
2348
|
+
}
|
|
2349
|
+
),
|
|
2350
|
+
new n(
|
|
2351
|
+
"STRPOS",
|
|
2352
|
+
"Returns the starting position (1-based index) of the first occurrence of the second string within the first string. Returns 0 if the substring is not found. Case-sensitive.",
|
|
2353
|
+
"function",
|
|
2354
|
+
{
|
|
2355
|
+
function: {
|
|
2356
|
+
inputTypes: ["STRING", "STRING"],
|
|
2357
|
+
outputType: "INTEGER",
|
|
2358
|
+
outputPurpose: "PROPERTY",
|
|
2359
|
+
example: 'SELECT STRPOS(url, "?") AS query_start_pos;'
|
|
2360
|
+
}
|
|
2361
|
+
}
|
|
2362
|
+
),
|
|
2363
|
+
new n(
|
|
2364
|
+
"SUBSTRING",
|
|
2365
|
+
"Extracts a substring from the first argument, starting at the 1-based index specified by the second argument, for a length specified by the third argument.",
|
|
2366
|
+
"function",
|
|
2367
|
+
{
|
|
2368
|
+
function: {
|
|
2369
|
+
inputTypes: ["STRING", "INTEGER", "INTEGER"],
|
|
2370
|
+
outputType: "STRING",
|
|
2371
|
+
outputPurpose: "PROPERTY",
|
|
2372
|
+
example: "SELECT SUBSTRING(phone_number, 2, 3) AS area_code; # Assuming format like +1XXX..."
|
|
2373
|
+
}
|
|
2374
|
+
}
|
|
2375
|
+
),
|
|
2376
|
+
new n(
|
|
2377
|
+
"CONCAT",
|
|
2378
|
+
"Concatenates two or more string arguments together. NULL arguments are typically ignored or result in NULL depending on implementation.",
|
|
2379
|
+
"function",
|
|
2380
|
+
{
|
|
2381
|
+
function: {
|
|
2382
|
+
inputTypes: ["STRING", "..."],
|
|
2383
|
+
// Variable string args
|
|
2384
|
+
outputType: "STRING",
|
|
2385
|
+
outputPurpose: "PROPERTY",
|
|
2386
|
+
example: 'SELECT CONCAT(first_name, " ", last_name) AS full_name;'
|
|
2387
|
+
}
|
|
2388
|
+
}
|
|
2389
|
+
),
|
|
2390
|
+
new n(
|
|
2391
|
+
"LENGTH",
|
|
2392
|
+
"Returns the length of a string (number of characters), the number of elements in an array/list, or the number of key-value pairs in a map.",
|
|
2393
|
+
"function",
|
|
2394
|
+
{
|
|
2395
|
+
function: {
|
|
2396
|
+
inputTypes: ["STRING", "ARRAY", "MAP", "LIST"],
|
|
2397
|
+
// Added LIST
|
|
2398
|
+
outputType: "INTEGER",
|
|
2399
|
+
outputPurpose: "PROPERTY",
|
|
2400
|
+
example: "SELECT LENGTH(comment) AS comment_length;"
|
|
2401
|
+
}
|
|
2402
|
+
}
|
|
2403
|
+
),
|
|
2404
|
+
new n(
|
|
2405
|
+
"LIKE",
|
|
2406
|
+
"Performs case-sensitive SQL LIKE pattern matching. Use '%' for any sequence of zero or more characters and '_' for any single character.",
|
|
2407
|
+
"function",
|
|
2408
|
+
{
|
|
2409
|
+
function: {
|
|
2410
|
+
inputTypes: ["STRING", "STRING"],
|
|
2411
|
+
outputType: "BOOL",
|
|
2412
|
+
outputPurpose: "PROPERTY",
|
|
2413
|
+
example: 'SELECT product_name WHERE LIKE(product_name, "Model %");'
|
|
2414
|
+
}
|
|
2415
|
+
}
|
|
2416
|
+
),
|
|
2417
|
+
new n(
|
|
2418
|
+
"ILIKE",
|
|
2419
|
+
"Performs case-insensitive SQL LIKE pattern matching (similar to Postgres ILIKE). Use '%' and '_' wildcards as with LIKE.",
|
|
2420
|
+
"function",
|
|
2421
|
+
{
|
|
2422
|
+
function: {
|
|
2423
|
+
inputTypes: ["STRING", "STRING"],
|
|
2424
|
+
outputType: "BOOL",
|
|
2425
|
+
outputPurpose: "PROPERTY",
|
|
2426
|
+
example: 'SELECT email WHERE ILIKE(email, "%@example.com");'
|
|
2427
|
+
}
|
|
2428
|
+
}
|
|
2429
|
+
),
|
|
2430
|
+
// NUMERIC FUNCTIONS
|
|
2431
|
+
new n(
|
|
2432
|
+
"Numeric Functions",
|
|
2433
|
+
"Functions for performing mathematical operations on numbers."
|
|
2434
|
+
),
|
|
2435
|
+
new n("ABS", "Computes the absolute value of a numeric argument.", "function", {
|
|
2436
|
+
function: {
|
|
2437
|
+
inputTypes: ["INTEGER", "FLOAT", "NUMBER"],
|
|
2438
|
+
outputType: "Same as input type",
|
|
2439
|
+
outputPurpose: "PROPERTY",
|
|
2440
|
+
example: "SELECT ABS(price_change) AS abs_price_change;"
|
|
2441
|
+
}
|
|
2442
|
+
}),
|
|
2443
|
+
new n(
|
|
2444
|
+
"ROUND",
|
|
2445
|
+
"Rounds the first numeric argument to the number of decimal places specified by the second integer argument. If the second argument is omitted or zero, rounds to the nearest integer.",
|
|
2446
|
+
"function",
|
|
2447
|
+
{
|
|
2448
|
+
function: {
|
|
2449
|
+
inputTypes: ["INTEGER/FLOAT/NUMBER/NUMERIC", "INTEGER"],
|
|
2450
|
+
outputType: "Same as first input type",
|
|
2451
|
+
outputPurpose: "PROPERTY",
|
|
2452
|
+
example: "SELECT ROUND(average_rating, 1) AS rounded_rating;"
|
|
2453
|
+
}
|
|
2454
|
+
}
|
|
2455
|
+
),
|
|
2456
|
+
new n(
|
|
2457
|
+
"SQRT",
|
|
2458
|
+
"Calculates the square root of a non-negative numeric argument. The result is typically a FLOAT or NUMBER.",
|
|
2459
|
+
"function",
|
|
2460
|
+
{
|
|
2461
|
+
function: {
|
|
2462
|
+
inputTypes: ["INTEGER", "FLOAT", "NUMBER", "NUMERIC"],
|
|
2463
|
+
outputType: "FLOAT or NUMBER",
|
|
2464
|
+
// Usually returns float/double
|
|
2465
|
+
outputPurpose: "PROPERTY",
|
|
2466
|
+
example: "SELECT SQRT(variance) AS standard_deviation;"
|
|
2467
|
+
}
|
|
2468
|
+
}
|
|
2469
|
+
),
|
|
2470
|
+
new n(
|
|
2471
|
+
"RANDOM",
|
|
2472
|
+
"Returns a random floating-point value between 0.0 (inclusive) and 1.0 (exclusive) at the grain of the provided concept. If no concept is provided, all rows have the same value.",
|
|
2473
|
+
"function",
|
|
2474
|
+
{
|
|
2475
|
+
function: {
|
|
2476
|
+
inputTypes: ["ANY"],
|
|
2477
|
+
outputType: "FLOAT",
|
|
2478
|
+
outputPurpose: "PROPERTY",
|
|
2479
|
+
// Often property, but can behave like constant per-row if not memoized
|
|
2480
|
+
example: "SELECT order_id, RANDOM(order_id) AS random_sort_key ORDER BY random_sort_key;"
|
|
2481
|
+
}
|
|
2482
|
+
}
|
|
2483
|
+
),
|
|
2484
|
+
new n(
|
|
2485
|
+
"ADD",
|
|
2486
|
+
"Performs arithmetic addition on two or more numeric arguments.",
|
|
2487
|
+
"function",
|
|
2488
|
+
{
|
|
2489
|
+
function: {
|
|
2490
|
+
inputTypes: ["INTEGER/FLOAT/NUMBER/NUMERIC", "..."],
|
|
2491
|
+
outputType: "Appropriate numeric type based on inputs",
|
|
2492
|
+
outputPurpose: "PROPERTY",
|
|
2493
|
+
example: "SELECT ADD(subtotal, tax, shipping_fee) AS grand_total;"
|
|
2494
|
+
}
|
|
2495
|
+
}
|
|
2496
|
+
),
|
|
2497
|
+
new n(
|
|
2498
|
+
"SUBTRACT",
|
|
2499
|
+
"Performs arithmetic subtraction. If two arguments, subtracts the second from the first. If more, behavior might vary (e.g., subtract all subsequent from first).",
|
|
2500
|
+
"function",
|
|
2501
|
+
{
|
|
2502
|
+
function: {
|
|
2503
|
+
inputTypes: ["INTEGER/FLOAT/NUMBER/NUMERIC", "..."],
|
|
2504
|
+
outputType: "Appropriate numeric type based on inputs",
|
|
2505
|
+
outputPurpose: "PROPERTY",
|
|
2506
|
+
example: "SELECT SUBTRACT(total_revenue, total_cost) AS profit;"
|
|
2507
|
+
}
|
|
2508
|
+
}
|
|
2509
|
+
),
|
|
2510
|
+
new n(
|
|
2511
|
+
"MULTIPLY",
|
|
2512
|
+
"Performs arithmetic multiplication on two or more numeric arguments.",
|
|
2513
|
+
"function",
|
|
2514
|
+
{
|
|
2515
|
+
function: {
|
|
2516
|
+
inputTypes: ["INTEGER/FLOAT/NUMBER/NUMERIC", "..."],
|
|
2517
|
+
outputType: "Appropriate numeric type based on inputs",
|
|
2518
|
+
outputPurpose: "PROPERTY",
|
|
2519
|
+
example: "SELECT MULTIPLY(quantity, unit_price) AS line_item_total;"
|
|
2520
|
+
}
|
|
2521
|
+
}
|
|
2522
|
+
),
|
|
2523
|
+
new n(
|
|
2524
|
+
"DIVIDE",
|
|
2525
|
+
"Performs arithmetic division. If two arguments, divides the first by the second. Division by zero typically results in an error or NULL/Infinity. Result type is often FLOAT or NUMBER.",
|
|
2526
|
+
"function",
|
|
2527
|
+
{
|
|
2528
|
+
function: {
|
|
2529
|
+
inputTypes: ["INTEGER/FLOAT/NUMBER/NUMERIC", "..."],
|
|
2530
|
+
outputType: "FLOAT or NUMBER (usually)",
|
|
2531
|
+
outputPurpose: "PROPERTY",
|
|
2532
|
+
example: "SELECT DIVIDE(total_sales, number_of_units) AS price_per_unit;"
|
|
2533
|
+
}
|
|
2534
|
+
}
|
|
2535
|
+
),
|
|
2536
|
+
new n(
|
|
2537
|
+
"MOD",
|
|
2538
|
+
"Computes the modulo (remainder) of the first numeric argument divided by the second integer argument.",
|
|
2539
|
+
"function",
|
|
2540
|
+
{
|
|
2541
|
+
function: {
|
|
2542
|
+
inputTypes: ["INTEGER/FLOAT/NUMBER/NUMERIC", "INTEGER"],
|
|
2543
|
+
outputType: "INTEGER",
|
|
2544
|
+
// Remainder is typically integer
|
|
2545
|
+
outputPurpose: "PROPERTY",
|
|
2546
|
+
example: "SELECT user_id WHERE MOD(user_id, 2) = 0; # Even user IDs"
|
|
2547
|
+
}
|
|
2548
|
+
}
|
|
2549
|
+
),
|
|
2550
|
+
// UTILITY FUNCTIONS
|
|
2551
|
+
new n(
|
|
2552
|
+
"Utility Functions",
|
|
2553
|
+
"General-purpose functions for data manipulation, control flow, and type handling."
|
|
2554
|
+
),
|
|
2555
|
+
new n(
|
|
2556
|
+
"ALIAS",
|
|
2557
|
+
"Assigns a new name (alias) to an expression or concept without changing its value, type, or purpose. Useful for clarity or renaming in SELECT clauses.",
|
|
2558
|
+
"function",
|
|
2559
|
+
{
|
|
2560
|
+
function: {
|
|
2561
|
+
inputTypes: ["Any"],
|
|
2562
|
+
outputType: "Same as input",
|
|
2563
|
+
outputPurpose: "Same as input",
|
|
2564
|
+
example: "SELECT user.profile.first_name ALIAS fname;"
|
|
2565
|
+
}
|
|
2566
|
+
}
|
|
2567
|
+
),
|
|
2568
|
+
new n(
|
|
2569
|
+
"PARENTHETICAL",
|
|
2570
|
+
"Used for explicit grouping of expressions, primarily to control the order of operations. Does not change the value, type, or purpose of the enclosed expression.",
|
|
2571
|
+
"function",
|
|
2572
|
+
{
|
|
2573
|
+
function: {
|
|
2574
|
+
inputTypes: ["Any"],
|
|
2575
|
+
outputType: "Same as input",
|
|
2576
|
+
outputPurpose: "Same as input",
|
|
2577
|
+
example: "SELECT (price + tax) * quantity AS total;"
|
|
2578
|
+
}
|
|
2579
|
+
}
|
|
2580
|
+
),
|
|
2581
|
+
new n(
|
|
2582
|
+
"COALESCE",
|
|
2583
|
+
"Returns the first non-null value from its list of arguments. All arguments must be of compatible types. Returns NULL if all arguments are NULL.",
|
|
2584
|
+
"function",
|
|
2585
|
+
{
|
|
2586
|
+
function: {
|
|
2587
|
+
inputTypes: ["Any (compatible types)", "..."],
|
|
2588
|
+
outputType: "Same as input types (common compatible type)",
|
|
2589
|
+
outputPurpose: "PROPERTY",
|
|
2590
|
+
example: 'SELECT COALESCE(nickname, first_name, "Valued Customer") AS display_name;'
|
|
2591
|
+
}
|
|
2592
|
+
}
|
|
2593
|
+
),
|
|
2594
|
+
new n(
|
|
2595
|
+
"CAST",
|
|
2596
|
+
"Explicitly converts an expression to a target data type specified as the second argument (using a DataType enum value or potentially a string literal).",
|
|
2597
|
+
"function",
|
|
2598
|
+
{
|
|
2599
|
+
function: {
|
|
2600
|
+
inputTypes: ["Any", "DataType"],
|
|
2601
|
+
outputType: "Specified by second argument (DataType)",
|
|
2602
|
+
outputPurpose: "PROPERTY",
|
|
2603
|
+
example: "SELECT CAST(order_id_string AS INTEGER) AS order_id_num;"
|
|
2604
|
+
}
|
|
2605
|
+
}
|
|
2606
|
+
),
|
|
2607
|
+
new n(
|
|
2608
|
+
"IS_NULL",
|
|
2609
|
+
"Returns true if the input argument is NULL, false otherwise.",
|
|
2610
|
+
"function",
|
|
2611
|
+
{
|
|
2612
|
+
function: {
|
|
2613
|
+
inputTypes: ["Any"],
|
|
2614
|
+
outputType: "BOOL",
|
|
2615
|
+
outputPurpose: "PROPERTY",
|
|
2616
|
+
example: "SELECT order_id WHERE IS_NULL(shipping_address);"
|
|
2617
|
+
}
|
|
2618
|
+
}
|
|
2619
|
+
),
|
|
2620
|
+
new n(
|
|
2621
|
+
"BOOL",
|
|
2622
|
+
"Attempts to convert the input argument to a boolean value. Behavior depends on the input type (e.g., 0 -> false, non-zero -> true; empty string -> false, non-empty -> true).",
|
|
2623
|
+
"function",
|
|
2624
|
+
{
|
|
2625
|
+
function: {
|
|
2626
|
+
inputTypes: ["Any"],
|
|
2627
|
+
// Usually numeric, string, potentially others
|
|
2628
|
+
outputType: "BOOL",
|
|
2629
|
+
outputPurpose: "PROPERTY",
|
|
2630
|
+
example: "SELECT product_id, BOOL(is_active_flag) AS is_active;"
|
|
2631
|
+
}
|
|
2632
|
+
}
|
|
2633
|
+
),
|
|
2634
|
+
new n(
|
|
2635
|
+
"CASE",
|
|
2636
|
+
"Evaluates a series of conditions and returns a result based on the first condition that evaluates to true. Syntax: `CASE WHEN condition1 THEN result1 [WHEN condition2 THEN result2 ...] [ELSE default_result] END`. All result expressions must have compatible types.",
|
|
2637
|
+
"function",
|
|
2638
|
+
{
|
|
2639
|
+
function: {
|
|
2640
|
+
inputTypes: ["BOOL", "Any", "..."],
|
|
2641
|
+
// Alternating condition/result pairs, optional ELSE
|
|
2642
|
+
outputType: "Common compatible type of result expressions",
|
|
2643
|
+
outputPurpose: "PROPERTY",
|
|
2644
|
+
example: 'SELECT CASE WHEN score > 90 THEN "A" WHEN score > 80 THEN "B" ELSE "C" END AS grade;'
|
|
2645
|
+
}
|
|
2646
|
+
}
|
|
2647
|
+
),
|
|
2648
|
+
new n(
|
|
2649
|
+
"CONSTANT",
|
|
2650
|
+
"Represents a literal value provided as an argument. The type and purpose are determined by the literal itself.",
|
|
2651
|
+
"function",
|
|
2652
|
+
{
|
|
2653
|
+
function: {
|
|
2654
|
+
inputTypes: ["Literal (String, Number, Bool, etc.)"],
|
|
2655
|
+
outputType: "Type of the literal",
|
|
2656
|
+
outputPurpose: "CONSTANT",
|
|
2657
|
+
example: 'SELECT "Default Category" AS category, product_id;'
|
|
2658
|
+
// String literal implicitly uses CONSTANT
|
|
2659
|
+
}
|
|
2660
|
+
}
|
|
2661
|
+
),
|
|
2662
|
+
new n(
|
|
2663
|
+
"CUSTOM",
|
|
2664
|
+
"Represents a user-defined or engine-specific function not built into the core Trilogy language. Input types, output type, and behavior depend on the specific custom function implementation.",
|
|
2665
|
+
"function",
|
|
2666
|
+
{
|
|
2667
|
+
function: {
|
|
2668
|
+
inputTypes: ["Depends on custom function"],
|
|
2669
|
+
outputType: "Depends on custom function",
|
|
2670
|
+
outputPurpose: "Usually PROPERTY or METRIC",
|
|
2671
|
+
example: "SELECT my_custom_scoring_function(user_data) AS score;"
|
|
2672
|
+
}
|
|
2673
|
+
}
|
|
2674
|
+
),
|
|
2675
|
+
// COLLECTION FUNCTIONS
|
|
2676
|
+
new n(
|
|
2677
|
+
"Collection Functions",
|
|
2678
|
+
"Functions for working with complex data types like arrays/lists, maps, and structs."
|
|
2679
|
+
),
|
|
2680
|
+
new n(
|
|
2681
|
+
"UNNEST",
|
|
2682
|
+
"Expands an array or list into a set of rows, where each row contains one element from the array/list. This typically changes the grain of the query, hence the KEY purpose.",
|
|
2683
|
+
"function",
|
|
2684
|
+
{
|
|
2685
|
+
function: {
|
|
2686
|
+
inputTypes: ["ARRAY", "LIST"],
|
|
2687
|
+
outputType: "Element type of the input collection",
|
|
2688
|
+
outputPurpose: "KEY",
|
|
2689
|
+
example: "SELECT order_id, UNNEST(product_ids) AS product_id;"
|
|
2690
|
+
}
|
|
2691
|
+
}
|
|
2692
|
+
),
|
|
2693
|
+
new n(
|
|
2694
|
+
"INDEX_ACCESS",
|
|
2695
|
+
"Retrieves an element from an array or list using its zero-based integer index. Accessing an index outside the bounds may result in NULL or an error.",
|
|
2696
|
+
"function",
|
|
2697
|
+
{
|
|
2698
|
+
function: {
|
|
2699
|
+
inputTypes: ["ARRAY/LIST", "INTEGER"],
|
|
2700
|
+
outputType: "Element type of the input collection",
|
|
2701
|
+
outputPurpose: "PROPERTY",
|
|
2702
|
+
example: "SELECT INDEX_ACCESS(sensor_readings, 0) AS first_reading;"
|
|
2703
|
+
}
|
|
2704
|
+
}
|
|
2705
|
+
),
|
|
2706
|
+
new n(
|
|
2707
|
+
"MAP_ACCESS",
|
|
2708
|
+
"Retrieves the value associated with a specified key from a map. The key type must match the map's key type (usually STRING or INTEGER). Returns NULL if the key is not found.",
|
|
2709
|
+
"function",
|
|
2710
|
+
{
|
|
2711
|
+
function: {
|
|
2712
|
+
inputTypes: ["MAP", "INTEGER/STRING"],
|
|
2713
|
+
// Key type
|
|
2714
|
+
outputType: "Value type of the map",
|
|
2715
|
+
outputPurpose: "PROPERTY",
|
|
2716
|
+
example: 'SELECT MAP_ACCESS(user_properties, "preferred_language") AS language;'
|
|
2717
|
+
}
|
|
2718
|
+
}
|
|
2719
|
+
),
|
|
2720
|
+
new n(
|
|
2721
|
+
"ATTR_ACCESS",
|
|
2722
|
+
"Retrieves the value of a named field (attribute) from a struct. The second argument is the attribute name (string). Accessing a non-existent attribute may result in NULL or an error.",
|
|
2723
|
+
"function",
|
|
2724
|
+
{
|
|
2725
|
+
function: {
|
|
2726
|
+
inputTypes: ["STRUCT", "STRING"],
|
|
2727
|
+
// Struct and attribute name
|
|
2728
|
+
outputType: "Type of the accessed attribute",
|
|
2729
|
+
outputPurpose: "PROPERTY",
|
|
2730
|
+
example: 'SELECT ATTR_ACCESS(address_struct, "zip_code") AS zip;'
|
|
2731
|
+
}
|
|
2732
|
+
}
|
|
2733
|
+
),
|
|
2734
|
+
new n(
|
|
2735
|
+
"STRUCT",
|
|
2736
|
+
"Constructs a struct (similar to a record or object) dynamically from pairs of arguments: field name (string literal) followed by the field value.",
|
|
2737
|
+
"function",
|
|
2738
|
+
{
|
|
2739
|
+
function: {
|
|
2740
|
+
inputTypes: ["STRING (name)", "Any (value)", "..."],
|
|
2741
|
+
// Alternating name/value pairs
|
|
2742
|
+
outputType: "STRUCT with specified fields and types",
|
|
2743
|
+
outputPurpose: "PROPERTY",
|
|
2744
|
+
example: 'SELECT STRUCT("id", user_id, "email", user_email) AS user_info;'
|
|
2745
|
+
}
|
|
2746
|
+
}
|
|
2747
|
+
),
|
|
2748
|
+
new n(
|
|
2749
|
+
"ARRAY",
|
|
2750
|
+
"Constructs an array containing the provided arguments. All arguments should ideally be of a compatible type; behavior/support depends on target DB. The output type depends on the input argument types.",
|
|
2751
|
+
"function",
|
|
2752
|
+
{
|
|
2753
|
+
function: {
|
|
2754
|
+
inputTypes: ["Any (compatible types)", "..."],
|
|
2755
|
+
// Python says ListType(STRING), but usually it's based on args
|
|
2756
|
+
outputType: "ARRAY of common compatible type of arguments",
|
|
2757
|
+
outputPurpose: "PROPERTY",
|
|
2758
|
+
example: "SELECT ARRAY(primary_color, secondary_color) AS palette;"
|
|
2759
|
+
}
|
|
2760
|
+
}
|
|
2761
|
+
),
|
|
2762
|
+
// SET/RELATIONAL FUNCTIONS (Could be its own category)
|
|
2763
|
+
new n("Set/Relational Functions", "Functions operating on sets or relations."),
|
|
2764
|
+
new n(
|
|
2765
|
+
"UNION",
|
|
2766
|
+
"Combines the results of two or more compatible inputs (concepts or queries) into a single result set. Behaves like UNION ALL (does not remove duplicates). The inputs must have compatible data types.",
|
|
2767
|
+
"function",
|
|
2768
|
+
{
|
|
2769
|
+
function: {
|
|
2770
|
+
inputTypes: ["Any (compatible concepts/queries)", "..."],
|
|
2771
|
+
outputType: "Depends on inputs (structure of the combined set)",
|
|
2772
|
+
outputPurpose: "KEY",
|
|
2773
|
+
// Usually produces a new set/relation
|
|
2774
|
+
example: "SELECT * FROM UNION(active_customers, recently_lapsed_customers);"
|
|
2775
|
+
}
|
|
2776
|
+
}
|
|
2777
|
+
),
|
|
2778
|
+
new n(
|
|
2779
|
+
"GROUP",
|
|
2780
|
+
"Explicitly specifies the grouping keys for an expression, often used with aggregate functions when a different grain is needed than the main query `BY` clause. The first argument is the expression to aggregate/group, subsequent arguments are the keys. Syntax is distinct in that is is group key by <over clause>, similar to a group by.",
|
|
2781
|
+
"function",
|
|
2782
|
+
{
|
|
2783
|
+
function: {
|
|
2784
|
+
inputTypes: ["Any (expression)", "Any (key)", "..."],
|
|
2785
|
+
outputType: "Same as first argument's type",
|
|
2786
|
+
// Purpose might depend on the first argument (Metric if aggregate, Property/Key otherwise)
|
|
2787
|
+
outputPurpose: "Depends on first argument",
|
|
2788
|
+
example: "SELECT SUM(revenue) AS total_revenue, GROUP SUM(revenue) BY product_category AS revenue_by_category, customer_id;"
|
|
2789
|
+
}
|
|
2790
|
+
}
|
|
2791
|
+
)
|
|
2792
|
+
]), mn = new M("Window Functions", [
|
|
2793
|
+
new n(
|
|
2794
|
+
"Trilogy Built-in Functions",
|
|
2795
|
+
"Window functions are a set of built-in functions in the Trilogy query language that allow you to perform calculations across a set of rows related to the current row. These functions are essential for data analysis, reporting, and complex aggregations."
|
|
2796
|
+
),
|
|
2797
|
+
new n(
|
|
2798
|
+
"Function Usage & Concepts",
|
|
2799
|
+
`Each function definition includes its input requirements and output characteristics. Key information includes:
|
|
2800
|
+
<ul>
|
|
2801
|
+
<li><b>Input Types:</b> The allowed data types for each argument.</li>
|
|
2802
|
+
<li><b>Output Type:</b> The data type of the value returned by the function.</li>
|
|
2803
|
+
<li><b>Output Purpose:</b> Describes the conceptual role of the output.
|
|
2804
|
+
<ul>
|
|
2805
|
+
<li><b>PROPERTY:</b> Represents an attribute derived from existing data, typically associated with the grain of the input(s). Example: <code>UPPER(name)</code>.</li>
|
|
2806
|
+
<li><b>METRIC:</b> Represents a calculated value that summarizes data across rows, respecting the query's grouping. Example: <code>SUM(revenue)</code>.</li>
|
|
2807
|
+
<li><b>KEY:</b> Represents an identifier or a dimension used for joining or grouping, often changing the grain of the data. Example: <code>UNNEST(tags)</code>.</li>
|
|
2808
|
+
<li><b>CONSTANT:</b> Represents a fixed value, independent of the input data rows. Example: <code>CURRENT_DATE()</code>.</li>
|
|
2809
|
+
</ul>
|
|
2810
|
+
</li>
|
|
2811
|
+
</ul>`
|
|
2812
|
+
),
|
|
2813
|
+
new n(
|
|
2814
|
+
"RANK",
|
|
2815
|
+
"Computes the rank of each row within its partition, with ties receiving the same rank. The rank starts at 1 for the first row in each partition.",
|
|
2816
|
+
"function",
|
|
2817
|
+
{
|
|
2818
|
+
function: {
|
|
2819
|
+
inputTypes: ["ANY"],
|
|
2820
|
+
outputType: "INT",
|
|
2821
|
+
outputPurpose: "PROPERTY",
|
|
2822
|
+
example: "rank repo.license by license_repo_count desc;"
|
|
2823
|
+
}
|
|
2824
|
+
}
|
|
2825
|
+
),
|
|
2826
|
+
// new Paragraph(
|
|
2827
|
+
// 'ROW_NUMBER',
|
|
2828
|
+
// 'Assigns a unique sequential integer to each row within its partition, starting at 1. Unlike RANK, it does not assign the same number to tied rows.',
|
|
2829
|
+
// 'function',
|
|
2830
|
+
// {
|
|
2831
|
+
// function: {
|
|
2832
|
+
// inputTypes: ['ANY'],
|
|
2833
|
+
// outputType: 'INT',
|
|
2834
|
+
// outputPurpose: 'PROPERTY',
|
|
2835
|
+
// example: 'row_number repo.license by license_repo_count desc;',
|
|
2836
|
+
// },
|
|
2837
|
+
// } as FuncData,
|
|
2838
|
+
// ),
|
|
2839
|
+
// new Paragraph(
|
|
2840
|
+
// 'DENSE_RANK',
|
|
2841
|
+
// 'Similar to RANK, but does not leave gaps in the ranking sequence when there are ties. The next rank after a tie is the next consecutive integer.',
|
|
2842
|
+
// 'function',
|
|
2843
|
+
// {
|
|
2844
|
+
// function: {
|
|
2845
|
+
// inputTypes: ['ANY'],
|
|
2846
|
+
// outputType: 'INT',
|
|
2847
|
+
// outputPurpose: 'PROPERTY',
|
|
2848
|
+
// example: 'dense_rank repo.license by license_repo_count desc;',
|
|
2849
|
+
// },
|
|
2850
|
+
// } as FuncData,
|
|
2851
|
+
// ),
|
|
2852
|
+
new n(
|
|
2853
|
+
"LAG",
|
|
2854
|
+
"Accesses data from a previous row in the same partition without changing the partitioning or ordering of the result set. The offset can be specified to retrieve data from a specific number of rows back.",
|
|
2855
|
+
"function",
|
|
2856
|
+
{
|
|
2857
|
+
function: {
|
|
2858
|
+
inputTypes: ["ANY", "INT"],
|
|
2859
|
+
outputType: "ANY",
|
|
2860
|
+
outputPurpose: "PROPERTY",
|
|
2861
|
+
example: "lag repo.license by license_repo_count desc;"
|
|
2862
|
+
}
|
|
2863
|
+
}
|
|
2864
|
+
),
|
|
2865
|
+
new n(
|
|
2866
|
+
"LEAD",
|
|
2867
|
+
"Accesses data from a subsequent row in the same partition without changing the partitioning or ordering of the result set. The offset can be specified to retrieve data from a specific number of rows ahead.",
|
|
2868
|
+
"function",
|
|
2869
|
+
{
|
|
2870
|
+
function: {
|
|
2871
|
+
inputTypes: ["ANY", "INT"],
|
|
2872
|
+
outputType: "ANY",
|
|
2873
|
+
outputPurpose: "PROPERTY",
|
|
2874
|
+
example: "lead repo.license by license_repo_count desc;"
|
|
2875
|
+
}
|
|
2876
|
+
}
|
|
2877
|
+
)
|
|
2878
|
+
]), hn = new M(
|
|
2879
|
+
"Modeling",
|
|
2880
|
+
// Article Title
|
|
2881
|
+
[
|
|
2882
|
+
// --- Introduction to Models ---
|
|
2883
|
+
new n(
|
|
2884
|
+
"What is a Model?",
|
|
2885
|
+
// Section Title
|
|
2886
|
+
"Models are the heart of Trilogy's semantic layer. They provide a structured, logical representation of data that can evolve independently of the underlying physical model. A model ist just a collection of Trilogy .preql files available for import. In Trilogy Studio, these are editors that have been marked as `sources`. These sources define the concepts, properties, and data retrieval logic for your domain."
|
|
2887
|
+
),
|
|
2888
|
+
new n(
|
|
2889
|
+
"Purpose and Benefits",
|
|
2890
|
+
// title
|
|
2891
|
+
// content - now using HTML syntax
|
|
2892
|
+
`Models enable several key benefits:
|
|
2893
|
+
<ul>
|
|
2894
|
+
<li><strong>Abstraction:</strong> Define data logically using concepts (like 'customer' or 'order') independent of physical table names or structures.</li>
|
|
2895
|
+
<li><strong>Reusability:</strong> Define concepts and logic once in a model source and import them into any number of queries, reports, or other models.</li>
|
|
2896
|
+
<li><strong>Maintainability:</strong> If your database schema changes (e.g., table or column rename), you only need to update the corresponding datasource mapping in the model. Queries relying on the logical concepts remain unchanged.</li>
|
|
2897
|
+
<li><strong>Consistency:</strong> Ensures everyone querying the data uses the same definitions, metrics, and relationships.</li>
|
|
2898
|
+
<li><strong>Governance:</strong> Provides a centralized place to manage data definitions, access rules (via datasources), and metadata (types, traits).</li>
|
|
2899
|
+
</ul>`,
|
|
2900
|
+
null,
|
|
2901
|
+
// type (assuming 'null' is for standard content)
|
|
2902
|
+
null
|
|
2903
|
+
// data (assuming no specific data object is needed here)
|
|
2904
|
+
),
|
|
2905
|
+
// --- Core Components of a Model ---
|
|
2906
|
+
new n(
|
|
2907
|
+
"Core Components",
|
|
2908
|
+
"Models have two core components: Concepts and Datasources. These are defined within Trilogy editors marked as model sources.",
|
|
2909
|
+
"section"
|
|
2910
|
+
// Using 'section' type for structure
|
|
2911
|
+
),
|
|
2912
|
+
new n(
|
|
2913
|
+
"Concepts",
|
|
2914
|
+
// Subsection Title
|
|
2915
|
+
"Concepts keys represent the core entities or logical keys in your data model (e.g., `customer.id`, `product.sku`, `order.id`). Each concept typically has a unique key that identifies individual instances (like `customer.id`). Concepts form the nouns of your data language. They are defined implicitly through properties and datasources associated with them.",
|
|
2916
|
+
"subsection"
|
|
2917
|
+
// Using 'subsection' type
|
|
2918
|
+
),
|
|
2919
|
+
new n(
|
|
2920
|
+
"Properties",
|
|
2921
|
+
// Subsection Title
|
|
2922
|
+
"Concept properties are dependent concepts or characteristics associated with a key (e.g., `customer.name`, `order.order_date`, `product.price`). They define context/attributes of keys.\n Properties have defined data types (like `string`, `number`, `datetime`) and can be further annotated with metadata traits (like `::usd` or `::us_state_short`).\n New properties can be added to existing concepts using the `property` keyword:",
|
|
2923
|
+
"subsection"
|
|
2924
|
+
// Using 'subsection' type
|
|
2925
|
+
),
|
|
2926
|
+
new n(
|
|
2927
|
+
// Code Example for Properties
|
|
2928
|
+
"Properties Example",
|
|
2929
|
+
// Title for the code block (can be descriptive)
|
|
2930
|
+
`property order.customer.nation.region.id.headquarters string;
|
|
2931
|
+
// This adds a 'headquarters' property of type string
|
|
2932
|
+
// under the key \`order.customer.nation.region.id.\`
|
|
2933
|
+
property <order.customer.nation.region.id>.headquarters string;
|
|
2934
|
+
// this does the same, but with explicit syntax
|
|
2935
|
+
// that can be useful when you have a property of multiple keys
|
|
2936
|
+
property <order.customer.nation.region.id,date.year>.point_in_time_hq string;
|
|
2937
|
+
`,
|
|
2938
|
+
"code"
|
|
2939
|
+
// type = 'code'
|
|
2940
|
+
),
|
|
2941
|
+
new n(
|
|
2942
|
+
"Types and Traits",
|
|
2943
|
+
// Subsection Title
|
|
2944
|
+
"Trilogy has a core type system (e.g., `string`, `number`, `list<T>`, `struct<...>`) that maps to database types.\n Additionally, a metadata-based trait system allows for richer semantic meaning. Traits are appended using `::`.\n Example: `auto states <- ['NY', 'CA', 'TX']::list<string::us_state_short>;` defines a list where each element is a string representing a US state abbreviation. Traits can influence validation, default visualizations (like maps for geo traits), or downstream system behavior.",
|
|
2945
|
+
"subsection",
|
|
2946
|
+
null
|
|
2947
|
+
),
|
|
2948
|
+
new n(
|
|
2949
|
+
// Code Example for Types and Traits
|
|
2950
|
+
"Types and Traits Example",
|
|
2951
|
+
`import std.geography; // Import traits like us_state_short
|
|
2952
|
+
|
|
2953
|
+
// Define a list of strings with a specific trait
|
|
2954
|
+
auto states <- ['NY', 'CA', 'TX']::list<string::us_state_short>;
|
|
2955
|
+
|
|
2956
|
+
// Define a price with a currency trait
|
|
2957
|
+
auto item_price <- 19.99::number::usd;`,
|
|
2958
|
+
"code",
|
|
2959
|
+
null
|
|
2960
|
+
),
|
|
2961
|
+
new n(
|
|
2962
|
+
"Datasources",
|
|
2963
|
+
// Subsection Title
|
|
2964
|
+
"Datasources are the bridge between the logical model of concept keys and properties and database tables. They define *how* and *where* to fetch the data for specific properties.\n A datasource maps logical properties to physical columns or calculations and specifies the source.\n Crucially, they also define the `grain` - the level of detail or the set of keys that uniquely identify a row returned by the datasource.",
|
|
2965
|
+
"subsection",
|
|
2966
|
+
null
|
|
2967
|
+
),
|
|
2968
|
+
new n(
|
|
2969
|
+
// Code Example for Datasource (DB)
|
|
2970
|
+
"Datasource Example (Database)",
|
|
2971
|
+
`import lineitem; // Assume lineitem provides base concepts like order.id etc.
|
|
2972
|
+
|
|
2973
|
+
// Add a new property first (as shown before)
|
|
2974
|
+
property order.customer.nation.region.id.headquarters string;
|
|
2975
|
+
|
|
2976
|
+
// Define a datasource to populate the new property
|
|
2977
|
+
datasource region_headquarters (
|
|
2978
|
+
region_id: order.customer.nation.region.id, // Map logical concept key to source column
|
|
2979
|
+
headquarters: order.customer.nation.region.headquarters, // Map logical property to source column
|
|
2980
|
+
)
|
|
2981
|
+
grain (order.customer.nation.region.id) // Define the unique key for this data
|
|
2982
|
+
address tbl_headquarters;
|
|
2983
|
+
''';`,
|
|
2984
|
+
"code",
|
|
2985
|
+
null
|
|
2986
|
+
),
|
|
2987
|
+
new n(
|
|
2988
|
+
"Datasource (Inline Example Description)",
|
|
2989
|
+
// Description for the inline example
|
|
2990
|
+
"Datasources can also use raw queries as a source, useful for constants, mappings, or small datasets directly within the model definition.",
|
|
2991
|
+
null,
|
|
2992
|
+
// Use null type for the description part
|
|
2993
|
+
null
|
|
2994
|
+
),
|
|
2995
|
+
new n(
|
|
2996
|
+
// Code Example for Datasource (Inline)
|
|
2997
|
+
"Datasource Example (Inline Query)",
|
|
2998
|
+
`datasource region_headquarters_inline (
|
|
2999
|
+
region_id: order.customer.nation.region.id,
|
|
3000
|
+
headquarters: order.customer.nation.region.headquarters,
|
|
3001
|
+
)
|
|
3002
|
+
grain (order.customer.nation.region.id)
|
|
3003
|
+
query '''
|
|
3004
|
+
-- Using an inline query (syntax might vary based on backend)
|
|
3005
|
+
select 1 as region_id, 'HQ1' as headquarters
|
|
3006
|
+
union all
|
|
3007
|
+
select 2 as region_id, 'HQ2' as headquarters
|
|
3008
|
+
union all
|
|
3009
|
+
select 3 as region_id, 'HQ3' as headquarters
|
|
3010
|
+
union all
|
|
3011
|
+
select 4 as region_id, 'HQ4' as headquarters
|
|
3012
|
+
''';`,
|
|
3013
|
+
"code",
|
|
3014
|
+
// type = 'code'
|
|
3015
|
+
null
|
|
3016
|
+
// data = null
|
|
3017
|
+
),
|
|
3018
|
+
// --- Using and Managing Models ---
|
|
3019
|
+
new n(
|
|
3020
|
+
"Using and Managing Models",
|
|
3021
|
+
"How to leverage and maintain your models.",
|
|
3022
|
+
"section",
|
|
3023
|
+
// Section Title
|
|
3024
|
+
null
|
|
3025
|
+
),
|
|
3026
|
+
new n(
|
|
3027
|
+
"Imports",
|
|
3028
|
+
// Subsection Title
|
|
3029
|
+
"Models are composed using the `import` statement. You can import entire model source editors by their name (or alias if specified in the model config). This makes the concepts, properties, and datasources defined in that source available in the current editor.\n The standard library (`std`) is always available for import, providing common functions and traits.",
|
|
3030
|
+
"subsection",
|
|
3031
|
+
null
|
|
3032
|
+
),
|
|
3033
|
+
new n(
|
|
3034
|
+
// Code Example for Imports
|
|
3035
|
+
"Imports Example",
|
|
3036
|
+
`// Import concepts/properties defined in the 'lineitem' editor source
|
|
3037
|
+
import lineitem;
|
|
3038
|
+
|
|
3039
|
+
// Import geography traits from the standard library
|
|
3040
|
+
import std.geography;
|
|
3041
|
+
|
|
3042
|
+
// Import concepts from 'customer_details' editor source, aliasing it to 'cust'
|
|
3043
|
+
import customer_details as cust;
|
|
3044
|
+
|
|
3045
|
+
// Now you can use concepts like:
|
|
3046
|
+
// lineitem.order.id
|
|
3047
|
+
// std.geography.us_state_short
|
|
3048
|
+
// cust.customer.address`,
|
|
3049
|
+
"code",
|
|
3050
|
+
null
|
|
3051
|
+
),
|
|
3052
|
+
new n(
|
|
3053
|
+
"Constants",
|
|
3054
|
+
// Subsection Title
|
|
3055
|
+
"The simplest form of a concept is a constant, defined using `const`. Constants do not require a datasource as their value is fixed directly in the definition. They are useful for defining fixed values, parameters, or variables within scripts or queries.",
|
|
3056
|
+
"subsection",
|
|
3057
|
+
null
|
|
3058
|
+
),
|
|
3059
|
+
new n(
|
|
3060
|
+
// Code Example for Constants
|
|
3061
|
+
"Constants Example",
|
|
3062
|
+
`const pi <- 3.14;
|
|
3063
|
+
const company_founding_year <- 2023;
|
|
3064
|
+
|
|
3065
|
+
select pi * 2 as circumference_ratio;`,
|
|
3066
|
+
"code",
|
|
3067
|
+
null
|
|
3068
|
+
),
|
|
3069
|
+
new n(
|
|
3070
|
+
"Creating Model Sources",
|
|
3071
|
+
// Subsection Title
|
|
3072
|
+
"Any Trilogy editor can be designated as a source file for a model. This is typically done through the Trilogy UI or configuration. Once an editor is part of a model, its definitions become importable.",
|
|
3073
|
+
"subsection",
|
|
3074
|
+
null
|
|
3075
|
+
),
|
|
3076
|
+
new n(
|
|
3077
|
+
// Tip paragraph
|
|
3078
|
+
"Tip: Generating Models",
|
|
3079
|
+
'You can quickly create a basic model source from a database table. When browsing tables in a connection, use the "Create model from table" action. This generates an editor with properties mapped to columns and a basic datasource.',
|
|
3080
|
+
"tip",
|
|
3081
|
+
// Use 'tip' type
|
|
3082
|
+
null
|
|
3083
|
+
),
|
|
3084
|
+
new n(
|
|
3085
|
+
"Model Parsing and Validation",
|
|
3086
|
+
// Subsection Title
|
|
3087
|
+
"Models are parsed and validated to ensure correctness and build the metadata necessary for queries and tooling. This typically happens automatically when a query referencing the model is run. You can also trigger parsing manually (e.g., via a 'Parse Model' button in the UI). Parsing checks syntax, type consistency, and resolves imports. Errors found during parsing will be reported, often linking back to the specific editor and line number causing the issue.",
|
|
3088
|
+
"subsection",
|
|
3089
|
+
null
|
|
3090
|
+
),
|
|
3091
|
+
new n(
|
|
3092
|
+
"Standard Library",
|
|
3093
|
+
// Subsection Title
|
|
3094
|
+
"Trilogy includes a standard library, typically available under the `std` namespace (e.g., `import std;` or `import std.math;`). This library provides common functions, operators, and useful metadata traits (like geo-location, currency, etc.).",
|
|
3095
|
+
"subsection",
|
|
3096
|
+
null
|
|
3097
|
+
),
|
|
3098
|
+
new n(
|
|
3099
|
+
// Tip paragraph
|
|
3100
|
+
"Tip: Standard Library",
|
|
3101
|
+
"Review the documentation for the standard library (`std`) to discover always-available functions and traits you can use in your models and queries.",
|
|
3102
|
+
"tip",
|
|
3103
|
+
// Use 'tip' type
|
|
3104
|
+
null
|
|
3105
|
+
)
|
|
3106
|
+
],
|
|
3107
|
+
"Modeling"
|
|
3108
|
+
), yn = new Ce("Trilogy Reference", [
|
|
3109
|
+
new M("Overview/Goals", [
|
|
3110
|
+
new n(
|
|
3111
|
+
"Introduction",
|
|
3112
|
+
"Trilogy is a new, SQL-derived language that compiles to SQL. Trilogy Studio provides you with both native Trilogy and SQL editors, allowing you to query your data in a way that is more expressive and easier to maintain than traditional SQL."
|
|
3113
|
+
),
|
|
3114
|
+
new n(
|
|
3115
|
+
"Introduction",
|
|
3116
|
+
"Trilogy aspires to simplify hard parts of SQL, keep and enhance the good, incentivize the best, and add modern reusability, type-checking, and ergonomics. It should be approachable to query by someone that knows only SQL, and easy to model for someone familiar with SQL or Python."
|
|
3117
|
+
),
|
|
3118
|
+
new n(
|
|
3119
|
+
"Iterative SQL Development",
|
|
3120
|
+
"To capture the iterative SQL development loop, Trilogy directly embeds a lightweight metadata definition syntax, allowing you to query and evolve the semantic layer in the same tool - and even in the same query session. This definition language (semantic layer, ERD, etc.) provides static typing/enforcement, and handles joins [1-1, 1-many, many-to-1], aggregations, filtering, and nulls automatically."
|
|
3121
|
+
),
|
|
3122
|
+
new n(
|
|
3123
|
+
"Trilogy Query Structure",
|
|
3124
|
+
"Let's take a look. Standard Trilogy reads like SQL SELECT, without the FROM or GROUP BY clauses."
|
|
3125
|
+
),
|
|
3126
|
+
new n(
|
|
3127
|
+
"Trilogy Query Example",
|
|
3128
|
+
`WHERE
|
|
3129
|
+
store_sales.date.year=2001
|
|
3130
|
+
AND store_sales.date.month_of_year=1
|
|
3131
|
+
AND store_sales.item.current_price > 1.2 * avg(store_sales.item.current_price) BY store_sales.item.category
|
|
3132
|
+
SELECT
|
|
3133
|
+
store_sales.customer.state,
|
|
3134
|
+
count(store_sales.customer.id) AS customer_count
|
|
3135
|
+
HAVING
|
|
3136
|
+
customer_count > 10
|
|
3137
|
+
ORDER BY
|
|
3138
|
+
customer_count ASC NULLS FIRST,
|
|
3139
|
+
store_sales.customer.state ASC NULLS FIRST
|
|
3140
|
+
LIMIT 100;`,
|
|
3141
|
+
"code"
|
|
3142
|
+
),
|
|
3143
|
+
new n(
|
|
3144
|
+
"How Trilogy Differs from SQL",
|
|
3145
|
+
"Those aren't the only clauses to be gone - Trilogy removes the need for joins - and even tables - via the metadata layer. Information about how to join tables is encoded once and used automatically if required. Definitions look like creating a SQL table, but columns are bound to an additionally abstracted concept label, not raw datatypes. This enables Trilogy to dynamically traverse joins when needed."
|
|
3146
|
+
),
|
|
3147
|
+
new n(
|
|
3148
|
+
"How Trilogy Differs from SQL",
|
|
3149
|
+
`key order_id int;
|
|
3150
|
+
key store_id int;
|
|
3151
|
+
property store_id.store_name string;
|
|
3152
|
+
|
|
3153
|
+
datasource orders (
|
|
3154
|
+
order_id: order_id,
|
|
3155
|
+
store_id: store_id
|
|
3156
|
+
)
|
|
3157
|
+
grain (order_id)
|
|
3158
|
+
address tbl_orders;
|
|
3159
|
+
|
|
3160
|
+
datasource stores (
|
|
3161
|
+
store_id: store_id
|
|
3162
|
+
store_name: store_name
|
|
3163
|
+
)
|
|
3164
|
+
grain (store_id)
|
|
3165
|
+
address tbl_stores;
|
|
3166
|
+
`,
|
|
3167
|
+
"code"
|
|
3168
|
+
),
|
|
3169
|
+
new n(
|
|
3170
|
+
"The Value of Trilogy",
|
|
3171
|
+
"But writing out that datasource is work - a table can be queried quickly because someone else set it up. Trilogy provides the same experience through model imports. It's expected that datasources will be written once, and reused many times. Trilogy can be shared and imported through .preql files using a python-like import syntax."
|
|
3172
|
+
),
|
|
3173
|
+
new n(
|
|
3174
|
+
"The Value of Trilogy",
|
|
3175
|
+
"Complex models spanning dozens of tables can be imported with a single line."
|
|
3176
|
+
),
|
|
3177
|
+
new n(
|
|
3178
|
+
"Trilogy Equivalent",
|
|
3179
|
+
`import concepts.sales AS sales;
|
|
3180
|
+
SELECT
|
|
3181
|
+
sales.territory_name,
|
|
3182
|
+
sales.sub_total,
|
|
3183
|
+
sales.total_taxes,
|
|
3184
|
+
sales.total_sales
|
|
3185
|
+
ORDER BY
|
|
3186
|
+
sales.territory_name DESC;`,
|
|
3187
|
+
"code"
|
|
3188
|
+
),
|
|
3189
|
+
new n(
|
|
3190
|
+
"How Trilogy Works",
|
|
3191
|
+
"Explore the rest of the reference documentation for more details on how Trilogy works and explore these concepts in more detail."
|
|
3192
|
+
)
|
|
3193
|
+
]),
|
|
3194
|
+
new M("Code", [
|
|
3195
|
+
new n(
|
|
3196
|
+
"How Trilogy Works",
|
|
3197
|
+
`Studio and dependent code is open-source under the MIT license. The code is available on GitHub at the following locations:
|
|
3198
|
+
<li><a href='https://github.com/trilogy-data/trilogy-studio-core' target='_blank'>trilogy-studio-core</a> - the core code for the studio, including the language server and query editor.</li>
|
|
3199
|
+
<li><a href='https://github.com/trilogy-data/pytrilogy' target='_blank'>pytrilogy</a> - reference implementation of Trilogy language parsing/execution.</li>`
|
|
3200
|
+
),
|
|
3201
|
+
new n(
|
|
3202
|
+
"How Trilogy Works",
|
|
3203
|
+
`Stars appreciated, contributions welcome! If you find a bug, please file an issue on the relevant repository.
|
|
3204
|
+
`
|
|
3205
|
+
)
|
|
3206
|
+
]),
|
|
3207
|
+
new M("Querying Data", [
|
|
3208
|
+
new n(
|
|
3209
|
+
"SELECT Without FROM, JOIN, or GROUP BY",
|
|
3210
|
+
"In Trilogy, you write queries without explicitly specifying tables, joins, or grouping."
|
|
3211
|
+
),
|
|
3212
|
+
new n(
|
|
3213
|
+
"Example Query",
|
|
3214
|
+
`SELECT
|
|
3215
|
+
product_line,
|
|
3216
|
+
revenue,
|
|
3217
|
+
revenue_from_top_customers,
|
|
3218
|
+
revenue_from_top_customers / revenue AS revenue_from_top_customers_pct
|
|
3219
|
+
WHERE
|
|
3220
|
+
product_line IN ('widgets', 'doodads');`,
|
|
3221
|
+
"code"
|
|
3222
|
+
),
|
|
3223
|
+
new n(
|
|
3224
|
+
"SELECT Without FROM, JOIN, or GROUP BY",
|
|
3225
|
+
"Queries begin with a SELECT, and can include WHERE, HAVING, ORDER BY, and LIMIT clauses. Trilogy automatically handles joins and grouping based on the defined model."
|
|
3226
|
+
),
|
|
3227
|
+
new n(
|
|
3228
|
+
"SELECT Without FROM, JOIN, or GROUP BY",
|
|
3229
|
+
"Like SQL, the where clause filters results *before* the selection, and the having *after*. The order by clause sorts the results, and the limit clause restricts the number of rows returned."
|
|
3230
|
+
),
|
|
3231
|
+
new n(
|
|
3232
|
+
"SELECT Without FROM, JOIN, or GROUP BY",
|
|
3233
|
+
"This query would restrict data to red products in Massachsusetts, then select the product name and aggregate total sales within the filter state, further filter to only those with total sales greater than 1000, ordering by total sales in descending order, and limiting the results to 10 rows."
|
|
3234
|
+
),
|
|
3235
|
+
new n(
|
|
3236
|
+
"Example Query",
|
|
3237
|
+
`WHERE product_name like '%red%' and sales.state = 'MA'
|
|
3238
|
+
SELECT
|
|
3239
|
+
product_name,
|
|
3240
|
+
sum(sales) AS total_sales
|
|
3241
|
+
HAVING total_sales > 1000
|
|
3242
|
+
ORDER BY
|
|
3243
|
+
total_sales DESC
|
|
3244
|
+
LIMIT 10;`,
|
|
3245
|
+
"code"
|
|
3246
|
+
),
|
|
3247
|
+
new n(
|
|
3248
|
+
"SELECT Without FROM, JOIN, or GROUP BY",
|
|
3249
|
+
"All concepts and outputs must be explicitly named, using AS to bind any transformation. The having clause and order clause can only reference fields in the select list, while the where clause can reference any field in the model."
|
|
3250
|
+
)
|
|
3251
|
+
]),
|
|
3252
|
+
new M("Syntax", [
|
|
3253
|
+
new n(
|
|
3254
|
+
"Basic SELECT Statement",
|
|
3255
|
+
"A Trilogy statement consists of one or more lines ending in a semicolon. Trilogy follows SQL syntax closely but removes redundant features like explicit joins and the FROM clause. A basic select could look like this:"
|
|
3256
|
+
),
|
|
3257
|
+
new n(
|
|
3258
|
+
"Example",
|
|
3259
|
+
`SELECT
|
|
3260
|
+
1 -> constant_one,
|
|
3261
|
+
1 AS constant_one_2,
|
|
3262
|
+
'2' -> constant_string_two;`,
|
|
3263
|
+
"code"
|
|
3264
|
+
),
|
|
3265
|
+
new n(
|
|
3266
|
+
"Select",
|
|
3267
|
+
"The general form of a select statement below. The where clause can also go after, but is idiomatically first."
|
|
3268
|
+
),
|
|
3269
|
+
new n(
|
|
3270
|
+
"Select",
|
|
3271
|
+
`where?
|
|
3272
|
+
select
|
|
3273
|
+
select_list
|
|
3274
|
+
having?
|
|
3275
|
+
order_by?
|
|
3276
|
+
limit?`,
|
|
3277
|
+
"code"
|
|
3278
|
+
),
|
|
3279
|
+
new n(
|
|
3280
|
+
"select_list",
|
|
3281
|
+
"A select list has one or more expressions, each with an optional alias. Aliased fields can be immediately referenced."
|
|
3282
|
+
),
|
|
3283
|
+
new n(
|
|
3284
|
+
"select_list",
|
|
3285
|
+
`select_item ("," select_item)* ","?
|
|
3286
|
+
select_item: expression "->" IDENTIFIER ","?`,
|
|
3287
|
+
"code"
|
|
3288
|
+
),
|
|
3289
|
+
new n(
|
|
3290
|
+
"where",
|
|
3291
|
+
"The where clause restricts data before the select expression. It can reference any field in the model, not just those in the select list. It cannot reference aggregates calculated in the select."
|
|
3292
|
+
),
|
|
3293
|
+
new n("where", 'where_clause: where expression ("," expression)* ","?', "code"),
|
|
3294
|
+
new n(
|
|
3295
|
+
"having",
|
|
3296
|
+
"The having clause restricts data after the select expression. It can reference any field in the select list, including aggregates."
|
|
3297
|
+
),
|
|
3298
|
+
new n("having", 'having_clause: where expression ("," expression)* ","?', "code"),
|
|
3299
|
+
new n(
|
|
3300
|
+
"Select List",
|
|
3301
|
+
"A multiselect statement can merge multiple select statements into a unified rowset by defining output keys to align on. This is rarely required, but can be used to produce certain outputs."
|
|
3302
|
+
),
|
|
3303
|
+
new n(
|
|
3304
|
+
"Multi-Select",
|
|
3305
|
+
`where? select_statement ( "merge" select_statement)+
|
|
3306
|
+
"align"i align_clause
|
|
3307
|
+
having?
|
|
3308
|
+
order_by?
|
|
3309
|
+
limit?`,
|
|
3310
|
+
"code"
|
|
3311
|
+
),
|
|
3312
|
+
new n(
|
|
3313
|
+
"Align Clause",
|
|
3314
|
+
`align_item: IDENTIFIER ":" IDENTIFIER ("," IDENTIFIER)* ","?
|
|
3315
|
+
align_clause: align_item ("," align_item)* ","?`,
|
|
3316
|
+
"code"
|
|
3317
|
+
),
|
|
3318
|
+
new n("datasource text", "A datasource defines a warehouse table to pull data from"),
|
|
3319
|
+
new n(
|
|
3320
|
+
"Datasource",
|
|
3321
|
+
`datasource IDENTIFIER
|
|
3322
|
+
( column_assignment_list )
|
|
3323
|
+
grain_clause?
|
|
3324
|
+
complete_for_clause?
|
|
3325
|
+
(address='string' | query='''string''')
|
|
3326
|
+
`,
|
|
3327
|
+
"code"
|
|
3328
|
+
),
|
|
3329
|
+
new n("Merge", "merge_statement: merge IDENTIFIER (, IDENTIFIER)_ ,? comment_", "code"),
|
|
3330
|
+
new n(
|
|
3331
|
+
"Import",
|
|
3332
|
+
"import_statement: import (IDENTIFIER .) * IDENTIFIER as IDENTIFIER",
|
|
3333
|
+
"code"
|
|
3334
|
+
),
|
|
3335
|
+
new n(
|
|
3336
|
+
"Function Definition",
|
|
3337
|
+
"function_derivation: def ( (IDENTIFIER ,)* ) -> EXPR;",
|
|
3338
|
+
"code"
|
|
3339
|
+
)
|
|
3340
|
+
]),
|
|
3341
|
+
new M("Concepts", [
|
|
3342
|
+
new n(
|
|
3343
|
+
"What Are Concepts?",
|
|
3344
|
+
"Concepts are core semantic building blocks in Trilogy. They represent keys, properties, or metrics: Keys (unique identifiers), Properties (additional values), and Metrics (aggregatable values)."
|
|
3345
|
+
),
|
|
3346
|
+
new n(
|
|
3347
|
+
"Example",
|
|
3348
|
+
`key product_id int;# the unique identifier of a product
|
|
3349
|
+
property product_id.product_name string;# the name of a product
|
|
3350
|
+
metric product_count <-count(product.id); # the count of products`,
|
|
3351
|
+
"code"
|
|
3352
|
+
),
|
|
3353
|
+
new n(
|
|
3354
|
+
"Keys",
|
|
3355
|
+
"Keys represent a unique conceptual grain. A combination of one or more keys will uniquely identify a set of properties. If familiar with databases, think of them as your primary/foreign keys. More generally, you can thing of them as something like a passport number, a product ID, a URL, or a stock ticker - a unique shorthand for an entity."
|
|
3356
|
+
),
|
|
3357
|
+
new n(
|
|
3358
|
+
"Key Syntax",
|
|
3359
|
+
"Keys have straight forward syntax; the keyword, the name, and the type."
|
|
3360
|
+
),
|
|
3361
|
+
new n("Example", "key product_id int;# the unique identifier of a product", "code"),
|
|
3362
|
+
new n("Properties", "Properties are values associated with one or more keys"),
|
|
3363
|
+
new n(
|
|
3364
|
+
"Property Syntax",
|
|
3365
|
+
'Properties have a richer syntax than keys - they require the associated keys, within <>, before the property name.. syntax: `"property" <key1, key2, ..> "." IDENTIFIER type;`'
|
|
3366
|
+
),
|
|
3367
|
+
new n(
|
|
3368
|
+
"Single Key Property",
|
|
3369
|
+
'A property can be associated with a single key with a shorthand syntax without the full <> group. syntax: `"property" key "." IDENTIFIER type;`',
|
|
3370
|
+
"tip"
|
|
3371
|
+
),
|
|
3372
|
+
new n(
|
|
3373
|
+
"code",
|
|
3374
|
+
"property product_id.product_name string;# the name of a product",
|
|
3375
|
+
"code"
|
|
3376
|
+
),
|
|
3377
|
+
new n(
|
|
3378
|
+
"Metrics",
|
|
3379
|
+
"Metrics are aggregatable values, and can come from properties, keys, or other metrics. Like keys, they have a grain, though this is inferred from the aggregation"
|
|
3380
|
+
),
|
|
3381
|
+
new n(
|
|
3382
|
+
"Example",
|
|
3383
|
+
"metric product_count <-count(product.id); # the count of products",
|
|
3384
|
+
"code"
|
|
3385
|
+
),
|
|
3386
|
+
new n(
|
|
3387
|
+
"Dynamic Grain",
|
|
3388
|
+
"A basic metric - like `metric product_count <- count(product_id);` - will have a dynamic aggregation level that corresponds to the query it is used in."
|
|
3389
|
+
),
|
|
3390
|
+
new n(
|
|
3391
|
+
"Static Grain",
|
|
3392
|
+
"A metric can be created by an aggregation with a defined grain, ex: `metric product_count <-count(product_id) by store;`, in which case it behaves similar to a property. However, where conditions for a select will still be pushed inside these aggregates."
|
|
3393
|
+
)
|
|
3394
|
+
]),
|
|
3395
|
+
new M("Datasources and Joins", [
|
|
3396
|
+
new n(
|
|
3397
|
+
"Defining Datasources",
|
|
3398
|
+
"A table in a warehouse is defined as a dataset with each column bound to a concept. When datasources share a common key, trilogy can join between them. Not all joins are equal; some are 1-1, 1-many, or many-1. Trilogy handles these by looking at the grain of each datasource involved. If a join is on a key other than the grain of the sources, the output may need to be grouped up to avoid duplication. "
|
|
3399
|
+
),
|
|
3400
|
+
new n(
|
|
3401
|
+
"Partial Keys",
|
|
3402
|
+
"A table may not have all values of a key. For example, a list of orders may not have every customer ID, as not all customers may have placed orders. A datasource can be defined with a key marked as partial by prefixing the ~ character. Trilogy will ensure that partial sources are used on the right side of an outer join to avoid implicitly reducing results."
|
|
3403
|
+
),
|
|
3404
|
+
new n(
|
|
3405
|
+
"Example",
|
|
3406
|
+
`datasource sales (
|
|
3407
|
+
order_id: orders.id,
|
|
3408
|
+
cu_id: ~customers.id,
|
|
3409
|
+
revenue: orders.revenue
|
|
3410
|
+
)
|
|
3411
|
+
grain (orders.id)
|
|
3412
|
+
address warehouse.sales;
|
|
3413
|
+
|
|
3414
|
+
datasource customers (
|
|
3415
|
+
customer_id: customers.id,
|
|
3416
|
+
name: customers.name
|
|
3417
|
+
)
|
|
3418
|
+
grain (customers.id)
|
|
3419
|
+
address warehouse.customers;`,
|
|
3420
|
+
"code"
|
|
3421
|
+
),
|
|
3422
|
+
new n(
|
|
3423
|
+
"Partial Keys",
|
|
3424
|
+
'A query of the form `SELECT sum(orders.revenue), customer.name` would mean "get all customer names, and their total revenue". This would be resolved via a join through customer.id, with the order table being on the right side of the join, to ensure that all customers were returned regardless of if they placed an order.'
|
|
3425
|
+
)
|
|
3426
|
+
]),
|
|
3427
|
+
new M("Grains and Aggregation", [
|
|
3428
|
+
new n(
|
|
3429
|
+
"What Is a Grain?",
|
|
3430
|
+
"A grain represents the unique combination of keys. Tables and aggregations both have grains, which determine the minimum keys required to uniquely identify a row of data. For example, finding the total sales by customer id, anme, and address would be an aggregation to the grain of a customer id, no matter how many other customer properties are included. Properties of a key are implicitly dropped from any grain that includes that key, though a grain without the key associated with a property will include that property in the grain."
|
|
3431
|
+
),
|
|
3432
|
+
new n(
|
|
3433
|
+
"Example",
|
|
3434
|
+
`SELECT
|
|
3435
|
+
order_date,
|
|
3436
|
+
order_year,
|
|
3437
|
+
SUM(total_spent) AS total_revenue;`,
|
|
3438
|
+
"code"
|
|
3439
|
+
),
|
|
3440
|
+
new n(
|
|
3441
|
+
"What Is a Grain?",
|
|
3442
|
+
"This query would aggregate revenue to the grain of order_date, as order year is a property of order date."
|
|
3443
|
+
)
|
|
3444
|
+
]),
|
|
3445
|
+
pn,
|
|
3446
|
+
mn,
|
|
3447
|
+
new M("Custom Functions", [
|
|
3448
|
+
new n(
|
|
3449
|
+
"Defining Functions",
|
|
3450
|
+
"Custom functions can be used to extend the language with reusable code macros. Functions are defined using the def keyword and have a list of arguments and are mapped to an expression. Any argument alias will be locally scoped within the function, but external concepts can be referenced as well."
|
|
3451
|
+
),
|
|
3452
|
+
new n(
|
|
3453
|
+
"Defining Functions",
|
|
3454
|
+
"This function will multiple the input concept by itself and then by whatever the value of the global scale_factor is. Note the @ - custom functions references require the @ prefix."
|
|
3455
|
+
),
|
|
3456
|
+
new n(
|
|
3457
|
+
"Example",
|
|
3458
|
+
`const scale_factor<-2;
|
|
3459
|
+
def square_scale(x) -> x * x *scale_factor;
|
|
3460
|
+
|
|
3461
|
+
SELECT
|
|
3462
|
+
number,
|
|
3463
|
+
@square_scale(number) AS squared
|
|
3464
|
+
;`,
|
|
3465
|
+
"code"
|
|
3466
|
+
),
|
|
3467
|
+
new n(
|
|
3468
|
+
"Defining Functions",
|
|
3469
|
+
"Functions may have optional defaults by adding an `= value` after the argument name."
|
|
3470
|
+
),
|
|
3471
|
+
new n(
|
|
3472
|
+
"Example",
|
|
3473
|
+
`def pretty_percent(x, digits=2) -> round(x*100, digits)::string || '%';
|
|
3474
|
+
|
|
3475
|
+
const number<-.4555;
|
|
3476
|
+
|
|
3477
|
+
SELECT
|
|
3478
|
+
number,
|
|
3479
|
+
@pretty_percent(number) AS percent,
|
|
3480
|
+
@pretty_percent(number, 3) AS three_percent
|
|
3481
|
+
;`,
|
|
3482
|
+
"code"
|
|
3483
|
+
)
|
|
3484
|
+
]),
|
|
3485
|
+
hn
|
|
3486
|
+
]), fn = new Ce("Terms of Service", [
|
|
3487
|
+
new M("Terms of Service", [
|
|
3488
|
+
new n("Last Updated", "February 22, 2025"),
|
|
3489
|
+
new n(
|
|
3490
|
+
"Service Description",
|
|
3491
|
+
'Trilogy Studio (referred to as "IDE" henceforth) enables users to interact with public data or data in databases they own. The IDE communicates with non-user services only to do basic telemetry and preprocessing of Trilogy code using the default language server (if a local one is not configured). The primary purpose of this preprocessing is to generate SQL to be returned to the browser for execution.',
|
|
3492
|
+
"section"
|
|
3493
|
+
),
|
|
3494
|
+
new n(
|
|
3495
|
+
"Data Privacy and Security",
|
|
3496
|
+
"No Data Collection: We do not collect, store, or process any of your data or database contents, beyond metadata provided in the model definition. All database interactions occur directly between your browser and your database through client-side JavaScript.",
|
|
3497
|
+
"section"
|
|
3498
|
+
),
|
|
3499
|
+
new n(
|
|
3500
|
+
"Local Processing",
|
|
3501
|
+
"All code execution and data processing occur locally in your browser. We have no access to your database credentials, queries, or results.",
|
|
3502
|
+
"subsection"
|
|
3503
|
+
),
|
|
3504
|
+
new n(
|
|
3505
|
+
"User Responsibility",
|
|
3506
|
+
"You are solely responsible for securing your database connections, managing database credentials, implementing appropriate security measures, backing up your data, and ensuring compliance with applicable data protection laws.",
|
|
3507
|
+
"subsection"
|
|
3508
|
+
),
|
|
3509
|
+
new n(
|
|
3510
|
+
"Service Limitations",
|
|
3511
|
+
"Browser Limitations: The IDE is subject to your browser's technical limitations, including memory constraints and processing capabilities.",
|
|
3512
|
+
"section"
|
|
3513
|
+
),
|
|
3514
|
+
new n(
|
|
3515
|
+
"Connection Requirements",
|
|
3516
|
+
"Stable internet connection required for IDE access. Database connectivity depends on your database configuration and network conditions.",
|
|
3517
|
+
"subsection"
|
|
3518
|
+
),
|
|
3519
|
+
new n(
|
|
3520
|
+
"User Obligations",
|
|
3521
|
+
"You agree to use the IDE in compliance with applicable laws, not attempt to circumvent browser security measures, not use the IDE for illegal or unauthorized purposes, maintain the security of your database credentials, and not redistribute or modify the IDE code without permission.",
|
|
3522
|
+
"section"
|
|
3523
|
+
),
|
|
3524
|
+
new n(
|
|
3525
|
+
"Disclaimers",
|
|
3526
|
+
'Service Availability: We provide the IDE "as is" and make no guarantees about its availability or functionality.',
|
|
3527
|
+
"section"
|
|
3528
|
+
),
|
|
3529
|
+
new n(
|
|
3530
|
+
"Security Disclaimer",
|
|
3531
|
+
"While we implement standard security measures in our code, we cannot guarantee the security of your database connections or local environment.",
|
|
3532
|
+
"subsection"
|
|
3533
|
+
),
|
|
3534
|
+
new n(
|
|
3535
|
+
"Liability Limitations",
|
|
3536
|
+
"We are not liable for data loss or corruption, database connection issues, browser performance problems, security breaches in your database, misuse of the IDE, or consequential damages.",
|
|
3537
|
+
"section"
|
|
3538
|
+
),
|
|
3539
|
+
new n(
|
|
3540
|
+
"User Rights",
|
|
3541
|
+
"You retain all rights to your code, your database, your data, and any outputs generated using the IDE.",
|
|
3542
|
+
"subsection"
|
|
3543
|
+
),
|
|
3544
|
+
new n(
|
|
3545
|
+
"Modifications",
|
|
3546
|
+
"We reserve the right to modify the IDE functionality, these Terms of Service, and supported features and libraries.",
|
|
3547
|
+
"section"
|
|
3548
|
+
),
|
|
3549
|
+
new n("Termination", "You may stop using the IDE at any time.", "section"),
|
|
3550
|
+
new n(
|
|
3551
|
+
"Contact",
|
|
3552
|
+
"For questions about these terms, please create an issue on the github repository <a href='https://github.com/trilogy-data/trilogy-studio-core'>here</a>.",
|
|
3553
|
+
"section"
|
|
3554
|
+
),
|
|
3555
|
+
new n(
|
|
3556
|
+
"Agreement",
|
|
3557
|
+
"By using the IDE, you agree to these terms and conditions.",
|
|
3558
|
+
"conclusion"
|
|
3559
|
+
)
|
|
3560
|
+
])
|
|
3561
|
+
]), bo = [
|
|
3562
|
+
new Ce("Studio", [
|
|
3563
|
+
un,
|
|
3564
|
+
ln,
|
|
3565
|
+
cn,
|
|
3566
|
+
dn,
|
|
3567
|
+
new M("Functionality", [
|
|
3568
|
+
new n(
|
|
3569
|
+
"Tip",
|
|
3570
|
+
"Trilogy Studio is a statically hosted website that uses a mix of precompiled scripts and dynamic imports for some connections to reduce bundle size."
|
|
3571
|
+
),
|
|
3572
|
+
new n(
|
|
3573
|
+
"Tip",
|
|
3574
|
+
"For Trilogy specific features, the studio relies on a pseudo-language server (there is a proper LSP available for vs-code, used in the vs-code extension, as well). By default this will use a cloud-hosted backend but studio can be configured to use a local address as well. "
|
|
3575
|
+
),
|
|
3576
|
+
new n(
|
|
3577
|
+
"Tip",
|
|
3578
|
+
"Trilogy Studio requires internet access to download certain dependencies - such as DuckDB WASM - on demand when utilizing a relevant connection. It can then be used offline if a local backend server is running. A pure offline option may be available in the future.",
|
|
3579
|
+
"tip"
|
|
3580
|
+
)
|
|
3581
|
+
]),
|
|
3582
|
+
new M("Navigation", [
|
|
3583
|
+
new n(
|
|
3584
|
+
"Navigation",
|
|
3585
|
+
"On desktop, Trilogy Studio uses a left-hand navigation bar, a sidebar with context, and a main pane (which may be split) to present information. The sidebar is further split into sections; the first icons change the sidebar for the query editor, while the next section configures entirely new main screen experiences. Configuration/profile are accessible at the bottom. On mobile, Trilogy will instead use a top menu to access a navigation screen, and the main display will show only one particular field at a time."
|
|
3586
|
+
),
|
|
3587
|
+
new n(
|
|
3588
|
+
"Tip",
|
|
3589
|
+
"Don't forget to save! By default, Trilogy Studio stores your editors, connections, and models in browser local storage. Use the save buttons on the left-hand nav to record changes. You can also use the keyboard shortcuts Ctrl + S to save your work.",
|
|
3590
|
+
"tip"
|
|
3591
|
+
)
|
|
3592
|
+
]),
|
|
3593
|
+
new M("Querying", [
|
|
3594
|
+
new n(
|
|
3595
|
+
"Querying",
|
|
3596
|
+
"A core goal of Trilogy Studio is to enable seamless running of Trilogy against backends. Raw SQL is fully supported as well to help with debugging, diagnostics, and other development tasks."
|
|
3597
|
+
),
|
|
3598
|
+
new n(
|
|
3599
|
+
"Editor Selection",
|
|
3600
|
+
"When creating an editor, you will select a type. Trilogy editors run Trilogy code; SQL editors run SQL. An editor must be associated with a connection and may be associated with a model."
|
|
3601
|
+
),
|
|
3602
|
+
new n(
|
|
3603
|
+
"Query Execution",
|
|
3604
|
+
"When running Trilogy queries, your command will first go to a backend server to be parsed/type-checked, then the output SQL will be returned to the editor to be run as a normal SQL query. SQL editors will submit directly to the configured connection without the first parsing pass."
|
|
3605
|
+
)
|
|
3606
|
+
]),
|
|
3607
|
+
new M("Connections", [
|
|
3608
|
+
new n(
|
|
3609
|
+
"Connections",
|
|
3610
|
+
"Editors must be associated with a connection. A connection represents a particular underlying backend database resource. Many IDEs can share one connection, but only a single query can be executed on a connection at a single point in time. Connections are also associated with a model, which enables configuration of additional editors as semantic sources."
|
|
3611
|
+
),
|
|
3612
|
+
new n(
|
|
3613
|
+
"Managing Connections",
|
|
3614
|
+
"You can view current connections below. Edit the model associated with a connection by clicking the model name next to it (or 'set model' if not set). Connections will not automatically connect on startup by default; click the connection button to connect. This connection view is always accessible through the connections page on the left side."
|
|
3615
|
+
),
|
|
3616
|
+
new n("ConnectionList", "", "connections")
|
|
3617
|
+
]),
|
|
3618
|
+
new M("DuckDB", [
|
|
3619
|
+
new n(
|
|
3620
|
+
"DuckDB",
|
|
3621
|
+
"DuckDB is always available as an in-browser database using the DuckDB WASM integration. No authentication is required. DuckDB also natively supports csv uploads through a widget available on the connection view. Most community duckdb models will reference publically available CSV or parquet files."
|
|
3622
|
+
)
|
|
3623
|
+
]),
|
|
3624
|
+
new M("Bigquery", [
|
|
3625
|
+
new n(
|
|
3626
|
+
"Connections",
|
|
3627
|
+
'Bigquery is supported through Oauth authentication as your identity. If you wish to use a service key file, please upvote this github issue: <a href="https://github.com/trilogy-data/trilogy-studio-core/issues/33" target="_blank">BQ Service Account Support</a>.'
|
|
3628
|
+
)
|
|
3629
|
+
]),
|
|
3630
|
+
new M("Snowflake", [
|
|
3631
|
+
new n(
|
|
3632
|
+
"Connections",
|
|
3633
|
+
'Snowflake is supported with private key authentication. Read more at this link: <a href="https://docs.snowflake.com/en/user-guide/key-pair-auth" target="_blank">Snowflake Private Key Pairs</a>. You will need to provide the private key to connect after configuring your user with the public key portion. The rest of the authentication header can be derived from this. Remember to use caution of saving this key.'
|
|
3634
|
+
)
|
|
3635
|
+
]),
|
|
3636
|
+
new M("Scheduling", [
|
|
3637
|
+
new n(
|
|
3638
|
+
"Scheduling",
|
|
3639
|
+
'Scheduling dashboards/scripts is a future feature. Please upvote this github issue: <a href="https://github.com/trilogy-data/trilogy-studio-core/issues/75" target="_blank">Scheduling</a>.'
|
|
3640
|
+
)
|
|
3641
|
+
])
|
|
3642
|
+
]),
|
|
3643
|
+
yn,
|
|
3644
|
+
new Ce("Privacy And Data", [
|
|
3645
|
+
new M("Privacy Policy", [
|
|
3646
|
+
new n("Last Updated", "February 22, 2025"),
|
|
3647
|
+
new n(
|
|
3648
|
+
"Introduction",
|
|
3649
|
+
"This Privacy Policy explains how Trilogy Studio handles your information. While most processing occurs in your browser, we utilize some external services to enhance your development experience.",
|
|
3650
|
+
"section"
|
|
3651
|
+
),
|
|
3652
|
+
new n(
|
|
3653
|
+
"Information We Collect",
|
|
3654
|
+
"Telemetry: We collect feature usage counts and patterns and coarse browser/geographic information to inform product decision and system performance using GoatTrack. This data is anonymous and does not include any personally identifiable information. Telemetry can be disabled in settings.",
|
|
3655
|
+
"section"
|
|
3656
|
+
),
|
|
3657
|
+
new n(
|
|
3658
|
+
"Query Processing",
|
|
3659
|
+
"We process Trilogy queries to transform them to SQL based on your model inputs if you use the default query service. Results are returned to your browser for execution. No actual database connections or credentials are transmitted.",
|
|
3660
|
+
"subsection"
|
|
3661
|
+
),
|
|
3662
|
+
new n(
|
|
3663
|
+
"What We Don't Collect",
|
|
3664
|
+
"We do not collect database credentials, database contents, query results, personal information, full source code, or authentication tokens, or any other personal information. Please report any issues with this to the github repository.",
|
|
3665
|
+
"section"
|
|
3666
|
+
),
|
|
3667
|
+
new n(
|
|
3668
|
+
"Data Processing",
|
|
3669
|
+
"Query Execution: All database execution happens between your browser and remote service. Query results never pass through our servers.",
|
|
3670
|
+
"section"
|
|
3671
|
+
),
|
|
3672
|
+
new n(
|
|
3673
|
+
"Security Measures",
|
|
3674
|
+
"Any saved local credentials will be encrypted in storage using a passphrase or Chrome credential storage. See Stored Info for more details.",
|
|
3675
|
+
"section"
|
|
3676
|
+
),
|
|
3677
|
+
new n(
|
|
3678
|
+
"Children's Privacy",
|
|
3679
|
+
"Trilogy Studio is intended for adult data professionals.",
|
|
3680
|
+
"section"
|
|
3681
|
+
),
|
|
3682
|
+
new n(
|
|
3683
|
+
"International Data",
|
|
3684
|
+
"Telemetry data may cross borders. SQL compilation happens in the US with default query service (fly.io).",
|
|
3685
|
+
"section"
|
|
3686
|
+
),
|
|
3687
|
+
new n(
|
|
3688
|
+
"Changes to Privacy Policy",
|
|
3689
|
+
"We may update this policy to reflect new features or services, changed functionality, legal requirements, and security improvements.",
|
|
3690
|
+
"section"
|
|
3691
|
+
),
|
|
3692
|
+
new n(
|
|
3693
|
+
"Google Account",
|
|
3694
|
+
"Trilogy Studio uses Google OAuth to authenticate users when using a Google Bigquery Oauth connection. Trilogy Studio uses a token provided by Google to authenticate your account. Trilogy Studio only requests scopes required for Bigquery read/write access, and the token never leaves your browser. It is used to communicate directly with Bigquery with the google javascript client library."
|
|
3695
|
+
),
|
|
3696
|
+
new n(
|
|
3697
|
+
"Contact Information",
|
|
3698
|
+
"For privacy-related questions: please post on the github repository <a href='https://github.com/trilogy-data/trilogy-studio-core'>here</a>.",
|
|
3699
|
+
"section"
|
|
3700
|
+
),
|
|
3701
|
+
new n(
|
|
3702
|
+
"Legal Rights",
|
|
3703
|
+
"You retain all legal rights regarding your personal data, your source code, your database contents, and generated outputs.",
|
|
3704
|
+
"section"
|
|
3705
|
+
),
|
|
3706
|
+
new n(
|
|
3707
|
+
"Effective Date",
|
|
3708
|
+
"This policy is effective as of February 22, 2025.",
|
|
3709
|
+
"conclusion"
|
|
3710
|
+
)
|
|
3711
|
+
]),
|
|
3712
|
+
new M("Stored Info", [
|
|
3713
|
+
new n(
|
|
3714
|
+
"Local Data",
|
|
3715
|
+
"Trilogy Studio uses browser local storage for your editors and models. These do not leave your browser (except when a model is sent in to generate a query)."
|
|
3716
|
+
),
|
|
3717
|
+
new n(
|
|
3718
|
+
"Secret Storage",
|
|
3719
|
+
"For databases and LLM connections that require credentials (password, API Key) to access, Trilogy Studio can optionally also store them locally for reuse. [They will never be sent to a remote server]. It will attempt to use secure browser credential storage but will fall back to storing the secret in local browser storage encrypted with a pass phrase if the browser APIs are not available. Be careful storing credentials and be prepared to rotate - consider using a password manager."
|
|
3720
|
+
),
|
|
3721
|
+
new n(
|
|
3722
|
+
"Secret Storage",
|
|
3723
|
+
"Local storage is convenient, but if you have a browser secret manager, that is a great place to store secrets as well!",
|
|
3724
|
+
"tip"
|
|
3725
|
+
),
|
|
3726
|
+
new n(
|
|
3727
|
+
"Secret Storage",
|
|
3728
|
+
"A best practice is to use unique API tokens (such as for LLMs) and passwords in the studio, both to easily track usage and make rotation simple.",
|
|
3729
|
+
"tip"
|
|
3730
|
+
)
|
|
3731
|
+
]),
|
|
3732
|
+
new M("Google", [
|
|
3733
|
+
new n(
|
|
3734
|
+
"Google Account",
|
|
3735
|
+
"Trilogy Studio uses Google OAuth to authenticate users when using a Google Bigquery connection. Trilogy Studio uses a token provided by Google to authenticate your account through the interactive sign-in flow. Trilogy Studio only requests scopes required for Bigquery read/write access, and the token never leaves your browser. This token is only used to communicate directly with BigQuery with the standard google javascript client library."
|
|
3736
|
+
)
|
|
3737
|
+
]),
|
|
3738
|
+
new M("Snowflake", [
|
|
3739
|
+
new n(
|
|
3740
|
+
"Google Account",
|
|
3741
|
+
"Trilogy Studio supports private key authentication for Snowflake. You will need to provide the private key to connect after configuring your user with the public key portion in Snowflake directly. The rest of the authentication header can be derived from this."
|
|
3742
|
+
)
|
|
3743
|
+
]),
|
|
3744
|
+
new M("Telemetry Details", [
|
|
3745
|
+
new n(
|
|
3746
|
+
"Telemetry",
|
|
3747
|
+
`<a href="https://www.goatcounter.com/">GoatCounter</a> is used to collect anonymized
|
|
3748
|
+
statistics about usage in the studio, such as feature usage. No uniquely identifying information is collected, though the system type, browser, screensize and country are recorded. You can disable telemetry in the settings menu.`
|
|
3749
|
+
)
|
|
3750
|
+
])
|
|
3751
|
+
]),
|
|
3752
|
+
fn
|
|
3753
|
+
], gn = ae({
|
|
3754
|
+
name: "LLMProviderIcon",
|
|
3755
|
+
props: {
|
|
3756
|
+
providerType: {
|
|
3757
|
+
type: String,
|
|
3758
|
+
required: !0
|
|
3759
|
+
}
|
|
3760
|
+
}
|
|
3761
|
+
}), wn = { class: "provider-icon-container" }, Tn = {
|
|
3762
|
+
key: 0,
|
|
3763
|
+
class: "mdi mdi-alpha-c-circle",
|
|
3764
|
+
title: "Anthropic"
|
|
3765
|
+
}, bn = {
|
|
3766
|
+
key: 1,
|
|
3767
|
+
class: "mdi mdi-flash",
|
|
3768
|
+
title: "OpenAI"
|
|
3769
|
+
}, vn = {
|
|
3770
|
+
key: 2,
|
|
3771
|
+
class: "mdi mdi-weather-windy",
|
|
3772
|
+
title: "Mistral AI"
|
|
3773
|
+
}, En = {
|
|
3774
|
+
key: 3,
|
|
3775
|
+
class: "mdi mdi-google",
|
|
3776
|
+
title: "Google"
|
|
3777
|
+
}, Sn = {
|
|
3778
|
+
key: 4,
|
|
3779
|
+
class: "mdi mdi-robot",
|
|
3780
|
+
title: "LLM Provider"
|
|
3781
|
+
};
|
|
3782
|
+
function Cn(t, e, o, i, c, p) {
|
|
3783
|
+
return r(), l("div", wn, [
|
|
3784
|
+
t.providerType === "anthropic" ? (r(), l("i", Tn)) : t.providerType === "openai" ? (r(), l("i", bn)) : t.providerType === "mistral" ? (r(), l("i", vn)) : t.providerType === "google" ? (r(), l("i", En)) : (r(), l("i", Sn))
|
|
3785
|
+
]);
|
|
3786
|
+
}
|
|
3787
|
+
const kn = /* @__PURE__ */ X(gn, [["render", Cn], ["__scopeId", "data-v-9c73c667"]]), An = ae({
|
|
3788
|
+
name: "ContextMenu",
|
|
3789
|
+
props: {
|
|
3790
|
+
items: {
|
|
3791
|
+
type: Array,
|
|
3792
|
+
required: !0
|
|
3793
|
+
},
|
|
3794
|
+
position: {
|
|
3795
|
+
type: Object,
|
|
3796
|
+
default: () => ({ x: 0, y: 0 })
|
|
3797
|
+
},
|
|
3798
|
+
isVisible: {
|
|
3799
|
+
type: Boolean,
|
|
3800
|
+
default: !1
|
|
3801
|
+
},
|
|
3802
|
+
id: {
|
|
3803
|
+
type: String,
|
|
3804
|
+
default: ""
|
|
3805
|
+
}
|
|
3806
|
+
},
|
|
3807
|
+
emits: ["item-click", "close"],
|
|
3808
|
+
setup(t, { emit: e }) {
|
|
3809
|
+
const o = $(() => ({
|
|
3810
|
+
left: `${t.position.x}px`,
|
|
3811
|
+
top: `${t.position.y}px`
|
|
3812
|
+
})), i = (p) => {
|
|
3813
|
+
e("item-click", p), e("close");
|
|
3814
|
+
}, c = (p) => {
|
|
3815
|
+
t.isVisible && e("close");
|
|
3816
|
+
};
|
|
3817
|
+
return Ae(() => {
|
|
3818
|
+
setTimeout(() => {
|
|
3819
|
+
document.addEventListener("click", c);
|
|
3820
|
+
}, 300);
|
|
3821
|
+
}), Ue(() => {
|
|
3822
|
+
document.removeEventListener("click", c);
|
|
3823
|
+
}), {
|
|
3824
|
+
positionStyle: o,
|
|
3825
|
+
handleItemClick: i
|
|
3826
|
+
};
|
|
3827
|
+
}
|
|
3828
|
+
}), In = ["onClick"];
|
|
3829
|
+
function Pn(t, e, o, i, c, p) {
|
|
3830
|
+
return t.isVisible ? (r(), l("div", {
|
|
3831
|
+
key: 0,
|
|
3832
|
+
style: Oe(t.positionStyle),
|
|
3833
|
+
class: "context-menu"
|
|
3834
|
+
}, [
|
|
3835
|
+
(r(!0), l(pe, null, fe(t.items, (a) => (r(), l("div", {
|
|
3836
|
+
key: a.id,
|
|
3837
|
+
class: me(["context-menu-item", { danger: a.danger }]),
|
|
3838
|
+
onClick: (d) => t.handleItemClick(a)
|
|
3839
|
+
}, [
|
|
3840
|
+
a.icon ? (r(), l("i", {
|
|
3841
|
+
key: 0,
|
|
3842
|
+
class: me(`mdi ${a.icon}`)
|
|
3843
|
+
}, null, 2)) : I("", !0),
|
|
3844
|
+
s("span", null, j(a.label), 1)
|
|
3845
|
+
], 10, In))), 128))
|
|
3846
|
+
], 4)) : I("", !0);
|
|
3847
|
+
}
|
|
3848
|
+
const Rn = /* @__PURE__ */ X(An, [["render", Pn], ["__scopeId", "data-v-48938153"]]), Mn = ae({
|
|
3849
|
+
name: "LLMConnectionListItem",
|
|
3850
|
+
components: {
|
|
3851
|
+
SidebarItem: Re,
|
|
3852
|
+
LLMProviderIcon: kn,
|
|
3853
|
+
ConnectionRefresh: De,
|
|
3854
|
+
ConnectionStatusIcon: Pe,
|
|
3855
|
+
LoadingButton: Se,
|
|
3856
|
+
ContextMenu: Rn,
|
|
3857
|
+
Tooltip: Ee
|
|
3858
|
+
},
|
|
3859
|
+
props: {
|
|
3860
|
+
item: {
|
|
3861
|
+
type: Object,
|
|
3862
|
+
required: !0
|
|
3863
|
+
},
|
|
3864
|
+
isCollapsed: {
|
|
3865
|
+
type: Boolean,
|
|
3866
|
+
default: !0
|
|
3867
|
+
},
|
|
3868
|
+
isSelected: {
|
|
3869
|
+
type: Boolean,
|
|
3870
|
+
default: !1
|
|
3871
|
+
}
|
|
3872
|
+
},
|
|
3873
|
+
emits: [
|
|
3874
|
+
"toggle",
|
|
3875
|
+
"setActive",
|
|
3876
|
+
"refresh",
|
|
3877
|
+
"updateApiKey",
|
|
3878
|
+
"updateModel",
|
|
3879
|
+
"updateFastModel",
|
|
3880
|
+
"toggleSaveCredential",
|
|
3881
|
+
"deleteConnection",
|
|
3882
|
+
"deleteChat"
|
|
3883
|
+
],
|
|
3884
|
+
setup(t, { emit: e }) {
|
|
3885
|
+
const o = C(""), i = C(!1), c = C(""), p = C("");
|
|
3886
|
+
Ae(() => {
|
|
3887
|
+
var y, D, u;
|
|
3888
|
+
t.item.type === "api-key" && ((y = t.item.connection) != null && y.getApiKey()) && (o.value = t.item.connection.getApiKey()), t.item.type === "model" && ((D = t.item.connection) != null && D.model) && (c.value = t.item.connection.model), t.item.type === "fast-model" && (p.value = ((u = t.item.connection) == null ? void 0 : u.fastModel) || "");
|
|
3889
|
+
}), ke(
|
|
3890
|
+
// @ts-ignore
|
|
3891
|
+
() => {
|
|
3892
|
+
var y;
|
|
3893
|
+
return (y = t.item.connection) == null ? void 0 : y.apiKey;
|
|
3894
|
+
},
|
|
3895
|
+
(y) => {
|
|
3896
|
+
t.item.type === "api-key" && y && (o.value = y);
|
|
3897
|
+
}
|
|
3898
|
+
), ke(
|
|
3899
|
+
() => {
|
|
3900
|
+
var y;
|
|
3901
|
+
return (y = t.item.connection) == null ? void 0 : y.model;
|
|
3902
|
+
},
|
|
3903
|
+
(y) => {
|
|
3904
|
+
t.item.type === "model" && y && (c.value = y);
|
|
3905
|
+
},
|
|
3906
|
+
{ immediate: !0 }
|
|
3907
|
+
), ke(
|
|
3908
|
+
() => {
|
|
3909
|
+
var y;
|
|
3910
|
+
return (y = t.item.connection) == null ? void 0 : y.fastModel;
|
|
3911
|
+
},
|
|
3912
|
+
(y) => {
|
|
3913
|
+
t.item.type === "fast-model" && (p.value = y || "");
|
|
3914
|
+
},
|
|
3915
|
+
{ immediate: !0 }
|
|
3916
|
+
);
|
|
3917
|
+
const a = C(!1), d = C({ x: 0, y: 0 }), w = $(() => {
|
|
3918
|
+
const y = [];
|
|
3919
|
+
return t.item.type === "connection" && y.push(
|
|
3920
|
+
{ id: "set-default", label: "Set as Default", icon: "mdi-star-outline" },
|
|
3921
|
+
{ id: "refresh", label: "Refresh Connection", icon: "mdi-refresh" },
|
|
3922
|
+
{ id: "delete", label: "Delete Connection", icon: "mdi-delete-outline", danger: !0 }
|
|
3923
|
+
), y;
|
|
3924
|
+
}), h = (y) => {
|
|
3925
|
+
t.item.type === "connection" && (d.value = {
|
|
3926
|
+
x: y.clientX,
|
|
3927
|
+
y: y.clientY
|
|
3928
|
+
}, a.value = !0);
|
|
3929
|
+
}, P = (y) => {
|
|
3930
|
+
var D;
|
|
3931
|
+
switch (y.id) {
|
|
3932
|
+
case "delete":
|
|
3933
|
+
L(t.item.id);
|
|
3934
|
+
break;
|
|
3935
|
+
case "set-default":
|
|
3936
|
+
v(t.item.id);
|
|
3937
|
+
break;
|
|
3938
|
+
case "refresh":
|
|
3939
|
+
e("refresh", t.item.id, ((D = t.item.connection) == null ? void 0 : D.name) || "", "connection");
|
|
3940
|
+
break;
|
|
3941
|
+
}
|
|
3942
|
+
}, E = $(() => ["connection"].includes(t.item.type)), b = () => ["api-key", "model", "fast-model", "toggle-save-credential", "refresh-connection"].includes(
|
|
3943
|
+
t.item.type
|
|
3944
|
+
) ? "" : t.item.name, m = () => {
|
|
3945
|
+
(E.value || t.item.type === "open-chat" || t.item.type === "open-validation" || t.item.type === "new-chat" || t.item.type === "chat-item") && F(t.item.id);
|
|
3946
|
+
}, F = (y) => {
|
|
3947
|
+
var u;
|
|
3948
|
+
const D = t.item.type === "chat-item" ? { chatId: t.item.chatId } : void 0;
|
|
3949
|
+
e("toggle", y, ((u = t.item.connection) == null ? void 0 : u.name) || "", t.item.type, D);
|
|
3950
|
+
}, g = (y) => {
|
|
3951
|
+
var D;
|
|
3952
|
+
y.stopPropagation(), e("refresh", t.item.id, ((D = t.item.connection) == null ? void 0 : D.name) || "", "connection");
|
|
3953
|
+
}, le = (y) => {
|
|
3954
|
+
e("toggleSaveCredential", y);
|
|
3955
|
+
}, f = (y) => y instanceof Ge ? "anthropic" : y instanceof je ? "openai" : y instanceof Ke ? "mistral" : y instanceof Qe ? "google" : "unknown", k = (y) => y && y.connected === !0, v = (y) => {
|
|
3956
|
+
var D;
|
|
3957
|
+
e("setActive", y, ((D = t.item.connection) == null ? void 0 : D.name) || "", "connection");
|
|
3958
|
+
}, L = (y) => {
|
|
3959
|
+
var D;
|
|
3960
|
+
e("deleteConnection", y, ((D = t.item.connection) == null ? void 0 : D.name) || "");
|
|
3961
|
+
};
|
|
3962
|
+
return {
|
|
3963
|
+
apiKeyInput: o,
|
|
3964
|
+
selectedModel: c,
|
|
3965
|
+
selectedFastModel: p,
|
|
3966
|
+
isExpandable: E,
|
|
3967
|
+
getItemName: b,
|
|
3968
|
+
handleItemClick: m,
|
|
3969
|
+
handleRefreshConnectionClick: g,
|
|
3970
|
+
getProviderType: f,
|
|
3971
|
+
isConnected: k,
|
|
3972
|
+
setAsActive: v,
|
|
3973
|
+
updateApiKey: (y, D) => {
|
|
3974
|
+
e("updateApiKey", y, D);
|
|
3975
|
+
},
|
|
3976
|
+
updateModel: (y, D) => {
|
|
3977
|
+
e("updateModel", y, D);
|
|
3978
|
+
},
|
|
3979
|
+
updateFastModel: (y, D) => {
|
|
3980
|
+
e("updateFastModel", y, D);
|
|
3981
|
+
},
|
|
3982
|
+
toggleSaveCredential: le,
|
|
3983
|
+
deleteConnection: L,
|
|
3984
|
+
deleteChat: (y) => {
|
|
3985
|
+
var D;
|
|
3986
|
+
y && e("deleteChat", y, ((D = t.item.connection) == null ? void 0 : D.name) || "");
|
|
3987
|
+
},
|
|
3988
|
+
// Context menu
|
|
3989
|
+
contextMenuVisible: a,
|
|
3990
|
+
contextMenuPosition: d,
|
|
3991
|
+
contextMenuItems: w,
|
|
3992
|
+
showContextMenu: h,
|
|
3993
|
+
handleContextMenuItemClick: P,
|
|
3994
|
+
toggleCollapse: F,
|
|
3995
|
+
// API key visibility
|
|
3996
|
+
showApiKey: i,
|
|
3997
|
+
toggleApiKeyVisibility: () => {
|
|
3998
|
+
i.value = !i.value;
|
|
3999
|
+
}
|
|
4000
|
+
};
|
|
4001
|
+
}
|
|
4002
|
+
}), Ln = {
|
|
4003
|
+
key: 1,
|
|
4004
|
+
class: "mdi mdi-alert-circle node-icon"
|
|
4005
|
+
}, Dn = {
|
|
4006
|
+
key: 2,
|
|
4007
|
+
class: "mdi mdi-chat-outline node-icon"
|
|
4008
|
+
}, _n = {
|
|
4009
|
+
key: 3,
|
|
4010
|
+
class: "mdi mdi-test-tube node-icon"
|
|
4011
|
+
}, Nn = {
|
|
4012
|
+
key: 4,
|
|
4013
|
+
class: "mdi mdi-chat-plus-outline node-icon"
|
|
4014
|
+
}, qn = {
|
|
4015
|
+
key: 5,
|
|
4016
|
+
class: "mdi mdi-chat node-icon"
|
|
4017
|
+
}, Un = {
|
|
4018
|
+
key: 6,
|
|
4019
|
+
class: "mdi mdi-folder-outline node-icon"
|
|
4020
|
+
}, On = { class: "api-key-input-wrapper" }, xn = ["type", "data-testid"], Bn = ["data-testid", "title"], Yn = ["data-testid"], Fn = ["data-testid"], Gn = ["data-testid"], jn = ["value", "data-testid"], Kn = ["data-testid"], Qn = ["data-testid"], Vn = ["data-testid"], Hn = ["value", "data-testid"], Wn = { class: "save-credential-toggle" }, zn = ["checked"], Xn = { key: 0 }, Jn = {
|
|
4021
|
+
key: 0,
|
|
4022
|
+
class: "chat-actions"
|
|
4023
|
+
}, Zn = {
|
|
4024
|
+
key: 1,
|
|
4025
|
+
class: "connection-actions"
|
|
4026
|
+
}, $n = {
|
|
4027
|
+
key: 0,
|
|
4028
|
+
class: "mdi mdi-star loading-button is-active"
|
|
4029
|
+
};
|
|
4030
|
+
function eo(t, e, o, i, c, p) {
|
|
4031
|
+
const a = U("context-menu"), d = U("LLMProviderIcon"), w = U("tooltip"), h = U("LoadingButton"), P = U("connection-refresh"), E = U("connection-status-icon"), b = U("sidebar-item");
|
|
4032
|
+
return r(), l("div", null, [
|
|
4033
|
+
x(b, {
|
|
4034
|
+
"item-id": t.item.id,
|
|
4035
|
+
name: t.getItemName(),
|
|
4036
|
+
indent: t.item.indent,
|
|
4037
|
+
"is-selected": t.isSelected,
|
|
4038
|
+
"is-collapsible": t.isExpandable,
|
|
4039
|
+
"is-collapsed": t.isCollapsed,
|
|
4040
|
+
itemType: "llm-connection",
|
|
4041
|
+
onClick: t.handleItemClick,
|
|
4042
|
+
onToggle: t.toggleCollapse,
|
|
4043
|
+
onContextmenu: A(t.showContextMenu, ["prevent"])
|
|
4044
|
+
}, {
|
|
4045
|
+
icon: q(() => [
|
|
4046
|
+
t.item.type === "connection" ? (r(), z(d, {
|
|
4047
|
+
key: 0,
|
|
4048
|
+
"provider-type": t.getProviderType(t.item.connection)
|
|
4049
|
+
}, null, 8, ["provider-type"])) : t.item.type === "error" ? (r(), l("i", Ln)) : t.item.type === "open-chat" ? (r(), l("i", Dn)) : t.item.type === "open-validation" ? (r(), l("i", _n)) : t.item.type === "new-chat" ? (r(), l("i", Nn)) : t.item.type === "chat-item" ? (r(), l("i", qn)) : t.item.type === "chats-header" ? (r(), l("i", Un)) : I("", !0)
|
|
4050
|
+
]),
|
|
4051
|
+
name: q(() => [
|
|
4052
|
+
t.item.type === "refresh-connection" ? (r(), l("div", {
|
|
4053
|
+
key: 0,
|
|
4054
|
+
class: "refresh title-pad-left truncate-text sidebar-sub-item",
|
|
4055
|
+
onClick: e[1] || (e[1] = (...m) => t.handleRefreshConnectionClick && t.handleRefreshConnectionClick(...m))
|
|
4056
|
+
}, j(t.item.name), 1)) : t.item.type === "api-key" ? (r(), l("div", {
|
|
4057
|
+
key: 1,
|
|
4058
|
+
class: "api-key-container",
|
|
4059
|
+
onClick: e[5] || (e[5] = A(() => {
|
|
4060
|
+
}, ["stop"]))
|
|
4061
|
+
}, [
|
|
4062
|
+
s("form", {
|
|
4063
|
+
onSubmit: e[4] || (e[4] = A((m) => t.updateApiKey(t.item.connection, t.apiKeyInput), ["prevent"]))
|
|
4064
|
+
}, [
|
|
4065
|
+
e[17] || (e[17] = s("button", {
|
|
4066
|
+
type: "submit",
|
|
4067
|
+
class: "customize-button"
|
|
4068
|
+
}, "Update API Key", -1)),
|
|
4069
|
+
s("div", On, [
|
|
4070
|
+
_(s("input", {
|
|
4071
|
+
type: t.showApiKey ? "text" : "password",
|
|
4072
|
+
id: "api-key",
|
|
4073
|
+
"onUpdate:modelValue": e[2] || (e[2] = (m) => t.apiKeyInput = m),
|
|
4074
|
+
placeholder: "API Key",
|
|
4075
|
+
class: "connection-customize",
|
|
4076
|
+
"data-testid": `api-key-input-${t.item.connection.name}`
|
|
4077
|
+
}, null, 8, xn), [
|
|
4078
|
+
[xe, t.apiKeyInput]
|
|
4079
|
+
]),
|
|
4080
|
+
s("button", {
|
|
4081
|
+
type: "button",
|
|
4082
|
+
class: "visibility-toggle",
|
|
4083
|
+
onClick: e[3] || (e[3] = (...m) => t.toggleApiKeyVisibility && t.toggleApiKeyVisibility(...m)),
|
|
4084
|
+
"data-testid": `toggle-api-key-visibility-${t.item.connection.name}`,
|
|
4085
|
+
title: t.showApiKey ? "Hide API Key" : "Show API Key"
|
|
4086
|
+
}, [
|
|
4087
|
+
s("i", {
|
|
4088
|
+
class: me(t.showApiKey ? "mdi mdi-eye-off" : "mdi mdi-eye")
|
|
4089
|
+
}, null, 2)
|
|
4090
|
+
], 8, Bn)
|
|
4091
|
+
])
|
|
4092
|
+
], 32)
|
|
4093
|
+
])) : t.item.type === "model" ? (r(), l("div", {
|
|
4094
|
+
key: 2,
|
|
4095
|
+
class: "api-key-container",
|
|
4096
|
+
onClick: e[8] || (e[8] = A(() => {
|
|
4097
|
+
}, ["stop"]))
|
|
4098
|
+
}, [
|
|
4099
|
+
s("form", {
|
|
4100
|
+
onSubmit: e[7] || (e[7] = A((m) => t.updateModel(t.item.connection, t.selectedModel), ["prevent"])),
|
|
4101
|
+
"data-testid": `model-update-form-${t.item.connection.name}`
|
|
4102
|
+
}, [
|
|
4103
|
+
s("button", {
|
|
4104
|
+
type: "submit",
|
|
4105
|
+
class: "customize-button",
|
|
4106
|
+
"data-testid": `update-model-${t.item.connection.name}`
|
|
4107
|
+
}, " Update Model ", 8, Fn),
|
|
4108
|
+
_(s("select", {
|
|
4109
|
+
"onUpdate:modelValue": e[6] || (e[6] = (m) => t.selectedModel = m),
|
|
4110
|
+
id: "connection-type",
|
|
4111
|
+
required: "",
|
|
4112
|
+
class: "connection-customize",
|
|
4113
|
+
"data-testid": `model-select-${t.item.connection.name}`
|
|
4114
|
+
}, [
|
|
4115
|
+
(r(!0), l(pe, null, fe(t.item.connection.models, (m) => (r(), l("option", {
|
|
4116
|
+
value: m,
|
|
4117
|
+
key: m,
|
|
4118
|
+
"data-testid": `model-option-${m}`
|
|
4119
|
+
}, j(m), 9, jn))), 128))
|
|
4120
|
+
], 8, Gn), [
|
|
4121
|
+
[ve, t.selectedModel]
|
|
4122
|
+
])
|
|
4123
|
+
], 40, Yn)
|
|
4124
|
+
])) : t.item.type === "fast-model" ? (r(), l("div", {
|
|
4125
|
+
key: 3,
|
|
4126
|
+
class: "api-key-container",
|
|
4127
|
+
onClick: e[11] || (e[11] = A(() => {
|
|
4128
|
+
}, ["stop"]))
|
|
4129
|
+
}, [
|
|
4130
|
+
s("form", {
|
|
4131
|
+
onSubmit: e[10] || (e[10] = A((m) => t.updateFastModel(t.item.connection, t.selectedFastModel || null), ["prevent"])),
|
|
4132
|
+
"data-testid": `fast-model-update-form-${t.item.connection.name}`
|
|
4133
|
+
}, [
|
|
4134
|
+
s("button", {
|
|
4135
|
+
type: "submit",
|
|
4136
|
+
class: "customize-button",
|
|
4137
|
+
"data-testid": `update-fast-model-${t.item.connection.name}`
|
|
4138
|
+
}, " Update Fast Model ", 8, Qn),
|
|
4139
|
+
_(s("select", {
|
|
4140
|
+
"onUpdate:modelValue": e[9] || (e[9] = (m) => t.selectedFastModel = m),
|
|
4141
|
+
class: "connection-customize",
|
|
4142
|
+
"data-testid": `fast-model-select-${t.item.connection.name}`
|
|
4143
|
+
}, [
|
|
4144
|
+
e[18] || (e[18] = s("option", {
|
|
4145
|
+
value: "",
|
|
4146
|
+
"data-testid": "fast-model-option-none"
|
|
4147
|
+
}, " (Use primary model) ", -1)),
|
|
4148
|
+
(r(!0), l(pe, null, fe(t.item.connection.models, (m) => (r(), l("option", {
|
|
4149
|
+
value: m,
|
|
4150
|
+
key: m,
|
|
4151
|
+
"data-testid": `fast-model-option-${m}`
|
|
4152
|
+
}, j(m), 9, Hn))), 128))
|
|
4153
|
+
], 8, Vn), [
|
|
4154
|
+
[ve, t.selectedFastModel]
|
|
4155
|
+
])
|
|
4156
|
+
], 40, Kn)
|
|
4157
|
+
])) : t.item.type === "toggle-save-credential" ? (r(), l("div", {
|
|
4158
|
+
key: 4,
|
|
4159
|
+
class: "md-token-container",
|
|
4160
|
+
onClick: e[13] || (e[13] = A(() => {
|
|
4161
|
+
}, ["stop"]))
|
|
4162
|
+
}, [
|
|
4163
|
+
s("label", Wn, [
|
|
4164
|
+
s("input", {
|
|
4165
|
+
type: "checkbox",
|
|
4166
|
+
checked: t.item.connection.saveCredential,
|
|
4167
|
+
onChange: e[12] || (e[12] = (m) => t.toggleSaveCredential(t.item.connection))
|
|
4168
|
+
}, null, 40, zn),
|
|
4169
|
+
e[19] || (e[19] = s("span", { class: "checkbox-label" }, "Save Credentials", -1))
|
|
4170
|
+
])
|
|
4171
|
+
])) : (r(), l("span", {
|
|
4172
|
+
key: 5,
|
|
4173
|
+
class: me(["title-pad-left truncate-text", { "error-indicator": t.item.type === "error" }])
|
|
4174
|
+
}, [
|
|
4175
|
+
de(j(t.item.name) + " ", 1),
|
|
4176
|
+
t.item.count !== void 0 && t.item.count > 0 ? (r(), l("span", Xn, " (" + j(t.item.count) + ") ", 1)) : I("", !0)
|
|
4177
|
+
], 2))
|
|
4178
|
+
]),
|
|
4179
|
+
"extra-content": q(() => [
|
|
4180
|
+
t.item.type === "chat-item" ? (r(), l("div", Jn, [
|
|
4181
|
+
x(w, {
|
|
4182
|
+
class: "tactile-button",
|
|
4183
|
+
content: "Delete Chat",
|
|
4184
|
+
position: "left"
|
|
4185
|
+
}, {
|
|
4186
|
+
default: q(() => [
|
|
4187
|
+
s("span", {
|
|
4188
|
+
class: "remove-btn hover-icon",
|
|
4189
|
+
onClick: e[14] || (e[14] = A((m) => t.deleteChat(t.item.chatId), ["stop"]))
|
|
4190
|
+
}, [...e[20] || (e[20] = [
|
|
4191
|
+
s("i", { class: "mdi mdi-trash-can-outline" }, null, -1)
|
|
4192
|
+
])])
|
|
4193
|
+
]),
|
|
4194
|
+
_: 1
|
|
4195
|
+
})
|
|
4196
|
+
])) : I("", !0),
|
|
4197
|
+
t.item.type === "connection" ? (r(), l("div", Zn, [
|
|
4198
|
+
t.item.connection && t.item.connection.isDefault ? (r(), l("i", $n)) : (r(), z(h, {
|
|
4199
|
+
key: 1,
|
|
4200
|
+
class: "loading-button",
|
|
4201
|
+
onClick: e[15] || (e[15] = A(() => {
|
|
4202
|
+
}, ["stop"])),
|
|
4203
|
+
action: () => t.setAsActive(t.item.id),
|
|
4204
|
+
title: "Set as default"
|
|
4205
|
+
}, {
|
|
4206
|
+
default: q(() => [...e[21] || (e[21] = [
|
|
4207
|
+
s("i", { class: "mdi mdi-star-outline" }, null, -1)
|
|
4208
|
+
])]),
|
|
4209
|
+
_: 1
|
|
4210
|
+
}, 8, ["action"])),
|
|
4211
|
+
t.item.connection ? (r(), z(P, {
|
|
4212
|
+
key: 2,
|
|
4213
|
+
connection: t.item.connection,
|
|
4214
|
+
type: "llm",
|
|
4215
|
+
"is-connected": t.isConnected(t.item.connection),
|
|
4216
|
+
"data-testid": `refresh-llm-connection-${t.item.connection.name}`
|
|
4217
|
+
}, null, 8, ["connection", "is-connected", "data-testid"])) : I("", !0),
|
|
4218
|
+
x(w, {
|
|
4219
|
+
class: "tacticle-button",
|
|
4220
|
+
content: "Delete Connection",
|
|
4221
|
+
position: "left"
|
|
4222
|
+
}, {
|
|
4223
|
+
default: q(() => [
|
|
4224
|
+
s("span", {
|
|
4225
|
+
class: "remove-btn",
|
|
4226
|
+
onClick: e[16] || (e[16] = A((m) => t.deleteConnection(t.item.id), ["stop"]))
|
|
4227
|
+
}, [...e[22] || (e[22] = [
|
|
4228
|
+
s("i", { class: "mdi mdi-trash-can-outline tactile-button" }, null, -1)
|
|
4229
|
+
])])
|
|
4230
|
+
]),
|
|
4231
|
+
_: 1
|
|
4232
|
+
}),
|
|
4233
|
+
t.item.connection ? (r(), z(E, {
|
|
4234
|
+
key: 3,
|
|
4235
|
+
connection: t.item.connection
|
|
4236
|
+
}, null, 8, ["connection"])) : I("", !0)
|
|
4237
|
+
])) : I("", !0)
|
|
4238
|
+
]),
|
|
4239
|
+
default: q(() => [
|
|
4240
|
+
x(a, {
|
|
4241
|
+
items: t.contextMenuItems,
|
|
4242
|
+
position: t.contextMenuPosition,
|
|
4243
|
+
"is-visible": t.contextMenuVisible,
|
|
4244
|
+
onItemClick: t.handleContextMenuItemClick,
|
|
4245
|
+
onClose: e[0] || (e[0] = (m) => t.contextMenuVisible = !1)
|
|
4246
|
+
}, null, 8, ["items", "position", "is-visible", "onItemClick"])
|
|
4247
|
+
]),
|
|
4248
|
+
_: 1
|
|
4249
|
+
}, 8, ["item-id", "name", "indent", "is-selected", "is-collapsible", "is-collapsed", "onClick", "onToggle", "onContextmenu"])
|
|
4250
|
+
]);
|
|
4251
|
+
}
|
|
4252
|
+
const to = /* @__PURE__ */ X(Mn, [["render", eo], ["__scopeId", "data-v-9a82e421"]]), no = ae({
|
|
4253
|
+
name: "LLMConnectionCreator",
|
|
4254
|
+
props: {
|
|
4255
|
+
visible: {
|
|
4256
|
+
type: Boolean,
|
|
4257
|
+
required: !0
|
|
4258
|
+
},
|
|
4259
|
+
testTag: {
|
|
4260
|
+
type: String,
|
|
4261
|
+
required: !1,
|
|
4262
|
+
default: ""
|
|
4263
|
+
}
|
|
4264
|
+
},
|
|
4265
|
+
methods: {
|
|
4266
|
+
close() {
|
|
4267
|
+
this.$emit("close");
|
|
4268
|
+
}
|
|
4269
|
+
},
|
|
4270
|
+
components: {
|
|
4271
|
+
LoadingButton: Se
|
|
4272
|
+
},
|
|
4273
|
+
setup(t, { emit: e }) {
|
|
4274
|
+
const o = C({
|
|
4275
|
+
name: "",
|
|
4276
|
+
type: "openai",
|
|
4277
|
+
options: {
|
|
4278
|
+
apiKey: "",
|
|
4279
|
+
model: "gpt-4o",
|
|
4280
|
+
saveCredential: !1
|
|
4281
|
+
}
|
|
4282
|
+
}), i = Y("llmConnectionStore");
|
|
4283
|
+
if (!i)
|
|
4284
|
+
throw new Error("must inject llmConnectionStore to LLMConnectionCreator");
|
|
4285
|
+
const c = i.connections, p = () => {
|
|
4286
|
+
o.value.name = "", o.value.type = "openai", o.value.options = {
|
|
4287
|
+
apiKey: "",
|
|
4288
|
+
model: "",
|
|
4289
|
+
saveCredential: !1
|
|
4290
|
+
}, a("openai");
|
|
4291
|
+
}, a = (h) => {
|
|
4292
|
+
switch (h) {
|
|
4293
|
+
case "openai":
|
|
4294
|
+
o.value.options.model = "gpt-5.2-mini";
|
|
4295
|
+
break;
|
|
4296
|
+
case "anthropic":
|
|
4297
|
+
o.value.options.model = "claude-3-sonnet-20240229";
|
|
4298
|
+
break;
|
|
4299
|
+
case "cohere":
|
|
4300
|
+
o.value.options.model = "command";
|
|
4301
|
+
break;
|
|
4302
|
+
case "mistral":
|
|
4303
|
+
o.value.options.model = "mistral-large-latest";
|
|
4304
|
+
break;
|
|
4305
|
+
case "google":
|
|
4306
|
+
o.value.options.model = "models/gemini-2.5-flash";
|
|
4307
|
+
break;
|
|
4308
|
+
default:
|
|
4309
|
+
o.value.options.model = "";
|
|
4310
|
+
}
|
|
4311
|
+
}, d = async () => {
|
|
4312
|
+
await w();
|
|
4313
|
+
}, w = async () => {
|
|
4314
|
+
if (!o.value.name)
|
|
4315
|
+
throw new Error("Connection name is required");
|
|
4316
|
+
if (!o.value.type)
|
|
4317
|
+
throw new Error("Provider type is required");
|
|
4318
|
+
if (!o.value.options.apiKey)
|
|
4319
|
+
throw new Error("API key is required");
|
|
4320
|
+
return await i.newConnection(
|
|
4321
|
+
o.value.name,
|
|
4322
|
+
o.value.type,
|
|
4323
|
+
o.value.options
|
|
4324
|
+
), e("close"), "Connection created successfully";
|
|
4325
|
+
};
|
|
4326
|
+
return {
|
|
4327
|
+
connectionDetails: o,
|
|
4328
|
+
connections: c,
|
|
4329
|
+
createConnection: p,
|
|
4330
|
+
handleSubmitConnection: w,
|
|
4331
|
+
submitConnectionCreation: d,
|
|
4332
|
+
updateDefaultModel: a
|
|
4333
|
+
};
|
|
4334
|
+
},
|
|
4335
|
+
watch: {
|
|
4336
|
+
"connectionDetails.type": {
|
|
4337
|
+
handler(t) {
|
|
4338
|
+
this.updateDefaultModel(t);
|
|
4339
|
+
}
|
|
4340
|
+
}
|
|
4341
|
+
}
|
|
4342
|
+
}), oo = {
|
|
4343
|
+
key: 0,
|
|
4344
|
+
class: "creator-container"
|
|
4345
|
+
}, io = { class: "form-row" }, ao = { class: "form-row" }, so = { class: "form-row" }, ro = { class: "form-row" }, lo = { class: "button-row" };
|
|
4346
|
+
function co(t, e, o, i, c, p) {
|
|
4347
|
+
const a = U("loading-button");
|
|
4348
|
+
return t.visible ? (r(), l("div", oo, [
|
|
4349
|
+
s("form", {
|
|
4350
|
+
onSubmit: e[5] || (e[5] = A((...d) => t.submitConnectionCreation && t.submitConnectionCreation(...d), ["prevent"]))
|
|
4351
|
+
}, [
|
|
4352
|
+
s("div", io, [
|
|
4353
|
+
e[6] || (e[6] = s("label", { for: "llm-connection-name" }, "Name", -1)),
|
|
4354
|
+
_(s("input", {
|
|
4355
|
+
type: "text",
|
|
4356
|
+
"onUpdate:modelValue": e[0] || (e[0] = (d) => t.connectionDetails.name = d),
|
|
4357
|
+
id: "llm-connection-name",
|
|
4358
|
+
required: "",
|
|
4359
|
+
"data-testid": "llm-connection-creator-name",
|
|
4360
|
+
placeholder: "Connection Name"
|
|
4361
|
+
}, null, 512), [
|
|
4362
|
+
[G, t.connectionDetails.name]
|
|
4363
|
+
])
|
|
4364
|
+
]),
|
|
4365
|
+
s("div", ao, [
|
|
4366
|
+
e[8] || (e[8] = s("label", { for: "llm-provider-type" }, "Provider", -1)),
|
|
4367
|
+
_(s("select", {
|
|
4368
|
+
"onUpdate:modelValue": e[1] || (e[1] = (d) => t.connectionDetails.type = d),
|
|
4369
|
+
id: "llm-provider-type",
|
|
4370
|
+
required: "",
|
|
4371
|
+
"data-testid": "llm-connection-creator-type"
|
|
4372
|
+
}, [...e[7] || (e[7] = [
|
|
4373
|
+
s("option", {
|
|
4374
|
+
value: "openai",
|
|
4375
|
+
"data-testid": "llm-connection-creator-openai"
|
|
4376
|
+
}, "OpenAI", -1),
|
|
4377
|
+
s("option", {
|
|
4378
|
+
value: "anthropic",
|
|
4379
|
+
"data-testid": "llm-connection-creator-anthropic"
|
|
4380
|
+
}, " Anthropic ", -1),
|
|
4381
|
+
s("option", {
|
|
4382
|
+
value: "google",
|
|
4383
|
+
"data-testid": "llm-connection-creator-google"
|
|
4384
|
+
}, "Google", -1)
|
|
4385
|
+
])], 512), [
|
|
4386
|
+
[ve, t.connectionDetails.type]
|
|
4387
|
+
])
|
|
4388
|
+
]),
|
|
4389
|
+
s("div", so, [
|
|
4390
|
+
e[9] || (e[9] = s("label", { for: "llm-api-key" }, "API Key", -1)),
|
|
4391
|
+
_(s("input", {
|
|
4392
|
+
type: "password",
|
|
4393
|
+
"onUpdate:modelValue": e[2] || (e[2] = (d) => t.connectionDetails.options.apiKey = d),
|
|
4394
|
+
id: "llm-api-key",
|
|
4395
|
+
placeholder: "API Key",
|
|
4396
|
+
required: "",
|
|
4397
|
+
"data-testid": "llm-connection-creator-api-key"
|
|
4398
|
+
}, null, 512), [
|
|
4399
|
+
[G, t.connectionDetails.options.apiKey]
|
|
4400
|
+
])
|
|
4401
|
+
]),
|
|
4402
|
+
s("div", ro, [
|
|
4403
|
+
e[10] || (e[10] = s("label", { for: "save-credential" }, "Save Credential?", -1)),
|
|
4404
|
+
_(s("input", {
|
|
4405
|
+
type: "checkbox",
|
|
4406
|
+
id: "save-credential",
|
|
4407
|
+
"onUpdate:modelValue": e[3] || (e[3] = (d) => t.connectionDetails.options.saveCredential = d),
|
|
4408
|
+
"data-testid": "llm-connection-creator-save-credential"
|
|
4409
|
+
}, null, 512), [
|
|
4410
|
+
[Ie, t.connectionDetails.options.saveCredential]
|
|
4411
|
+
])
|
|
4412
|
+
]),
|
|
4413
|
+
s("div", lo, [
|
|
4414
|
+
x(a, {
|
|
4415
|
+
"data-testid": "llm-connection-creator-submit",
|
|
4416
|
+
action: t.handleSubmitConnection,
|
|
4417
|
+
class: "submit-button"
|
|
4418
|
+
}, {
|
|
4419
|
+
default: q(() => [...e[11] || (e[11] = [
|
|
4420
|
+
de(" Submit ", -1)
|
|
4421
|
+
])]),
|
|
4422
|
+
_: 1
|
|
4423
|
+
}, 8, ["action"]),
|
|
4424
|
+
s("button", {
|
|
4425
|
+
type: "button",
|
|
4426
|
+
onClick: e[4] || (e[4] = (d) => t.close())
|
|
4427
|
+
}, "Cancel")
|
|
4428
|
+
])
|
|
4429
|
+
], 32)
|
|
4430
|
+
])) : I("", !0);
|
|
4431
|
+
}
|
|
4432
|
+
const uo = /* @__PURE__ */ X(no, [["render", co], ["__scopeId", "data-v-2aa622d0"]]), po = {
|
|
4433
|
+
name: "LLMConnectionList",
|
|
4434
|
+
props: {
|
|
4435
|
+
activeLLMKey: {
|
|
4436
|
+
type: String,
|
|
4437
|
+
default: "",
|
|
4438
|
+
optional: !0
|
|
4439
|
+
},
|
|
4440
|
+
testTag: {
|
|
4441
|
+
type: String,
|
|
4442
|
+
default: "",
|
|
4443
|
+
optional: !0
|
|
4444
|
+
}
|
|
4445
|
+
},
|
|
4446
|
+
emits: ["llm-open-view", "create-new-chat", "open-chat"],
|
|
4447
|
+
setup(t, { emit: e }) {
|
|
4448
|
+
const o = Y("llmConnectionStore"), i = Y("saveLLMConnections"), c = Y("chatStore", null);
|
|
4449
|
+
if (!o || !i)
|
|
4450
|
+
throw new Error("LLM connection store is not provided!");
|
|
4451
|
+
const p = C({}), a = C({}), d = C(!1), w = async (f, k) => {
|
|
4452
|
+
k && (await o.connections[f.name].setApiKey(k), o.resetConnection(f.name), await i());
|
|
4453
|
+
}, h = (f, k) => {
|
|
4454
|
+
k && (o.connections[f.name].setModel(k), o.resetConnection(f.name), i());
|
|
4455
|
+
}, P = (f, k) => {
|
|
4456
|
+
o.connections[f.name].setFastModel(k), i();
|
|
4457
|
+
}, E = C({}), b = async (f, k, v) => {
|
|
4458
|
+
if (!o.connections[k]) {
|
|
4459
|
+
a.value[f] = "Connection not found";
|
|
4460
|
+
return;
|
|
4461
|
+
}
|
|
4462
|
+
try {
|
|
4463
|
+
if (p.value[f] = !0, v === "connection") {
|
|
4464
|
+
const L = o.connections[k];
|
|
4465
|
+
L.testConnection && await L.testConnection();
|
|
4466
|
+
}
|
|
4467
|
+
delete a.value[f];
|
|
4468
|
+
} catch (L) {
|
|
4469
|
+
L instanceof Error ? a.value[f] = L.message : a.value[f] = "An error occurred";
|
|
4470
|
+
}
|
|
4471
|
+
delete p.value[f];
|
|
4472
|
+
}, m = async (f, k, v, L) => {
|
|
4473
|
+
if (v === "new-chat") {
|
|
4474
|
+
e("create-new-chat", k);
|
|
4475
|
+
return;
|
|
4476
|
+
}
|
|
4477
|
+
if (v === "chat-item") {
|
|
4478
|
+
c && (L != null && L.chatId) && (c.setActiveChat(L.chatId), o.activeConnection = k), e("llm-open-view", k, "chat", L == null ? void 0 : L.chatId);
|
|
4479
|
+
return;
|
|
4480
|
+
}
|
|
4481
|
+
if (v === "open-chat") {
|
|
4482
|
+
e("llm-open-view", k, "chat");
|
|
4483
|
+
return;
|
|
4484
|
+
}
|
|
4485
|
+
if (v === "open-validation") {
|
|
4486
|
+
e("llm-open-view", k, "validation");
|
|
4487
|
+
return;
|
|
4488
|
+
}
|
|
4489
|
+
if (v === "connection" && (E.value[f] === void 0 || E.value[f] === !0)) {
|
|
4490
|
+
const T = o.connections[k];
|
|
4491
|
+
if (!T) {
|
|
4492
|
+
console.log(`Connection not found ${T}`);
|
|
4493
|
+
return;
|
|
4494
|
+
}
|
|
4495
|
+
(!T.models || T.models.length === 0) && await b(f, k, "models");
|
|
4496
|
+
}
|
|
4497
|
+
E.value[f] === void 0 ? E.value[f] = !1 : E.value[f] = !E.value[f];
|
|
4498
|
+
};
|
|
4499
|
+
Object.entries(o.connections).forEach(([f, k]) => {
|
|
4500
|
+
let v = f;
|
|
4501
|
+
E.value[v] = !0;
|
|
4502
|
+
}), Ae(() => {
|
|
4503
|
+
const f = Ve("llm-key", "");
|
|
4504
|
+
if (f) {
|
|
4505
|
+
const k = f.split(N), v = k[0], L = k[1];
|
|
4506
|
+
v && o.connections[v] && (E.value[v] = !1, o.activeConnection = v, L && c && c.setActiveChat(L));
|
|
4507
|
+
}
|
|
4508
|
+
});
|
|
4509
|
+
const F = $(() => {
|
|
4510
|
+
const f = [];
|
|
4511
|
+
return Object.entries(o.connections).sort(
|
|
4512
|
+
([v, L], [T, V]) => {
|
|
4513
|
+
const J = L, Q = V;
|
|
4514
|
+
return J.connected && !Q.connected ? -1 : !J.connected && Q.connected ? 1 : v.localeCompare(T);
|
|
4515
|
+
}
|
|
4516
|
+
).forEach(([v, L]) => {
|
|
4517
|
+
var J;
|
|
4518
|
+
const T = L, V = ((J = T.availableModels) == null ? void 0 : J.length) || 0;
|
|
4519
|
+
if (!T.deleted && (f.push({
|
|
4520
|
+
id: v,
|
|
4521
|
+
name: v,
|
|
4522
|
+
indent: 0,
|
|
4523
|
+
count: V,
|
|
4524
|
+
type: "connection",
|
|
4525
|
+
connection: T
|
|
4526
|
+
}), E.value[v] === !1)) {
|
|
4527
|
+
const Q = c ? c.getConnectionChats(v) : [];
|
|
4528
|
+
f.push({
|
|
4529
|
+
id: `${v}-new-chat`,
|
|
4530
|
+
name: "New Chat",
|
|
4531
|
+
indent: 1,
|
|
4532
|
+
count: Q.length,
|
|
4533
|
+
type: "new-chat",
|
|
4534
|
+
connection: T
|
|
4535
|
+
}), Q.forEach((K) => {
|
|
4536
|
+
f.push({
|
|
4537
|
+
id: `${v}-chat-${K.id}`,
|
|
4538
|
+
name: K.name,
|
|
4539
|
+
indent: 2,
|
|
4540
|
+
count: K.messages.length,
|
|
4541
|
+
type: "chat-item",
|
|
4542
|
+
connection: T,
|
|
4543
|
+
chat: K,
|
|
4544
|
+
chatId: K.id
|
|
4545
|
+
});
|
|
4546
|
+
}), f.push({
|
|
4547
|
+
id: `${v}-open-validation`,
|
|
4548
|
+
name: "Validation Tests",
|
|
4549
|
+
indent: 1,
|
|
4550
|
+
count: 0,
|
|
4551
|
+
type: "open-validation",
|
|
4552
|
+
connection: T
|
|
4553
|
+
}), f.push({
|
|
4554
|
+
id: `${v}-api-key`,
|
|
4555
|
+
name: "API Key",
|
|
4556
|
+
indent: 1,
|
|
4557
|
+
count: 0,
|
|
4558
|
+
type: "api-key",
|
|
4559
|
+
connection: T
|
|
4560
|
+
}), f.push({
|
|
4561
|
+
id: `${v}-model`,
|
|
4562
|
+
name: "Model",
|
|
4563
|
+
indent: 1,
|
|
4564
|
+
count: 0,
|
|
4565
|
+
type: "model",
|
|
4566
|
+
connection: T
|
|
4567
|
+
}), f.push({
|
|
4568
|
+
id: `${v}-fast-model`,
|
|
4569
|
+
name: "Fast Model",
|
|
4570
|
+
indent: 1,
|
|
4571
|
+
count: 0,
|
|
4572
|
+
type: "fast-model",
|
|
4573
|
+
connection: T
|
|
4574
|
+
}), f.push({
|
|
4575
|
+
id: `${v}-toggle-save-credential`,
|
|
4576
|
+
name: "Toggle Save Credential",
|
|
4577
|
+
indent: 1,
|
|
4578
|
+
count: 0,
|
|
4579
|
+
type: "toggle-save-credential",
|
|
4580
|
+
connection: T
|
|
4581
|
+
}), p.value[v] && f.push({
|
|
4582
|
+
id: `${v}-loading`,
|
|
4583
|
+
name: "Loading...",
|
|
4584
|
+
indent: 1,
|
|
4585
|
+
count: 0,
|
|
4586
|
+
type: "loading",
|
|
4587
|
+
connection: T
|
|
4588
|
+
}), a.value[v] && f.push({
|
|
4589
|
+
id: `${v}-error`,
|
|
4590
|
+
name: a.value[v],
|
|
4591
|
+
indent: 1,
|
|
4592
|
+
count: 0,
|
|
4593
|
+
type: "error",
|
|
4594
|
+
connection: T
|
|
4595
|
+
});
|
|
4596
|
+
}
|
|
4597
|
+
}), f;
|
|
4598
|
+
});
|
|
4599
|
+
return {
|
|
4600
|
+
llmConnectionStore: o,
|
|
4601
|
+
chatStore: c,
|
|
4602
|
+
contentList: F,
|
|
4603
|
+
toggleCollapse: m,
|
|
4604
|
+
collapsed: E,
|
|
4605
|
+
saveConnections: i,
|
|
4606
|
+
updateApiKey: w,
|
|
4607
|
+
updateModel: h,
|
|
4608
|
+
updateFastModel: P,
|
|
4609
|
+
refreshId: b,
|
|
4610
|
+
rightSplit: (f) => {
|
|
4611
|
+
const k = f.lastIndexOf(N);
|
|
4612
|
+
return k !== -1 ? f.substring(0, k) : f;
|
|
4613
|
+
},
|
|
4614
|
+
creatorVisible: d,
|
|
4615
|
+
isItemSelected: (f) => f.type === "chat-item" && f.chatId && c ? f.chatId === c.activeChatId : f.type === "connection" ? f.id === o.activeConnection : !1
|
|
4616
|
+
};
|
|
4617
|
+
},
|
|
4618
|
+
components: {
|
|
4619
|
+
SidebarList: Le,
|
|
4620
|
+
LLMConnectionListItem: to,
|
|
4621
|
+
LLMConnectionCreator: uo,
|
|
4622
|
+
LoadingButton: Se,
|
|
4623
|
+
StatusIcon: Me,
|
|
4624
|
+
Tooltip: Ee
|
|
4625
|
+
},
|
|
4626
|
+
methods: {
|
|
4627
|
+
resetConnection(t) {
|
|
4628
|
+
return this.llmConnectionStore.resetConnection(t.name);
|
|
4629
|
+
},
|
|
4630
|
+
setActiveConnection(t) {
|
|
4631
|
+
this.llmConnectionStore.activeConnection = t, this.llmConnectionStore.connections[t].isDefault = !0, Object.keys(this.llmConnectionStore.connections).forEach((e) => {
|
|
4632
|
+
e !== t && (this.llmConnectionStore.connections[e].isDefault = !1);
|
|
4633
|
+
}), this.saveConnections();
|
|
4634
|
+
},
|
|
4635
|
+
deleteConnection(t, e) {
|
|
4636
|
+
confirm(`Are you sure you want to delete the connection "${e}"?`) && (this.llmConnectionStore.connections[e].delete(), this.llmConnectionStore.activeConnection === t && (this.llmConnectionStore.activeConnection = ""));
|
|
4637
|
+
},
|
|
4638
|
+
deleteChat(t, e) {
|
|
4639
|
+
confirm("Are you sure you want to delete this chat?") && this.chatStore && this.chatStore.removeChat(t);
|
|
4640
|
+
},
|
|
4641
|
+
toggleSaveCredential(t) {
|
|
4642
|
+
t.saveCredential = !t.saveCredential, this.saveConnections();
|
|
4643
|
+
}
|
|
4644
|
+
},
|
|
4645
|
+
computed: {
|
|
4646
|
+
connections() {
|
|
4647
|
+
return Object.values(this.llmConnectionStore.connections);
|
|
4648
|
+
}
|
|
4649
|
+
}
|
|
4650
|
+
}, mo = { class: "button-container" }, ho = ["data-testid"];
|
|
4651
|
+
function yo(t, e, o, i, c, p) {
|
|
4652
|
+
const a = U("LLMConnectionCreator"), d = U("LLMConnectionListItem"), w = U("sidebar-list");
|
|
4653
|
+
return r(), z(w, { title: "LLM Connections" }, {
|
|
4654
|
+
actions: q(() => [
|
|
4655
|
+
s("div", mo, [
|
|
4656
|
+
s("button", {
|
|
4657
|
+
onClick: e[0] || (e[0] = (h) => i.creatorVisible = !i.creatorVisible),
|
|
4658
|
+
"data-testid": o.testTag ? `llm-connection-creator-add-${o.testTag}` : "llm-connection-creator-add"
|
|
4659
|
+
}, j(i.creatorVisible ? "Hide" : "New"), 9, ho)
|
|
4660
|
+
]),
|
|
4661
|
+
x(a, {
|
|
4662
|
+
visible: i.creatorVisible,
|
|
4663
|
+
onClose: e[1] || (e[1] = (h) => i.creatorVisible = !i.creatorVisible)
|
|
4664
|
+
}, null, 8, ["visible"])
|
|
4665
|
+
]),
|
|
4666
|
+
default: q(() => [
|
|
4667
|
+
(r(!0), l(pe, null, fe(i.contentList, (h) => (r(), z(d, {
|
|
4668
|
+
key: h.id,
|
|
4669
|
+
item: h,
|
|
4670
|
+
"is-collapsed": i.collapsed[h.id],
|
|
4671
|
+
isSelected: i.isItemSelected(h),
|
|
4672
|
+
onToggle: i.toggleCollapse,
|
|
4673
|
+
onRefresh: i.refreshId,
|
|
4674
|
+
onUpdateApiKey: i.updateApiKey,
|
|
4675
|
+
onUpdateModel: i.updateModel,
|
|
4676
|
+
onUpdateFastModel: i.updateFastModel,
|
|
4677
|
+
onSetActive: p.setActiveConnection,
|
|
4678
|
+
onDeleteConnection: p.deleteConnection,
|
|
4679
|
+
onDeleteChat: p.deleteChat,
|
|
4680
|
+
onToggleSaveCredential: p.toggleSaveCredential
|
|
4681
|
+
}, null, 8, ["item", "is-collapsed", "isSelected", "onToggle", "onRefresh", "onUpdateApiKey", "onUpdateModel", "onUpdateFastModel", "onSetActive", "onDeleteConnection", "onDeleteChat", "onToggleSaveCredential"]))), 128))
|
|
4682
|
+
]),
|
|
4683
|
+
_: 1
|
|
4684
|
+
});
|
|
4685
|
+
}
|
|
4686
|
+
const vo = /* @__PURE__ */ X(po, [["render", yo], ["__scopeId", "data-v-b094467c"]]);
|
|
4687
|
+
export {
|
|
4688
|
+
To as C,
|
|
4689
|
+
vo as L,
|
|
4690
|
+
yt as a,
|
|
4691
|
+
bo as d
|
|
4692
|
+
};
|