From 5b3fca5f6506e8a86691e5fde0509dcb70dffc3e Mon Sep 17 00:00:00 2001 From: Himanshu Singh Date: Wed, 27 Mar 2024 11:59:57 +0100 Subject: [PATCH] feat: made FieldStore aware of multi connections - Start using ConnectionScopedGlobalAppRegistry in the plugins to emit event on GlobalAppRegistry with the connectionInfo - FieldStorePlugin now expect ConnectionInfo to be provided when listening for events on GlobalAppRegistry - Test cases are changed to add provider for ConnectionInfo --- package-lock.json | 12 +++ packages/compass-aggregations/package.json | 1 + .../focus-mode-stage-editor.spec.tsx | 22 +++-- .../components/focus-mode/focus-mode.spec.tsx | 16 +++- .../pipeline-builder-workspace/index.spec.tsx | 16 +++- .../pipeline-as-text-workspace/index.spec.tsx | 16 +++- .../pipeline-editor.spec.tsx | 34 +++++--- .../pipeline-editor.tsx | 4 +- .../index.spec.tsx | 24 ++++-- .../pipeline-results-list.spec.tsx | 59 +++++++------ .../stage-editor/stage-editor.spec.tsx | 34 +++++--- .../components/stage-editor/stage-editor.tsx | 4 +- .../components/stage-wizard/index.spec.tsx | 40 +++++---- .../src/components/stage-wizard/index.tsx | 4 +- packages/compass-crud/package.json | 2 + .../src/components/crud-toolbar.spec.tsx | 66 ++++++++------- .../src/components/json-editor.tsx | 4 +- packages/compass-crud/src/index.ts | 6 ++ .../src/stores/crud-store.spec.ts | 84 +++++++++++++++++++ .../compass-crud/src/stores/crud-store.ts | 20 ++++- packages/compass-field-store/package.json | 1 + .../compass-field-store/src/index.spec.ts | 26 ++++-- .../compass-field-store/src/modules/index.ts | 33 ++++++-- .../compass-field-store/src/stores/context.ts | 14 ++-- .../src/stores/store.spec.ts | 54 +++++++----- .../compass-field-store/src/stores/store.ts | 27 ++++-- packages/compass-home/src/components/home.tsx | 22 ++--- .../create-index-form/create-index-form.tsx | 4 +- .../src/components/indexes/indexes.spec.tsx | 16 +++- .../base-search-index-modal.spec.tsx | 36 +++++--- .../base-search-index-modal.tsx | 4 +- packages/compass-query-bar/package.json | 1 + .../src/components/option-editor.spec.tsx | 72 +++++++--------- .../src/components/option-editor.tsx | 4 +- .../src/components/query-bar.spec.tsx | 30 ++++--- .../compass-schema-validation/package.json | 1 + .../validation-editor.spec.tsx | 67 +++++++++------ .../validation-editor/validation-editor.tsx | 4 +- .../validation-states.spec.tsx | 16 +++- .../schema-toolbar/schema-toolbar.spec.tsx | 34 +++++--- packages/compass-schema/src/index.ts | 4 + .../compass-schema/src/stores/store.spec.ts | 9 +- packages/compass-schema/src/stores/store.ts | 15 +++- 43 files changed, 668 insertions(+), 294 deletions(-) diff --git a/package-lock.json b/package-lock.json index 993cda1734b..92485fd8047 100644 --- a/package-lock.json +++ b/package-lock.json @@ -44953,6 +44953,7 @@ "@mongodb-js/compass-logging": "^1.2.14", "@mongodb-js/compass-utils": "^0.6.1", "@mongodb-js/compass-workspaces": "^0.5.1", + "@mongodb-js/connection-storage": "^0.8.1", "@mongodb-js/explain-plan-helper": "^1.1.10", "@mongodb-js/mongodb-constants": "^0.9.0", "@mongodb-js/my-queries-storage": "^0.5.1", @@ -45493,6 +45494,7 @@ "@mongodb-js/compass-logging": "^1.2.14", "@mongodb-js/compass-query-bar": "^8.25.1", "@mongodb-js/compass-workspaces": "^0.5.1", + "@mongodb-js/connection-storage": "^0.8.1", "@mongodb-js/explain-plan-helper": "^1.1.10", "@mongodb-js/my-queries-storage": "^0.5.1", "ag-grid-community": "^20.2.0", @@ -45516,6 +45518,7 @@ }, "devDependencies": { "@mongodb-js/compass-test-server": "^0.1.13", + "@mongodb-js/connection-info": "^0.1.5", "@mongodb-js/eslint-config-compass": "^1.0.17", "@mongodb-js/mocha-config-compass": "^1.3.7", "@mongodb-js/prettier-config-compass": "^1.0.1", @@ -46130,6 +46133,7 @@ "version": "9.0.19", "license": "SSPL", "dependencies": { + "@mongodb-js/connection-info": "^0.1.5", "hadron-app-registry": "^9.1.8", "lodash": "^4.17.21", "mongodb-schema": "^12.1.0", @@ -47017,6 +47021,7 @@ "@mongodb-js/compass-field-store": "^9.0.19", "@mongodb-js/compass-generative-ai": "^0.8.1", "@mongodb-js/compass-logging": "^1.2.14", + "@mongodb-js/connection-storage": "^0.8.1", "@mongodb-js/mongodb-constants": "^0.9.0", "@mongodb-js/my-queries-storage": "^0.5.1", "bson": "^6.5.0", @@ -47226,6 +47231,7 @@ "@mongodb-js/compass-editor": "^0.21.1", "@mongodb-js/compass-field-store": "^9.0.19", "@mongodb-js/compass-logging": "^1.2.14", + "@mongodb-js/connection-storage": "^0.8.1", "bson": "^6.5.0", "compass-preferences-model": "^2.18.1", "hadron-app-registry": "^9.1.8", @@ -56852,6 +56858,7 @@ "@mongodb-js/compass-logging": "^1.2.14", "@mongodb-js/compass-utils": "^0.6.1", "@mongodb-js/compass-workspaces": "^0.5.1", + "@mongodb-js/connection-storage": "^0.8.1", "@mongodb-js/eslint-config-compass": "^1.0.17", "@mongodb-js/explain-plan-helper": "^1.1.10", "@mongodb-js/mocha-config-compass": "^1.3.7", @@ -57327,6 +57334,8 @@ "@mongodb-js/compass-query-bar": "^8.25.1", "@mongodb-js/compass-test-server": "^0.1.13", "@mongodb-js/compass-workspaces": "^0.5.1", + "@mongodb-js/connection-info": "^0.1.5", + "@mongodb-js/connection-storage": "^0.8.1", "@mongodb-js/eslint-config-compass": "^1.0.17", "@mongodb-js/explain-plan-helper": "^1.1.10", "@mongodb-js/mocha-config-compass": "^1.3.7", @@ -57683,6 +57692,7 @@ "@mongodb-js/compass-field-store": { "version": "file:packages/compass-field-store", "requires": { + "@mongodb-js/connection-info": "^0.1.5", "@mongodb-js/eslint-config-compass": "^1.0.17", "@mongodb-js/mocha-config-compass": "^1.3.7", "@mongodb-js/prettier-config-compass": "^1.0.1", @@ -58346,6 +58356,7 @@ "@mongodb-js/compass-field-store": "^9.0.19", "@mongodb-js/compass-generative-ai": "^0.8.1", "@mongodb-js/compass-logging": "^1.2.14", + "@mongodb-js/connection-storage": "^0.8.1", "@mongodb-js/eslint-config-compass": "^1.0.17", "@mongodb-js/mocha-config-compass": "^1.3.7", "@mongodb-js/mongodb-constants": "^0.9.0", @@ -58557,6 +58568,7 @@ "@mongodb-js/compass-editor": "^0.21.1", "@mongodb-js/compass-field-store": "^9.0.19", "@mongodb-js/compass-logging": "^1.2.14", + "@mongodb-js/connection-storage": "^0.8.1", "@mongodb-js/eslint-config-compass": "^1.0.17", "@mongodb-js/mocha-config-compass": "^1.3.7", "@mongodb-js/prettier-config-compass": "^1.0.1", diff --git a/packages/compass-aggregations/package.json b/packages/compass-aggregations/package.json index 997ce399c45..d9162adea95 100644 --- a/packages/compass-aggregations/package.json +++ b/packages/compass-aggregations/package.json @@ -72,6 +72,7 @@ "@mongodb-js/compass-logging": "^1.2.14", "@mongodb-js/compass-utils": "^0.6.1", "@mongodb-js/compass-workspaces": "^0.5.1", + "@mongodb-js/connection-storage": "^0.8.1", "@mongodb-js/explain-plan-helper": "^1.1.10", "@mongodb-js/mongodb-constants": "^0.9.0", "@mongodb-js/my-queries-storage": "^0.5.1", diff --git a/packages/compass-aggregations/src/components/focus-mode/focus-mode-stage-editor.spec.tsx b/packages/compass-aggregations/src/components/focus-mode/focus-mode-stage-editor.spec.tsx index ea996661234..93d7a047f6b 100644 --- a/packages/compass-aggregations/src/components/focus-mode/focus-mode-stage-editor.spec.tsx +++ b/packages/compass-aggregations/src/components/focus-mode/focus-mode-stage-editor.spec.tsx @@ -6,18 +6,28 @@ import { Provider } from 'react-redux'; import configureStore from '../../../test/configure-store'; import { FocusModeStageEditor } from './focus-mode-stage-editor'; +import { ConnectionInfoProvider } from '@mongodb-js/connection-storage/provider'; const renderFocusModeStageEditor = ( props: Partial> = {} ) => { render( - - - + + + + ); }; diff --git a/packages/compass-aggregations/src/components/focus-mode/focus-mode.spec.tsx b/packages/compass-aggregations/src/components/focus-mode/focus-mode.spec.tsx index 233da5f7375..885ed0956b4 100644 --- a/packages/compass-aggregations/src/components/focus-mode/focus-mode.spec.tsx +++ b/packages/compass-aggregations/src/components/focus-mode/focus-mode.spec.tsx @@ -6,15 +6,25 @@ import { Provider } from 'react-redux'; import configureStore from '../../../test/configure-store'; import FocusMode from './focus-mode'; import { disableFocusMode, enableFocusMode } from '../../modules/focus-mode'; +import { ConnectionInfoProvider } from '@mongodb-js/connection-storage/provider'; const renderFocusMode = () => { const store = configureStore({ pipeline: [{ $match: { _id: 1 } }, { $limit: 10 }, { $out: 'out' }], }); render( - - - + + + + + ); return store; }; diff --git a/packages/compass-aggregations/src/components/pipeline-builder-workspace/index.spec.tsx b/packages/compass-aggregations/src/components/pipeline-builder-workspace/index.spec.tsx index 0e15d165d6a..1a464effb60 100644 --- a/packages/compass-aggregations/src/components/pipeline-builder-workspace/index.spec.tsx +++ b/packages/compass-aggregations/src/components/pipeline-builder-workspace/index.spec.tsx @@ -6,15 +6,25 @@ import { expect } from 'chai'; import configureStore from '../../../test/configure-store'; import { PipelineBuilderWorkspace } from '.'; import { toggleSidePanel } from '../../modules/side-panel'; +import { ConnectionInfoProvider } from '@mongodb-js/connection-storage/provider'; const renderBuilderWorkspace = ( props: Partial> = {} ) => { const store = configureStore(); render( - - - + + + + + ); return store; }; diff --git a/packages/compass-aggregations/src/components/pipeline-builder-workspace/pipeline-as-text-workspace/index.spec.tsx b/packages/compass-aggregations/src/components/pipeline-builder-workspace/pipeline-as-text-workspace/index.spec.tsx index 1c3607c0c2a..c11028ab060 100644 --- a/packages/compass-aggregations/src/components/pipeline-builder-workspace/pipeline-as-text-workspace/index.spec.tsx +++ b/packages/compass-aggregations/src/components/pipeline-builder-workspace/pipeline-as-text-workspace/index.spec.tsx @@ -7,14 +7,24 @@ import { Provider } from 'react-redux'; import configureStore from '../../../../test/configure-store'; import { PipelineAsTextWorkspace } from '.'; +import { ConnectionInfoProvider } from '@mongodb-js/connection-storage/provider'; const renderPipelineAsTextWorkspace = ( props: Partial> = {} ) => { render( - - - + + + + + ); }; diff --git a/packages/compass-aggregations/src/components/pipeline-builder-workspace/pipeline-as-text-workspace/pipeline-editor.spec.tsx b/packages/compass-aggregations/src/components/pipeline-builder-workspace/pipeline-as-text-workspace/pipeline-editor.spec.tsx index d9bb32d7638..4f6fe07c326 100644 --- a/packages/compass-aggregations/src/components/pipeline-builder-workspace/pipeline-as-text-workspace/pipeline-editor.spec.tsx +++ b/packages/compass-aggregations/src/components/pipeline-builder-workspace/pipeline-as-text-workspace/pipeline-editor.spec.tsx @@ -9,23 +9,33 @@ import configureStore from '../../../../test/configure-store'; import { PipelineEditor } from './pipeline-editor'; import { PipelineParserError } from '../../../modules/pipeline-builder/pipeline-parser/utils'; +import { ConnectionInfoProvider } from '@mongodb-js/connection-storage/provider'; const renderPipelineEditor = ( props: Partial> = {} ) => { render( - - {}} - num_stages={1} - {...props} - /> - + + + {}} + num_stages={1} + {...props} + /> + + ); }; diff --git a/packages/compass-aggregations/src/components/pipeline-builder-workspace/pipeline-as-text-workspace/pipeline-editor.tsx b/packages/compass-aggregations/src/components/pipeline-builder-workspace/pipeline-as-text-workspace/pipeline-editor.tsx index 823d0264af2..dc0d3eca95d 100644 --- a/packages/compass-aggregations/src/components/pipeline-builder-workspace/pipeline-as-text-workspace/pipeline-editor.tsx +++ b/packages/compass-aggregations/src/components/pipeline-builder-workspace/pipeline-as-text-workspace/pipeline-editor.tsx @@ -21,6 +21,7 @@ import { changeEditorValue } from '../../../modules/pipeline-builder/text-editor import type { PipelineParserError } from '../../../modules/pipeline-builder/pipeline-parser/utils'; import { useLoggerAndTelemetry } from '@mongodb-js/compass-logging/provider'; import { useAutocompleteFields } from '@mongodb-js/compass-field-store'; +import { useConnectionInfo } from '@mongodb-js/connection-storage/provider'; const containerStyles = css({ position: 'relative', @@ -78,7 +79,8 @@ export const PipelineEditor: React.FunctionComponent = ({ serverVersion, onChangePipelineText, }) => { - const fields = useAutocompleteFields(namespace); + const connectionInfo = useConnectionInfo(); + const fields = useAutocompleteFields(connectionInfo, namespace); const { track } = useLoggerAndTelemetry('COMPASS-AGGREGATIONS-UI'); const editorInitialValueRef = useRef(pipelineText); const editorCurrentValueRef = useRef(pipelineText); diff --git a/packages/compass-aggregations/src/components/pipeline-builder-workspace/pipeline-builder-ui-workspace/index.spec.tsx b/packages/compass-aggregations/src/components/pipeline-builder-workspace/pipeline-builder-ui-workspace/index.spec.tsx index 7725995bdcf..c1d3da262cc 100644 --- a/packages/compass-aggregations/src/components/pipeline-builder-workspace/pipeline-builder-ui-workspace/index.spec.tsx +++ b/packages/compass-aggregations/src/components/pipeline-builder-workspace/pipeline-builder-ui-workspace/index.spec.tsx @@ -4,6 +4,7 @@ import { expect } from 'chai'; import { Provider } from 'react-redux'; import configureStore from '../../../../test/configure-store'; import PipelineBuilderUIWorkspace from '.'; +import { ConnectionInfoProvider } from '@mongodb-js/connection-storage/provider'; const SOURCE_PIPELINE = [ { $match: { _id: 1 } }, @@ -13,14 +14,23 @@ const SOURCE_PIPELINE = [ const renderPipelineBuilderUIWorkspace = (props = {}, options = {}) => { render( - - - + + + + ); }; diff --git a/packages/compass-aggregations/src/components/pipeline-results-workspace/pipeline-results-list.spec.tsx b/packages/compass-aggregations/src/components/pipeline-results-workspace/pipeline-results-list.spec.tsx index ed8e52f9181..d0e84b4e462 100644 --- a/packages/compass-aggregations/src/components/pipeline-results-workspace/pipeline-results-list.spec.tsx +++ b/packages/compass-aggregations/src/components/pipeline-results-workspace/pipeline-results-list.spec.tsx @@ -1,52 +1,59 @@ -import React from 'react'; +import React, { type ComponentProps } from 'react'; import HadronDocument from 'hadron-document'; import { render, screen } from '@testing-library/react'; import { expect } from 'chai'; import PipelineResultsList from './pipeline-results-list'; +import { ConnectionInfoProvider } from '@mongodb-js/connection-storage/provider'; -describe('PipelineResultsList', function () { - it('does not render when documents are empty', function () { - render( +function renderPipelineResultsList( + props?: Partial> +) { + render( + - ); + + ); +} + +describe('PipelineResultsList', function () { + it('does not render when documents are empty', function () { + renderPipelineResultsList(); expect(() => { screen.getByTestId('document-list-item'); }).to.throw; }); it('renders list view', function () { - render( - - ); + renderPipelineResultsList({ + documents: [new HadronDocument({ id: 1 }), new HadronDocument({ id: 2 })], + }); expect( document.querySelectorAll('[data-testid="document-list-item"]') ).to.have.lengthOf(2); }); it('renders json view', function () { - render( - - ); + renderPipelineResultsList({ + documents: [ + new HadronDocument({ id: 3 }), + new HadronDocument({ id: 4 }), + new HadronDocument({ id: 5 }), + ], + view: 'json', + }); expect( document.querySelectorAll('[data-testid="document-json-item"]') ).to.have.lengthOf(3); diff --git a/packages/compass-aggregations/src/components/stage-editor/stage-editor.spec.tsx b/packages/compass-aggregations/src/components/stage-editor/stage-editor.spec.tsx index 809a399f7e9..29d10d91f41 100644 --- a/packages/compass-aggregations/src/components/stage-editor/stage-editor.spec.tsx +++ b/packages/compass-aggregations/src/components/stage-editor/stage-editor.spec.tsx @@ -4,6 +4,7 @@ import sinon from 'sinon'; import { expect } from 'chai'; import { StageEditor } from './stage-editor'; +import { ConnectionInfoProvider } from '@mongodb-js/connection-storage/provider'; describe('StageEditor [Component]', function () { let component: ReturnType | null; @@ -13,18 +14,27 @@ describe('StageEditor [Component]', function () { beforeEach(function () { component = mount( - + + + ); }); diff --git a/packages/compass-aggregations/src/components/stage-editor/stage-editor.tsx b/packages/compass-aggregations/src/components/stage-editor/stage-editor.tsx index 15952f95e46..851f44d808d 100644 --- a/packages/compass-aggregations/src/components/stage-editor/stage-editor.tsx +++ b/packages/compass-aggregations/src/components/stage-editor/stage-editor.tsx @@ -25,6 +25,7 @@ import { mapPipelineModeToEditorViewType } from '../../modules/pipeline-builder/ import type { RootState } from '../../modules'; import type { PipelineParserError } from '../../modules/pipeline-builder/pipeline-parser/utils'; import { useAutocompleteFields } from '@mongodb-js/compass-field-store'; +import { useConnectionInfo } from '@mongodb-js/connection-storage/provider'; const editorContainerStyles = css({ display: 'flex', @@ -102,7 +103,8 @@ export const StageEditor = ({ const editorCurrentValueRef = useRef(stageValue); editorCurrentValueRef.current = stageValue; - const fields = useAutocompleteFields(namespace); + const connectionInfo = useConnectionInfo(); + const fields = useAutocompleteFields(connectionInfo, namespace); const { utmSource, utmMedium } = useRequiredURLSearchParams(); diff --git a/packages/compass-aggregations/src/components/stage-wizard/index.spec.tsx b/packages/compass-aggregations/src/components/stage-wizard/index.spec.tsx index d698a7f6eb4..aea90c52ebc 100644 --- a/packages/compass-aggregations/src/components/stage-wizard/index.spec.tsx +++ b/packages/compass-aggregations/src/components/stage-wizard/index.spec.tsx @@ -5,26 +5,36 @@ import { render, screen } from '@testing-library/react'; import { expect } from 'chai'; import sinon from 'sinon'; import * as StageWizardUseCases from '../aggregation-side-panel/stage-wizard-use-cases'; +import { ConnectionInfoProvider } from '@mongodb-js/connection-storage/provider'; const renderStageWizard = ( props: Partial> = {} ) => { return render( - {}} - onCancel={() => {}} - onChange={() => {}} - syntaxError={null} - value={null} - useCaseId="test" - index={0} - setNodeRef={() => {}} - style={{}} - listeners={undefined} - previousStageFields={[]} - {...props} - /> + + {}} + onCancel={() => {}} + onChange={() => {}} + syntaxError={null} + value={null} + useCaseId="test" + index={0} + setNodeRef={() => {}} + style={{}} + listeners={undefined} + previousStageFields={[]} + {...props} + /> + ); }; diff --git a/packages/compass-aggregations/src/components/stage-wizard/index.tsx b/packages/compass-aggregations/src/components/stage-wizard/index.tsx index 10508f798ce..fd3533fca49 100644 --- a/packages/compass-aggregations/src/components/stage-wizard/index.tsx +++ b/packages/compass-aggregations/src/components/stage-wizard/index.tsx @@ -34,6 +34,7 @@ import type { SortableProps } from '../pipeline-builder-workspace/pipeline-build import type { DocumentSchema } from '../../utils/get-schema'; import type { TypeCastTypes } from 'hadron-type-checker'; import { useFieldsSchema } from '@mongodb-js/compass-field-store'; +import { useConnectionInfo } from '@mongodb-js/connection-storage/provider'; const containerStyles = css({ display: 'flex', @@ -162,7 +163,8 @@ export const StageWizard = ({ ...sortableProps }: StageWizardProps) => { const { returnFocus, focusContainerRef } = useGrabFocus(); - const fieldsSchema = useFieldsSchema(namespace); + const connectionInfo = useConnectionInfo(); + const fieldsSchema = useFieldsSchema(connectionInfo, namespace); const fields: DocumentSchema = useMemo(() => { function schemaTypeToKindaTypeCastType(type: string | string[]) { // we don't expect any handling for multi-type schemas, pick the first diff --git a/packages/compass-crud/package.json b/packages/compass-crud/package.json index 2b489bba54f..d89565736c3 100644 --- a/packages/compass-crud/package.json +++ b/packages/compass-crud/package.json @@ -49,6 +49,7 @@ }, "devDependencies": { "@mongodb-js/compass-test-server": "^0.1.13", + "@mongodb-js/connection-info": "^0.1.5", "@mongodb-js/eslint-config-compass": "^1.0.17", "@mongodb-js/mocha-config-compass": "^1.3.7", "@mongodb-js/prettier-config-compass": "^1.0.1", @@ -80,6 +81,7 @@ "@mongodb-js/compass-logging": "^1.2.14", "@mongodb-js/compass-query-bar": "^8.25.1", "@mongodb-js/compass-workspaces": "^0.5.1", + "@mongodb-js/connection-storage": "^0.8.1", "@mongodb-js/explain-plan-helper": "^1.1.10", "@mongodb-js/my-queries-storage": "^0.5.1", "ag-grid-community": "^20.2.0", diff --git a/packages/compass-crud/src/components/crud-toolbar.spec.tsx b/packages/compass-crud/src/components/crud-toolbar.spec.tsx index 15564afb9c2..009e1a32df8 100644 --- a/packages/compass-crud/src/components/crud-toolbar.spec.tsx +++ b/packages/compass-crud/src/components/crud-toolbar.spec.tsx @@ -19,6 +19,8 @@ import { compassFavoriteQueryStorageAccess, compassRecentQueryStorageAccess, } from '@mongodb-js/my-queries-storage'; +import { ConnectionInfoProvider } from '@mongodb-js/connection-storage/provider'; +import type { ConnectionInfo } from '@mongodb-js/connection-info'; const noop = () => { /* noop */ @@ -53,39 +55,47 @@ describe('CrudToolbar Component', function () { function renderCrudToolbar( props?: Partial> ) { + const CONNECTION_INFO: ConnectionInfo = { + id: '1234', + connectionOptions: { + connectionString: 'mongodb://webscales.com:27017', + }, + }; const appRegistry = new AppRegistry(); const queryBarProps = {}; return render( - - - + + + + + ); } diff --git a/packages/compass-crud/src/components/json-editor.tsx b/packages/compass-crud/src/components/json-editor.tsx index 380a5b0b25c..25f6a32c3d2 100644 --- a/packages/compass-crud/src/components/json-editor.tsx +++ b/packages/compass-crud/src/components/json-editor.tsx @@ -22,6 +22,7 @@ import { import type { EditorRef, Action } from '@mongodb-js/compass-editor'; import type { CrudActions } from '../stores/crud-store'; import { useAutocompleteFields } from '@mongodb-js/compass-field-store'; +import { useConnectionInfo } from '@mongodb-js/connection-storage/provider'; const editorStyles = css({ minHeight: spacing[5] + spacing[3], @@ -156,7 +157,8 @@ const JSONEditor: React.FunctionComponent = ({ } }, [isExpanded]); - const fields = useAutocompleteFields(namespace); + const connectionInfo = useConnectionInfo(); + const fields = useAutocompleteFields(connectionInfo, namespace); const completer = useMemo(() => { return createDocumentAutocompleter( diff --git a/packages/compass-crud/src/index.ts b/packages/compass-crud/src/index.ts index 3d038098b2b..ceb5d93fdc6 100644 --- a/packages/compass-crud/src/index.ts +++ b/packages/compass-crud/src/index.ts @@ -6,6 +6,8 @@ import InsertDocumentDialog from './components/insert-document-dialog'; import { DocumentListWithReadonly } from './components/connected-document-list'; import { activateDocumentsPlugin } from './stores/crud-store'; import { + connectionScopedGlobalAppRegistryLocator, + type ConnectionScopedGlobalAppRegistryLocator, dataServiceLocator, type DataServiceLocator, } from '@mongodb-js/compass-connections/provider'; @@ -38,6 +40,10 @@ export const CompassDocumentsHadronPlugin = registerHadronPlugin( logger: createLoggerAndTelemetryLocator('COMPASS-CRUD-UI'), favoriteQueryStorageAccess: favoriteQueryStorageAccessLocator, recentQueryStorageAccess: recentQueryStorageAccessLocator, + connectionScopedGlobalAppRegistry: + connectionScopedGlobalAppRegistryLocator as ConnectionScopedGlobalAppRegistryLocator< + 'document-inserted' | 'documents-paginated' | 'documents-refreshed' + >, } ); diff --git a/packages/compass-crud/src/stores/crud-store.spec.ts b/packages/compass-crud/src/stores/crud-store.spec.ts index de16add8fd7..b2af7b676b1 100644 --- a/packages/compass-crud/src/stores/crud-store.spec.ts +++ b/packages/compass-crud/src/stores/crud-store.spec.ts @@ -190,6 +190,9 @@ describe('store', function () { logger: createNoopLoggerAndTelemetry(), favoriteQueryStorageAccess: compassFavoriteQueryStorageAccess, recentQueryStorageAccess: compassRecentQueryStorageAccess, + connectionScopedGlobalAppRegistry: { + emit() {}, + }, }, createActivateHelpers() ); @@ -291,6 +294,9 @@ describe('store', function () { logger: createNoopLoggerAndTelemetry(), favoriteQueryStorageAccess: compassFavoriteQueryStorageAccess, recentQueryStorageAccess: compassRecentQueryStorageAccess, + connectionScopedGlobalAppRegistry: { + emit() {}, + }, }, createActivateHelpers() ); @@ -348,6 +354,9 @@ describe('store', function () { logger: createNoopLoggerAndTelemetry(), favoriteQueryStorageAccess: compassFavoriteQueryStorageAccess, recentQueryStorageAccess: compassRecentQueryStorageAccess, + connectionScopedGlobalAppRegistry: { + emit() {}, + }, }, createActivateHelpers() ); @@ -398,6 +407,9 @@ describe('store', function () { logger: createNoopLoggerAndTelemetry(), favoriteQueryStorageAccess: compassFavoriteQueryStorageAccess, recentQueryStorageAccess: compassRecentQueryStorageAccess, + connectionScopedGlobalAppRegistry: { + emit() {}, + }, }, createActivateHelpers() ); @@ -447,6 +459,9 @@ describe('store', function () { logger: createNoopLoggerAndTelemetry(), favoriteQueryStorageAccess: compassFavoriteQueryStorageAccess, recentQueryStorageAccess: compassRecentQueryStorageAccess, + connectionScopedGlobalAppRegistry: { + emit() {}, + }, }, createActivateHelpers() ); @@ -564,6 +579,9 @@ describe('store', function () { logger: createNoopLoggerAndTelemetry(), favoriteQueryStorageAccess: compassFavoriteQueryStorageAccess, recentQueryStorageAccess: compassRecentQueryStorageAccess, + connectionScopedGlobalAppRegistry: { + emit() {}, + }, }, createActivateHelpers() ); @@ -850,6 +868,9 @@ describe('store', function () { logger: createNoopLoggerAndTelemetry(), favoriteQueryStorageAccess: compassFavoriteQueryStorageAccess, recentQueryStorageAccess: compassRecentQueryStorageAccess, + connectionScopedGlobalAppRegistry: { + emit() {}, + }, }, createActivateHelpers() ); @@ -959,6 +980,9 @@ describe('store', function () { logger: createNoopLoggerAndTelemetry(), favoriteQueryStorageAccess: compassFavoriteQueryStorageAccess, recentQueryStorageAccess: compassRecentQueryStorageAccess, + connectionScopedGlobalAppRegistry: { + emit() {}, + }, }, createActivateHelpers() ); @@ -998,6 +1022,9 @@ describe('store', function () { logger: createNoopLoggerAndTelemetry(), favoriteQueryStorageAccess: compassFavoriteQueryStorageAccess, recentQueryStorageAccess: compassRecentQueryStorageAccess, + connectionScopedGlobalAppRegistry: { + emit() {}, + }, }, createActivateHelpers() ); @@ -1081,6 +1108,9 @@ describe('store', function () { logger: createNoopLoggerAndTelemetry(), favoriteQueryStorageAccess: compassFavoriteQueryStorageAccess, recentQueryStorageAccess: compassRecentQueryStorageAccess, + connectionScopedGlobalAppRegistry: { + emit() {}, + }, }, createActivateHelpers() ); @@ -1242,6 +1272,9 @@ describe('store', function () { logger: createNoopLoggerAndTelemetry(), favoriteQueryStorageAccess: compassFavoriteQueryStorageAccess, recentQueryStorageAccess: compassRecentQueryStorageAccess, + connectionScopedGlobalAppRegistry: { + emit() {}, + }, }, createActivateHelpers() ); @@ -1417,6 +1450,9 @@ describe('store', function () { logger: createNoopLoggerAndTelemetry(), favoriteQueryStorageAccess: compassFavoriteQueryStorageAccess, recentQueryStorageAccess: compassRecentQueryStorageAccess, + connectionScopedGlobalAppRegistry: { + emit() {}, + }, }, createActivateHelpers() ); @@ -1592,6 +1628,9 @@ describe('store', function () { logger: createNoopLoggerAndTelemetry(), favoriteQueryStorageAccess: compassFavoriteQueryStorageAccess, recentQueryStorageAccess: compassRecentQueryStorageAccess, + connectionScopedGlobalAppRegistry: { + emit() {}, + }, }, createActivateHelpers() ); @@ -1779,6 +1818,9 @@ describe('store', function () { logger: createNoopLoggerAndTelemetry(), favoriteQueryStorageAccess: compassFavoriteQueryStorageAccess, recentQueryStorageAccess: compassRecentQueryStorageAccess, + connectionScopedGlobalAppRegistry: { + emit() {}, + }, }, createActivateHelpers() ); @@ -1824,6 +1866,9 @@ describe('store', function () { logger: createNoopLoggerAndTelemetry(), favoriteQueryStorageAccess: compassFavoriteQueryStorageAccess, recentQueryStorageAccess: compassRecentQueryStorageAccess, + connectionScopedGlobalAppRegistry: { + emit() {}, + }, }, createActivateHelpers() ); @@ -1866,6 +1911,9 @@ describe('store', function () { logger: createNoopLoggerAndTelemetry(), favoriteQueryStorageAccess: compassFavoriteQueryStorageAccess, recentQueryStorageAccess: compassRecentQueryStorageAccess, + connectionScopedGlobalAppRegistry: { + emit() {}, + }, }, createActivateHelpers() ); @@ -1906,6 +1954,9 @@ describe('store', function () { logger: createNoopLoggerAndTelemetry(), favoriteQueryStorageAccess: compassFavoriteQueryStorageAccess, recentQueryStorageAccess: compassRecentQueryStorageAccess, + connectionScopedGlobalAppRegistry: { + emit() {}, + }, }, createActivateHelpers() ); @@ -1986,6 +2037,9 @@ describe('store', function () { logger: createNoopLoggerAndTelemetry(), favoriteQueryStorageAccess: compassFavoriteQueryStorageAccess, recentQueryStorageAccess: compassRecentQueryStorageAccess, + connectionScopedGlobalAppRegistry: { + emit() {}, + }, }, createActivateHelpers() ); @@ -2035,6 +2089,9 @@ describe('store', function () { logger: createNoopLoggerAndTelemetry(), favoriteQueryStorageAccess: compassFavoriteQueryStorageAccess, recentQueryStorageAccess: compassRecentQueryStorageAccess, + connectionScopedGlobalAppRegistry: { + emit() {}, + }, }, createActivateHelpers() ); @@ -2081,6 +2138,9 @@ describe('store', function () { logger: createNoopLoggerAndTelemetry(), favoriteQueryStorageAccess: compassFavoriteQueryStorageAccess, recentQueryStorageAccess: compassRecentQueryStorageAccess, + connectionScopedGlobalAppRegistry: { + emit() {}, + }, }, createActivateHelpers() ); @@ -2129,6 +2189,9 @@ describe('store', function () { logger: createNoopLoggerAndTelemetry(), favoriteQueryStorageAccess: compassFavoriteQueryStorageAccess, recentQueryStorageAccess: compassRecentQueryStorageAccess, + connectionScopedGlobalAppRegistry: { + emit() {}, + }, }, createActivateHelpers() ); @@ -2184,6 +2247,9 @@ describe('store', function () { logger: createNoopLoggerAndTelemetry(), favoriteQueryStorageAccess: compassFavoriteQueryStorageAccess, recentQueryStorageAccess: compassRecentQueryStorageAccess, + connectionScopedGlobalAppRegistry: { + emit() {}, + }, }, createActivateHelpers() ); @@ -2254,6 +2320,9 @@ describe('store', function () { logger: createNoopLoggerAndTelemetry(), favoriteQueryStorageAccess: compassFavoriteQueryStorageAccess, recentQueryStorageAccess: compassRecentQueryStorageAccess, + connectionScopedGlobalAppRegistry: { + emit() {}, + }, }, createActivateHelpers() ); @@ -2365,6 +2434,9 @@ describe('store', function () { logger: createNoopLoggerAndTelemetry(), favoriteQueryStorageAccess: compassFavoriteQueryStorageAccess, recentQueryStorageAccess: compassRecentQueryStorageAccess, + connectionScopedGlobalAppRegistry: { + emit() {}, + }, }, createActivateHelpers() ); @@ -2816,6 +2888,9 @@ describe('store', function () { }, }, recentQueryStorageAccess: compassRecentQueryStorageAccess, + connectionScopedGlobalAppRegistry: { + emit() {}, + }, }, createActivateHelpers() ); @@ -2875,6 +2950,9 @@ describe('store', function () { logger: createNoopLoggerAndTelemetry(), favoriteQueryStorageAccess: compassFavoriteQueryStorageAccess, recentQueryStorageAccess: compassRecentQueryStorageAccess, + connectionScopedGlobalAppRegistry: { + emit() {}, + }, }, createActivateHelpers() ); @@ -2964,6 +3042,9 @@ describe('store', function () { logger: createNoopLoggerAndTelemetry(), favoriteQueryStorageAccess: compassFavoriteQueryStorageAccess, recentQueryStorageAccess: compassRecentQueryStorageAccess, + connectionScopedGlobalAppRegistry: { + emit() {}, + }, }, createActivateHelpers() ); @@ -3029,6 +3110,9 @@ describe('store', function () { return recentQueriesStorage; }, }, + connectionScopedGlobalAppRegistry: { + emit() {}, + }, }, createActivateHelpers() ); diff --git a/packages/compass-crud/src/stores/crud-store.ts b/packages/compass-crud/src/stores/crud-store.ts index 33c72809f1c..5c6647ed3f4 100644 --- a/packages/compass-crud/src/stores/crud-store.ts +++ b/packages/compass-crud/src/stores/crud-store.ts @@ -19,6 +19,7 @@ import type { RecentQueryStorageAccess, RecentQueryStorage, } from '@mongodb-js/my-queries-storage/provider'; +import { type ConnectionScopedGlobalAppRegistry } from '@mongodb-js/compass-connections/provider'; import { countDocuments, @@ -391,6 +392,9 @@ class CrudStoreImpl preferences: PreferencesAccess; localAppRegistry: Pick; globalAppRegistry: Pick; + connectionScopedGlobalAppRegistry: ConnectionScopedGlobalAppRegistry< + 'documents-refreshed' | 'documents-paginated' | 'document-inserted' + >; favoriteQueriesStorage?: FavoriteQueryStorage; recentQueriesStorage?: RecentQueryStorage; logger: LoggerAndTelemetry; @@ -404,6 +408,7 @@ class CrudStoreImpl | 'dataService' | 'localAppRegistry' | 'globalAppRegistry' + | 'connectionScopedGlobalAppRegistry' | 'preferences' | 'logger' > & { @@ -418,6 +423,8 @@ class CrudStoreImpl this.dataService = services.dataService; this.localAppRegistry = services.localAppRegistry; this.globalAppRegistry = services.globalAppRegistry; + this.connectionScopedGlobalAppRegistry = + services.connectionScopedGlobalAppRegistry; this.preferences = services.preferences; this.logger = services.logger; this.instance = services.instance; @@ -926,7 +933,7 @@ class CrudStoreImpl resultId: resultId(), abortController: null, }); - this.globalAppRegistry.emit('documents-paginated', { + this.connectionScopedGlobalAppRegistry.emit('documents-paginated', { ns: this.state.ns, docs: [documents[0]?.generateObject()], }); @@ -1363,7 +1370,7 @@ class CrudStoreImpl multiple: true, docs, }; - this.globalAppRegistry.emit('document-inserted', payload); + this.connectionScopedGlobalAppRegistry.emit('document-inserted', payload); this.state.insert = this.getInitialInsertState(); } catch (error) { @@ -1417,7 +1424,7 @@ class CrudStoreImpl multiple: false, docs: [doc], }; - this.globalAppRegistry.emit('document-inserted', payload); + this.connectionScopedGlobalAppRegistry.emit('document-inserted', payload); this.state.insert = this.getInitialInsertState(); } catch (error) { @@ -1730,7 +1737,7 @@ class CrudStoreImpl shardKeys, }); - this.globalAppRegistry.emit('documents-refreshed', { + this.connectionScopedGlobalAppRegistry.emit('documents-refreshed', { ns: this.state.ns, docs: [docs[0]?.generateObject()], }); @@ -1941,6 +1948,9 @@ export type DocumentsPluginServices = { instance: MongoDBInstance; localAppRegistry: Pick; globalAppRegistry: Pick; + connectionScopedGlobalAppRegistry: ConnectionScopedGlobalAppRegistry< + 'documents-refreshed' | 'documents-paginated' | 'document-inserted' + >; preferences: PreferencesAccess; logger: LoggerAndTelemetry; favoriteQueryStorageAccess?: FavoriteQueryStorageAccess; @@ -1953,6 +1963,7 @@ export function activateDocumentsPlugin( instance, localAppRegistry, globalAppRegistry, + connectionScopedGlobalAppRegistry, preferences, logger, favoriteQueryStorageAccess, @@ -1969,6 +1980,7 @@ export function activateDocumentsPlugin( dataService, localAppRegistry, globalAppRegistry, + connectionScopedGlobalAppRegistry, preferences, logger, favoriteQueryStorage: favoriteQueryStorageAccess?.getStorage(), diff --git a/packages/compass-field-store/package.json b/packages/compass-field-store/package.json index 31ea8a30b42..e4f3c36b710 100644 --- a/packages/compass-field-store/package.json +++ b/packages/compass-field-store/package.json @@ -70,6 +70,7 @@ "xvfb-maybe": "^0.2.1" }, "dependencies": { + "@mongodb-js/connection-info": "^0.1.5", "hadron-app-registry": "^9.1.8", "lodash": "^4.17.21", "mongodb-schema": "^12.1.0", diff --git a/packages/compass-field-store/src/index.spec.ts b/packages/compass-field-store/src/index.spec.ts index 945d7a0e948..8bddcde26b7 100644 --- a/packages/compass-field-store/src/index.spec.ts +++ b/packages/compass-field-store/src/index.spec.ts @@ -4,10 +4,17 @@ import FieldStorePlugin from './'; import { useAutocompleteFields } from './'; import { expect } from 'chai'; import AppRegistry from 'hadron-app-registry'; +import type { ConnectionInfo } from '@mongodb-js/connection-info'; describe('useAutocompleteFields', function () { let appRegistry: AppRegistry; let Plugin: ReturnType; + const connectionInfo: ConnectionInfo = { + id: '1234', + connectionOptions: { + connectionString: 'mongodb://webscales.com:27017', + }, + }; beforeEach(function () { appRegistry = new AppRegistry(); @@ -19,19 +26,26 @@ describe('useAutocompleteFields', function () { afterEach(cleanup); it('returns empty list when namespace schema is not available', function () { - const { result } = renderHook(() => useAutocompleteFields('foo.bar'), { - wrapper: Plugin, - }); + const { result } = renderHook( + () => useAutocompleteFields(connectionInfo, 'foo.bar'), + { + wrapper: Plugin, + } + ); expect(result.current).to.deep.eq([]); }); it('updates when fields are added', async function () { - const { result } = renderHook(() => useAutocompleteFields('foo.bar'), { - wrapper: Plugin, - }); + const { result } = renderHook( + () => useAutocompleteFields(connectionInfo, 'foo.bar'), + { + wrapper: Plugin, + } + ); appRegistry.emit('document-inserted', { + connectionInfo: connectionInfo, ns: 'foo.bar', docs: [{ foo: 1 }, { bar: false }, { buz: 'str' }], }); diff --git a/packages/compass-field-store/src/modules/index.ts b/packages/compass-field-store/src/modules/index.ts index 47d90120c06..ad7347bbc49 100644 --- a/packages/compass-field-store/src/modules/index.ts +++ b/packages/compass-field-store/src/modules/index.ts @@ -1,19 +1,29 @@ import type { Reducer } from 'redux'; import { uniq } from 'lodash'; import type { SchemaField } from 'mongodb-schema'; +import type { ConnectionInfo } from '@mongodb-js/connection-info'; import type { SchemaFieldSubset } from './fields'; import { mergeSchema } from './fields'; export const CHANGE_FIELDS = 'field-store/CHANGE_FIELDS'; -export type FieldsState = Record< - string, +type Namespace = string; + +export type NamespacesFieldsState = Record< + Namespace, { fields: Record; topLevelFields: string[] } >; -const reducer: Reducer = (state = {}, action) => { +export type ConnectionNamespacesState = Record< + ConnectionInfo['id'], + NamespacesFieldsState +>; + +const reducer: Reducer = (state = {}, action) => { if (action.type === CHANGE_FIELDS) { - const currentNamespaceFields = state[action.namespace] ?? {}; + const currentConnectionNamespaces = state[action.connectionInfoId] ?? {}; + const currentNamespaceFields = + currentConnectionNamespaces[action.namespace] ?? {}; const { fields, topLevelFields } = mergeSchema( currentNamespaceFields.fields ?? {}, action.schemaFields @@ -21,11 +31,14 @@ const reducer: Reducer = (state = {}, action) => { return { ...state, - [action.namespace]: { - fields, - topLevelFields: uniq( - (currentNamespaceFields.topLevelFields ?? []).concat(topLevelFields) - ), + [action.connectionInfoId]: { + ...state[action.connectionInfoId], + [action.namespace]: { + fields, + topLevelFields: uniq( + (currentNamespaceFields.topLevelFields ?? []).concat(topLevelFields) + ), + }, }, }; } @@ -33,10 +46,12 @@ const reducer: Reducer = (state = {}, action) => { }; export const changeFields = ( + connectionInfoId: ConnectionInfo['id'], namespace: string, schemaFields: SchemaField[] ) => ({ type: CHANGE_FIELDS, + connectionInfoId, namespace, schemaFields, }); diff --git a/packages/compass-field-store/src/stores/context.ts b/packages/compass-field-store/src/stores/context.ts index 1340c679e3e..9a761011003 100644 --- a/packages/compass-field-store/src/stores/context.ts +++ b/packages/compass-field-store/src/stores/context.ts @@ -1,29 +1,32 @@ import React, { useMemo } from 'react'; import type { ReactReduxContextValue, TypedUseSelectorHook } from 'react-redux'; import { createSelectorHook } from 'react-redux'; -import type { FieldsState } from '../modules'; +import type { ConnectionNamespacesState } from '../modules'; import type { SchemaFieldSubset } from '../modules/fields'; import { schemaFieldsToAutocompleteItems } from '../modules/fields'; +import type { ConnectionInfo } from '@mongodb-js/connection-info'; export const FieldStoreContext = React.createContext< - ReactReduxContextValue + ReactReduxContextValue >( // @ts-expect-error react-redux types null ); -const useSelector: TypedUseSelectorHook = +const useSelector: TypedUseSelectorHook = createSelectorHook(FieldStoreContext); const EMPTY_FIELDS_OBJECT = Object.create(null); export function useFieldsSchema( + connectionInfo: ConnectionInfo, namespace: string ): Readonly> { let fields: Record = EMPTY_FIELDS_OBJECT; try { fields = useSelector( - (state) => state[namespace]?.fields ?? EMPTY_FIELDS_OBJECT + (state) => + state[connectionInfo.id]?.[namespace]?.fields ?? EMPTY_FIELDS_OBJECT ); } catch (err) { // We can only end up with an error here if store is missing in context, @@ -36,9 +39,10 @@ export function useFieldsSchema( } export function useAutocompleteFields( + connectionInfo: ConnectionInfo, namespace: string ): ReturnType { - const fields = useFieldsSchema(namespace); + const fields = useFieldsSchema(connectionInfo, namespace); return useMemo(() => { return schemaFieldsToAutocompleteItems(fields); }, [fields]); diff --git a/packages/compass-field-store/src/stores/store.spec.ts b/packages/compass-field-store/src/stores/store.spec.ts index 9d3f56a5f5a..ab51424b9d2 100644 --- a/packages/compass-field-store/src/stores/store.spec.ts +++ b/packages/compass-field-store/src/stores/store.spec.ts @@ -5,17 +5,25 @@ import { expect } from 'chai'; import sinon from 'sinon'; import { schemaFieldsToAutocompleteItems } from '../modules/fields'; import { once } from 'events'; +import type { ConnectionInfo } from '@mongodb-js/connection-info'; describe('FieldStore', function () { let deactivate = () => {}; let store: ReturnType['store']; let appRegistry: AppRegistry; + const connectionInfo: ConnectionInfo = { + id: '1234', + connectionOptions: { + connectionString: 'mongodb://webscales.com:27017', + }, + }; async function documentsChanged( docs: any | any[], eventName = 'documents-refreshed' ) { appRegistry.emit(eventName, { + connectionInfo, ns: 'test.test', docs: Array.isArray(docs) ? docs : [docs], }); @@ -24,6 +32,7 @@ describe('FieldStore', function () { function schemaChanged(schema: any = schemaFixture) { appRegistry.emit('schema-analyzed', { + connectionInfo, ns: 'test.test', schema, }); @@ -70,7 +79,7 @@ describe('FieldStore', function () { it('on schema store trigger', function () { schemaChanged(); - const state = store.getState()['test.test']; + const state = store.getState()[connectionInfo.id]['test.test']; expect(Object.keys(state.fields)).to.have.all.members([ '_id', 'review', @@ -86,7 +95,7 @@ describe('FieldStore', function () { it('on documents-refreshed', async function () { await documentsChanged(doc, 'documents-refreshed'); - const state = store.getState()['test.test']; + const state = store.getState()[connectionInfo.id]['test.test']; expect(Object.keys(state.fields)).to.have.all.members([ 'harry', 'potter', @@ -98,7 +107,7 @@ describe('FieldStore', function () { it('on document-inserted', async function () { await documentsChanged(doc, 'document-inserted'); - const state = store.getState()['test.test']; + const state = store.getState()[connectionInfo.id]['test.test']; expect(Object.keys(state.fields)).to.have.all.members([ 'harry', 'potter', @@ -110,7 +119,7 @@ describe('FieldStore', function () { it('on documents-paginated', async function () { await documentsChanged(doc, 'documents-paginated'); - const state = store.getState()['test.test']; + const state = store.getState()[connectionInfo.id]['test.test']; expect(Object.keys(state.fields)).to.have.all.members([ 'harry', 'potter', @@ -127,6 +136,7 @@ describe('FieldStore', function () { await documentsChanged(doc); // eslint-disable-next-line @typescript-eslint/unbound-method expect(appRegistry.emit).to.have.been.calledWithMatch('fields-changed', { + connectionInfo, ns: 'test.test', fields: { harry: { name: 'harry', path: ['harry'], count: 1, type: 'Number' }, @@ -164,7 +174,7 @@ describe('FieldStore', function () { it('samples a single document', async function () { const doc = { harry: 1, potter: true }; await documentsChanged(doc); - const state = store.getState()['test.test']; + const state = store.getState()[connectionInfo.id]['test.test']; expect(Object.keys(state.fields)).to.have.all.members([ 'harry', 'potter', @@ -195,7 +205,7 @@ describe('FieldStore', function () { { ron: 'test', weasley: null }, ]; await documentsChanged(docs); - const state = store.getState()['test.test']; + const state = store.getState()[connectionInfo.id]['test.test']; expect(Object.keys(state.fields)).to.have.all.members([ 'harry', 'potter', @@ -243,7 +253,7 @@ describe('FieldStore', function () { await documentsChanged(doc); const doc2 = { hermione: 0, granger: false }; await documentsChanged(doc2); - const state = store.getState()['test.test']; + const state = store.getState()[connectionInfo.id]['test.test']; expect(Object.keys(state.fields)).to.have.all.members([ 'harry', 'potter', @@ -290,7 +300,7 @@ describe('FieldStore', function () { const doc = { harry: 1, potter: true }; await documentsChanged(doc); schemaChanged(); - const state = store.getState()['test.test']; + const state = store.getState()[connectionInfo.id]['test.test']; expect(Object.keys(state.fields)).to.have.all.members([ 'harry', 'potter', @@ -398,20 +408,20 @@ describe('FieldStore', function () { it('flattens the schema', async function () { await documentsChanged({ a: { b: { c: 1 } } }); - const state = store.getState()['test.test']; + const state = store.getState()[connectionInfo.id]['test.test']; expect(state.fields).to.have.all.keys(['a', 'a.b', 'a.b.c']); }); it('maintains list of root fields', async function () { await documentsChanged({ a: { b: { c: 1 } }, d: 5, e: { f: 3 } }); - const state = store.getState()['test.test']; + const state = store.getState()[connectionInfo.id]['test.test']; expect(state.topLevelFields).to.have.all.members(['a', 'd', 'e']); }); describe('multidimensional arrays', function () { it('identifies empty 1d arrays', async function () { await documentsChanged({ a: [] }); - const state = store.getState()['test.test']; + const state = store.getState()[connectionInfo.id]['test.test']; const expected = { a: { count: 1, @@ -425,7 +435,7 @@ describe('FieldStore', function () { it('identifies populated 1d arrays', async function () { await documentsChanged({ a: [1, 2, 3] }); - const state = store.getState()['test.test']; + const state = store.getState()[connectionInfo.id]['test.test']; const expected = { a: { count: 1, @@ -444,7 +454,7 @@ describe('FieldStore', function () { ['2_1', '2_2', '2_3'], ], }); - const state = store.getState()['test.test']; + const state = store.getState()[connectionInfo.id]['test.test']; const expected = { a: { count: 1, @@ -470,7 +480,7 @@ describe('FieldStore', function () { ], ], }); - const state = store.getState()['test.test']; + const state = store.getState()[connectionInfo.id]['test.test']; const expected = { a: { count: 1, @@ -504,14 +514,16 @@ describe('FieldStore', function () { // Call that matters, the one that should be kept around await documentsChanged({ a: [1, 2, 3] }); - expect(store.getState()['test.test'].fields).to.be.deep.equal(expected); + expect( + store.getState()[connectionInfo.id]['test.test'].fields + ).to.be.deep.equal(expected); }); }); describe('mixed nested arrays and subdocuments', function () { it('identifies 1d arrays of subdocuments', async function () { await documentsChanged({ a: [{ b: 'foo' }, { b: 'bar' }] }); - const state = store.getState()['test.test']; + const state = store.getState()[connectionInfo.id]['test.test']; const expected = { a: { count: 1, @@ -536,7 +548,7 @@ describe('FieldStore', function () { [{ b: 'foo' }, { b: 'bar' }], ], }); - const state = store.getState()['test.test']; + const state = store.getState()[connectionInfo.id]['test.test']; const expected = { a: { count: 1, @@ -558,7 +570,7 @@ describe('FieldStore', function () { await documentsChanged({ a: [{ b: { c: 'foo' } }, { b: { c: 'bar' } }], }); - const state = store.getState()['test.test']; + const state = store.getState()[connectionInfo.id]['test.test']; const expected = { a: { count: 1, @@ -632,7 +644,7 @@ describe('FieldStore', function () { ], }, }); - const state = store.getState()['test.test']; + const state = store.getState()[connectionInfo.id]['test.test']; expect(state.fields).to.be.deep.equal(expected); }); }); @@ -664,7 +676,7 @@ describe('FieldStore', function () { foo1: [{ age: 10, name: 'bazillion' }], }; await documentsChanged(doc); - const state = store.getState()['test.test']; + const state = store.getState()[connectionInfo.id]['test.test']; expect(state.fields).to.be.deep.equal(expected); }); it('handles path', async function () { @@ -693,7 +705,7 @@ describe('FieldStore', function () { foo1: [{ age: 10, path: 'bazillion' }], }; await documentsChanged(doc); - const state = store.getState()['test.test']; + const state = store.getState()[connectionInfo.id]['test.test']; expect(state.fields).to.be.deep.equal(expected); }); }); diff --git a/packages/compass-field-store/src/stores/store.ts b/packages/compass-field-store/src/stores/store.ts index 4c9ef3a2553..a1f93efca85 100644 --- a/packages/compass-field-store/src/stores/store.ts +++ b/packages/compass-field-store/src/stores/store.ts @@ -5,6 +5,7 @@ import parseSchema from 'mongodb-schema'; import type { AppRegistry, ActivateHelpers } from 'hadron-app-registry'; import { schemaFieldsToAutocompleteItems } from '../modules/fields'; import { FieldStoreContext } from './context'; +import type { ConnectionInfo } from '@mongodb-js/connection-info'; export function activatePlugin( _initialProps: unknown, @@ -13,9 +14,11 @@ export function activatePlugin( ) { const store = createStore(reducer); - const emitFieldsChanged = (ns: string) => { - const fieldsState = store.getState()[ns]; + const emitFieldsChanged = (connectionInfo: ConnectionInfo, ns: string) => { + const namespacesState = store.getState()[connectionInfo.id] ?? {}; + const fieldsState = namespacesState[ns]; globalAppRegistry.emit('fields-changed', { + connectionInfo, ns, ...fieldsState, autocompleteFields: schemaFieldsToAutocompleteItems(fieldsState.fields), @@ -23,16 +26,18 @@ export function activatePlugin( }; const onDocumentsChanged = async ({ + connectionInfo, ns, docs, }: { + connectionInfo: ConnectionInfo; ns: string; docs: Document[]; }) => { try { const { fields } = await parseSchema(docs); - store.dispatch(changeFields(ns, fields)); - emitFieldsChanged(ns); + store.dispatch(changeFields(connectionInfo.id, ns, fields)); + emitFieldsChanged(connectionInfo, ns); } catch { // ignore errors } @@ -47,9 +52,17 @@ export function activatePlugin( on( globalAppRegistry, 'schema-analyzed', - ({ ns, schema }: { ns: string; schema: Schema }) => { - store.dispatch(changeFields(ns, schema.fields)); - emitFieldsChanged(ns); + ({ + connectionInfo, + ns, + schema, + }: { + connectionInfo: ConnectionInfo; + ns: string; + schema: Schema; + }) => { + store.dispatch(changeFields(connectionInfo.id, ns, schema.fields)); + emitFieldsChanged(connectionInfo, ns); } ); diff --git a/packages/compass-home/src/components/home.tsx b/packages/compass-home/src/components/home.tsx index b26d9c9116b..904a43b2893 100644 --- a/packages/compass-home/src/components/home.tsx +++ b/packages/compass-home/src/components/home.tsx @@ -401,21 +401,21 @@ function Home({ - - {isConnected && connectionInfo && ( - - + + + {isConnected && connectionInfo && ( + - - - )} - + + )} + + {/* TODO(COMPASS-7397): Hide but keep it in scope if connected so that the connection import/export functionality can still diff --git a/packages/compass-indexes/src/components/create-index-form/create-index-form.tsx b/packages/compass-indexes/src/components/create-index-form/create-index-form.tsx index 1ab4a0b7937..f11c802ba36 100644 --- a/packages/compass-indexes/src/components/create-index-form/create-index-form.tsx +++ b/packages/compass-indexes/src/components/create-index-form/create-index-form.tsx @@ -1,6 +1,7 @@ import React, { useMemo } from 'react'; import { css, spacing, Accordion, Body } from '@mongodb-js/compass-components'; import { useAutocompleteFields } from '@mongodb-js/compass-field-store'; +import { useConnectionInfo } from '@mongodb-js/connection-storage/provider'; import { CreateIndexFields } from '../create-index-fields'; import { hasColumnstoreIndexesSupport } from '../../utils/columnstore-indexes'; import CheckboxInput from './checkbox-input'; @@ -39,7 +40,8 @@ function CreateIndexForm({ addField, removeField, }: CreateIndexFormProps) { - const schemaFields = useAutocompleteFields(namespace); + const connectionInfo = useConnectionInfo(); + const schemaFields = useAutocompleteFields(connectionInfo, namespace); const schemaFieldNames = useMemo(() => { return schemaFields .filter((field) => { diff --git a/packages/compass-indexes/src/components/indexes/indexes.spec.tsx b/packages/compass-indexes/src/components/indexes/indexes.spec.tsx index a5bf1cb61cd..7641d0a4594 100644 --- a/packages/compass-indexes/src/components/indexes/indexes.spec.tsx +++ b/packages/compass-indexes/src/components/indexes/indexes.spec.tsx @@ -16,6 +16,7 @@ import Indexes from './indexes'; import { setupStore } from '../../../test/setup-store'; import { searchIndexes } from '../../../test/fixtures/search-indexes'; import type { RootState } from '../../modules'; +import { ConnectionInfoProvider } from '@mongodb-js/connection-storage/provider'; const DEFAULT_PROPS: Partial = { regularIndexes: { indexes: [], error: null, isRefreshing: false }, @@ -43,9 +44,18 @@ const renderIndexes = (props: Partial = {}) => { Object.assign(store.getState(), allProps); render( - - - + + + + + ); return store; diff --git a/packages/compass-indexes/src/components/search-indexes-modals/base-search-index-modal.spec.tsx b/packages/compass-indexes/src/components/search-indexes-modals/base-search-index-modal.spec.tsx index 164ad403081..0464c65eaef 100644 --- a/packages/compass-indexes/src/components/search-indexes-modals/base-search-index-modal.spec.tsx +++ b/packages/compass-indexes/src/components/search-indexes-modals/base-search-index-modal.spec.tsx @@ -14,6 +14,7 @@ import { getCodemirrorEditorValue, setCodemirrorEditorValue, } from '@mongodb-js/compass-editor'; +import { ConnectionInfoProvider } from '@mongodb-js/connection-storage/provider'; function normalizedTemplateNamed(name: string) { const snippet = @@ -43,19 +44,28 @@ function renderBaseSearchIndexModal( props?: Partial> ) { return render( - + + + ); } diff --git a/packages/compass-indexes/src/components/search-indexes-modals/base-search-index-modal.tsx b/packages/compass-indexes/src/components/search-indexes-modals/base-search-index-modal.tsx index c0d38f6195b..d3d393c8923 100644 --- a/packages/compass-indexes/src/components/search-indexes-modals/base-search-index-modal.tsx +++ b/packages/compass-indexes/src/components/search-indexes-modals/base-search-index-modal.tsx @@ -35,6 +35,7 @@ import type { EditorRef } from '@mongodb-js/compass-editor'; import _parseShellBSON, { ParseMode } from 'ejson-shell-parser'; import type { Document } from 'mongodb'; import { useTrackOnChange } from '@mongodb-js/compass-logging/provider'; +import { useConnectionInfo } from '@mongodb-js/connection-storage/provider'; import { SearchIndexTemplateDropdown } from '../search-index-template-dropdown'; import { ATLAS_SEARCH_TEMPLATES, @@ -273,7 +274,8 @@ export const BaseSearchIndexModal: React.FunctionComponent< [setSearchIndexType, onChangeTemplate, setIndexDefinition] ); - const fields = useAutocompleteFields(namespace); + const connectionInfo = useConnectionInfo(); + const fields = useAutocompleteFields(connectionInfo, namespace); const completer = useMemo(() => { return createSearchIndexAutocompleter({ fields }); diff --git a/packages/compass-query-bar/package.json b/packages/compass-query-bar/package.json index 0411fc7a644..91ae31420ee 100644 --- a/packages/compass-query-bar/package.json +++ b/packages/compass-query-bar/package.json @@ -76,6 +76,7 @@ "@mongodb-js/compass-field-store": "^9.0.19", "@mongodb-js/compass-generative-ai": "^0.8.1", "@mongodb-js/compass-logging": "^1.2.14", + "@mongodb-js/connection-storage": "^0.8.1", "@mongodb-js/mongodb-constants": "^0.9.0", "@mongodb-js/my-queries-storage": "^0.5.1", "bson": "^6.5.0", diff --git a/packages/compass-query-bar/src/components/option-editor.spec.tsx b/packages/compass-query-bar/src/components/option-editor.spec.tsx index f59d8230eab..9d2ef703cf3 100644 --- a/packages/compass-query-bar/src/components/option-editor.spec.tsx +++ b/packages/compass-query-bar/src/components/option-editor.spec.tsx @@ -1,8 +1,10 @@ +import type { ComponentProps } from 'react'; import React from 'react'; import { expect } from 'chai'; import { cleanup, render, screen, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { OptionEditor } from './option-editor'; +import { ConnectionInfoProvider } from '@mongodb-js/connection-storage/provider'; class MockPasteEvent extends window.Event { constructor(private text: string) { @@ -15,6 +17,29 @@ class MockPasteEvent extends window.Event { }; } +function renderOptionEditor( + props?: Partial> +) { + render( + + {}} + value="" + {...props} + > + + ); +} + describe('OptionEditor', function () { beforeEach(function () { if ((process as any).type === 'renderer') { @@ -29,14 +54,7 @@ describe('OptionEditor', function () { describe('with autofix enabled', function () { it('fills the input with an empty object "{}" when empty on focus', async function () { - render( - {}} - value="" - > - ); + renderOptionEditor(); expect(screen.getByRole('textbox').textContent).to.eq(''); @@ -48,14 +66,9 @@ describe('OptionEditor', function () { }); it('does not change input value when empty on focus', async function () { - render( - {}} - value="{ foo: 1 }" - > - ); + renderOptionEditor({ + value: '{ foo: 1 }', + }); expect(screen.getByRole('textbox').textContent).to.eq('{ foo: 1 }'); @@ -67,14 +80,7 @@ describe('OptionEditor', function () { }); it('should adjust pasted query if pasting over empty brackets with the cursor in the middle', async function () { - render( - {}} - value="" - > - ); + renderOptionEditor(); userEvent.tab(); @@ -92,14 +98,7 @@ describe('OptionEditor', function () { }); it('should not modify user text whe pasting when cursor moved', async function () { - render( - {}} - value="" - > - ); + renderOptionEditor(); userEvent.tab(); @@ -119,14 +118,7 @@ describe('OptionEditor', function () { }); it('should not modify user text when pasting in empty input', async function () { - render( - {}} - value="" - > - ); + renderOptionEditor(); userEvent.tab(); userEvent.keyboard('{arrowright}{backspace}{backspace}{backspace}'); diff --git a/packages/compass-query-bar/src/components/option-editor.tsx b/packages/compass-query-bar/src/components/option-editor.tsx index 779eb8f26f4..a801fc80b68 100644 --- a/packages/compass-query-bar/src/components/option-editor.tsx +++ b/packages/compass-query-bar/src/components/option-editor.tsx @@ -19,6 +19,7 @@ import { usePreference } from 'compass-preferences-model/provider'; import { lenientlyFixQuery } from '../query/leniently-fix-query'; import type { RootState } from '../stores/query-bar-store'; import { useAutocompleteFields } from '@mongodb-js/compass-field-store'; +import { useConnectionInfo } from '@mongodb-js/connection-storage/provider'; const editorContainerStyles = css({ position: 'relative', @@ -135,7 +136,8 @@ export const OptionEditor: React.FunctionComponent = ({ ]; }, []); - const schemaFields = useAutocompleteFields(namespace); + const connectionInfo = useConnectionInfo(); + const schemaFields = useAutocompleteFields(connectionInfo, namespace); const completer = useMemo(() => { return createQueryAutocompleter({ diff --git a/packages/compass-query-bar/src/components/query-bar.spec.tsx b/packages/compass-query-bar/src/components/query-bar.spec.tsx index febd8c01456..42f0c23b59e 100644 --- a/packages/compass-query-bar/src/components/query-bar.spec.tsx +++ b/packages/compass-query-bar/src/components/query-bar.spec.tsx @@ -24,6 +24,7 @@ import { compassFavoriteQueryStorageAccess, compassRecentQueryStorageAccess, } from '@mongodb-js/my-queries-storage'; +import { ConnectionInfoProvider } from '@mongodb-js/connection-storage/provider'; const noop = () => { /* no op */ @@ -55,16 +56,25 @@ describe('QueryBar Component', function () { - - - + + + + + diff --git a/packages/compass-schema-validation/package.json b/packages/compass-schema-validation/package.json index 7c21f629639..d270e966464 100644 --- a/packages/compass-schema-validation/package.json +++ b/packages/compass-schema-validation/package.json @@ -75,6 +75,7 @@ "@mongodb-js/compass-editor": "^0.21.1", "@mongodb-js/compass-field-store": "^9.0.19", "@mongodb-js/compass-logging": "^1.2.14", + "@mongodb-js/connection-storage": "^0.8.1", "bson": "^6.5.0", "compass-preferences-model": "^2.18.1", "hadron-app-registry": "^9.1.8", diff --git a/packages/compass-schema-validation/src/components/validation-editor/validation-editor.spec.tsx b/packages/compass-schema-validation/src/components/validation-editor/validation-editor.spec.tsx index fc75062041d..9e0cac2329c 100644 --- a/packages/compass-schema-validation/src/components/validation-editor/validation-editor.spec.tsx +++ b/packages/compass-schema-validation/src/components/validation-editor/validation-editor.spec.tsx @@ -5,6 +5,7 @@ import sinon from 'sinon'; import ValidationEditor from '.'; import { CodemirrorMultilineEditor } from '@mongodb-js/compass-editor'; +import { ConnectionInfoProvider } from '@mongodb-js/connection-storage/provider'; describe('ValidationEditor [Component]', function () { context('when it is an editable mode', function () { @@ -28,18 +29,27 @@ describe('ValidationEditor [Component]', function () { beforeEach(function () { component = mount( - + + + ); }); @@ -76,18 +86,27 @@ describe('ValidationEditor [Component]', function () { beforeEach(function () { component = mount( - + + + ); }); diff --git a/packages/compass-schema-validation/src/components/validation-editor/validation-editor.tsx b/packages/compass-schema-validation/src/components/validation-editor/validation-editor.tsx index 14b1e2a9881..4fc2859fb99 100644 --- a/packages/compass-schema-validation/src/components/validation-editor/validation-editor.tsx +++ b/packages/compass-schema-validation/src/components/validation-editor/validation-editor.tsx @@ -19,6 +19,7 @@ import { createValidationAutocompleter, } from '@mongodb-js/compass-editor'; import { useAutocompleteFields } from '@mongodb-js/compass-field-store'; +import { useConnectionInfo } from '@mongodb-js/connection-storage/provider'; import type { Validation, @@ -79,7 +80,8 @@ const ValidationCodeEditor = ({ readOnly, serverVersion, }: ValidationCodeEditorProps) => { - const fields = useAutocompleteFields(namespace); + const connectionInfo = useConnectionInfo(); + const fields = useAutocompleteFields(connectionInfo, namespace); const completer = React.useMemo(() => { return createValidationAutocompleter({ fields, serverVersion }); diff --git a/packages/compass-schema-validation/src/components/validation-states/validation-states.spec.tsx b/packages/compass-schema-validation/src/components/validation-states/validation-states.spec.tsx index 9aa5cb1336b..eb819cbe153 100644 --- a/packages/compass-schema-validation/src/components/validation-states/validation-states.spec.tsx +++ b/packages/compass-schema-validation/src/components/validation-states/validation-states.spec.tsx @@ -12,6 +12,7 @@ import { Provider } from 'react-redux'; import ValidationStates from '.'; import ValidationEditor from '../validation-editor'; import { configureStore } from '../../stores/store'; +import { ConnectionInfoProvider } from '@mongodb-js/connection-storage/provider'; describe('ValidationStates [Component]', function () { let props: any; @@ -20,9 +21,18 @@ describe('ValidationStates [Component]', function () { const mountComponent = (props: any) => { const store = configureStore({}, {} as any); return mount( - - - + + + + + ); }; diff --git a/packages/compass-schema/src/components/schema-toolbar/schema-toolbar.spec.tsx b/packages/compass-schema/src/components/schema-toolbar/schema-toolbar.spec.tsx index 3aacbfc47ce..aa98049b8ee 100644 --- a/packages/compass-schema/src/components/schema-toolbar/schema-toolbar.spec.tsx +++ b/packages/compass-schema/src/components/schema-toolbar/schema-toolbar.spec.tsx @@ -9,6 +9,7 @@ import { compassFavoriteQueryStorageAccess, compassRecentQueryStorageAccess, } from '@mongodb-js/my-queries-storage'; +import { ConnectionInfoProvider } from '@mongodb-js/connection-storage/provider'; const MockQueryBarPlugin = QueryBarPlugin.withMockServices({ dataService: { @@ -34,18 +35,27 @@ const renderSchemaToolbar = ( ) => { const queryBarProps = {}; render( - - {}} - onResetClicked={() => {}} - sampleSize={10} - schemaResultId="123" - {...props} - /> - + + + {}} + onResetClicked={() => {}} + sampleSize={10} + schemaResultId="123" + {...props} + /> + + ); }; diff --git a/packages/compass-schema/src/index.ts b/packages/compass-schema/src/index.ts index f9b04df3d84..a43020da276 100644 --- a/packages/compass-schema/src/index.ts +++ b/packages/compass-schema/src/index.ts @@ -1,4 +1,6 @@ import { + connectionScopedGlobalAppRegistryLocator, + type ConnectionScopedGlobalAppRegistryLocator, dataServiceLocator, type DataServiceLocator, } from '@mongodb-js/compass-connections/provider'; @@ -19,6 +21,7 @@ export const CompassSchemaHadronPlugin = registerHadronPlugin< dataService: () => DataService; loggerAndTelemetry: () => LoggerAndTelemetry; preferences: () => PreferencesAccess; + connectionScopedGlobalAppRegistry: ConnectionScopedGlobalAppRegistryLocator<'schema-analyzed'>; } >( { @@ -32,6 +35,7 @@ export const CompassSchemaHadronPlugin = registerHadronPlugin< >, loggerAndTelemetry: createLoggerAndTelemetryLocator('COMPASS-SCHEMA-UI'), preferences: preferencesLocator, + connectionScopedGlobalAppRegistry: connectionScopedGlobalAppRegistryLocator, } ); export const CompassSchemaPlugin = { diff --git a/packages/compass-schema/src/stores/store.spec.ts b/packages/compass-schema/src/stores/store.spec.ts index cb74d8e72dc..f31a4a65e22 100644 --- a/packages/compass-schema/src/stores/store.spec.ts +++ b/packages/compass-schema/src/stores/store.spec.ts @@ -30,6 +30,9 @@ describe('Schema Store', function () { dataService: dataService as any, loggerAndTelemetry: dummyLogger, preferences: await createSandboxFromDefaultPreferences(), + connectionScopedGlobalAppRegistry: { + emit: globalAppRegistry.emit.bind(globalAppRegistry), + }, }, createActivateHelpers() ); @@ -77,6 +80,7 @@ describe('Schema Store', function () { context('when query change events are emitted', function () { let store: SchemaStore; let deactivate: () => void; + const globalAppRegistry = new EventEmitter() as any; const localAppRegistry = new AppRegistry(); const filter = { name: 'test' }; const limit = 50; @@ -89,10 +93,13 @@ describe('Schema Store', function () { }, { localAppRegistry: localAppRegistry, - globalAppRegistry: new EventEmitter() as any, + globalAppRegistry: globalAppRegistry, dataService: {} as any, loggerAndTelemetry: dummyLogger, preferences: await createSandboxFromDefaultPreferences(), + connectionScopedGlobalAppRegistry: { + emit: globalAppRegistry.emit.bind(globalAppRegistry), + }, }, createActivateHelpers() ); diff --git a/packages/compass-schema/src/stores/store.ts b/packages/compass-schema/src/stores/store.ts index 89010885642..ae0fdc731c4 100644 --- a/packages/compass-schema/src/stores/store.ts +++ b/packages/compass-schema/src/stores/store.ts @@ -20,7 +20,10 @@ import { import { capMaxTimeMSAtPreferenceLimit } from 'compass-preferences-model/provider'; import { openToast } from '@mongodb-js/compass-components'; import type { CollectionTabPluginMetadata } from '@mongodb-js/compass-collection'; -import type { DataService as OriginalDataService } from '@mongodb-js/compass-connections/provider'; +import type { + ConnectionScopedGlobalAppRegistry, + DataService as OriginalDataService, +} from '@mongodb-js/compass-connections/provider'; import type { ActivateHelpers } from 'hadron-app-registry'; import type AppRegistry from 'hadron-app-registry'; import { configureActions } from '../actions'; @@ -57,6 +60,7 @@ export type SchemaPluginServices = { dataService: DataService; localAppRegistry: Pick; globalAppRegistry: Pick; + connectionScopedGlobalAppRegistry: ConnectionScopedGlobalAppRegistry<'schema-analyzed'>; loggerAndTelemetry: LoggerAndTelemetry; preferences: PreferencesAccess; }; @@ -86,6 +90,7 @@ export type SchemaStore = Reflux.Store & { localAppRegistry: SchemaPluginServices['localAppRegistry']; globalAppRegistry: SchemaPluginServices['globalAppRegistry']; + connectionScopedGlobalAppRegistry: SchemaPluginServices['connectionScopedGlobalAppRegistry']; // TODO(COMPASS-6847): We don't really need this state in store, but it's hard // to factor away while the store is reflux query: QueryState; @@ -135,6 +140,7 @@ export function activateSchemaPlugin( dataService, localAppRegistry, globalAppRegistry, + connectionScopedGlobalAppRegistry, loggerAndTelemetry, preferences, }: SchemaPluginServices, @@ -165,6 +171,8 @@ export function activateSchemaPlugin( this.dataService = dataService; this.localAppRegistry = localAppRegistry; this.globalAppRegistry = globalAppRegistry; + this.connectionScopedGlobalAppRegistry = + connectionScopedGlobalAppRegistry; }, handleSchemaShare(this: SchemaStore) { @@ -343,7 +351,10 @@ export function activateSchemaPlugin( ); const analysisTime = Date.now() - analysisStartTime; - this.globalAppRegistry.emit('schema-analyzed', { ns: this.ns, schema }); + this.connectionScopedGlobalAppRegistry.emit('schema-analyzed', { + ns: this.ns, + schema, + }); this.setState({ analysisState: schema