diff --git a/package-lock.json b/package-lock.json index 9c486fd9200..d10527a060a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -31562,99 +31562,6 @@ "node": ">=12" } }, - "node_modules/mongodb-schema": { - "version": "12.2.0", - "resolved": "https://registry.npmjs.org/mongodb-schema/-/mongodb-schema-12.2.0.tgz", - "integrity": "sha512-YszO0B8yxeu2yD6KtjM5x5DjWi++gS+p74hEuoQKCmR/89aft1q2/FuBvV8gslgoT04lWbtLwI2eQNvklePLMw==", - "dependencies": { - "reservoir": "^0.1.2" - }, - "bin": { - "mongodb-schema": "bin/mongodb-schema" - }, - "optionalDependencies": { - "bson": "^6.7.0", - "cli-table": "^0.3.4", - "js-yaml": "^4.0.0", - "mongodb": "^6.6.1", - "mongodb-ns": "^2.4.0", - "numeral": "^2.0.6", - "progress": "^2.0.3", - "stats-lite": "^2.0.0", - "yargs": "^17.6.2" - } - }, - "node_modules/mongodb-schema/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "optional": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/mongodb-schema/node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "optional": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/mongodb-schema/node_modules/numeral": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/numeral/-/numeral-2.0.6.tgz", - "integrity": "sha512-qaKRmtYPZ5qdw4jWJD6bxEf1FJEqllJrwxCLIm0sQU/A7v2/czigzOb+C2uSiFsa9lBUzeH7M1oK+Q+OLxL3kA==", - "optional": true, - "engines": { - "node": "*" - } - }, - "node_modules/mongodb-schema/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "optional": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/mongodb-schema/node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "optional": true, - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/mongodb-schema/node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "optional": true, - "engines": { - "node": ">=12" - } - }, "node_modules/moo": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.1.tgz", @@ -43332,7 +43239,7 @@ "mongodb-instance-model": "^12.26.0", "mongodb-ns": "^2.4.2", "mongodb-query-parser": "^4.3.0", - "mongodb-schema": "^12.2.0", + "mongodb-schema": "^12.3.2", "prop-types": "^15.7.2", "re-resizable": "^6.9.0", "react": "^17.0.2", @@ -43377,6 +43284,31 @@ "bson": "^4.6.3 || ^5 || ^6" } }, + "packages/compass-aggregations/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "packages/compass-aggregations/node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "license": "ISC", + "optional": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, "packages/compass-aggregations/node_modules/diff": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", @@ -43401,6 +43333,39 @@ "bson": "^4.6.3 || ^5 || ^6" } }, + "packages/compass-aggregations/node_modules/mongodb-schema": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/mongodb-schema/-/mongodb-schema-12.3.2.tgz", + "integrity": "sha512-6OSM7vx55q2w/rT++ZMJLb2Liq+W5BPI+zYpWfJpO4O481LHWTZBI6/Un6mB9gYJW+kBJUVczIDGsUkYrqsdHQ==", + "license": "Apache-2.0", + "dependencies": { + "reservoir": "^0.1.2" + }, + "bin": { + "mongodb-schema": "bin/mongodb-schema" + }, + "optionalDependencies": { + "bson": "^6.7.0", + "cli-table": "^0.3.4", + "js-yaml": "^4.0.0", + "mongodb": "^6.6.1", + "mongodb-ns": "^2.4.0", + "numeral": "^2.0.6", + "progress": "^2.0.3", + "stats-lite": "^2.0.0", + "yargs": "^17.6.2" + } + }, + "packages/compass-aggregations/node_modules/numeral": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/numeral/-/numeral-2.0.6.tgz", + "integrity": "sha512-qaKRmtYPZ5qdw4jWJD6bxEf1FJEqllJrwxCLIm0sQU/A7v2/czigzOb+C2uSiFsa9lBUzeH7M1oK+Q+OLxL3kA==", + "license": "MIT", + "optional": true, + "engines": { + "node": "*" + } + }, "packages/compass-aggregations/node_modules/sinon": { "version": "9.2.4", "resolved": "https://registry.npmjs.org/sinon/-/sinon-9.2.4.tgz", @@ -43419,6 +43384,48 @@ "url": "https://opencollective.com/sinon" } }, + "packages/compass-aggregations/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "optional": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "packages/compass-aggregations/node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "license": "MIT", + "optional": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "packages/compass-aggregations/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "license": "ISC", + "optional": true, + "engines": { + "node": ">=12" + } + }, "packages/compass-app-stores": { "name": "@mongodb-js/compass-app-stores", "version": "7.36.0", @@ -44706,7 +44713,7 @@ "@mongodb-js/compass-logging": "^1.6.0", "hadron-app-registry": "^9.4.0", "lodash": "^4.17.21", - "mongodb-schema": "^12.2.0", + "mongodb-schema": "^12.3.2", "react": "^17.0.2", "react-redux": "^8.1.3", "redux": "^4.2.1", @@ -44733,6 +44740,31 @@ "xvfb-maybe": "^0.2.1" } }, + "packages/compass-field-store/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "packages/compass-field-store/node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "license": "ISC", + "optional": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, "packages/compass-field-store/node_modules/diff": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", @@ -44742,6 +44774,39 @@ "node": ">=0.3.1" } }, + "packages/compass-field-store/node_modules/mongodb-schema": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/mongodb-schema/-/mongodb-schema-12.3.2.tgz", + "integrity": "sha512-6OSM7vx55q2w/rT++ZMJLb2Liq+W5BPI+zYpWfJpO4O481LHWTZBI6/Un6mB9gYJW+kBJUVczIDGsUkYrqsdHQ==", + "license": "Apache-2.0", + "dependencies": { + "reservoir": "^0.1.2" + }, + "bin": { + "mongodb-schema": "bin/mongodb-schema" + }, + "optionalDependencies": { + "bson": "^6.7.0", + "cli-table": "^0.3.4", + "js-yaml": "^4.0.0", + "mongodb": "^6.6.1", + "mongodb-ns": "^2.4.0", + "numeral": "^2.0.6", + "progress": "^2.0.3", + "stats-lite": "^2.0.0", + "yargs": "^17.6.2" + } + }, + "packages/compass-field-store/node_modules/numeral": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/numeral/-/numeral-2.0.6.tgz", + "integrity": "sha512-qaKRmtYPZ5qdw4jWJD6bxEf1FJEqllJrwxCLIm0sQU/A7v2/czigzOb+C2uSiFsa9lBUzeH7M1oK+Q+OLxL3kA==", + "license": "MIT", + "optional": true, + "engines": { + "node": "*" + } + }, "packages/compass-field-store/node_modules/sinon": { "version": "9.2.4", "resolved": "https://registry.npmjs.org/sinon/-/sinon-9.2.4.tgz", @@ -44760,6 +44825,48 @@ "url": "https://opencollective.com/sinon" } }, + "packages/compass-field-store/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "optional": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "packages/compass-field-store/node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "license": "MIT", + "optional": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "packages/compass-field-store/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "license": "ISC", + "optional": true, + "engines": { + "node": ">=12" + } + }, "packages/compass-find-in-page": { "name": "@mongodb-js/compass-find-in-page", "version": "4.35.0", @@ -44841,7 +44948,7 @@ "compass-preferences-model": "^2.33.0", "hadron-app-registry": "^9.4.0", "mongodb": "^6.12.0", - "mongodb-schema": "^12.2.0", + "mongodb-schema": "^12.3.2", "react": "^17.0.2", "react-redux": "^8.1.3", "redux": "^4.2.1", @@ -44872,6 +44979,31 @@ "xvfb-maybe": "^0.2.1" } }, + "packages/compass-generative-ai/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "packages/compass-generative-ai/node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "license": "ISC", + "optional": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, "packages/compass-generative-ai/node_modules/diff": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", @@ -44887,6 +45019,39 @@ "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", "dev": true }, + "packages/compass-generative-ai/node_modules/mongodb-schema": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/mongodb-schema/-/mongodb-schema-12.3.2.tgz", + "integrity": "sha512-6OSM7vx55q2w/rT++ZMJLb2Liq+W5BPI+zYpWfJpO4O481LHWTZBI6/Un6mB9gYJW+kBJUVczIDGsUkYrqsdHQ==", + "license": "Apache-2.0", + "dependencies": { + "reservoir": "^0.1.2" + }, + "bin": { + "mongodb-schema": "bin/mongodb-schema" + }, + "optionalDependencies": { + "bson": "^6.7.0", + "cli-table": "^0.3.4", + "js-yaml": "^4.0.0", + "mongodb": "^6.6.1", + "mongodb-ns": "^2.4.0", + "numeral": "^2.0.6", + "progress": "^2.0.3", + "stats-lite": "^2.0.0", + "yargs": "^17.6.2" + } + }, + "packages/compass-generative-ai/node_modules/numeral": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/numeral/-/numeral-2.0.6.tgz", + "integrity": "sha512-qaKRmtYPZ5qdw4jWJD6bxEf1FJEqllJrwxCLIm0sQU/A7v2/czigzOb+C2uSiFsa9lBUzeH7M1oK+Q+OLxL3kA==", + "license": "MIT", + "optional": true, + "engines": { + "node": "*" + } + }, "packages/compass-generative-ai/node_modules/p-queue": { "version": "7.4.1", "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-7.4.1.tgz", @@ -44933,6 +45098,48 @@ "url": "https://opencollective.com/sinon" } }, + "packages/compass-generative-ai/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "optional": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "packages/compass-generative-ai/node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "license": "MIT", + "optional": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "packages/compass-generative-ai/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "license": "ISC", + "optional": true, + "engines": { + "node": ">=12" + } + }, "packages/compass-global-writes": { "name": "@mongodb-js/compass-global-writes", "version": "1.9.0", @@ -45152,7 +45359,7 @@ "mongodb-data-service": "^22.25.0", "mongodb-ns": "^2.4.2", "mongodb-query-parser": "^4.3.0", - "mongodb-schema": "^12.2.0", + "mongodb-schema": "^12.3.2", "papaparse": "^5.3.2", "react": "^17.0.2", "react-redux": "^8.1.3", @@ -45206,6 +45413,31 @@ "bson": "^4.6.3 || ^5 || ^6" } }, + "packages/compass-import-export/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "packages/compass-import-export/node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "license": "ISC", + "optional": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, "packages/compass-import-export/node_modules/diff": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", @@ -45230,6 +45462,39 @@ "bson": "^4.6.3 || ^5 || ^6" } }, + "packages/compass-import-export/node_modules/mongodb-schema": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/mongodb-schema/-/mongodb-schema-12.3.2.tgz", + "integrity": "sha512-6OSM7vx55q2w/rT++ZMJLb2Liq+W5BPI+zYpWfJpO4O481LHWTZBI6/Un6mB9gYJW+kBJUVczIDGsUkYrqsdHQ==", + "license": "Apache-2.0", + "dependencies": { + "reservoir": "^0.1.2" + }, + "bin": { + "mongodb-schema": "bin/mongodb-schema" + }, + "optionalDependencies": { + "bson": "^6.7.0", + "cli-table": "^0.3.4", + "js-yaml": "^4.0.0", + "mongodb": "^6.6.1", + "mongodb-ns": "^2.4.0", + "numeral": "^2.0.6", + "progress": "^2.0.3", + "stats-lite": "^2.0.0", + "yargs": "^17.6.2" + } + }, + "packages/compass-import-export/node_modules/numeral": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/numeral/-/numeral-2.0.6.tgz", + "integrity": "sha512-qaKRmtYPZ5qdw4jWJD6bxEf1FJEqllJrwxCLIm0sQU/A7v2/czigzOb+C2uSiFsa9lBUzeH7M1oK+Q+OLxL3kA==", + "license": "MIT", + "optional": true, + "engines": { + "node": "*" + } + }, "packages/compass-import-export/node_modules/sinon": { "version": "9.2.4", "resolved": "https://registry.npmjs.org/sinon/-/sinon-9.2.4.tgz", @@ -45248,6 +45513,48 @@ "url": "https://opencollective.com/sinon" } }, + "packages/compass-import-export/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "optional": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "packages/compass-import-export/node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "license": "MIT", + "optional": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "packages/compass-import-export/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "license": "ISC", + "optional": true, + "engines": { + "node": ">=12" + } + }, "packages/compass-indexes": { "name": "@mongodb-js/compass-indexes", "version": "5.49.0", @@ -45715,7 +46022,7 @@ "mongodb-ns": "^2.4.2", "mongodb-query-parser": "^4.3.0", "mongodb-query-util": "^2.4.0", - "mongodb-schema": "^12.2.0", + "mongodb-schema": "^12.3.2", "react": "^17.0.2", "react-redux": "^8.1.3", "redux": "^4.2.1", @@ -45752,6 +46059,31 @@ "bson": "^4.6.3 || ^5 || ^6" } }, + "packages/compass-query-bar/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "packages/compass-query-bar/node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "license": "ISC", + "optional": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, "packages/compass-query-bar/node_modules/diff": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", @@ -45776,6 +46108,39 @@ "bson": "^4.6.3 || ^5 || ^6" } }, + "packages/compass-query-bar/node_modules/mongodb-schema": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/mongodb-schema/-/mongodb-schema-12.3.2.tgz", + "integrity": "sha512-6OSM7vx55q2w/rT++ZMJLb2Liq+W5BPI+zYpWfJpO4O481LHWTZBI6/Un6mB9gYJW+kBJUVczIDGsUkYrqsdHQ==", + "license": "Apache-2.0", + "dependencies": { + "reservoir": "^0.1.2" + }, + "bin": { + "mongodb-schema": "bin/mongodb-schema" + }, + "optionalDependencies": { + "bson": "^6.7.0", + "cli-table": "^0.3.4", + "js-yaml": "^4.0.0", + "mongodb": "^6.6.1", + "mongodb-ns": "^2.4.0", + "numeral": "^2.0.6", + "progress": "^2.0.3", + "stats-lite": "^2.0.0", + "yargs": "^17.6.2" + } + }, + "packages/compass-query-bar/node_modules/numeral": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/numeral/-/numeral-2.0.6.tgz", + "integrity": "sha512-qaKRmtYPZ5qdw4jWJD6bxEf1FJEqllJrwxCLIm0sQU/A7v2/czigzOb+C2uSiFsa9lBUzeH7M1oK+Q+OLxL3kA==", + "license": "MIT", + "optional": true, + "engines": { + "node": "*" + } + }, "packages/compass-query-bar/node_modules/sinon": { "version": "9.2.4", "resolved": "https://registry.npmjs.org/sinon/-/sinon-9.2.4.tgz", @@ -45794,6 +46159,48 @@ "url": "https://opencollective.com/sinon" } }, + "packages/compass-query-bar/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "optional": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "packages/compass-query-bar/node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "license": "MIT", + "optional": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "packages/compass-query-bar/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "license": "ISC", + "optional": true, + "engines": { + "node": ">=12" + } + }, "packages/compass-saved-aggregations-queries": { "name": "@mongodb-js/compass-saved-aggregations-queries", "version": "1.50.0", @@ -45894,7 +46301,7 @@ "lodash": "^4.17.21", "mongodb": "^6.12.0", "mongodb-query-util": "^2.4.0", - "mongodb-schema": "^12.2.0", + "mongodb-schema": "^12.3.2", "numeral": "^1.5.6", "prop-types": "^15.7.2", "react": "^17.0.2", @@ -46006,6 +46413,31 @@ "bson": "^4.6.3 || ^5 || ^6" } }, + "packages/compass-schema/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "packages/compass-schema/node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "license": "ISC", + "optional": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, "packages/compass-schema/node_modules/diff": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", @@ -46015,6 +46447,39 @@ "node": ">=0.3.1" } }, + "packages/compass-schema/node_modules/mongodb-schema": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/mongodb-schema/-/mongodb-schema-12.3.2.tgz", + "integrity": "sha512-6OSM7vx55q2w/rT++ZMJLb2Liq+W5BPI+zYpWfJpO4O481LHWTZBI6/Un6mB9gYJW+kBJUVczIDGsUkYrqsdHQ==", + "license": "Apache-2.0", + "dependencies": { + "reservoir": "^0.1.2" + }, + "bin": { + "mongodb-schema": "bin/mongodb-schema" + }, + "optionalDependencies": { + "bson": "^6.7.0", + "cli-table": "^0.3.4", + "js-yaml": "^4.0.0", + "mongodb": "^6.6.1", + "mongodb-ns": "^2.4.0", + "numeral": "^2.0.6", + "progress": "^2.0.3", + "stats-lite": "^2.0.0", + "yargs": "^17.6.2" + } + }, + "packages/compass-schema/node_modules/mongodb-schema/node_modules/numeral": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/numeral/-/numeral-2.0.6.tgz", + "integrity": "sha512-qaKRmtYPZ5qdw4jWJD6bxEf1FJEqllJrwxCLIm0sQU/A7v2/czigzOb+C2uSiFsa9lBUzeH7M1oK+Q+OLxL3kA==", + "license": "MIT", + "optional": true, + "engines": { + "node": "*" + } + }, "packages/compass-schema/node_modules/sinon": { "version": "9.2.4", "resolved": "https://registry.npmjs.org/sinon/-/sinon-9.2.4.tgz", @@ -46033,6 +46498,48 @@ "url": "https://opencollective.com/sinon" } }, + "packages/compass-schema/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "optional": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "packages/compass-schema/node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "license": "MIT", + "optional": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "packages/compass-schema/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "license": "ISC", + "optional": true, + "engines": { + "node": ">=12" + } + }, "packages/compass-serverstats": { "name": "@mongodb-js/compass-serverstats", "version": "16.49.0", @@ -55576,7 +56083,7 @@ "mongodb-instance-model": "^12.26.0", "mongodb-ns": "^2.4.2", "mongodb-query-parser": "^4.3.0", - "mongodb-schema": "^12.2.0", + "mongodb-schema": "^12.3.2", "nyc": "^15.1.0", "prettier": "^2.7.1", "prop-types": "^15.7.2", @@ -55600,6 +56107,23 @@ "acorn": "^8.1.0" } }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "optional": true + }, + "cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "optional": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + } + }, "diff": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", @@ -55617,6 +56141,29 @@ "lodash": "^4.17.21" } }, + "mongodb-schema": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/mongodb-schema/-/mongodb-schema-12.3.2.tgz", + "integrity": "sha512-6OSM7vx55q2w/rT++ZMJLb2Liq+W5BPI+zYpWfJpO4O481LHWTZBI6/Un6mB9gYJW+kBJUVczIDGsUkYrqsdHQ==", + "requires": { + "bson": "^6.7.0", + "cli-table": "^0.3.4", + "js-yaml": "^4.0.0", + "mongodb": "^6.6.1", + "mongodb-ns": "^2.4.0", + "numeral": "^2.0.6", + "progress": "^2.0.3", + "reservoir": "^0.1.2", + "stats-lite": "^2.0.0", + "yargs": "^17.6.2" + } + }, + "numeral": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/numeral/-/numeral-2.0.6.tgz", + "integrity": "sha512-qaKRmtYPZ5qdw4jWJD6bxEf1FJEqllJrwxCLIm0sQU/A7v2/czigzOb+C2uSiFsa9lBUzeH7M1oK+Q+OLxL3kA==", + "optional": true + }, "sinon": { "version": "9.2.4", "resolved": "https://registry.npmjs.org/sinon/-/sinon-9.2.4.tgz", @@ -55630,6 +56177,36 @@ "nise": "^4.0.4", "supports-color": "^7.1.0" } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "optional": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "optional": true, + "requires": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + } + }, + "yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "optional": true } } }, @@ -56441,7 +57018,7 @@ "hadron-app-registry": "^9.4.0", "lodash": "^4.17.21", "mocha": "^10.2.0", - "mongodb-schema": "^12.2.0", + "mongodb-schema": "^12.3.2", "nyc": "^15.1.0", "prettier": "^2.7.1", "react": "^17.0.2", @@ -56453,12 +57030,52 @@ "xvfb-maybe": "^0.2.1" }, "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "optional": true + }, + "cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "optional": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + } + }, "diff": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", "dev": true }, + "mongodb-schema": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/mongodb-schema/-/mongodb-schema-12.3.2.tgz", + "integrity": "sha512-6OSM7vx55q2w/rT++ZMJLb2Liq+W5BPI+zYpWfJpO4O481LHWTZBI6/Un6mB9gYJW+kBJUVczIDGsUkYrqsdHQ==", + "requires": { + "bson": "^6.7.0", + "cli-table": "^0.3.4", + "js-yaml": "^4.0.0", + "mongodb": "^6.6.1", + "mongodb-ns": "^2.4.0", + "numeral": "^2.0.6", + "progress": "^2.0.3", + "reservoir": "^0.1.2", + "stats-lite": "^2.0.0", + "yargs": "^17.6.2" + } + }, + "numeral": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/numeral/-/numeral-2.0.6.tgz", + "integrity": "sha512-qaKRmtYPZ5qdw4jWJD6bxEf1FJEqllJrwxCLIm0sQU/A7v2/czigzOb+C2uSiFsa9lBUzeH7M1oK+Q+OLxL3kA==", + "optional": true + }, "sinon": { "version": "9.2.4", "resolved": "https://registry.npmjs.org/sinon/-/sinon-9.2.4.tgz", @@ -56472,6 +57089,36 @@ "nise": "^4.0.4", "supports-color": "^7.1.0" } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "optional": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "optional": true, + "requires": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + } + }, + "yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "optional": true } } }, @@ -56563,7 +57210,7 @@ "hadron-app-registry": "^9.4.0", "mocha": "^10.2.0", "mongodb": "^6.12.0", - "mongodb-schema": "^12.2.0", + "mongodb-schema": "^12.3.2", "nyc": "^15.1.0", "p-queue": "^7.4.1", "prettier": "^2.7.1", @@ -56576,6 +57223,23 @@ "xvfb-maybe": "^0.2.1" }, "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "optional": true + }, + "cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "optional": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + } + }, "diff": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", @@ -56588,6 +57252,29 @@ "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", "dev": true }, + "mongodb-schema": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/mongodb-schema/-/mongodb-schema-12.3.2.tgz", + "integrity": "sha512-6OSM7vx55q2w/rT++ZMJLb2Liq+W5BPI+zYpWfJpO4O481LHWTZBI6/Un6mB9gYJW+kBJUVczIDGsUkYrqsdHQ==", + "requires": { + "bson": "^6.7.0", + "cli-table": "^0.3.4", + "js-yaml": "^4.0.0", + "mongodb": "^6.6.1", + "mongodb-ns": "^2.4.0", + "numeral": "^2.0.6", + "progress": "^2.0.3", + "reservoir": "^0.1.2", + "stats-lite": "^2.0.0", + "yargs": "^17.6.2" + } + }, + "numeral": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/numeral/-/numeral-2.0.6.tgz", + "integrity": "sha512-qaKRmtYPZ5qdw4jWJD6bxEf1FJEqllJrwxCLIm0sQU/A7v2/czigzOb+C2uSiFsa9lBUzeH7M1oK+Q+OLxL3kA==", + "optional": true + }, "p-queue": { "version": "7.4.1", "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-7.4.1.tgz", @@ -56617,6 +57304,36 @@ "nise": "^4.0.4", "supports-color": "^7.1.0" } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "optional": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "optional": true, + "requires": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + } + }, + "yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "optional": true } } }, @@ -56782,7 +57499,7 @@ "mongodb-data-service": "^22.25.0", "mongodb-ns": "^2.4.2", "mongodb-query-parser": "^4.3.0", - "mongodb-schema": "^12.2.0", + "mongodb-schema": "^12.3.2", "nyc": "^15.1.0", "papaparse": "^5.3.2", "prettier": "^2.7.1", @@ -56808,6 +57525,23 @@ "acorn": "^8.1.0" } }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "optional": true + }, + "cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "optional": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + } + }, "diff": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", @@ -56825,6 +57559,29 @@ "lodash": "^4.17.21" } }, + "mongodb-schema": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/mongodb-schema/-/mongodb-schema-12.3.2.tgz", + "integrity": "sha512-6OSM7vx55q2w/rT++ZMJLb2Liq+W5BPI+zYpWfJpO4O481LHWTZBI6/Un6mB9gYJW+kBJUVczIDGsUkYrqsdHQ==", + "requires": { + "bson": "^6.7.0", + "cli-table": "^0.3.4", + "js-yaml": "^4.0.0", + "mongodb": "^6.6.1", + "mongodb-ns": "^2.4.0", + "numeral": "^2.0.6", + "progress": "^2.0.3", + "reservoir": "^0.1.2", + "stats-lite": "^2.0.0", + "yargs": "^17.6.2" + } + }, + "numeral": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/numeral/-/numeral-2.0.6.tgz", + "integrity": "sha512-qaKRmtYPZ5qdw4jWJD6bxEf1FJEqllJrwxCLIm0sQU/A7v2/czigzOb+C2uSiFsa9lBUzeH7M1oK+Q+OLxL3kA==", + "optional": true + }, "sinon": { "version": "9.2.4", "resolved": "https://registry.npmjs.org/sinon/-/sinon-9.2.4.tgz", @@ -56838,6 +57595,36 @@ "nise": "^4.0.4", "supports-color": "^7.1.0" } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "optional": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "optional": true, + "requires": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + } + }, + "yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "optional": true } } }, @@ -57174,7 +57961,7 @@ "mongodb-ns": "^2.4.2", "mongodb-query-parser": "^4.3.0", "mongodb-query-util": "^2.4.0", - "mongodb-schema": "^12.2.0", + "mongodb-schema": "^12.3.2", "nyc": "^15.1.0", "react": "^17.0.2", "react-dom": "^17.0.2", @@ -57194,6 +57981,23 @@ "acorn": "^8.1.0" } }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "optional": true + }, + "cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "optional": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + } + }, "diff": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", @@ -57211,6 +58015,29 @@ "lodash": "^4.17.21" } }, + "mongodb-schema": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/mongodb-schema/-/mongodb-schema-12.3.2.tgz", + "integrity": "sha512-6OSM7vx55q2w/rT++ZMJLb2Liq+W5BPI+zYpWfJpO4O481LHWTZBI6/Un6mB9gYJW+kBJUVczIDGsUkYrqsdHQ==", + "requires": { + "bson": "^6.7.0", + "cli-table": "^0.3.4", + "js-yaml": "^4.0.0", + "mongodb": "^6.6.1", + "mongodb-ns": "^2.4.0", + "numeral": "^2.0.6", + "progress": "^2.0.3", + "reservoir": "^0.1.2", + "stats-lite": "^2.0.0", + "yargs": "^17.6.2" + } + }, + "numeral": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/numeral/-/numeral-2.0.6.tgz", + "integrity": "sha512-qaKRmtYPZ5qdw4jWJD6bxEf1FJEqllJrwxCLIm0sQU/A7v2/czigzOb+C2uSiFsa9lBUzeH7M1oK+Q+OLxL3kA==", + "optional": true + }, "sinon": { "version": "9.2.4", "resolved": "https://registry.npmjs.org/sinon/-/sinon-9.2.4.tgz", @@ -57224,6 +58051,36 @@ "nise": "^4.0.4", "supports-color": "^7.1.0" } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "optional": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "optional": true, + "requires": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + } + }, + "yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "optional": true } } }, @@ -57335,7 +58192,7 @@ "mocha": "^10.2.0", "mongodb": "^6.12.0", "mongodb-query-util": "^2.4.0", - "mongodb-schema": "^12.2.0", + "mongodb-schema": "^12.3.2", "numeral": "^1.5.6", "nyc": "^15.1.0", "prop-types": "^15.7.2", @@ -57351,12 +58208,54 @@ "xvfb-maybe": "^0.2.1" }, "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "optional": true + }, + "cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "optional": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + } + }, "diff": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", "dev": true }, + "mongodb-schema": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/mongodb-schema/-/mongodb-schema-12.3.2.tgz", + "integrity": "sha512-6OSM7vx55q2w/rT++ZMJLb2Liq+W5BPI+zYpWfJpO4O481LHWTZBI6/Un6mB9gYJW+kBJUVczIDGsUkYrqsdHQ==", + "requires": { + "bson": "^6.7.0", + "cli-table": "^0.3.4", + "js-yaml": "^4.0.0", + "mongodb": "^6.6.1", + "mongodb-ns": "^2.4.0", + "numeral": "^2.0.6", + "progress": "^2.0.3", + "reservoir": "^0.1.2", + "stats-lite": "^2.0.0", + "yargs": "^17.6.2" + }, + "dependencies": { + "numeral": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/numeral/-/numeral-2.0.6.tgz", + "integrity": "sha512-qaKRmtYPZ5qdw4jWJD6bxEf1FJEqllJrwxCLIm0sQU/A7v2/czigzOb+C2uSiFsa9lBUzeH7M1oK+Q+OLxL3kA==", + "optional": true + } + } + }, "sinon": { "version": "9.2.4", "resolved": "https://registry.npmjs.org/sinon/-/sinon-9.2.4.tgz", @@ -57370,6 +58269,36 @@ "nise": "^4.0.4", "supports-color": "^7.1.0" } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "optional": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "optional": true, + "requires": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + } + }, + "yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "optional": true } } }, @@ -79922,78 +80851,6 @@ } } }, - "mongodb-schema": { - "version": "12.2.0", - "resolved": "https://registry.npmjs.org/mongodb-schema/-/mongodb-schema-12.2.0.tgz", - "integrity": "sha512-YszO0B8yxeu2yD6KtjM5x5DjWi++gS+p74hEuoQKCmR/89aft1q2/FuBvV8gslgoT04lWbtLwI2eQNvklePLMw==", - "requires": { - "bson": "^6.7.0", - "cli-table": "^0.3.4", - "js-yaml": "^4.0.0", - "mongodb": "^6.6.1", - "mongodb-ns": "^2.4.0", - "numeral": "^2.0.6", - "progress": "^2.0.3", - "reservoir": "^0.1.2", - "stats-lite": "^2.0.0", - "yargs": "^17.6.2" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "optional": true - }, - "cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "optional": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - } - }, - "numeral": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/numeral/-/numeral-2.0.6.tgz", - "integrity": "sha512-qaKRmtYPZ5qdw4jWJD6bxEf1FJEqllJrwxCLIm0sQU/A7v2/czigzOb+C2uSiFsa9lBUzeH7M1oK+Q+OLxL3kA==", - "optional": true - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "optional": true, - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "optional": true, - "requires": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - } - }, - "yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "optional": true - } - } - }, "moo": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.1.tgz", diff --git a/packages/compass-aggregations/package.json b/packages/compass-aggregations/package.json index 7d2b904c998..f51166ede45 100644 --- a/packages/compass-aggregations/package.json +++ b/packages/compass-aggregations/package.json @@ -91,7 +91,7 @@ "mongodb-instance-model": "^12.26.0", "mongodb-ns": "^2.4.2", "mongodb-query-parser": "^4.3.0", - "mongodb-schema": "^12.2.0", + "mongodb-schema": "^12.3.2", "prop-types": "^15.7.2", "re-resizable": "^6.9.0", "react": "^17.0.2", diff --git a/packages/compass-e2e-tests/helpers/selectors.ts b/packages/compass-e2e-tests/helpers/selectors.ts index 7ed8ee95ff4..3568bf38908 100644 --- a/packages/compass-e2e-tests/helpers/selectors.ts +++ b/packages/compass-e2e-tests/helpers/selectors.ts @@ -1011,6 +1011,10 @@ export const AggregationWizardSortFormDirectionSelect = (idx: number) => // Schema tab export const AnalyzeSchemaButton = '[data-testid="analyze-schema-button"]'; +export const ExportSchemaButton = '[data-testid="open-schema-export-button"]'; +export const ExportSchemaFormatOptions = + '[data-testid="export-schema-format-type-box-group"]'; +export const ExportSchemaOutput = '[data-testid="export-schema-content"]'; export const SchemaFieldList = '[data-testid="schema-field-list"]'; export const AnalysisMessage = '[data-testid="schema-content"] [data-testid="schema-analysis-message"]'; diff --git a/packages/compass-e2e-tests/tests/collection-schema-tab.test.ts b/packages/compass-e2e-tests/tests/collection-schema-tab.test.ts index f60b032a901..a979c759cef 100644 --- a/packages/compass-e2e-tests/tests/collection-schema-tab.test.ts +++ b/packages/compass-e2e-tests/tests/collection-schema-tab.test.ts @@ -109,6 +109,54 @@ describe('Collection schema tab', function () { }); } + describe('with the enableExportSchema feature flag enabled', function () { + beforeEach(async function () { + // TODO(COMPASS-8819): remove web skip when defaulted true. + skipForWeb(this, "can't toggle features in compass-web"); + await browser.setFeature('enableExportSchema', true); + }); + + it('shows an exported schema to copy', async function () { + await browser.navigateToCollectionTab( + DEFAULT_CONNECTION_NAME_1, + 'test', + 'numbers', + 'Schema' + ); + await browser.clickVisible(Selectors.AnalyzeSchemaButton); + + const element = browser.$(Selectors.SchemaFieldList); + await element.waitForDisplayed(); + + await browser.clickVisible(Selectors.ExportSchemaButton); + + const exportModal = browser.$(Selectors.ExportSchemaFormatOptions); + await exportModal.waitForDisplayed(); + + const exportSchemaContent = browser.$(Selectors.ExportSchemaOutput); + await exportSchemaContent.waitForDisplayed(); + const text = await browser.$(Selectors.ExportSchemaOutput).getText(); + const parsedText = JSON.parse(text); + delete parsedText.$defs; + expect(parsedText).to.deep.equal({ + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'object', + required: ['_id', 'i', 'j'], + properties: { + _id: { + $ref: '#/$defs/ObjectId', + }, + i: { + type: 'integer', + }, + j: { + type: 'integer', + }, + }, + }); + }); + }); + it('analyzes the schema with a query'); it('can reset the query'); it('can create a geoquery from a map'); diff --git a/packages/compass-field-store/package.json b/packages/compass-field-store/package.json index f30c27031fc..86dc1b13784 100644 --- a/packages/compass-field-store/package.json +++ b/packages/compass-field-store/package.json @@ -73,7 +73,7 @@ "@mongodb-js/compass-logging": "^1.6.0", "hadron-app-registry": "^9.4.0", "lodash": "^4.17.21", - "mongodb-schema": "^12.2.0", + "mongodb-schema": "^12.3.2", "react": "^17.0.2", "react-redux": "^8.1.3", "redux": "^4.2.1", diff --git a/packages/compass-generative-ai/package.json b/packages/compass-generative-ai/package.json index 9bb061f9209..17b437f4944 100644 --- a/packages/compass-generative-ai/package.json +++ b/packages/compass-generative-ai/package.json @@ -62,7 +62,7 @@ "compass-preferences-model": "^2.33.0", "hadron-app-registry": "^9.4.0", "mongodb": "^6.12.0", - "mongodb-schema": "^12.2.0", + "mongodb-schema": "^12.3.2", "react": "^17.0.2", "react-redux": "^8.1.3", "redux": "^4.2.1", diff --git a/packages/compass-import-export/package.json b/packages/compass-import-export/package.json index 1569386f360..859d94906c3 100644 --- a/packages/compass-import-export/package.json +++ b/packages/compass-import-export/package.json @@ -68,7 +68,7 @@ "mongodb-data-service": "^22.25.0", "mongodb-ns": "^2.4.2", "mongodb-query-parser": "^4.3.0", - "mongodb-schema": "^12.2.0", + "mongodb-schema": "^12.3.2", "papaparse": "^5.3.2", "react": "^17.0.2", "react-redux": "^8.1.3", diff --git a/packages/compass-preferences-model/src/feature-flags.ts b/packages/compass-preferences-model/src/feature-flags.ts index ec0e14dd434..ba21f08a7b0 100644 --- a/packages/compass-preferences-model/src/feature-flags.ts +++ b/packages/compass-preferences-model/src/feature-flags.ts @@ -17,6 +17,7 @@ export type FeatureFlags = { enableOidc: boolean; // Not capitalized "OIDC" for spawn arg casing. newExplainPlan: boolean; showInsights: boolean; + enableExportSchema: boolean; enableRenameCollectionModal: boolean; enableQueryHistoryAutocomplete: boolean; enableProxySupport: boolean; @@ -100,4 +101,14 @@ export const featureFlags: Required<{ short: 'Enable Global Writes tab in Atlas Cloud', }, }, + + /** + * Feature flag for export schema. Epic: COMPASS-6862. + */ + enableExportSchema: { + stage: 'development', + description: { + short: 'Enable schema export', + }, + }, }; diff --git a/packages/compass-query-bar/package.json b/packages/compass-query-bar/package.json index 42e8070f733..5d7cc1aff09 100644 --- a/packages/compass-query-bar/package.json +++ b/packages/compass-query-bar/package.json @@ -87,7 +87,7 @@ "mongodb-ns": "^2.4.2", "mongodb-query-parser": "^4.3.0", "mongodb-query-util": "^2.4.0", - "mongodb-schema": "^12.2.0", + "mongodb-schema": "^12.3.2", "react": "^17.0.2", "react-redux": "^8.1.3", "redux": "^4.2.1", diff --git a/packages/compass-schema/package.json b/packages/compass-schema/package.json index 49292116eee..faf1d736631 100644 --- a/packages/compass-schema/package.json +++ b/packages/compass-schema/package.json @@ -91,7 +91,7 @@ "lodash": "^4.17.21", "mongodb": "^6.12.0", "mongodb-query-util": "^2.4.0", - "mongodb-schema": "^12.2.0", + "mongodb-schema": "^12.3.2", "numeral": "^1.5.6", "prop-types": "^15.7.2", "react": "^17.0.2", diff --git a/packages/compass-schema/src/components/compass-schema.tsx b/packages/compass-schema/src/components/compass-schema.tsx index 01f9abd716d..8a466f03d20 100644 --- a/packages/compass-schema/src/components/compass-schema.tsx +++ b/packages/compass-schema/src/components/compass-schema.tsx @@ -36,7 +36,9 @@ import { getAtlasPerformanceAdvisorLink } from '../utils'; import { useIsLastAppliedQueryOutdated } from '@mongodb-js/compass-query-bar'; import { useTelemetry } from '@mongodb-js/compass-telemetry/provider'; import type { RootState } from '../stores/store'; -import { startAnalysis, stopAnalysis } from '../stores/reducer'; +import { startAnalysis, stopAnalysis } from '../stores/schema-analysis-reducer'; +import { openExportSchema } from '../stores/schema-export-reducer'; +import ExportSchemaModal from './export-schema-modal'; const rootStyles = css({ width: '100%', @@ -373,6 +375,7 @@ const Schema: React.FunctionComponent<{ schema: MongodbSchema | null; count?: number; resultId?: string; + onExportSchemaClicked: () => void; onStartAnalysis: () => Promise; onStopAnalysis: () => void; }> = ({ @@ -380,6 +383,7 @@ const Schema: React.FunctionComponent<{ errorMessage, schema, resultId, + onExportSchemaClicked, onStartAnalysis, onStopAnalysis, }) => { @@ -393,47 +397,54 @@ const Schema: React.FunctionComponent<{ 'enablePerformanceAdvisorBanner' ); + const enableExportSchema = usePreference('enableExportSchema'); + return ( -
- - } - > -
- {enablePerformanceAdvisorBanner && } - {analysisState === ANALYSIS_STATE_INITIAL && ( - - )} - {analysisState === ANALYSIS_STATE_ANALYZING && ( - - )} - {analysisState === ANALYSIS_STATE_COMPLETE && ( - - )} -
-
-
+ <> +
+ + } + > +
+ {enablePerformanceAdvisorBanner && } + {analysisState === ANALYSIS_STATE_INITIAL && ( + + )} + {analysisState === ANALYSIS_STATE_ANALYZING && ( + + )} + {analysisState === ANALYSIS_STATE_COMPLETE && ( + + )} +
+
+
+ {enableExportSchema && } + ); }; export default connect( (state: RootState) => ({ - analysisState: state.analysisState, - errorMessage: state.errorMessage, - schema: state.schema, - resultId: state.resultId, + analysisState: state.schemaAnalysis.analysisState, + errorMessage: state.schemaAnalysis.errorMessage, + schema: state.schemaAnalysis.schema, + resultId: state.schemaAnalysis.resultId, }), { onStartAnalysis: startAnalysis, onStopAnalysis: stopAnalysis, + onExportSchemaClicked: openExportSchema, } )(Schema); diff --git a/packages/compass-schema/src/components/coordinates-minichart/coordinates-minichart.jsx b/packages/compass-schema/src/components/coordinates-minichart/coordinates-minichart.jsx index 79f70b24aeb..eb5286d9f95 100644 --- a/packages/compass-schema/src/components/coordinates-minichart/coordinates-minichart.jsx +++ b/packages/compass-schema/src/components/coordinates-minichart/coordinates-minichart.jsx @@ -22,7 +22,7 @@ import { geoLayerAdded, geoLayersDeleted, geoLayersEdited, -} from '../../stores/reducer'; +} from '../../stores/schema-analysis-reducer'; // TODO: Disable boxZoom handler for circle lasso. // diff --git a/packages/compass-schema/src/components/export-schema-modal.tsx b/packages/compass-schema/src/components/export-schema-modal.tsx new file mode 100644 index 00000000000..cf8cceae5f2 --- /dev/null +++ b/packages/compass-schema/src/components/export-schema-modal.tsx @@ -0,0 +1,194 @@ +import React, { type ChangeEvent, useCallback } from 'react'; +import { connect } from 'react-redux'; +import { + Button, + Code, + ModalBody, + ModalHeader, + ModalFooter, + Modal, + RadioBox, + RadioBoxGroup, + css, + spacing, + ErrorSummary, + Label, + CancelLoader, +} from '@mongodb-js/compass-components'; + +import type { RootState } from '../stores/store'; +import { + cancelExportSchema, + changeExportSchemaFormat, + closeExportSchema, + type SchemaFormat, + type ExportStatus, +} from '../stores/schema-export-reducer'; + +const loaderStyles = css({ + marginTop: spacing[400], +}); + +const contentContainerStyles = css({ + paddingTop: spacing[400], + paddingBottom: spacing[400], +}); + +const codeStyles = css({ + maxHeight: `${spacing[1600] * 4 - spacing[800]}px`, + overflow: 'auto', +}); + +const footerStyles = css({ + display: 'flex', + gap: spacing[200], +}); + +const exportSchemaFormatOptions: { + title: string; + id: SchemaFormat; +}[] = [ + { + title: 'Standard', + id: 'standardJSON', + }, + { + title: 'MongoDB', + id: 'mongoDBJSON', + }, + { + title: 'Extended', + id: 'extendedJSON', + }, + { + title: 'Extended (Legacy)', + id: 'legacyJSON', + }, +]; + +const formatTypeRadioBoxGroupId = 'export-schema-format-type-box-group'; +const formatTypeRadioBoxGroupLabelId = `${formatTypeRadioBoxGroupId}-label`; + +const ExportSchemaModal: React.FunctionComponent<{ + errorMessage?: string; + exportStatus: ExportStatus; + isOpen: boolean; + resultId?: string; + exportFormat: SchemaFormat; + exportedSchema?: string; + onCancelSchemaExport: () => void; + onChangeSchemaExportFormat: (format: SchemaFormat) => Promise; + onClose: () => void; +}> = ({ + errorMessage, + exportStatus, + isOpen, + exportFormat, + exportedSchema, + onCancelSchemaExport, + onChangeSchemaExportFormat, + onClose, +}) => { + const onFormatOptionSelected = useCallback( + (event: ChangeEvent) => { + event.preventDefault(); + + void onChangeSchemaExportFormat(event.target.value as SchemaFormat); + }, + [onChangeSchemaExportFormat] + ); + + return ( + + + + + + {exportSchemaFormatOptions.map(({ title, id }) => { + return ( + + {title} + + ); + })} + +
+ {exportStatus === 'inprogress' && ( + + )} + {exportStatus === 'complete' && ( + + {exportedSchema ?? 'Empty'} + + )} + {exportStatus === 'error' && errorMessage && ( + + )} +
+
+ + + + +
+ ); +}; + +export default connect( + (state: RootState) => ({ + exportStatus: state.schemaExport.exportStatus, + errorMessage: state.schemaExport.errorMessage, + exportFormat: state.schemaExport.exportFormat, + isOpen: state.schemaExport.isOpen, + exportedSchema: state.schemaExport.exportedSchema, + }), + { + onCancelSchemaExport: cancelExportSchema, + onChangeSchemaExportFormat: changeExportSchemaFormat, + onClose: closeExportSchema, + } +)(ExportSchemaModal); 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 633350e5fb3..1e86ef32a5c 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 @@ -3,6 +3,11 @@ import React from 'react'; import { render, screen } from '@mongodb-js/testing-library-compass'; import { expect } from 'chai'; import sinon from 'sinon'; +import { + createSandboxFromDefaultPreferences, + type PreferencesAccess, +} from 'compass-preferences-model'; +import { PreferencesProvider } from 'compass-preferences-model/provider'; import { SchemaToolbar } from './schema-toolbar'; import QueryBarPlugin from '@mongodb-js/compass-query-bar'; import { @@ -27,28 +32,39 @@ const MockQueryBarPlugin = QueryBarPlugin.withMockServices({ const testErrorMessage = 'An error occurred during schema analysis: test error msg'; - -const renderSchemaToolbar = ( - props: Partial> = {} -) => { - const queryBarProps = {}; - render( - - {}} - onResetClicked={() => {}} - sampleSize={10} - schemaResultId="123" - {...props} - /> - - ); -}; +const exportSchemaTestId = 'open-schema-export-button'; describe('SchemaToolbar', function () { + let defaultPreferences: PreferencesAccess; + + before(async function () { + defaultPreferences = await createSandboxFromDefaultPreferences(); + }); + + const renderSchemaToolbar = ( + props: Partial> = {}, + preferences: PreferencesAccess = defaultPreferences + ) => { + const queryBarProps = {}; + render( + + + {}} + onResetClicked={() => {}} + sampleSize={10} + schemaResultId="123" + onExportSchemaClicked={() => {}} + {...props} + /> + + + ); + }; + afterEach(function () { sinon.restore(); }); @@ -98,4 +114,33 @@ describe('SchemaToolbar', function () { renderSchemaToolbar(); expect(screen.getByTestId('query-bar')).to.be.visible; }); + + it('does not render the export schema button', function () { + renderSchemaToolbar({ + sampleSize: 100, + }); + expect(screen.getByText(/documents/)).to.be.visible; + + expect(screen.queryByTestId(exportSchemaTestId)).to.not.exist; + }); + + describe('when rendered with the enableExportSchema feature flag true', function () { + beforeEach(async function () { + const preferences = await createSandboxFromDefaultPreferences(); + await preferences.savePreferences({ + enableExportSchema: true, + }); + + renderSchemaToolbar( + { + sampleSize: 100, + }, + preferences + ); + }); + + it('renders the export schema button', function () { + expect(screen.getByTestId(exportSchemaTestId)).to.be.visible; + }); + }); }); diff --git a/packages/compass-schema/src/components/schema-toolbar/schema-toolbar.tsx b/packages/compass-schema/src/components/schema-toolbar/schema-toolbar.tsx index 313c6ee9e36..f84f6e13c87 100644 --- a/packages/compass-schema/src/components/schema-toolbar/schema-toolbar.tsx +++ b/packages/compass-schema/src/components/schema-toolbar/schema-toolbar.tsx @@ -1,12 +1,15 @@ import React, { useMemo } from 'react'; import { Body, + Button, ErrorSummary, + Icon, Link, WarningSummary, css, spacing, } from '@mongodb-js/compass-components'; +import { usePreference } from 'compass-preferences-model/provider'; import type { AnalysisState } from '../../constants/analysis-states'; import { ANALYSIS_STATE_ERROR, @@ -60,6 +63,7 @@ type SchemaToolbarProps = { errorMessage: string; isOutdated: boolean; onAnalyzeSchemaClicked: () => void; + onExportSchemaClicked: () => void; onResetClicked: () => void; sampleSize: number; schemaResultId: string; @@ -70,6 +74,7 @@ const SchemaToolbar: React.FunctionComponent = ({ errorMessage, isOutdated, onAnalyzeSchemaClicked, + onExportSchemaClicked, onResetClicked, sampleSize, schemaResultId, @@ -79,6 +84,8 @@ const SchemaToolbar: React.FunctionComponent = ({ [sampleSize] ); + const enableExportSchema = usePreference('enableExportSchema'); + return (
@@ -92,6 +99,19 @@ const SchemaToolbar: React.FunctionComponent = ({
{analysisState === ANALYSIS_STATE_COMPLETE && !isOutdated && (
+ {enableExportSchema && ANALYSIS_STATE_COMPLETE && ( +
+ +
+ )}
!isInternalFieldPath(path[0]) + ); + + expect(internalSchema).to.deep.equal(expectedSchema); }); it('adds promoteValues: false so the analyzer can report more accurate types', async function () { diff --git a/packages/compass-schema/src/modules/schema-analysis.ts b/packages/compass-schema/src/modules/schema-analysis.ts index 30749af83cf..0774f9a54b8 100644 --- a/packages/compass-schema/src/modules/schema-analysis.ts +++ b/packages/compass-schema/src/modules/schema-analysis.ts @@ -1,6 +1,5 @@ -import { isInternalFieldPath } from 'hadron-document'; import type { AggregateOptions, Filter, Document } from 'mongodb'; -import mongodbSchema from 'mongodb-schema'; +import { analyzeDocuments } from 'mongodb-schema'; import type { Schema, ArraySchemaType, @@ -36,6 +35,8 @@ function promoteMongoErrorCode(err?: Error & { code?: unknown }) { return err; } +export type SchemaAccessor = Awaited>; + export const analyzeSchema = async ( dataService: DataService, abortSignal: AbortSignal, @@ -49,7 +50,7 @@ export const analyzeSchema = async ( | undefined, aggregateOptions: AggregateOptions, { log, mongoLogId, debug }: Logger -): Promise => { +): Promise => { try { log.info(mongoLogId(1001000089), 'Schema', 'Starting schema analysis', { ns, @@ -67,14 +68,13 @@ export const analyzeSchema = async ( fallbackReadPreference: 'secondaryPreferred', } ); - const schemaData = await mongodbSchema(docs); - schemaData.fields = schemaData.fields.filter( - ({ path }) => !isInternalFieldPath(path[0]) - ); + const schemaAccessor = await analyzeDocuments(docs, { + signal: abortSignal, + }); log.info(mongoLogId(1001000090), 'Schema', 'Schema analysis completed', { ns, }); - return schemaData; + return schemaAccessor; } catch (err: any) { log.error(mongoLogId(1001000091), 'Schema', 'Schema analysis failed', { ns, diff --git a/packages/compass-schema/src/stores/reducer.ts b/packages/compass-schema/src/stores/schema-analysis-reducer.ts similarity index 77% rename from packages/compass-schema/src/stores/reducer.ts rename to packages/compass-schema/src/stores/schema-analysis-reducer.ts index c632a01af85..21e7b74d469 100644 --- a/packages/compass-schema/src/stores/reducer.ts +++ b/packages/compass-schema/src/stores/schema-analysis-reducer.ts @@ -1,5 +1,6 @@ import type { Schema } from 'mongodb-schema'; -import type { Action, AnyAction, Reducer } from 'redux'; +import { isInternalFieldPath } from 'hadron-document'; +import type { Action, Reducer } from 'redux'; import type { AggregateOptions } from 'mongodb'; import { type AnalysisState } from '../constants/analysis-states'; import { @@ -13,6 +14,7 @@ import { addLayer, generateGeoQuery } from '../modules/geo'; import { analyzeSchema, calculateSchemaDepth, + type SchemaAccessor, schemaContainsGeoData, } from '../modules/schema-analysis'; import { capMaxTimeMSAtPreferenceLimit } from 'compass-preferences-model/provider'; @@ -21,60 +23,65 @@ import type { Circle, Layer, LayerGroup, Polygon } from 'leaflet'; import { mongoLogId } from '@mongodb-js/compass-logging/provider'; import type { SchemaThunkAction } from './store'; import { UUID } from 'bson'; +import { isAction } from '../utils'; const DEFAULT_SAMPLE_SIZE = 1000; const ERROR_CODE_MAX_TIME_MS_EXPIRED = 50; -export function isAction( - action: AnyAction, - type: A['type'] -): action is A { - return action.type === type; -} - -export type SchemaState = { +export type SchemaAnalysisState = { analysisState: AnalysisState; errorMessage: string; schema: Schema | null; + schemaAccessor: SchemaAccessor | null; resultId: string; }; -export const enum SchemaActions { - analysisStarted = 'schema-service/schema/analysisStarted', - analysisFinished = 'schema-service/schema/analysisFinished', - analysisFailed = 'schema-service/schema/analysisFailed', +export const enum SchemaAnalysisActions { + analysisStarted = 'schema-service/schema-analysis/analysisStarted', + analysisFinished = 'schema-service/schema-analysis/analysisFinished', + analysisFailed = 'schema-service/schema-analysis/analysisFailed', } export type AnalysisStartedAction = { - type: SchemaActions.analysisStarted; + type: SchemaAnalysisActions.analysisStarted; }; export type AnalysisFinishedAction = { - type: SchemaActions.analysisFinished; + type: SchemaAnalysisActions.analysisFinished; + schemaAccessor: SchemaAccessor | null; schema: Schema | null; }; export type AnalysisFailedAction = { - type: SchemaActions.analysisFailed; + type: SchemaAnalysisActions.analysisFailed; error: Error; }; -const reducer: Reducer = ( +export const schemaAnalysisReducer: Reducer = ( state = getInitialState(), action ) => { - if (isAction(action, SchemaActions.analysisStarted)) { + if ( + isAction( + action, + SchemaAnalysisActions.analysisStarted + ) + ) { return { ...state, analysisState: ANALYSIS_STATE_ANALYZING, errorMessage: '', schema: null, + schemaAccessor: null, }; } if ( - isAction(action, SchemaActions.analysisFinished) + isAction( + action, + SchemaAnalysisActions.analysisFinished + ) ) { return { ...state, @@ -82,11 +89,14 @@ const reducer: Reducer = ( ? ANALYSIS_STATE_COMPLETE : ANALYSIS_STATE_INITIAL, schema: action.schema, + schemaAccessor: action.schemaAccessor, resultId: resultId(), }; } - if (isAction(action, SchemaActions.analysisFailed)) { + if ( + isAction(action, SchemaAnalysisActions.analysisFailed) + ) { return { ...state, ...getErrorState(action.error), @@ -118,7 +128,9 @@ function resultId(): string { export const handleSchemaShare = (): SchemaThunkAction => { return (dispatch, getState, { namespace }) => { - const { schema } = getState(); + const { + schemaAnalysis: { schema }, + } = getState(); const hasSchema = schema !== null; if (hasSchema) { void navigator.clipboard.writeText(JSON.stringify(schema, null, ' ')); @@ -147,7 +159,9 @@ export const _trackSchemaShared = ( hasSchema: boolean ): SchemaThunkAction => { return (dispatch, getState, { track, connectionInfoRef }) => { - const { schema } = getState(); + const { + schemaAnalysis: { schema }, + } = getState(); // Use a function here to a) ensure that the calculations here // are only made when telemetry is enabled and b) that errors from // those calculations are caught and logged rather than displayed to @@ -162,10 +176,11 @@ export const _trackSchemaShared = ( }; }; -const getInitialState = (): SchemaState => ({ +const getInitialState = (): SchemaAnalysisState => ({ analysisState: ANALYSIS_STATE_INITIAL, errorMessage: '', schema: null, + schemaAccessor: null, resultId: resultId(), }); @@ -234,7 +249,9 @@ export const startAnalysis = (): SchemaThunkAction< track, } ) => { - const { analysisState } = getState(); + const { + schemaAnalysis: { analysisState }, + } = getState(); if (analysisState === ANALYSIS_STATE_ANALYZING) { debug('analysis already in progress. ignoring subsequent start'); return; @@ -255,16 +272,16 @@ export const startAnalysis = (): SchemaThunkAction< maxTimeMS: capMaxTimeMSAtPreferenceLimit(preferences, query.maxTimeMS), }; + abortControllerRef.current = new AbortController(); + const abortSignal = abortControllerRef.current.signal; + try { debug('analysis started'); - abortControllerRef.current = new AbortController(); - const abortSignal = abortControllerRef.current.signal; - - dispatch({ type: SchemaActions.analysisStarted }); + dispatch({ type: SchemaAnalysisActions.analysisStarted }); const analysisStartTime = Date.now(); - const schema = await analyzeSchema( + const schemaAccessor = await analyzeSchema( dataService, abortSignal, namespace, @@ -272,13 +289,24 @@ export const startAnalysis = (): SchemaThunkAction< driverOptions, logger ); + let schema: Schema | null = null; + if (schemaAccessor) { + schema = await schemaAccessor.getInternalSchema(); + schema.fields = schema.fields.filter( + ({ path }) => !isInternalFieldPath(path[0]) + ); + } const analysisTime = Date.now() - analysisStartTime; if (schema !== null) { fieldStoreService.updateFieldsFromSchema(namespace, schema); } - dispatch({ type: SchemaActions.analysisFinished, schema }); + dispatch({ + type: SchemaAnalysisActions.analysisFinished, + schema, + schemaAccessor, + }); // track schema analyzed const trackEvent = () => ({ @@ -300,11 +328,12 @@ export const startAnalysis = (): SchemaThunkAction< error: err.stack, } ); - dispatch({ type: SchemaActions.analysisFailed, error: err as Error }); + dispatch({ + type: SchemaAnalysisActions.analysisFailed, + error: err as Error, + }); } finally { abortControllerRef.current = undefined; } }; }; - -export default reducer; diff --git a/packages/compass-schema/src/stores/schema-export-reducer.ts b/packages/compass-schema/src/stores/schema-export-reducer.ts new file mode 100644 index 00000000000..7c8b4147d2c --- /dev/null +++ b/packages/compass-schema/src/stores/schema-export-reducer.ts @@ -0,0 +1,321 @@ +import type { Action, Reducer } from 'redux'; +import { mongoLogId } from '@mongodb-js/compass-logging/provider'; +import type { + StandardJSONSchema, + InternalSchema, + MongoDBJSONSchema, + ExpandedJSONSchema, +} from 'mongodb-schema'; + +import type { SchemaThunkAction } from './store'; +import { isAction } from '../utils'; +import type { SchemaAccessor } from '../modules/schema-analysis'; + +export type SchemaFormat = + | 'standardJSON' + | 'mongoDBJSON' + | 'extendedJSON' + | 'legacyJSON'; +export type ExportStatus = 'inprogress' | 'complete' | 'error'; +export type SchemaExportState = { + abortController?: AbortController; + isOpen: boolean; + exportedSchema?: string; + exportFormat: SchemaFormat; + errorMessage?: string; + exportStatus: ExportStatus; +}; + +const defaultSchemaFormat: SchemaFormat = 'standardJSON'; + +const getInitialState = (): SchemaExportState => ({ + errorMessage: undefined, + exportFormat: defaultSchemaFormat, + exportStatus: 'inprogress', + exportedSchema: undefined, + isOpen: false, +}); + +export const enum SchemaExportActions { + openExportSchema = 'schema-service/schema-export/openExportSchema', + closeExportSchema = 'schema-service/schema-export/closeExportSchema', + changeExportSchemaStatus = 'schema-service/schema-export/changeExportSchemaStatus', + changeExportSchemaFormatStarted = 'schema-service/schema-export/changeExportSchemaFormatStarted', + changeExportSchemaFormatComplete = 'schema-service/schema-export/changeExportSchemaFormatComplete', + changeExportSchemaFormatError = 'schema-service/schema-export/changeExportSchemaFormatError', + cancelExportSchema = 'schema-service/schema-export/cancelExportSchema', +} + +export type OpenExportSchemaAction = { + type: SchemaExportActions.openExportSchema; +}; +export const openExportSchema = (): SchemaThunkAction< + void, + OpenExportSchemaAction +> => { + return (dispatch) => { + void dispatch(changeExportSchemaFormat(defaultSchemaFormat)); + + dispatch({ + type: SchemaExportActions.openExportSchema, + }); + }; +}; + +export type CloseExportSchemaAction = { + type: SchemaExportActions.closeExportSchema; +}; +export const closeExportSchema = (): SchemaThunkAction< + void, + CloseExportSchemaAction +> => { + return (dispatch, getState) => { + const { + schemaExport: { abortController }, + } = getState(); + abortController?.abort(); + + return dispatch({ + type: SchemaExportActions.closeExportSchema, + }); + }; +}; + +export type CancelExportSchemaAction = { + type: SchemaExportActions.cancelExportSchema; +}; + +export type ChangeExportSchemaFormatStartedAction = { + type: SchemaExportActions.changeExportSchemaFormatStarted; + abortController: AbortController; + exportFormat: SchemaFormat; +}; + +export type ChangeExportSchemaFormatErroredAction = { + type: SchemaExportActions.changeExportSchemaFormatError; + errorMessage: string; +}; + +export type ChangeExportSchemaFormatCompletedAction = { + type: SchemaExportActions.changeExportSchemaFormatComplete; + exportedSchema: string; +}; + +export const cancelExportSchema = (): SchemaThunkAction< + void, + CancelExportSchemaAction +> => { + return (dispatch, getState) => { + const { + schemaExport: { abortController }, + } = getState(); + abortController?.abort(); + + return dispatch({ + type: SchemaExportActions.cancelExportSchema, + }); + }; +}; + +async function getSchemaByFormat({ + exportFormat, + schemaAccessor, +}: { + exportFormat: SchemaFormat; + schemaAccessor: SchemaAccessor; + signal: AbortSignal; +}): Promise { + // TODO: Use the signal once we pull in the schema accessor type changes. + let schema: + | StandardJSONSchema + | MongoDBJSONSchema + | ExpandedJSONSchema + | InternalSchema; + switch (exportFormat) { + case 'standardJSON': + schema = await schemaAccessor.getStandardJsonSchema(); + break; + case 'mongoDBJSON': + schema = await schemaAccessor.getMongoDBJsonSchema(); + break; + case 'extendedJSON': + schema = await schemaAccessor.getExpandedJSONSchema(); + break; + case 'legacyJSON': + schema = await schemaAccessor.getInternalSchema(); + break; + } + + return JSON.stringify(schema, null, 2); +} + +export const changeExportSchemaFormat = ( + exportFormat: SchemaFormat +): SchemaThunkAction< + Promise, + | ChangeExportSchemaFormatStartedAction + | ChangeExportSchemaFormatErroredAction + | ChangeExportSchemaFormatCompletedAction +> => { + return async (dispatch, getState, { logger: { log } }) => { + const { + schemaExport: { abortController: existingAbortController }, + } = getState(); + + // If we're already in progress we abort their current operation. + existingAbortController?.abort(); + + const abortController = new AbortController(); + + dispatch({ + type: SchemaExportActions.changeExportSchemaFormatStarted, + abortController, + exportFormat, + }); + + let exportedSchema: string; + try { + log.info( + mongoLogId(1_001_000_342), + 'Schema export formatting', + 'Formatting schema', + { + format: exportFormat, + } + ); + + const schemaAccessor = getState().schemaAnalysis.schemaAccessor; + if (!schemaAccessor) { + throw new Error('No schema analysis available'); + } + + exportedSchema = await getSchemaByFormat({ + schemaAccessor, + exportFormat, + signal: abortController.signal, + }); + } catch (err: any) { + if (abortController.signal.aborted) { + return; + } + log.error( + mongoLogId(1_001_000_343), + 'Schema export formatting', + 'Error formatting schema', + { + error: err.stack, + } + ); + + dispatch({ + type: SchemaExportActions.changeExportSchemaFormatError, + errorMessage: (err as Error).message, + }); + return; + } + + if (abortController.signal.aborted) { + return; + } + + log.info( + mongoLogId(1_001_000_344), + 'Schema export formatting complete', + 'Formatting schema complete', + { + format: exportFormat, + exportedSchemaLength: exportedSchema.length, + } + ); + + dispatch({ + type: SchemaExportActions.changeExportSchemaFormatComplete, + exportedSchema, + }); + }; +}; + +export const schemaExportReducer: Reducer = ( + state = getInitialState(), + action +) => { + if ( + isAction( + action, + SchemaExportActions.openExportSchema + ) + ) { + return { + ...state, + isOpen: true, + }; + } + + if ( + isAction( + action, + SchemaExportActions.closeExportSchema + ) + ) { + return { + ...state, + isOpen: false, + }; + } + + if ( + isAction( + action, + SchemaExportActions.changeExportSchemaFormatStarted + ) + ) { + return { + ...state, + abortController: action.abortController, + exportStatus: 'inprogress', + exportFormat: action.exportFormat, + }; + } + + if ( + isAction( + action, + SchemaExportActions.changeExportSchemaFormatError + ) + ) { + return { + ...state, + errorMessage: action.errorMessage, + exportStatus: 'error', + }; + } + + if ( + isAction( + action, + SchemaExportActions.changeExportSchemaFormatComplete + ) + ) { + return { + ...state, + exportedSchema: action.exportedSchema, + exportStatus: 'complete', + }; + } + + if ( + isAction( + action, + SchemaExportActions.cancelExportSchema + ) + ) { + return { + ...state, + exportStatus: 'error', + errorMessage: 'cancelled', + abortController: undefined, + }; + } + + return state; +}; diff --git a/packages/compass-schema/src/stores/store.spec.ts b/packages/compass-schema/src/stores/store.spec.ts index e45fa172854..470302af466 100644 --- a/packages/compass-schema/src/stores/store.spec.ts +++ b/packages/compass-schema/src/stores/store.spec.ts @@ -2,14 +2,19 @@ import { activateSchemaPlugin } from './store'; import type { SchemaStore, SchemaPluginServices } from './store'; import AppRegistry, { createActivateHelpers } from 'hadron-app-registry'; import { expect } from 'chai'; +import { waitFor } from '@mongodb-js/testing-library-compass'; import { ANALYSIS_STATE_INITIAL } from '../constants/analysis-states'; import { createSandboxFromDefaultPreferences } from 'compass-preferences-model'; import { createNoopLogger } from '@mongodb-js/compass-logging/provider'; import type { FieldStoreService } from '@mongodb-js/compass-field-store'; import { createNoopTrack } from '@mongodb-js/compass-telemetry/provider'; -import { startAnalysis, stopAnalysis } from './reducer'; +import { startAnalysis, stopAnalysis } from './schema-analysis-reducer'; import Sinon from 'sinon'; +import { + changeExportSchemaFormat, + openExportSchema, +} from './schema-export-reducer'; const dummyLogger = createNoopLogger('TEST'); const dummyTrack = createNoopTrack(); @@ -89,24 +94,26 @@ describe('Schema Store', function () { }); it('defaults analysis state to initial', function () { - expect(store.getState().analysisState).to.equal(ANALYSIS_STATE_INITIAL); + expect(store.getState().schemaAnalysis.analysisState).to.equal( + ANALYSIS_STATE_INITIAL + ); }); it('defaults the error to empty', function () { - expect(store.getState().errorMessage).to.equal(''); + expect(store.getState().schemaAnalysis.errorMessage).to.equal(''); }); it('defaults the schema to null', function () { - expect(store.getState().schema).to.equal(null); + expect(store.getState().schemaAnalysis.schema).to.equal(null); }); it('runs analysis', async function () { - const oldResultId = store.getState().resultId; + const oldResultId = store.getState().schemaAnalysis.resultId; sampleStub.resolves([{ name: 'Hans' }, { name: 'Greta' }]); await store.dispatch(startAnalysis()); expect(sampleStub).to.have.been.called; const { analysisState, errorMessage, schema, resultId } = - store.getState(); + store.getState().schemaAnalysis; expect(analysisState).to.equal('complete'); expect(!!errorMessage).to.be.false; expect(schema).not.to.be.null; @@ -115,12 +122,68 @@ describe('Schema Store', function () { it('analysis can be aborted', async function () { const analysisPromise = store.dispatch(startAnalysis()); - expect(store.getState().analysisState).to.equal('analyzing'); + expect(store.getState().schemaAnalysis.analysisState).to.equal( + 'analyzing' + ); sampleStub.rejects(new Error('abort')); store.dispatch(stopAnalysis()); isCancelErrorStub.returns(true); await analysisPromise; - expect(store.getState().analysisState).to.equal('initial'); + expect(store.getState().schemaAnalysis.analysisState).to.equal('initial'); + }); + + describe('schema export', function () { + describe('with an analyzed schema', function () { + beforeEach(async function () { + sampleStub.resolves([{ name: 'Hans' }, { name: 'Greta' }]); + await store.dispatch(startAnalysis()); + }); + + it('runs schema export formatting with the analyzed schema when opened', async function () { + sampleStub.resolves([{ name: 'Hans' }, { name: 'Greta' }]); + expect(sampleStub).to.have.been.called; + expect(store.getState().schemaExport.exportStatus).to.equal( + 'inprogress' + ); + store.dispatch(openExportSchema()); + await waitFor(() => { + expect(store.getState().schemaExport.exportStatus).to.equal( + 'complete' + ); + }); + const { exportStatus, errorMessage, exportedSchema } = + store.getState().schemaExport; + expect(exportStatus).to.equal('complete'); + expect(!!errorMessage).to.be.false; + expect(exportedSchema).not.to.be.undefined; + expect(JSON.parse(exportedSchema!).type).to.equal('object'); + expect(JSON.parse(exportedSchema!)['$schema']).to.equal( + 'https://json-schema.org/draft/2020-12/schema' + ); + expect(JSON.parse(exportedSchema!).required).to.deep.equal(['name']); + expect(JSON.parse(exportedSchema!).properties).to.deep.equal({ + name: { type: 'string' }, + }); + }); + + it('runs schema export formatting with a new format', async function () { + sampleStub.resolves([{ name: 'Hans' }, { name: 'Greta' }]); + await store.dispatch(changeExportSchemaFormat('mongoDBJSON')); + expect(sampleStub).to.have.been.called; + const { exportStatus, errorMessage, exportedSchema } = + store.getState().schemaExport; + expect(exportStatus).to.equal('complete'); + expect(!!errorMessage).to.be.false; + expect(exportedSchema).not.to.be.undefined; + expect(JSON.parse(exportedSchema!).type).to.equal(undefined); + expect(JSON.parse(exportedSchema!).bsonType).to.equal('object'); + expect(JSON.parse(exportedSchema!)['$schema']).to.equal(undefined); + expect(JSON.parse(exportedSchema!).required).to.deep.equal(['name']); + expect(JSON.parse(exportedSchema!).properties).to.deep.equal({ + name: { bsonType: 'string' }, + }); + }); + }); }); it('runs the analysis with fallback read pref secondaryPreferred', async function () { diff --git a/packages/compass-schema/src/stores/store.ts b/packages/compass-schema/src/stores/store.ts index 243a8117b06..d7efe6b7ab2 100644 --- a/packages/compass-schema/src/stores/store.ts +++ b/packages/compass-schema/src/stores/store.ts @@ -1,5 +1,10 @@ import type { Logger } from '@mongodb-js/compass-logging'; -import { createStore, applyMiddleware, type AnyAction } from 'redux'; +import { + createStore, + applyMiddleware, + type AnyAction, + combineReducers, +} from 'redux'; import thunk, { type ThunkDispatch, type ThunkAction } from 'redux-thunk'; import type { CollectionTabPluginMetadata } from '@mongodb-js/compass-collection'; import type { @@ -12,7 +17,15 @@ import type { PreferencesAccess } from 'compass-preferences-model/provider'; import type { FieldStoreService } from '@mongodb-js/compass-field-store'; import type { QueryBarService } from '@mongodb-js/compass-query-bar'; import type { TrackFunction } from '@mongodb-js/compass-telemetry'; -import reducer, { handleSchemaShare, stopAnalysis } from './reducer'; +import { + schemaAnalysisReducer, + handleSchemaShare, + stopAnalysis, +} from './schema-analysis-reducer'; +import { + cancelExportSchema, + schemaExportReducer, +} from './schema-export-reducer'; import type { InternalLayer } from '../modules/geo'; export type DataService = Pick; @@ -28,7 +41,12 @@ export type SchemaPluginServices = { queryBar: QueryBarService; }; -export type RootState = ReturnType; +export const rootReducer = combineReducers({ + schemaAnalysis: schemaAnalysisReducer, + schemaExport: schemaExportReducer, +}); + +export type RootState = ReturnType; export type SchemaExtraArgs = SchemaPluginServices & { abortControllerRef: { current?: AbortController }; geoLayersRef: { current: Record }; @@ -65,6 +83,7 @@ export function activateSchemaPlugin( ); addCleanup(() => store.dispatch(stopAnalysis())); + addCleanup(() => store.dispatch(cancelExportSchema())); return { store, @@ -85,7 +104,7 @@ export function configureStore( current: {}, }; const store = createStore( - reducer, + rootReducer, applyMiddleware( thunk.withExtraArgument({ ...services, diff --git a/packages/compass-schema/src/utils.ts b/packages/compass-schema/src/utils.ts index a1bfe2e6c67..c77e45d6307 100644 --- a/packages/compass-schema/src/utils.ts +++ b/packages/compass-schema/src/utils.ts @@ -1,4 +1,12 @@ import type { AtlasClusterMetadata } from '@mongodb-js/connection-storage/renderer'; +import type { AnyAction } from 'redux'; + +export function isAction( + action: AnyAction, + type: A['type'] +): action is A { + return action.type === type; +} export function getAtlasPerformanceAdvisorLink({ metricsId,