From 7dd0c0bec5d504dcf963d8a2792d9786f0855d71 Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Wed, 28 May 2025 17:47:47 +0200 Subject: [PATCH] Revert "feat: initial feature-flagged, new autocompleter MONGOSH-2036 (#2424)" This reverts commit 493993ec5ddb634a5d17095acff7212bd9a92a96. Startup performance appears to have regressed around ~15 percent. --- package-lock.json | 216 +----------------- .../src/open-context-runtime.ts | 1 - packages/cli-repl/package.json | 1 - packages/cli-repl/src/mongosh-repl.spec.ts | 199 +++++++--------- packages/cli-repl/src/mongosh-repl.ts | 49 +--- packages/cli-repl/test/repl-helpers.ts | 20 -- packages/e2e-tests/test/e2e-snippet.spec.ts | 1 - packages/shell-api/package.json | 4 +- packages/shell-api/src/collection.ts | 33 +-- packages/shell-api/src/integration.spec.ts | 38 --- packages/shell-api/src/mongo.ts | 8 - .../shell-api/src/shell-instance-state.ts | 80 ------- packages/types/src/index.ts | 5 +- 13 files changed, 94 insertions(+), 561 deletions(-) diff --git a/package-lock.json b/package-lock.json index a9677cccf4..adc48854e5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6539,19 +6539,6 @@ "tar": "^6.1.15" } }, - "node_modules/@mongodb-js/mongodb-ts-autocomplete": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/@mongodb-js/mongodb-ts-autocomplete/-/mongodb-ts-autocomplete-0.2.2.tgz", - "integrity": "sha512-5GwS2zm8OKJeWFK25PalpstMimIrnif1T07Ur+HECOCFhndTQmIV7VJve86GBwrnmM5Cy4P4Pv7FrjwvfE222A==", - "license": "Apache-2.0", - "dependencies": { - "@mongodb-js/ts-autocomplete": "^0.3.1", - "@mongosh/shell-api": "^3.11.0", - "mongodb-schema": "^12.6.2", - "node-cache": "^5.1.2", - "typescript": "^5.0.4" - } - }, "node_modules/@mongodb-js/monorepo-tools": { "version": "1.1.16", "resolved": "https://registry.npmjs.org/@mongodb-js/monorepo-tools/-/monorepo-tools-1.1.16.tgz", @@ -6878,40 +6865,6 @@ "node": ">=0.10.0" } }, - "node_modules/@mongodb-js/ts-autocomplete": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@mongodb-js/ts-autocomplete/-/ts-autocomplete-0.3.1.tgz", - "integrity": "sha512-2ui9y88PM+PIad/3htoGn/8kiNK8V4vVTrqicgAt1Bozt0AwCUqJFUfnpqf40eJVD20XbPWfeKPjPMPkA7SruQ==", - "license": "Apache-2.0", - "dependencies": { - "debug": "^4.4.0", - "lodash": "^4.17.21", - "typescript": "^5.0.4" - } - }, - "node_modules/@mongodb-js/ts-autocomplete/node_modules/debug": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", - "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@mongodb-js/ts-autocomplete/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "license": "MIT" - }, "node_modules/@mongodb-js/tsconfig-mongosh": { "resolved": "configs/tsconfig-mongosh", "link": true @@ -14767,18 +14720,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/cli-table": { - "version": "0.3.11", - "resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.11.tgz", - "integrity": "sha512-IqLQi4lO0nIB4tcdTpN4LCB9FI3uqrJZK7RC515EnhZ6qBaglkIgICb1wjeAqpdoOabm1+SuQtkXIPdYC93jhQ==", - "optional": true, - "dependencies": { - "colors": "1.0.3" - }, - "engines": { - "node": ">= 0.2.0" - } - }, "node_modules/cli-width": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", @@ -14812,15 +14753,6 @@ "wrap-ansi": "^7.0.0" } }, - "node_modules/clone": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", - "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", - "license": "MIT", - "engines": { - "node": ">=0.8" - } - }, "node_modules/clone-deep": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", @@ -14921,16 +14853,6 @@ "dev": true, "license": "MIT" }, - "node_modules/colors": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", - "integrity": "sha512-pFGrxThWcWQ2MsAz6RtgeWe4NK2kUE1WfsrvvlctdII745EW9I0yflqhe7++M5LEc7bV2c/9/5zc8sFcpL0Drw==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">=0.1.90" - } - }, "node_modules/columnify": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/columnify/-/columnify-1.6.0.tgz", @@ -21329,13 +21251,6 @@ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "license": "ISC" }, - "node_modules/isnumber": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isnumber/-/isnumber-1.0.0.tgz", - "integrity": "sha512-JLiSz/zsZcGFXPrB4I/AGBvtStkt+8QmksyZBZnVXnnK9XdTEyz0tX8CRYljtwYDuIuZzih6DpHQdi+3Q6zHPw==", - "license": "MIT", - "optional": true - }, "node_modules/isobject": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", @@ -23661,6 +23576,7 @@ "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "devOptional": true, "license": "MIT" }, "node_modules/lodash.clonedeep": { @@ -25062,13 +24978,6 @@ "bson": "6.x" } }, - "node_modules/mongodb-ns": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/mongodb-ns/-/mongodb-ns-2.4.2.tgz", - "integrity": "sha512-gYJjEYG4v4a1WSXgUf81OBoBRlj+Z1SlnQVO392fC/4a1CN7CLWDITajZWPFTPh/yRozYk6sHHtZwZmQhodBEA==", - "license": "MIT", - "optional": true - }, "node_modules/mongodb-runner": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/mongodb-runner/-/mongodb-runner-5.7.1.tgz", @@ -25131,93 +25040,6 @@ "node": ">=12" } }, - "node_modules/mongodb-schema": { - "version": "12.6.2", - "resolved": "https://registry.npmjs.org/mongodb-schema/-/mongodb-schema-12.6.2.tgz", - "integrity": "sha512-uKjkTAx6MqJi0Xj0aeYRjvYr3O7LrUQgXH1c0WQCOByPoYbNG9RAhWoc4IwriIqTHyBw1RJn0C/p7DISOPYpMg==", - "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" - } - }, - "node_modules/mongodb-schema/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "license": "Python-2.0", - "optional": true - }, - "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==", - "license": "ISC", - "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/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "license": "MIT", - "optional": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "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==", - "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" - } - }, - "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==", - "license": "ISC", - "optional": true, - "engines": { - "node": ">=12" - } - }, "node_modules/mongosh": { "resolved": "packages/mongosh", "link": true @@ -25544,18 +25366,6 @@ "integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==", "license": "MIT" }, - "node_modules/node-cache": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/node-cache/-/node-cache-5.1.2.tgz", - "integrity": "sha512-t1QzWwnk4sjLWaQAS8CHgOJ+RAfmHpxFWmc36IWTiWHQfs0w5JDMBS1b1ZxQteo0vVVuWJvIUKHDkkeK7vIGCg==", - "license": "MIT", - "dependencies": { - "clone": "2.x" - }, - "engines": { - "node": ">= 8.0.0" - } - }, "node_modules/node-domexception": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", @@ -29494,12 +29304,6 @@ "dev": true, "license": "MIT" }, - "node_modules/reservoir": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/reservoir/-/reservoir-0.1.2.tgz", - "integrity": "sha512-ysyw95gLBhMAzqIVrOHJ2yMrRQHAS+h97bS9r89Z7Ou10Jhl2k5KOsyjPqrxL+WfEanov0o5bAMVzQ7AKyENHA==", - "license": "MIT" - }, "node_modules/resolve": { "version": "1.22.8", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", @@ -30956,19 +30760,6 @@ "dev": true, "license": "MIT" }, - "node_modules/stats-lite": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/stats-lite/-/stats-lite-2.2.0.tgz", - "integrity": "sha512-/Kz55rgUIv2KP2MKphwYT/NCuSfAlbbMRv2ZWw7wyXayu230zdtzhxxuXXcvsc6EmmhS8bSJl3uS1wmMHFumbA==", - "license": "MIT", - "optional": true, - "dependencies": { - "isnumber": "~1.0.0" - }, - "engines": { - "node": ">=2.0.0" - } - }, "node_modules/statuses": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", @@ -34322,7 +34113,6 @@ "license": "Apache-2.0", "dependencies": { "@mongodb-js/devtools-proxy-support": "^0.4.2", - "@mongodb-js/mongodb-ts-autocomplete": "^0.2.2", "@mongosh/arg-parser": "^3.10.3", "@mongosh/autocomplete": "^3.11.0", "@mongosh/editor": "^3.11.0", @@ -35092,13 +34882,11 @@ "@mongosh/history": "2.4.6", "@mongosh/i18n": "^2.13.1", "@mongosh/service-provider-core": "3.3.3", - "mongodb-redact": "^1.1.5", - "mongodb-schema": "^12.6.2" + "mongodb-redact": "^1.1.5" }, "devDependencies": { "@microsoft/api-extractor": "^7.39.3", "@mongodb-js/eslint-config-mongosh": "^1.0.0", - "@mongodb-js/mongodb-ts-autocomplete": "^0.2.2", "@mongodb-js/prettier-config-devtools": "^1.0.1", "@mongodb-js/tsconfig-mongosh": "^1.0.0", "@mongosh/types": "3.6.2", diff --git a/packages/browser-runtime-core/src/open-context-runtime.ts b/packages/browser-runtime-core/src/open-context-runtime.ts index 65686b503e..50d5ea97cd 100644 --- a/packages/browser-runtime-core/src/open-context-runtime.ts +++ b/packages/browser-runtime-core/src/open-context-runtime.ts @@ -29,7 +29,6 @@ export interface InterpreterEnvironment { */ export class OpenContextRuntime implements Runtime { private interpreterEnvironment: InterpreterEnvironment; - // TODO(MONGOSH-2205): we have to also port this to the new autocomplete private autocompleter: ShellApiAutocompleter | null = null; private shellEvaluator: ShellEvaluator; private instanceState: ShellInstanceState; diff --git a/packages/cli-repl/package.json b/packages/cli-repl/package.json index be39d217d7..2fcf36b518 100644 --- a/packages/cli-repl/package.json +++ b/packages/cli-repl/package.json @@ -77,7 +77,6 @@ "@mongosh/shell-evaluator": "^3.11.0", "@mongosh/snippet-manager": "^3.11.0", "@mongosh/types": "3.6.2", - "@mongodb-js/mongodb-ts-autocomplete": "^0.2.2", "@segment/analytics-node": "^1.3.0", "ansi-escape-sequences": "^5.1.2", "askcharacter": "^2.0.4", diff --git a/packages/cli-repl/src/mongosh-repl.spec.ts b/packages/cli-repl/src/mongosh-repl.spec.ts index 02d6ac3b54..54cd324fd8 100644 --- a/packages/cli-repl/src/mongosh-repl.spec.ts +++ b/packages/cli-repl/src/mongosh-repl.spec.ts @@ -1,9 +1,6 @@ /* eslint-disable no-control-regex */ import { MongoshCommandFailed } from '@mongosh/errors'; -import type { - AggregationCursor, - ServiceProvider, -} from '@mongosh/service-provider-core'; +import type { ServiceProvider } from '@mongosh/service-provider-core'; import { bson } from '@mongosh/service-provider-core'; import { ADMIN_DB } from '../../shell-api/lib/enums'; import { CliUserConfig } from '@mongosh/types'; @@ -20,7 +17,6 @@ import { tick, useTmpdir, waitEval, - waitMongoshCompletionResults, } from '../test/repl-helpers'; import type { MongoshIOProvider, MongoshNodeReplOptions } from './mongosh-repl'; import MongoshNodeRepl from './mongosh-repl'; @@ -93,14 +89,6 @@ describe('MongoshNodeRepl', function () { }, }); sp.runCommandWithCheck.resolves({ ok: 1 }); - - if (process.env.USE_NEW_AUTOCOMPLETE) { - sp.listCollections.resolves([{ name: 'coll' }]); - const aggCursor = stubInterface(); - aggCursor.toArray.resolves([{ foo: 1, bar: 2 }]); - sp.aggregate.returns(aggCursor); - } - serviceProvider = sp; calledServiceProviderFunctions = () => Object.fromEntries( @@ -364,9 +352,6 @@ describe('MongoshNodeRepl', function () { }; const tabtab = async () => { await tab(); - if (process.env.USE_NEW_AUTOCOMPLETE) { - await waitMongoshCompletionResults(bus); - } await tab(); }; @@ -394,28 +379,19 @@ describe('MongoshNodeRepl', function () { expect(output).to.include('65537'); }); - context( - `autocompleting during .editor [${ - process.env.USE_NEW_AUTOCOMPLETE ? 'new' : 'old' - }]`, - function () { - it('does not stop input when autocompleting during .editor', async function () { - input.write('.editor\n'); - await tick(); - expect(output).to.include('Entering editor mode'); - output = ''; - input.write('db.'); - await tabtab(); - await tick(); - input.write('version()\n'); - input.write('\u0004'); // Ctrl+D - await waitEval(bus); - expect(output, output).to.include( - 'Error running command serverBuildInfo' - ); - }); - } - ); + it('does not stop input when autocompleting during .editor', async function () { + input.write('.editor\n'); + await tick(); + expect(output).to.include('Entering editor mode'); + output = ''; + input.write('db.'); + await tabtab(); + await tick(); + input.write('version()\n'); + input.write('\u0004'); // Ctrl+D + await waitEval(bus); + expect(output).to.include('Error running command serverBuildInfo'); + }); it('can enter multiline code', async function () { for (const line of multilineCode.split('\n')) { @@ -473,86 +449,73 @@ describe('MongoshNodeRepl', function () { expect(code).to.equal(undefined); }); - context( - `autocompletion [${process.env.USE_NEW_AUTOCOMPLETE ? 'new' : 'old'}]`, - function () { - it('autocompletes collection methods', async function () { - input.write('db.coll.'); - await tabtab(); - await tick(); - expect(output, output).to.include('db.coll.updateOne'); - }); - it('autocompletes collection schema fields', async function () { - if (!process.env.USE_NEW_AUTOCOMPLETE) { - // not supported in the old autocomplete - this.skip(); - } - input.write('db.coll.find({'); - await tabtab(); - await tick(); - expect(output, output).to.include('db.coll.find({foo'); - }); - it('autocompletes shell-api methods (once)', async function () { - input.write('vers'); - await tabtab(); - await tick(); - expect(output, output).to.include('version'); - expect(output, output).to.not.match(/version[ \t]+version/); - }); - it('autocompletes async shell api methods', async function () { - input.write('db.coll.find().'); - await tabtab(); - await tick(); - expect(output, output).to.include('db.coll.find().toArray'); - }); - it('autocompletes local variables', async function () { - input.write('let somelongvariable = 0\n'); - await waitEval(bus); - output = ''; - input.write('somelong'); - await tabtab(); - await tick(); - expect(output, output).to.include('somelongvariable'); - }); - it('autocompletes partial repl commands', async function () { - input.write('.e'); - await tabtab(); - await tick(); - expect(output, output).to.include('editor'); - expect(output, output).to.include('exit'); - }); - it('autocompletes full repl commands', async function () { - input.write('.ed'); - await tabtab(); - await tick(); - expect(output, output).to.include('.editor'); - expect(output, output).not.to.include('exit'); - }); - it('autocompletion during .editor does not reset the prompt', async function () { - input.write('.editor\n'); - await tick(); - output = ''; - expect((mongoshRepl.runtimeState().repl as any)._prompt).to.equal(''); - input.write('db.'); - await tabtab(); - await tick(); - input.write('foo\nbar\n'); - expect((mongoshRepl.runtimeState().repl as any)._prompt).to.equal(''); - input.write('\u0003'); // Ctrl+C for abort - await tick(); - expect((mongoshRepl.runtimeState().repl as any)._prompt).to.equal( - 'test> ' - ); - expect(stripAnsi(output)).to.equal('db.foo\r\nbar\r\n\r\ntest> '); - }); - it('does not autocomplete tab-indented code', async function () { - output = ''; - input.write('\t\tfoo'); - await tick(); - expect(output, output).to.equal('\t\tfoo'); - }); - } - ); + context('autocompletion', function () { + it('autocompletes collection methods', async function () { + input.write('db.coll.'); + await tabtab(); + await tick(); + expect(output).to.include('db.coll.updateOne'); + }); + it('autocompletes shell-api methods (once)', async function () { + input.write('vers'); + await tabtab(); + await tick(); + expect(output).to.include('version'); + expect(output).to.not.match(/version[ \t]+version/); + }); + it('autocompletes async shell api methods', async function () { + input.write('db.coll.find().'); + await tabtab(); + await tick(); + expect(output).to.include('db.coll.find().close'); + }); + it('autocompletes local variables', async function () { + input.write('let somelongvariable = 0\n'); + await waitEval(bus); + output = ''; + input.write('somelong'); + await tabtab(); + await tick(); + expect(output).to.include('somelongvariable'); + }); + it('autocompletes partial repl commands', async function () { + input.write('.e'); + await tabtab(); + await tick(); + expect(output).to.include('editor'); + expect(output).to.include('exit'); + }); + it('autocompletes full repl commands', async function () { + input.write('.ed'); + await tabtab(); + await tick(); + expect(output).to.include('.editor'); + expect(output).not.to.include('exit'); + }); + it('autocompletion during .editor does not reset the prompt', async function () { + input.write('.editor\n'); + await tick(); + output = ''; + expect((mongoshRepl.runtimeState().repl as any)._prompt).to.equal(''); + input.write('db.'); + await tabtab(); + await tick(); + input.write('foo\nbar\n'); + expect((mongoshRepl.runtimeState().repl as any)._prompt).to.equal(''); + input.write('\u0003'); // Ctrl+C for abort + await tick(); + expect((mongoshRepl.runtimeState().repl as any)._prompt).to.equal( + 'test> ' + ); + expect(stripAnsi(output)).to.equal('db.foo\r\nbar\r\n\r\ntest> '); + }); + it('does not autocomplete tab-indented code', async function () { + output = ''; + input.write('\t\tfoo'); + await tick(); + expect(output).to.equal('\t\tfoo'); + }); + }); context('history support', function () { const arrowUp = '\x1b[A'; diff --git a/packages/cli-repl/src/mongosh-repl.ts b/packages/cli-repl/src/mongosh-repl.ts index b9c9f96ef9..4d9f9598ef 100644 --- a/packages/cli-repl/src/mongosh-repl.ts +++ b/packages/cli-repl/src/mongosh-repl.ts @@ -49,8 +49,6 @@ import { Script, createContext, runInContext } from 'vm'; import { installPasteSupport } from './repl-paste-support'; import util from 'util'; -import { MongoDBAutocompleter } from '@mongodb-js/mongodb-ts-autocomplete'; - declare const __non_webpack_require__: any; /** @@ -133,13 +131,6 @@ type Mutable = { -readonly [P in keyof T]: T[P]; }; -function transformAutocompleteResults( - line: string, - results: { result: string }[] -): [string[], string] { - return [results.map((result) => result.result), line]; -} - /** * An instance of a `mongosh` REPL, without any of the actual I/O. * Specifically, code called by this class should not do any @@ -439,21 +430,10 @@ class MongoshNodeRepl implements EvaluationListener { this.outputFinishString += installPasteSupport(repl); const origReplCompleter = promisify(repl.completer.bind(repl)); // repl.completer is callback-style - let newMongoshCompleter: MongoDBAutocompleter; - let oldMongoshCompleter: ( - line: string - ) => Promise<[string[], string, 'exclusive'] | [string[], string]>; - if (process.env.USE_NEW_AUTOCOMPLETE) { - const autocompletionContext = instanceState.getAutocompletionContext(); - newMongoshCompleter = new MongoDBAutocompleter({ - context: autocompletionContext, - }); - } else { - oldMongoshCompleter = completer.bind( - null, - instanceState.getAutocompleteParameters() - ); - } + const mongoshCompleter = completer.bind( + null, + instanceState.getAutocompleteParameters() + ); const innerCompleter = async ( text: string ): Promise<[string[], string]> => { @@ -462,25 +442,10 @@ class MongoshNodeRepl implements EvaluationListener { [replResults, replOrig], [mongoshResults, , mongoshResultsExclusive], ] = await Promise.all([ - (async () => { - const nodeResults = (await origReplCompleter(text)) || [[]]; - return nodeResults; - })(), - (async () => { - if (process.env.USE_NEW_AUTOCOMPLETE) { - const results = await newMongoshCompleter.autocomplete(text); - const transformed = transformAutocompleteResults(text, results); - return transformed; - } else { - return oldMongoshCompleter(text); - } - })(), + (async () => (await origReplCompleter(text)) || [[]])(), + (async () => await mongoshCompleter(text))(), ]); - this.bus.emit( - 'mongosh:autocompletion-complete', - replResults, - mongoshResults - ); // For testing. + this.bus.emit('mongosh:autocompletion-complete'); // For testing. // Sometimes the mongosh completion knows that what it is doing is right, // and that autocompletion based on inspecting the actual objects that diff --git a/packages/cli-repl/test/repl-helpers.ts b/packages/cli-repl/test/repl-helpers.ts index 5cd5f50334..87bedb63ec 100644 --- a/packages/cli-repl/test/repl-helpers.ts +++ b/packages/cli-repl/test/repl-helpers.ts @@ -75,25 +75,6 @@ async function waitCompletion(bus: MongoshBus) { await tick(); } -async function waitMongoshCompletionResults(bus: MongoshBus) { - // Waiting for the completion results can "time out" if an async action such - // as listing the databases or collections or loading the schema takes longer - // than 200ms (at the time of writing), but by the next try or at least - // eventually the action should complete and then the next autocomplete call - // will return the cached result. - let found = false; - while (!found) { - const [, mongoshResults] = await waitBus( - bus, - 'mongosh:autocompletion-complete' - ); - if (mongoshResults.length === 0) { - found = true; - } - } - await tick(); -} - const fakeTTYProps: Partial = { isTTY: true, isRaw: true, @@ -125,7 +106,6 @@ export { waitBus, waitEval, waitCompletion, - waitMongoshCompletionResults, fakeTTYProps, readReplLogFile, }; diff --git a/packages/e2e-tests/test/e2e-snippet.spec.ts b/packages/e2e-tests/test/e2e-snippet.spec.ts index bf4a843073..239e818625 100644 --- a/packages/e2e-tests/test/e2e-snippet.spec.ts +++ b/packages/e2e-tests/test/e2e-snippet.spec.ts @@ -72,7 +72,6 @@ describe('snippet integration tests', function () { shell.assertNoErrors(); }); - // TODO(MONGOSH-2205): port to the new autocomplete it('autocompletes snippet commands', async function () { if (process.arch === 's390x') { return this.skip(); // https://jira.mongodb.org/browse/MONGOSH-746 diff --git a/packages/shell-api/package.json b/packages/shell-api/package.json index 170acc1d2f..302c897adb 100644 --- a/packages/shell-api/package.json +++ b/packages/shell-api/package.json @@ -58,13 +58,11 @@ "@mongosh/history": "2.4.6", "@mongosh/i18n": "^2.13.1", "@mongosh/service-provider-core": "3.3.3", - "mongodb-redact": "^1.1.5", - "mongodb-schema": "^12.6.2" + "mongodb-redact": "^1.1.5" }, "devDependencies": { "@microsoft/api-extractor": "^7.39.3", "@mongodb-js/eslint-config-mongosh": "^1.0.0", - "@mongodb-js/mongodb-ts-autocomplete": "^0.2.2", "@mongodb-js/prettier-config-devtools": "^1.0.1", "@mongodb-js/tsconfig-mongosh": "^1.0.0", "@mongosh/types": "3.6.2", diff --git a/packages/shell-api/src/collection.ts b/packages/shell-api/src/collection.ts index 115b6e7eca..b8825e3548 100644 --- a/packages/shell-api/src/collection.ts +++ b/packages/shell-api/src/collection.ts @@ -122,7 +122,7 @@ export class Collection< _mongo: Mongo; _database: DatabaseWithSchema; _name: N; - _cachedSampleDocs: Document[] = []; + constructor( mongo: Mongo, database: DatabaseWithSchema | Database, @@ -2389,7 +2389,7 @@ export class Collection< ): Promise { this._emitCollectionApiCall('checkMetadataConsistency', { options }); - return await this._database._runCursorCommand({ + return this._database._runCursorCommand({ checkMetadataConsistency: this._name, }); } @@ -2528,35 +2528,6 @@ export class Collection< definition ); } - - async _getSampleDocs(): Promise { - this._cachedSampleDocs = await ( - await this.aggregate([{ $sample: { size: 10 } }], { - allowDiskUse: true, - maxTimeMS: 1000, - readPreference: 'secondaryPreferred', - }) - ).toArray(); - return this._cachedSampleDocs; - } - - async _getSampleDocsForCompletion(): Promise { - return await Promise.race([ - (async () => { - return await this._getSampleDocs(); - })(), - (async () => { - // 200ms should be a good compromise between giving the server a chance - // to reply and responsiveness for human perception. It's not the end - // of the world if we end up using the cached results; usually, they - // are not going to differ from fresh ones, and even if they do, a - // subsequent autocompletion request will almost certainly have at least - // the new cached results. - await new Promise((resolve) => setTimeout(resolve, 200)?.unref?.()); - return this._cachedSampleDocs; - })(), - ]); - } } export type GetShardDistributionResult = { diff --git a/packages/shell-api/src/integration.spec.ts b/packages/shell-api/src/integration.spec.ts index 98e3d7d9e8..41eddfc286 100644 --- a/packages/shell-api/src/integration.spec.ts +++ b/packages/shell-api/src/integration.spec.ts @@ -2772,44 +2772,6 @@ describe('Shell API (integration)', function () { }); }); - describe('getAutocompletionContext', function () { - beforeEach(async function () { - // Make sure the collection is present so it is included in autocompletion. - await collection.insertOne({}); - // Make sure 'database' is the current db in the eyes of the instance state object. - instanceState.setDbFunc(database); - }); - - it('returns information for autocomplete', async function () { - const context = instanceState.getAutocompletionContext(); - const { connectionId, databaseName } = - context.currentDatabaseAndConnection(); - const databaseNames = await context.databasesForConnection( - connectionId - ); - expect(databaseNames).to.include(database.getName()); - const collectionNames = await context.collectionsForDatabase( - connectionId, - databaseName - ); - expect(collectionNames).to.include(collection.getName()); - const schema = await context.schemaInformationForCollection( - connectionId, - database.getName(), - collection.getName() - ); - expect(schema).to.deep.equal({ - bsonType: 'object', - properties: { - _id: { - bsonType: 'objectId', - }, - }, - required: ['_id'], - }); - }); - }); - describe('getAutocompleteParameters', function () { let connectionString: string; beforeEach(async function () { diff --git a/packages/shell-api/src/mongo.ts b/packages/shell-api/src/mongo.ts index 9af7198b77..efaf5ab047 100644 --- a/packages/shell-api/src/mongo.ts +++ b/packages/shell-api/src/mongo.ts @@ -73,8 +73,6 @@ type Mutable = { -readonly [P in keyof T]: T[P]; }; -let nextId = 1; - @shellApiClassDefault @classPlatforms(['CLI']) export default class Mongo< @@ -83,7 +81,6 @@ export default class Mongo< private __serviceProvider: ServiceProvider | null = null; public readonly _databases: Record, DatabaseWithSchema> = Object.create(null); - private _connectionId: number; public _instanceState: ShellInstanceState; public _connectionInfo: ConnectionInfo; private _explicitEncryptionOnly = false; @@ -100,7 +97,6 @@ export default class Mongo< sp?: ServiceProvider ) { super(); - this._connectionId = nextId++; this._instanceState = instanceState; if (sp) { this.__serviceProvider = sp; @@ -303,10 +299,6 @@ export default class Mongo< ) as CollectionWithSchema; } - _getConnectionId(): string { - return `connection_${this._connectionId}`; - } - getURI(): string { return this._uri; } diff --git a/packages/shell-api/src/shell-instance-state.ts b/packages/shell-api/src/shell-instance-state.ts index eb67f8a2b0..4d34899899 100644 --- a/packages/shell-api/src/shell-instance-state.ts +++ b/packages/shell-api/src/shell-instance-state.ts @@ -37,10 +37,6 @@ import constructShellBson from './shell-bson'; import { Streams } from './streams'; import { ShellLog } from './shell-log'; -import type { AutocompletionContext } from '@mongodb-js/mongodb-ts-autocomplete'; -import type { JSONSchema } from 'mongodb-schema'; -import { analyzeDocuments } from 'mongodb-schema'; - /** * The subset of CLI options that is relevant for the shell API's behavior itself. */ @@ -406,82 +402,6 @@ export class ShellInstanceState { this.evaluationListener = listener; } - public getMongoByConnectionId(connectionId: string): Mongo { - for (const mongo of this.mongos) { - if (mongo._getConnectionId() === connectionId) { - return mongo; - } - } - throw new Error(`mongo with connection id ${connectionId} not found`); - } - - public getAutocompletionContext(): AutocompletionContext { - return { - currentDatabaseAndConnection: () => { - return { - connectionId: this.currentDb.getMongo()._getConnectionId(), - databaseName: this.currentDb.getName(), - }; - }, - databasesForConnection: async ( - connectionId: string - ): Promise => { - const mongo = this.getMongoByConnectionId(connectionId); - try { - const dbNames = await mongo._getDatabaseNamesForCompletion(); - return dbNames.filter( - (name: string) => !CONTROL_CHAR_REGEXP.test(name) - ); - } catch (err: any) { - if ( - err?.code === ShellApiErrors.NotConnected || - err?.codeName === 'Unauthorized' - ) { - return []; - } - throw err; - } - }, - collectionsForDatabase: async ( - connectionId: string, - databaseName: string - ): Promise => { - const mongo = this.getMongoByConnectionId(connectionId); - try { - const collectionNames = await mongo - ._getDb(databaseName) - ._getCollectionNamesForCompletion(); - return collectionNames.filter( - (name: string) => !CONTROL_CHAR_REGEXP.test(name) - ); - } catch (err: any) { - if ( - err?.code === ShellApiErrors.NotConnected || - err?.codeName === 'Unauthorized' - ) { - return []; - } - throw err; - } - }, - schemaInformationForCollection: async ( - connectionId: string, - databaseName: string, - collectionName: string - ): Promise => { - const mongo = this.getMongoByConnectionId(connectionId); - const docs = await mongo - ._getDb(databaseName) - .getCollection(collectionName) - ._getSampleDocsForCompletion(); - const schemaAccessor = await analyzeDocuments(docs); - - const schema = await schemaAccessor.getMongoDBJsonSchema(); - return schema; - }, - }; - } - public getAutocompleteParameters(): AutocompleteParameters { return { topology: () => { diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts index cd5a29e3df..cc53bf6fcc 100644 --- a/packages/types/src/index.ts +++ b/packages/types/src/index.ts @@ -335,10 +335,7 @@ export interface MongoshBusEventsMap extends ConnectEventMap { * Signals the completion of the autocomplete suggestion providers. * _ONLY AVAILABLE FOR TESTING._ */ - 'mongosh:autocompletion-complete': ( - resplResults: string[], - mongoshResults: string[] - ) => void; + 'mongosh:autocompletion-complete': () => void; /** * Signals the completion of the asynchronous interrupt handler in MongoshRepl. Not fired for interrupts of _synchronous_ code. * _ONLY AVAILABLE FOR TESTING._