Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@mongosh/service-provider-server

Package Overview
Dependencies
Maintainers
11
Versions
121
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@mongosh/service-provider-server - npm Package Compare versions

Comparing version 0.11.0 to 0.12.0

2

lib/cli-service-provider.d.ts

@@ -13,3 +13,3 @@ import { MongoClient, ReadPreference, ClientMetadata, Topology, ReadPreferenceFromOptions, ReadPreferenceLike, OperationOptions } from 'mongodb';

declare type ExtraConnectionInfo = ReturnType<typeof getConnectInfo>;
export declare function connectMongoClient(uri: string, clientOptions: MongoClientOptions, mClient?: typeof MongoClient): Promise<MongoClient>;
export declare function connectMongoClient(uri: string, clientOptions: MongoClientOptions, MClient?: typeof MongoClient): Promise<MongoClient>;
declare class CliServiceProvider extends ServiceProviderCore implements ServiceProvider {

@@ -16,0 +16,0 @@ static connect(this: typeof CliServiceProvider, uri: string, driverOptions?: MongoClientOptions, cliOptions?: {

@@ -22,2 +22,3 @@ "use strict";

calculateObjectSize: service_provider_core_1.bson.calculateObjectSize,
EJSON: service_provider_core_1.bson.EJSON
};

@@ -35,3 +36,22 @@ const DEFAULT_DRIVER_OPTIONS = Object.freeze({});

});
async function connectMongoClient(uri, clientOptions, mClient = mongodb_1.MongoClient) {
async function connectWithFailFast(client) {
let failFastErr;
const heartbeatFailureListener = ({ failure }) => {
if (service_provider_core_1.isFastFailureConnectionError(failure)) {
failFastErr = failure;
client.close();
}
};
client.addListener('serverHeartbeatFailed', heartbeatFailureListener);
try {
await client.connect();
}
catch (err) {
throw failFastErr || err;
}
finally {
client.removeListener('serverHeartbeatFailed', heartbeatFailureListener);
}
}
async function connectMongoClient(uri, clientOptions, MClient = mongodb_1.MongoClient) {
var _a, _b;

@@ -42,3 +62,4 @@ if (clientOptions.autoEncryption !== undefined &&

delete optionsWithoutFLE.autoEncryption;
const client = await mClient.connect(uri, optionsWithoutFLE);
const client = new MClient(uri, optionsWithoutFLE);
await connectWithFailFast(client);
const buildInfo = await client.db('admin').admin().command({ buildInfo: 1 });

@@ -52,3 +73,5 @@ if (!((_a = buildInfo.modules) === null || _a === void 0 ? void 0 : _a.includes('enterprise')) &&

}
return mClient.connect(uri, clientOptions);
const client = new MClient(uri, clientOptions);
await connectWithFailFast(client);
return client;
}

@@ -113,11 +136,7 @@ exports.connectMongoClient = connectMongoClient;

const { version } = require('../package.json');
let cmdLineOpts = null;
try {
cmdLineOpts = await this.runCommandWithCheck('admin', {
getCmdLineOpts: 1
}, this.baseCmdOptions);
}
catch (e) {
}
const extraConnectionInfo = service_provider_core_1.getConnectInfo((_b = (_a = this.uri) === null || _a === void 0 ? void 0 : _a.toString()) !== null && _b !== void 0 ? _b : '', version, buildInfo, cmdLineOpts, topology);
const [cmdLineOpts = null, atlasVersion = null] = await Promise.all([
this.runCommandWithCheck('admin', { getCmdLineOpts: 1 }, this.baseCmdOptions).catch(() => { }),
this.runCommandWithCheck('admin', { atlasVersion: 1 }, this.baseCmdOptions).catch(() => { })
]);
const extraConnectionInfo = service_provider_core_1.getConnectInfo((_b = (_a = this.uri) === null || _a === void 0 ? void 0 : _a.toString()) !== null && _b !== void 0 ? _b : '', version, buildInfo, cmdLineOpts, atlasVersion, topology);
return {

@@ -124,0 +143,0 @@ buildInfo: buildInfo,

{
"name": "@mongosh/service-provider-server",
"version": "0.11.0",
"version": "0.12.0",
"description": "MongoDB Shell Server Service Provider Package",

@@ -19,3 +19,3 @@ "main": "lib/index.js",

"prepublish": "npm run compile-ts",
"lint": "eslint \"**/*.{js,ts,tsx}\"",
"lint": "eslint --report-unused-disable-directives \"**/*.{js,ts,tsx}\"",
"check": "npm run lint"

@@ -42,4 +42,4 @@ },

"dependencies": {
"@mongosh/errors": "0.11.0",
"@mongosh/service-provider-core": "0.11.0",
"@mongosh/errors": "0.12.0",
"@mongosh/service-provider-core": "0.12.0",
"@types/sinon": "^7.5.1",

@@ -57,3 +57,3 @@ "@types/sinon-chai": "^3.2.3",

},
"gitHead": "3f9e4337ee20219985800d99923a4903a21bfa5a"
"gitHead": "0ede48aaa7f42d18eb81069ac19cc0a5d4751e69"
}

@@ -5,5 +5,6 @@ import { CommonErrors } from '@mongosh/errors';

import sinonChai from 'sinon-chai';
import sinon, { StubbedInstance, stubInterface } from 'ts-sinon';
import sinon, { StubbedInstance, stubInterface, stubConstructor } from 'ts-sinon';
import CliServiceProvider, { connectMongoClient } from './cli-service-provider';
import { ConnectionString } from '@mongosh/service-provider-core';
import { EventEmitter } from 'events';

@@ -40,13 +41,17 @@ chai.use(sinonChai);

describe('connectMongoClient', () => {
class FakeMongoClient extends EventEmitter {
connect() {}
db() {}
close() {}
}
it('connects once when no AutoEncryption set', async() => {
const uri = 'localhost:27017';
const mClientType = stubInterface<typeof MongoClient>();
const mClient = stubInterface<MongoClient>();
mClientType.connect.onFirstCall().resolves(mClient);
const result = await connectMongoClient(uri, {}, mClientType);
const calls = mClientType.connect.getCalls();
expect(calls.length).to.equal(1);
expect(calls[0].args).to.deep.equal([
uri, {}
]);
const mClient = stubConstructor(FakeMongoClient);
const mClientType = sinon.stub().returns(mClient);
mClient.connect.onFirstCall().resolves(mClient);
const result = await connectMongoClient(uri, {}, mClientType as any);
expect(mClientType.getCalls()).to.have.lengthOf(1);
expect(mClientType.getCalls()[0].args).to.deep.equal([uri, {}]);
expect(mClient.connect.getCalls()).to.have.lengthOf(1);
expect(result).to.equal(mClient);

@@ -57,11 +62,9 @@ });

const opts = { autoEncryption: { bypassAutoEncryption: true } };
const mClientType = stubInterface<typeof MongoClient>();
const mClient = stubInterface<MongoClient>();
mClientType.connect.onFirstCall().resolves(mClient);
const result = await connectMongoClient(uri, opts, mClientType);
const calls = mClientType.connect.getCalls();
expect(calls.length).to.equal(1);
expect(calls[0].args).to.deep.equal([
uri, opts
]);
const mClient = stubConstructor(FakeMongoClient);
const mClientType = sinon.stub().returns(mClient);
mClient.connect.onFirstCall().resolves(mClient);
const result = await connectMongoClient(uri, opts, mClientType as any);
expect(mClientType.getCalls()).to.have.lengthOf(1);
expect(mClientType.getCalls()[0].args).to.deep.equal([uri, opts]);
expect(mClient.connect.getCalls()).to.have.lengthOf(1);
expect(result).to.equal(mClient);

@@ -72,4 +75,5 @@ });

const opts = { autoEncryption: { bypassAutoEncryption: false } };
const mClientType = stubInterface<typeof MongoClient>();
const mClientFirst = stubInterface<MongoClient>();
const mClientFirst = stubConstructor(FakeMongoClient);
const mClientSecond = stubConstructor(FakeMongoClient);
const mClientType = sinon.stub();
const commandSpy = sinon.spy();

@@ -80,7 +84,6 @@ mClientFirst.db.returns({ admin: () => ({ command: (...args) => {

} } as any) } as any);
const mClientSecond = stubInterface<MongoClient>();
mClientType.connect.onFirstCall().resolves(mClientFirst);
mClientType.connect.onSecondCall().resolves(mClientSecond);
const result = await connectMongoClient(uri, opts, mClientType);
const calls = mClientType.connect.getCalls();
mClientType.onFirstCall().returns(mClientFirst);
mClientType.onSecondCall().returns(mClientSecond);
const result = await connectMongoClient(uri, opts, mClientType as any);
const calls = mClientType.getCalls();
expect(calls.length).to.equal(2);

@@ -96,4 +99,5 @@ expect(calls[0].args).to.deep.equal([

const opts = { autoEncryption: {} };
const mClientType = stubInterface<typeof MongoClient>();
const mClientFirst = stubInterface<MongoClient>();
const mClientFirst = stubConstructor(FakeMongoClient);
const mClientSecond = stubConstructor(FakeMongoClient);
const mClientType = sinon.stub();
const commandSpy = sinon.spy();

@@ -104,7 +108,6 @@ mClientFirst.db.returns({ admin: () => ({ command: (...args) => {

} } as any) } as any);
const mClientSecond = stubInterface<MongoClient>();
mClientType.connect.onFirstCall().resolves(mClientFirst);
mClientType.connect.onSecondCall().resolves(mClientSecond);
mClientType.onFirstCall().returns(mClientFirst);
mClientType.onSecondCall().returns(mClientSecond);
try {
await connectMongoClient(uri, opts, mClientType);
await connectMongoClient(uri, opts, mClientType as any);
} catch (e) {

@@ -118,4 +121,5 @@ return expect(e.message.toLowerCase()).to.include('automatic encryption');

const opts = { autoEncryption: {} };
const mClientType = stubInterface<typeof MongoClient>();
const mClientFirst = stubInterface<MongoClient>();
const mClientFirst = stubConstructor(FakeMongoClient);
const mClientSecond = stubConstructor(FakeMongoClient);
const mClientType = sinon.stub();
const commandSpy = sinon.spy();

@@ -126,7 +130,6 @@ mClientFirst.db.returns({ admin: () => ({ command: (...args) => {

} } as any) } as any);
const mClientSecond = stubInterface<MongoClient>();
mClientType.connect.onFirstCall().resolves(mClientFirst);
mClientType.connect.onSecondCall().resolves(mClientSecond);
mClientType.onFirstCall().returns(mClientFirst);
mClientType.onSecondCall().returns(mClientSecond);
try {
await connectMongoClient(uri, opts, mClientType);
await connectMongoClient(uri, opts, mClientType as any);
} catch (e) {

@@ -137,2 +140,26 @@ return expect(e.message.toLowerCase()).to.include('automatic encryption');

});
it('fails fast if there is a fail-fast connection error', async() => {
const err = Object.assign(new Error('ENOTFOUND'), { name: 'MongoNetworkError' });
const uri = 'localhost:27017';
const mClient = new FakeMongoClient();
const mClientType = sinon.stub().returns(mClient);
let rejectConnect;
mClient.close = sinon.stub().callsFake(() => {
rejectConnect(new Error('discarded error'));
});
mClient.connect = () => new Promise((resolve, reject) => {
rejectConnect = reject;
setImmediate(() => {
mClient.emit('serverHeartbeatFailed', { failure: err });
});
});
try {
await connectMongoClient(uri, {}, mClientType as any);
} catch (e) {
expect((mClient.close as any).getCalls()).to.have.lengthOf(1);
return expect(e).to.equal(err);
}
expect.fail('Failed to throw expected error');
});
});

@@ -794,3 +821,3 @@

let dbStub: any;
let firstCall = true;
let firstCall;

@@ -800,2 +827,3 @@ beforeEach(() => {

clientStub = stubInterface<MongoClient>();
firstCall = true;
dbStub.command.callsFake(() => {

@@ -824,5 +852,5 @@ if (firstCall) {

expect(info.extraInfo.is_localhost).to.equal(true);
expect(dbStub.command).to.have.callCount(3);
expect(dbStub.command).to.have.callCount(4);
});
});
});

@@ -22,3 +22,4 @@ import {

ReadPreferenceLike,
OperationOptions
OperationOptions,
ServerHeartbeatFailedEvent
} from 'mongodb';

@@ -79,3 +80,4 @@

FLE,
AutoEncryptionOptions
AutoEncryptionOptions,
isFastFailureConnectionError
} from '@mongosh/service-provider-core';

