diff --git a/.eslintrc b/.eslintrc index d8301ce2..3ecca9d1 100644 --- a/.eslintrc +++ b/.eslintrc @@ -4,6 +4,10 @@ "node": true, "es6": true }, + "parserOptions": { + "ecmaVersion": 2018, + "sourceType": "module" + }, "rules": { "strict": "off", "no-undef": "error", diff --git a/lib/data-service.js b/lib/data-service.js index d01481eb..c8321e38 100644 --- a/lib/data-service.js +++ b/lib/data-service.js @@ -1,4 +1,5 @@ const EventEmitter = require('events'); +const debug = require('debug')('mongodb-data-service:data-service'); /** * Instantiate a new DataService object. @@ -31,6 +32,7 @@ class DataService extends EventEmitter { .on('topologyOpening', (evt) => this.emit('topologyOpening', evt)) .on('topologyClosed', (evt) => this.emit('topologyClosed', evt)) .on('topologyDescriptionChanged', (evt) => { + debug('got new topologyDescriptionChanged', evt.newDescription); this.lastSeenTopology = evt.newDescription; this.emit('topologyDescriptionChanged', evt); }); @@ -151,17 +153,13 @@ class DataService extends EventEmitter { /** * Connect to the server. - * - * @param {function} done - The callback function. */ - connect(done) { - this.client.connect((err) => { - if (err) { - return done(err); - } - done(null, this); - this.emit('readable'); - }); + async connect() { + await this.client.connect(); + + this.emit('readable'); + + return this; } /** @@ -180,6 +178,7 @@ class DataService extends EventEmitter { * and options. * * @param {string} ns - The namespace to search on. + * @param {object} filter - The filter for the count. * @param {object} options - The query options. * @param {function} callback - The callback function. */ diff --git a/lib/native-client.js b/lib/native-client.js index 22af5bd0..aabce242 100644 --- a/lib/native-client.js +++ b/lib/native-client.js @@ -98,39 +98,37 @@ class NativeClient extends EventEmitter { /** * Connect to the server. * - * @param {function} done - The callback function. * @return {NativeClient} */ - connect(done) { + async connect() { debug('connecting...'); this.connectionOptions = null; this.isWritable = false; this.isMongos = false; - connect( + const [ + // eslint-disable-next-line no-unused-vars + _, // The client is set in the `setupListeners` method. + connectionOptions + ] = await connect( this.model, - this.setupListeners.bind(this), - (err, _client, connectionOptions) => { - if (err) { - return done(this._translateMessage(err)); - } + this.setupListeners.bind(this) + ); - this.connectionOptions = connectionOptions; + this.connectionOptions = connectionOptions; - this.isWritable = this.client.isWritable; - this.isMongos = this.client.isMongos; + this.isWritable = this.client.isWritable; + this.isMongos = this.client.isMongos; - debug('connected!', { - isWritable: this.isWritable, - isMongos: this.isMongos - }); + debug('connected!', { + isWritable: this.isWritable, + isMongos: this.isMongos + }); + + this.client.on('status', (evt) => this.emit('status', evt)); + this.database = this.client.db(this.model.ns || ADMIN); - this.client.on('status', (evt) => this.emit('status', evt)); - this.database = this.client.db(this.model.ns || ADMIN); - done(null, this); - } - ); return this; } @@ -301,7 +299,8 @@ class NativeClient extends EventEmitter { */ collections(databaseName, callback) { if (databaseName === SYSTEM) { - return callback(null, []); + callback(null, []); + return; } this.collectionNames(databaseName, (error, names) => { if (error) { @@ -521,6 +520,7 @@ class NativeClient extends EventEmitter { /** * Disconnect the client. + * @param {Function} callback - Callback called after connection closed. */ disconnect(callback) { this.client.close(true, callback); diff --git a/test/data-service.test.js b/test/data-service.test.js index 4031009b..f792ed96 100644 --- a/test/data-service.test.js +++ b/test/data-service.test.js @@ -10,8 +10,8 @@ describe('DataService', function() { this.timeout(20000); const service = new DataService(helper.connection); - before(function(done) { - service.connect(done); + before(async() => { + await service.connect(); }); after(function(done) { service.disconnect(done); diff --git a/test/instance-detail-helper.test.js b/test/instance-detail-helper.test.js index 3094e8e6..485a862e 100644 --- a/test/instance-detail-helper.test.js +++ b/test/instance-detail-helper.test.js @@ -4,60 +4,72 @@ const connect = Connection.connect; const { getInstance } = require('../lib/instance-detail-helper'); const helper = require('./helper'); const DataService = require('../lib/data-service'); +const { promisify } = require('util'); const _ = require('lodash'); describe('mongodb-data-service#instance', function() { describe('local', function() { let client; - let db; - after(function(done) { - client.close(true, done); - }); - it('should connect to `localhost:27018`', function(done) { - Connection.from( - 'mongodb://localhost:27018/data-service', - function(error, model) { - assert.equal(error, null); - connect( - model, - null, - function(err, _client) { - if (err) { - return done(err); - } - client = _client; - db = client.db('data-service'); - done(); - } - ); - } + let model; + + before(async() => { + model = await Connection.from( + 'mongodb://localhost:27018/data-service' ); }); - it('should not close the db after getting instance details', function(done) { - assert(db); - getInstance(client, db, function(err) { - if (err) { - return done(err); - } - db.admin().ping(function(_err, pingResult) { - if (_err) { - done(_err); + + describe('connecting', () => { + after(function(done) { + client.close(true, done); + }); + it('should connect to `localhost:27018`', async() => { + const [ _client ] = await connect( + model, + null + ); + client = _client; + }); + }); + + describe('after connecting', () => { + before(async() => { + const [ _client ] = await connect( + model, + null + ); + client = _client; + }); + after(function(done) { + client.close(true, done); + }); + + it('should not close the db after getting instance details', (done) => { + const db = client.db('data-service'); + + assert(db); + getInstance(client, db, function(err) { + if (err) { + return done(err); } - done(null, pingResult); + db.admin().ping(function(_err, pingResult) { + if (_err) { + done(_err); + } + done(null, pingResult); + }); }); }); }); + if (process.env.MONGODB_TOPOLOGY !== 'cluster') { describe('views', function() { - var service = new DataService(helper.connection); - var instanceDetails = null; - before(function(done) { - service.connect(function(err) { - if (err) return done(err); - helper.insertTestDocuments(service.client, function() { - done(); - }); - }); + const service = new DataService(helper.connection); + let instanceDetails; + before(async() => { + await service.connect(); + + const runInsertDocuments = promisify(helper.insertTestDocuments); + await runInsertDocuments(service.client); }); after(function(done) { diff --git a/test/native-client.test.js b/test/native-client.test.js index e98e0f1e..ed909b61 100644 --- a/test/native-client.test.js +++ b/test/native-client.test.js @@ -1,25 +1,23 @@ -var sinon = require('sinon'); -var helper = require('./helper'); -var assert = helper.assert; -var expect = helper.expect; -var ObjectId = require('bson').ObjectId; -var mock = require('mock-require'); +const sinon = require('sinon'); +const helper = require('./helper'); +const assert = helper.assert; +const expect = helper.expect; +const ObjectId = require('bson').ObjectId; +const mock = require('mock-require'); const EventEmitter = require('events'); -var NativeClient = require('../lib/native-client'); +const NativeClient = require('../lib/native-client'); describe('NativeClient', function() { this.slow(10000); this.timeout(20000); - var client = new NativeClient(helper.connection); - - before(function(done) { - const callback = (err, result) => { - const adminDb = client.database.admin(); - adminDb.addUser('dba-admin', 'password', { roles: ['root'] }); - done(err, result); - }; - client.connect(callback); + const client = new NativeClient(helper.connection); + + before(async() => { + await client.connect(); + + const adminDb = client.database.admin(); + adminDb.addUser('dba-admin', 'password', { roles: ['root'] }); }); after(function(done) { @@ -64,14 +62,18 @@ describe('NativeClient', function() { }; return { - connect(_model, setupListeners, cb) { + async connect(_model, setupListeners) { const mockedClient = new EventEmitter(); mockedClient.db = () => {}; setupListeners(mockedClient); mockedClient.emit('topologyDescriptionChanged', { newDescription: _topologyDescription }); - cb(null, mockedClient, _connectionOptions); + + return [ + mockedClient, + _connectionOptions + ]; } }; } @@ -80,59 +82,54 @@ describe('NativeClient', function() { mock.stop('mongodb-connection-model'); }); - it('sets .connectionOptions after successful connection', function(done) { + it('sets .connectionOptions after successful connection', async() => { mock( 'mongodb-connection-model', mockedConnectionModel() ); - var MockedNativeClient = mock.reRequire('../lib/native-client'); - var mockedClient = new MockedNativeClient(helper.connection); + const MockedNativeClient = mock.reRequire('../lib/native-client'); + const mockedClient = new MockedNativeClient(helper.connection); expect(mockedClient.connectionOptions).to.be.null; - mockedClient.connect(function() { - expect(mockedClient.connectionOptions).to.deep.equal({ - url: 'mongodb://127.0.0.1:27018/data-service?readPreference=primary&ssl=false', - options: { - connectWithNoPrimary: true, - readPreference: 'primary', - useNewUrlParser: true, - useUnifiedTopology: true - } - }); - done(); + await mockedClient.connect(); + + expect(mockedClient.connectionOptions).to.deep.equal({ + url: 'mongodb://127.0.0.1:27018/data-service?readPreference=primary&ssl=false', + options: { + connectWithNoPrimary: true, + readPreference: 'primary', + useNewUrlParser: true, + useUnifiedTopology: true + } }); }); - it('sets .isMongos to true when topology is sharded', function(done) { + it('sets .isMongos to true when topology is sharded', async() => { mock( 'mongodb-connection-model', mockedConnectionModel(mockedTopologyDescription('Sharded')) ); - var MockedNativeClient = mock.reRequire('../lib/native-client'); - var mockedClient = new MockedNativeClient(helper.connection); + const MockedNativeClient = mock.reRequire('../lib/native-client'); + const mockedClient = new MockedNativeClient(helper.connection); - mockedClient.connect(function() { - expect(mockedClient.isMongos).to.be.true; - done(); - }); + await mockedClient.connect(); + expect(mockedClient.isMongos).to.be.true; }); - it('sets .isMongos to false when topology is not sharded', function(done) { + it('sets .isMongos to false when topology is not sharded', async() => { mock('mongodb-connection-model', mockedConnectionModel()); - var MockedNativeClient = mock.reRequire('../lib/native-client'); - var mockedClient = new MockedNativeClient(helper.connection); + const MockedNativeClient = mock.reRequire('../lib/native-client'); + const mockedClient = new MockedNativeClient(helper.connection); - mockedClient.connect(function() { - expect(mockedClient.isMongos).to.be.false; - done(); - }); + await mockedClient.connect(); + expect(mockedClient.isMongos).to.be.false; }); - it('sets .isWritable to true when the node is a primary replset member', function(done) { + it('sets .isWritable to true when the node is a primary replset member', async() => { mock( 'mongodb-connection-model', mockedConnectionModel( @@ -143,13 +140,11 @@ describe('NativeClient', function() { var MockedNativeClient = mock.reRequire('../lib/native-client'); var mockedClient = new MockedNativeClient(helper.connection); - mockedClient.connect(function() { - expect(mockedClient.isWritable).to.be.true; - done(); - }); + await mockedClient.connect(); + expect(mockedClient.isWritable).to.be.true; }); - it('sets .isWritable to false when the node is a secondary replset member', function(done) { + it('sets .isWritable to false when the node is a secondary replset member', async() => { mock( 'mongodb-connection-model', mockedConnectionModel( @@ -160,13 +155,11 @@ describe('NativeClient', function() { var MockedNativeClient = mock.reRequire('../lib/native-client'); var mockedClient = new MockedNativeClient(helper.connection); - mockedClient.connect(function() { - expect(mockedClient.isWritable).to.be.false; - done(); - }); + await mockedClient.connect(); + expect(mockedClient.isWritable).to.be.false; }); - it('sets .isWritable to true when the node is a mongos', function(done) { + it('sets .isWritable to true when the node is a mongos', async() => { mock( 'mongodb-connection-model', mockedConnectionModel(mockedTopologyDescription('Single', 'Mongos')) @@ -175,10 +168,8 @@ describe('NativeClient', function() { var MockedNativeClient = mock.reRequire('../lib/native-client'); var mockedClient = new MockedNativeClient(helper.connection); - mockedClient.connect(function() { - expect(mockedClient.isWritable).to.be.true; - done(); - }); + await mockedClient.connect(); + expect(mockedClient.isWritable).to.be.true; }); }); }); @@ -555,10 +546,6 @@ describe('NativeClient', function() { }); }); }); - - context('when the user is not authorized', function() { - it('passes an error to the callback'); - }); }); describe('#estimatedCount', function() {