diff --git a/.tool-versions b/.tool-versions index 98c84e7ee29..f69216ccdba 100644 --- a/.tool-versions +++ b/.tool-versions @@ -3,4 +3,4 @@ # This Node.js version matches the one required in # the "engines" in the package.json. -nodejs 22.21.1 +nodejs 22.21.1 \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 8865f53cd09..95ed095a225 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26,12 +26,6 @@ "npm": ">=10.2.4" } }, - "@mongodb-js/diagramming": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/@mongodb-js/diagramming/-/diagramming-1.8.0.tgz", - "integrity": "sha512-ABg9MVNUm4wD5UijQHf3Il6WSrHPqchmMFHJMJ1OAgMEDXXKJNzUvK1Zhz5iDEEO5uIHOYSQRcCY8MeC9bo+fA==", - "extraneous": true - }, "configs/eslint-config-compass": { "name": "@mongodb-js/eslint-config-compass", "version": "1.4.12", @@ -9991,6 +9985,29 @@ "url": "https://opencollective.com/node-fetch" } }, + "node_modules/@mongodb-js/diagramming": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@mongodb-js/diagramming/-/diagramming-2.3.1.tgz", + "integrity": "sha512-u1s0H8Pyqai7tmDVzkUvlnHK/xCFuhZIpwix6LJOl2ADiwc7l30yCrgiM0qRXlcJKWDbbZDmE0uGpYA9swv9tw==", + "license": "MIT", + "dependencies": { + "@emotion/react": "^11.14.0", + "@emotion/styled": "^11.14.0", + "@leafygreen-ui/icon": "^14.3.0", + "@leafygreen-ui/inline-definition": "^9.0.5", + "@leafygreen-ui/leafygreen-provider": "^5.0.2", + "@leafygreen-ui/palette": "^5.0.0", + "@leafygreen-ui/select": "^16.2.0", + "@leafygreen-ui/tokens": "^3.2.1", + "@leafygreen-ui/tooltip": "^14.2.1", + "@leafygreen-ui/typography": "^22.1.0", + "@xyflow/react": "12.5.1", + "d3-path": "^3.1.0", + "elkjs": "^0.11.0", + "react": "17.0.2", + "react-dom": "17.0.2" + } + }, "node_modules/@mongodb-js/dl-center": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/@mongodb-js/dl-center/-/dl-center-1.3.0.tgz", @@ -47970,7 +47987,7 @@ "@lg-chat/leafygreen-chat-provider": "^5.0.2", "@lg-chat/message": "^8.2.0", "@mongodb-js/compass-context-menu": "^0.3.1", - "@mongodb-js/diagramming": "^2.2.2", + "@mongodb-js/diagramming": "^2.3.1", "@react-aria/interactions": "^3.9.1", "@react-aria/utils": "^3.13.1", "@react-aria/visually-hidden": "^3.3.1", @@ -48008,33 +48025,11 @@ "typescript": "^5.9.3" } }, - "packages/compass-components/node_modules/@mongodb-js/diagramming": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/@mongodb-js/diagramming/-/diagramming-2.2.2.tgz", - "integrity": "sha512-GCI+L9TBC7sbuEeJaazhdz1ELcvPRi6cjuOf9Lhx/9FhyV+7IpIGCQbm4V7OflBrqBTfZD4XrwzlkuZ55hRLaA==", - "license": "MIT", - "dependencies": { - "@emotion/react": "^11.14.0", - "@emotion/styled": "^11.14.0", - "@leafygreen-ui/icon": "^14.3.0", - "@leafygreen-ui/inline-definition": "^9.0.5", - "@leafygreen-ui/leafygreen-provider": "^5.0.2", - "@leafygreen-ui/palette": "^5.0.0", - "@leafygreen-ui/select": "^16.2.0", - "@leafygreen-ui/tokens": "^3.2.1", - "@leafygreen-ui/tooltip": "^14.2.1", - "@leafygreen-ui/typography": "^22.1.0", - "@xyflow/react": "12.5.1", - "d3-path": "^3.1.0", - "elkjs": "^0.11.0", - "react": "17.0.2", - "react-dom": "17.0.2" - } - }, "packages/compass-components/node_modules/@mongodb-js/diagramming/node_modules/@leafygreen-ui/select": { "version": "16.3.0", "resolved": "https://registry.npmjs.org/@leafygreen-ui/select/-/select-16.3.0.tgz", "integrity": "sha512-/UP9NO4HKyOmN8fac8DFQnW2ia/O/odp5LPxehymvRPSSgDGzTBoVK8JPocayEZHTO+kLRjmiJm6QaQ09xmhRQ==", + "extraneous": true, "license": "Apache-2.0", "dependencies": { "@leafygreen-ui/button": "^25.1.2", @@ -48058,21 +48053,11 @@ "@leafygreen-ui/leafygreen-provider": ">=3.2.0" } }, - "packages/compass-components/node_modules/@mongodb-js/diagramming/node_modules/@leafygreen-ui/select/node_modules/@leafygreen-ui/tokens": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@leafygreen-ui/tokens/-/tokens-4.1.0.tgz", - "integrity": "sha512-5GfNFP0iRT4O+CnqYHpvtCUiT3aStUa2EhrV3tkrTwffemHN10M4G5nc/DhLGLNp2aQDP1+ppAtjZI5zczDSiA==", - "license": "Apache-2.0", - "dependencies": { - "@leafygreen-ui/emotion": "^5.1.0", - "@leafygreen-ui/lib": "^15.6.2", - "@leafygreen-ui/palette": "^5.0.2" - } - }, "packages/compass-components/node_modules/@mongodb-js/diagramming/node_modules/@leafygreen-ui/tokens": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/@leafygreen-ui/tokens/-/tokens-3.2.4.tgz", "integrity": "sha512-Bd11x/ext/vVozd/HL+AD8LbL71Z6B6VbtQ/+qLqoX8qHMsJt7VWL0CmmGs5NVHh3v5sAlfT5DYbB9uhwVM8Qw==", + "extraneous": true, "license": "Apache-2.0", "dependencies": { "@leafygreen-ui/emotion": "^5.0.2", @@ -48081,12 +48066,6 @@ "polished": "^4.2.2" } }, - "packages/compass-components/node_modules/react-is": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", - "license": "MIT" - }, "packages/compass-components/node_modules/sinon": { "version": "9.2.4", "resolved": "https://registry.npmjs.org/sinon/-/sinon-9.2.4.tgz", @@ -61498,7 +61477,7 @@ "@lg-chat/leafygreen-chat-provider": "^5.0.2", "@lg-chat/message": "^8.2.0", "@mongodb-js/compass-context-menu": "^0.3.1", - "@mongodb-js/diagramming": "^2.2.2", + "@mongodb-js/diagramming": "^2.3.1", "@mongodb-js/eslint-config-compass": "^1.4.12", "@mongodb-js/mocha-config-compass": "^1.7.2", "@mongodb-js/prettier-config-compass": "^1.2.9", @@ -61532,81 +61511,6 @@ "typescript": "^5.9.3" }, "dependencies": { - "@mongodb-js/diagramming": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/@mongodb-js/diagramming/-/diagramming-2.2.2.tgz", - "integrity": "sha512-GCI+L9TBC7sbuEeJaazhdz1ELcvPRi6cjuOf9Lhx/9FhyV+7IpIGCQbm4V7OflBrqBTfZD4XrwzlkuZ55hRLaA==", - "requires": { - "@emotion/react": "^11.14.0", - "@emotion/styled": "^11.14.0", - "@leafygreen-ui/icon": "^14.3.0", - "@leafygreen-ui/inline-definition": "^9.0.5", - "@leafygreen-ui/leafygreen-provider": "^5.0.2", - "@leafygreen-ui/palette": "^5.0.0", - "@leafygreen-ui/select": "^16.2.0", - "@leafygreen-ui/tokens": "^3.2.1", - "@leafygreen-ui/tooltip": "^14.2.1", - "@leafygreen-ui/typography": "^22.1.0", - "@xyflow/react": "12.5.1", - "d3-path": "^3.1.0", - "elkjs": "^0.11.0", - "react": "17.0.2", - "react-dom": "17.0.2" - }, - "dependencies": { - "@leafygreen-ui/select": { - "version": "16.3.0", - "resolved": "https://registry.npmjs.org/@leafygreen-ui/select/-/select-16.3.0.tgz", - "integrity": "sha512-/UP9NO4HKyOmN8fac8DFQnW2ia/O/odp5LPxehymvRPSSgDGzTBoVK8JPocayEZHTO+kLRjmiJm6QaQ09xmhRQ==", - "requires": { - "@leafygreen-ui/button": "^25.1.2", - "@leafygreen-ui/emotion": "^5.1.0", - "@leafygreen-ui/form-field": "^4.0.6", - "@leafygreen-ui/hooks": "^9.2.2", - "@leafygreen-ui/icon": "^14.6.1", - "@leafygreen-ui/input-option": "^4.1.2", - "@leafygreen-ui/lib": "^15.6.2", - "@leafygreen-ui/palette": "^5.0.2", - "@leafygreen-ui/popover": "^14.3.0", - "@leafygreen-ui/tokens": "^4.0.0", - "@leafygreen-ui/typography": "^22.2.0", - "@lg-tools/test-harnesses": "^0.3.4", - "@types/react-is": "^18.0.0", - "lodash": "^4.17.21", - "polished": "^4.1.3", - "react-is": "^18.0.1" - }, - "dependencies": { - "@leafygreen-ui/tokens": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@leafygreen-ui/tokens/-/tokens-4.1.0.tgz", - "integrity": "sha512-5GfNFP0iRT4O+CnqYHpvtCUiT3aStUa2EhrV3tkrTwffemHN10M4G5nc/DhLGLNp2aQDP1+ppAtjZI5zczDSiA==", - "requires": { - "@leafygreen-ui/emotion": "^5.1.0", - "@leafygreen-ui/lib": "^15.6.2", - "@leafygreen-ui/palette": "^5.0.2" - } - } - } - }, - "@leafygreen-ui/tokens": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/@leafygreen-ui/tokens/-/tokens-3.2.4.tgz", - "integrity": "sha512-Bd11x/ext/vVozd/HL+AD8LbL71Z6B6VbtQ/+qLqoX8qHMsJt7VWL0CmmGs5NVHh3v5sAlfT5DYbB9uhwVM8Qw==", - "requires": { - "@leafygreen-ui/emotion": "^5.0.2", - "@leafygreen-ui/lib": "^15.3.0", - "@leafygreen-ui/palette": "^5.0.2", - "polished": "^4.2.2" - } - } - } - }, - "react-is": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==" - }, "sinon": { "version": "9.2.4", "resolved": "https://registry.npmjs.org/sinon/-/sinon-9.2.4.tgz", @@ -65089,6 +64993,28 @@ } } }, + "@mongodb-js/diagramming": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@mongodb-js/diagramming/-/diagramming-2.3.1.tgz", + "integrity": "sha512-u1s0H8Pyqai7tmDVzkUvlnHK/xCFuhZIpwix6LJOl2ADiwc7l30yCrgiM0qRXlcJKWDbbZDmE0uGpYA9swv9tw==", + "requires": { + "@emotion/react": "^11.14.0", + "@emotion/styled": "^11.14.0", + "@leafygreen-ui/icon": "^14.3.0", + "@leafygreen-ui/inline-definition": "^9.0.5", + "@leafygreen-ui/leafygreen-provider": "^5.0.4", + "@leafygreen-ui/palette": "^5.0.0", + "@leafygreen-ui/select": "^17.0.1", + "@leafygreen-ui/tokens": "^4.0.0", + "@leafygreen-ui/tooltip": "^14.2.1", + "@leafygreen-ui/typography": "^22.2.2", + "@xyflow/react": "12.5.1", + "d3-path": "^3.1.0", + "elkjs": "^0.11.0", + "react": "^17.0.2", + "react-dom": "^17.0.2" + } + }, "@mongodb-js/dl-center": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/@mongodb-js/dl-center/-/dl-center-1.3.0.tgz", diff --git a/packages/compass-components/package.json b/packages/compass-components/package.json index f7140299da7..f74b7838652 100644 --- a/packages/compass-components/package.json +++ b/packages/compass-components/package.json @@ -85,7 +85,7 @@ "@lg-chat/leafygreen-chat-provider": "^5.0.2", "@lg-chat/message": "^8.2.0", "@mongodb-js/compass-context-menu": "^0.3.1", - "@mongodb-js/diagramming": "^2.2.2", + "@mongodb-js/diagramming": "^2.3.1", "@react-aria/interactions": "^3.9.1", "@react-aria/utils": "^3.13.1", "@react-aria/visually-hidden": "^3.3.1", diff --git a/packages/compass-data-modeling/src/components/diagram-editor.tsx b/packages/compass-data-modeling/src/components/diagram-editor.tsx index ef08e257deb..66686ddabe1 100644 --- a/packages/compass-data-modeling/src/components/diagram-editor.tsx +++ b/packages/compass-data-modeling/src/components/diagram-editor.tsx @@ -289,9 +289,9 @@ const DiagramContent: React.FunctionComponent<{ !!selectedItems && selectedItems.type === 'relationship' && selectedItems.id === relationship.id; - return relationshipToDiagramEdge(relationship, selected, nodes); + return relationshipToDiagramEdge(relationship, selected); }); - }, [model?.relationships, selectedItems, nodes]); + }, [model?.relationships, selectedItems]); // Fit to view on initial mount useEffect(() => { diff --git a/packages/compass-data-modeling/src/store/analysis-process.ts b/packages/compass-data-modeling/src/store/analysis-process.ts index 1c1ab5e81e1..d44b098cfff 100644 --- a/packages/compass-data-modeling/src/store/analysis-process.ts +++ b/packages/compass-data-modeling/src/store/analysis-process.ts @@ -176,7 +176,7 @@ async function getInitialLayout({ }); return await applyLayout({ nodes, - edges: relations.map((rel) => relationshipToDiagramEdge(rel, false, [])), // nodes are not important here + edges: relations.map((rel) => relationshipToDiagramEdge(rel, false)), direction: hasRelations ? 'STAR' : 'RECTANGLE', }); } diff --git a/packages/compass-data-modeling/src/utils/nodes-and-edges.spec.ts b/packages/compass-data-modeling/src/utils/nodes-and-edges.spec.ts index 3fe2a957b4b..37ab49f4116 100644 --- a/packages/compass-data-modeling/src/utils/nodes-and-edges.spec.ts +++ b/packages/compass-data-modeling/src/utils/nodes-and-edges.spec.ts @@ -4,7 +4,6 @@ import { relationshipToDiagramEdge, } from './nodes-and-edges'; import { type Relationship } from '../services/data-model-storage'; -import { type NodeProps } from '@mongodb-js/compass-components'; describe('getFieldsFromSchema', function () { describe('flat schema', function () { @@ -699,17 +698,9 @@ describe('relationshipToDiagramEdge', function () { note: 'Test relationship', }; - const node: NodeProps = { - id: relationship.relationship[0].ns!, - title: 'Collection A', - type: 'collection', - position: { x: 0, y: 0 }, - fields: [], - }; - it('should forward basic properties', function () { const isSelected = true; - const edge = relationshipToDiagramEdge(relationship, isSelected, []); + const edge = relationshipToDiagramEdge(relationship, isSelected); expect(edge.id).to.equal(relationship.id); expect(edge.source).to.equal(relationship.relationship[0].ns); expect(edge.target).to.equal(relationship.relationship[1].ns); @@ -717,60 +708,15 @@ describe('relationshipToDiagramEdge', function () { }); it('should map cardinality to markers', function () { - const edge = relationshipToDiagramEdge(relationship, false, []); + const edge = relationshipToDiagramEdge(relationship, false); expect(edge.markerStart).to.equal('one'); expect(edge.markerEnd).to.equal('many'); }); - it('should find field indices', function () { - const nodes: NodeProps[] = [ - { - ...node, - id: relationship.relationship[0].ns!, - fields: [ - { - id: ['otherPath'], - name: 'fieldA', // same name but different path - type: 'string', - }, - { - id: ['parent', 'otherField'], // same parent but different field - name: 'otherField', - type: 'string', - }, - { - id: relationship.relationship[0].fields as string[], - name: 'fieldA', - type: 'string', - }, - ], - }, - { - ...node, - id: relationship.relationship[1].ns!, - fields: [ - { - id: ['otherPath'], - name: 'fieldB', // same name but different path - type: 'string', - }, - { - id: relationship.relationship[1].fields as string[], - name: 'fieldB', - type: 'string', - }, - { - id: ['otherParent', 'otherField'], // same parent but different field - name: 'otherField', - type: 'string', - }, - ], - }, - ]; - - const edge = relationshipToDiagramEdge(relationship, false, nodes); - expect(edge.sourceFieldIndex).to.equal(2); - expect(edge.targetFieldIndex).to.equal(1); + it('should map field ids', function () { + const edge = relationshipToDiagramEdge(relationship, false); + expect(edge.sourceFieldId).to.equal(relationship.relationship[0].fields); + expect(edge.targetFieldId).to.equal(relationship.relationship[1].fields); }); it('should choose animated for incomplete relationships', function () { diff --git a/packages/compass-data-modeling/src/utils/nodes-and-edges.ts b/packages/compass-data-modeling/src/utils/nodes-and-edges.ts index 0c98c1583dd..43398319eb3 100644 --- a/packages/compass-data-modeling/src/utils/nodes-and-edges.ts +++ b/packages/compass-data-modeling/src/utils/nodes-and-edges.ts @@ -198,50 +198,17 @@ export function collectionToDiagramNode({ }; } -function findNodeByNS(ns: string, nodes: NodeProps[]): NodeProps | undefined { - return nodes.find((node) => node.id === ns); -} - -function findFieldIndex({ - fieldPath, - nodes, - ns, -}: { - fieldPath: string[]; - nodes: NodeProps[]; - ns?: string; -}): number | undefined { - if (!ns || !fieldPath.length) return undefined; - const node = findNodeByNS(ns, nodes); - if (!node) return undefined; - - for (const [index, field] of node.fields.entries()) { - if (!field.id || !Array.isArray(field.id)) continue; - // TODO(COMPASS-9504 and COMPASS-9935): Accept partial paths for collapsed nodes and fields. - if (areFieldPathsEqual(field.id, fieldPath)) return index; - } -} - export function relationshipToDiagramEdge( relationship: Relationship, - selected = false, - nodes: NodeProps[] + selected = false ): EdgeProps { const [source, target] = relationship.relationship; return { id: relationship.id, source: source.ns ?? '', target: target.ns ?? '', - sourceFieldIndex: findFieldIndex({ - fieldPath: source.fields ?? [], - nodes, - ns: source.ns ?? undefined, - }), - targetFieldIndex: findFieldIndex({ - fieldPath: target.fields ?? [], - nodes, - ns: target.ns ?? undefined, - }), + sourceFieldId: source.fields || [], + targetFieldId: target.fields ?? [], markerStart: source.cardinality === 1 ? 'one' : 'many', markerEnd: target.cardinality === 1 ? 'one' : 'many', selected,