@@ -100,2 +102,3 @@

calculateObjectSize: BSON.calculateObjectSize,
EJSON: BSON.EJSON
};

@@ -137,2 +140,25 @@

/**
* Takes an unconnected MongoClient and connects it, but fails fast for certain
* errors.
*/
async function connectWithFailFast(client: MongoClient): Promise<void> {
let failFastErr;
const heartbeatFailureListener = ({ failure }: ServerHeartbeatFailedEvent) => {
if (isFastFailureConnectionError(failure)) {
failFastErr = failure;
client.close();
}
};
client.addListener('serverHeartbeatFailed', heartbeatFailureListener);
try {
await client.connect();
} catch (err) {
throw failFastErr || err;
} finally {
client.removeListener('serverHeartbeatFailed', heartbeatFailureListener);
}
}
/**
* Connect a MongoClient. If AutoEncryption is requested, first connect without the encryption options and verify that

@@ -143,5 +169,5 @@ * the connection is to an enterprise cluster. If not, then error, otherwise close the connection and reconnect with the

* @param clientOptions {MongoClientOptions}
* @param mClient {MongoClient}
* @param MClient {MongoClient}
*/
export async function connectMongoClient(uri: string, clientOptions: MongoClientOptions, mClient = MongoClient): Promise<MongoClient> {
export async function connectMongoClient(uri: string, clientOptions: MongoClientOptions, MClient = MongoClient): Promise<MongoClient> {
if (clientOptions.autoEncryption !== undefined &&

@@ -152,3 +178,4 @@ !clientOptions.autoEncryption.bypassAutoEncryption) {

delete optionsWithoutFLE.autoEncryption;
const client = await mClient.connect(uri, optionsWithoutFLE);
const client = new MClient(uri, optionsWithoutFLE);
await connectWithFailFast(client);
const buildInfo = await client.db('admin').admin().command({ buildInfo: 1 });

@@ -164,3 +191,5 @@ if (

}
return mClient.connect(uri, clientOptions);
const client = new MClient(uri, clientOptions);
await connectWithFailFast(client);
return client;
}

@@ -269,10 +298,6 @@

const { version } = require('../package.json');
let cmdLineOpts = null;
try {
cmdLineOpts = await this.runCommandWithCheck('admin', {
getCmdLineOpts: 1
}, this.baseCmdOptions);
// eslint-disable-next-line no-empty
} catch (e) {
}
const [cmdLineOpts = null, atlasVersion = null] = await Promise.all([
this.runCommandWithCheck('admin', { getCmdLineOpts: 1 }, this.baseCmdOptions).catch(() => {}),
this.runCommandWithCheck('admin', { atlasVersion: 1 }, this.baseCmdOptions).catch(() => {})
]);

@@ -284,2 +309,3 @@ const extraConnectionInfo = getConnectInfo(

cmdLineOpts,
atlasVersion,
topology

@@ -286,0 +312,0 @@ );

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc