@mongosh/service-provider-node-driver 2.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json ADDED
@@ -0,0 +1,76 @@
1
+ {
2
+ "name": "@mongosh/service-provider-node-driver",
3
+ "version": "2.3.3",
4
+ "description": "MongoDB Shell Server Service Provider Package",
5
+ "main": "lib/index.js",
6
+ "types": "lib/index.d.ts",
7
+ "config": {
8
+ "unsafe-perm": true
9
+ },
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "git://github.com/mongodb-js/mongosh.git"
13
+ },
14
+ "scripts": {
15
+ "compile": "tsc -p tsconfig.json",
16
+ "test": "mocha -r \"../../scripts/import-expansions.js\" --timeout 60000 -r ts-node/register --reporter \"../../configs/mocha-config-mongosh/reporter.ts\" \"./src/**/*.spec.ts\"",
17
+ "test-ci": "node ../../scripts/run-if-package-requested.js npm test",
18
+ "test-coverage": "nyc --no-clean --cwd ../.. --reporter=none npm run test",
19
+ "test-ci-coverage": "nyc --no-clean --cwd ../.. --reporter=none npm run test-ci",
20
+ "prepublish": "npm run compile",
21
+ "eslint": "eslint",
22
+ "lint": "npm run eslint . && npm run prettier -- --check .",
23
+ "check": "npm run lint && npm run depcheck",
24
+ "depcheck": "depcheck",
25
+ "prettier": "prettier",
26
+ "reformat": "npm run prettier -- --write . && npm run eslint --fix"
27
+ },
28
+ "license": "Apache-2.0",
29
+ "publishConfig": {
30
+ "access": "public"
31
+ },
32
+ "engines": {
33
+ "node": ">=14.15.1"
34
+ },
35
+ "mongosh": {
36
+ "ciRequiredOptionalDependencies": {
37
+ "mongodb-client-encryption": [
38
+ "darwin",
39
+ "linux",
40
+ "win32"
41
+ ],
42
+ "kerberos": [
43
+ "darwin",
44
+ "linux",
45
+ "win32"
46
+ ]
47
+ }
48
+ },
49
+ "dependencies": {
50
+ "@mongodb-js/devtools-connect": "^3.3.0",
51
+ "@mongodb-js/oidc-plugin": "^1.1.1",
52
+ "@mongosh/errors": "2.3.3",
53
+ "@mongosh/service-provider-core": "2.3.3",
54
+ "@mongosh/types": "2.3.3",
55
+ "aws4": "^1.12.0",
56
+ "kerberos": "2.1.0",
57
+ "mongodb": "^6.10.0",
58
+ "mongodb-client-encryption": "^6.1.0",
59
+ "mongodb-connection-string-url": "^3.0.1",
60
+ "socks": "^2.8.3"
61
+ },
62
+ "optionalDependencies": {
63
+ "kerberos": "2.1.0",
64
+ "mongodb-client-encryption": "^6.1.0"
65
+ },
66
+ "devDependencies": {
67
+ "@mongodb-js/eslint-config-mongosh": "2.3.3",
68
+ "@mongodb-js/prettier-config-devtools": "^1.0.1",
69
+ "@mongodb-js/tsconfig-mongosh": "2.3.3",
70
+ "@types/sinon-chai": "^3.2.4",
71
+ "depcheck": "^1.4.7",
72
+ "eslint": "^7.25.0",
73
+ "prettier": "^2.8.8"
74
+ },
75
+ "gitHead": "e78998f6c73b2aefa47cecd09860ff23c49d1971"
76
+ }
@@ -0,0 +1,30 @@
1
+ import type { DevtoolsConnectOptions } from '../node-driver-service-provider';
2
+ import { NodeDriverServiceProvider } from '../node-driver-service-provider';
3
+ import type { MongoClient } from 'mongodb';
4
+ import type { ReplPlatform } from '@mongosh/service-provider-core';
5
+ import type ConnectionString from 'mongodb-connection-string-url';
6
+ import type { EventEmitter } from 'events';
7
+
8
+ /**
9
+ * A service provider that is meant to be used in compass.
10
+ */
11
+ export class CompassServiceProvider extends NodeDriverServiceProvider {
12
+ public readonly platform: ReplPlatform;
13
+ /**
14
+ * Instantiate a new CompassServiceProvider with the data-service's connected
15
+ * MongoClient instance.
16
+ *
17
+ * @param {MongoClient} mongoClient - The Node drivers' MongoClient instance.
18
+ * @param {MongoClientOptions} driverOptions
19
+ * @param {string} uri - optional URI for telemetry.
20
+ */
21
+ constructor(
22
+ mongoClient: MongoClient,
23
+ bus: EventEmitter,
24
+ driverOptions: DevtoolsConnectOptions,
25
+ uri?: ConnectionString
26
+ ) {
27
+ super(mongoClient, bus, driverOptions, uri);
28
+ this.platform = 'Compass';
29
+ }
30
+ }
package/src/index.ts ADDED
@@ -0,0 +1,4 @@
1
+ import { NodeDriverServiceProvider } from './node-driver-service-provider';
2
+ import { CompassServiceProvider } from './compass/compass-service-provider';
3
+ export type { DevtoolsConnectOptions } from '@mongodb-js/devtools-connect';
4
+ export { NodeDriverServiceProvider, CompassServiceProvider };
@@ -0,0 +1,67 @@
1
+ import { expect } from 'chai';
2
+ import { MongoClient } from 'mongodb';
3
+ import {
4
+ skipIfServerVersion,
5
+ startSharedTestServer,
6
+ } from '../../../testing/integration-testing-hooks';
7
+ import { forceCloseMongoClient } from './mongodb-patches';
8
+ import { promisify } from 'util';
9
+
10
+ const delay = promisify(setTimeout);
11
+
12
+ describe('forceCloseMongoClient [integration]', function () {
13
+ const testServer = startSharedTestServer();
14
+
15
+ context('for server >= 4.1', function () {
16
+ skipIfServerVersion(testServer, '< 4.1');
17
+
18
+ it('force-closes connections that are currently checked out', async function () {
19
+ if (process.env.MONGOSH_TEST_FORCE_API_STRICT) {
20
+ return this.skip(); // $currentOp is unversioned
21
+ }
22
+
23
+ let client = await MongoClient.connect(
24
+ await testServer.connectionString()
25
+ );
26
+ const testDbName = `test-db-${Date.now()}`;
27
+ const testDb = client.db(testDbName);
28
+
29
+ await testDb.collection('ctrlc').insertOne({});
30
+ let err: any;
31
+ testDb
32
+ .collection('ctrlc')
33
+ .find({
34
+ $where: 'while(true) { /* loop1 */ }',
35
+ })
36
+ .toArray()
37
+ .catch((e) => {
38
+ err = e;
39
+ });
40
+ await delay(100);
41
+ const result = await forceCloseMongoClient(client);
42
+ expect(result.forceClosedConnections).to.equal(1);
43
+ await delay(1);
44
+ expect(err.message).to.include('Topology is closed');
45
+
46
+ client = await MongoClient.connect(await testServer.connectionString());
47
+ for (let i = 0; ; i++) {
48
+ const [out] = await client
49
+ .db('admin')
50
+ .aggregate([
51
+ { $currentOp: {} },
52
+ { $match: { 'command.find': 'ctrlc' } },
53
+ { $count: 'waitingCommands' },
54
+ ])
55
+ .toArray();
56
+ if (i === 100 || !out?.waitingCommands) {
57
+ expect(out?.waitingCommands || 0).to.equal(0);
58
+ break;
59
+ }
60
+ await delay(100);
61
+ }
62
+
63
+ await client.db(testDbName).dropDatabase();
64
+ await client.close();
65
+ });
66
+ });
67
+ });
@@ -0,0 +1,25 @@
1
+ import type { MongoClient } from 'mongodb';
2
+
3
+ // Close a MongoClient + abort currently ongoing operations.
4
+ export function forceCloseMongoClient(
5
+ client: MongoClient
6
+ ): Promise<{ forceClosedConnections: number }> {
7
+ let forceClosedConnections = 0;
8
+ for (const server of (client as any).topology?.s?.servers?.values()) {
9
+ const checkedOutConnections = server?.pool?.checkedOutConnections;
10
+ for (const connection of checkedOutConnections ?? []) {
11
+ forceClosedConnections++;
12
+ connection.destroy({ force: true });
13
+ // Immediately after destroying, act as if the close had happened,
14
+ // but *not* as an actual 'close' event on the socket itself --
15
+ // a close on the socket is communicated as a network error, which
16
+ // is considered an retryable error by operations which are currently
17
+ // running on this connection, but the whole point here is that these
18
+ // operations should *not* be retried. So, we just act as if something
19
+ // had happened that interrupts all ongoing operations and also is
20
+ // supposed to destroy the connection (which is a no-op at this point).
21
+ connection.onError(new Error('connection canceled by force close'));
22
+ }
23
+ }
24
+ return client.close(true).then(() => ({ forceClosedConnections }));
25
+ }