mongodb 3.6.4 → 3.6.8

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.
Files changed (39) hide show
  1. package/HISTORY.md +43 -0
  2. package/README.md +63 -67
  3. package/lib/bulk/common.js +76 -0
  4. package/lib/cmap/connection.js +36 -32
  5. package/lib/collection.js +50 -34
  6. package/lib/core/auth/mongo_credentials.js +5 -5
  7. package/lib/core/auth/scram.js +2 -1
  8. package/lib/core/connection/connect.js +1 -1
  9. package/lib/core/connection/logger.js +1 -0
  10. package/lib/core/connection/msg.js +3 -1
  11. package/lib/core/connection/utils.js +9 -14
  12. package/lib/core/error.js +2 -2
  13. package/lib/core/index.js +1 -1
  14. package/lib/core/sdam/monitor.js +8 -3
  15. package/lib/core/sdam/topology.js +2 -2
  16. package/lib/core/sdam/topology_description.js +24 -6
  17. package/lib/core/tools/smoke_plugin.js +1 -0
  18. package/lib/core/topologies/read_preference.js +2 -1
  19. package/lib/core/topologies/replset.js +1 -1
  20. package/lib/core/uri_parser.js +2 -1
  21. package/lib/core/utils.js +2 -5
  22. package/lib/core/wireprotocol/command.js +10 -5
  23. package/lib/core/wireprotocol/kill_cursors.js +2 -1
  24. package/lib/db.js +9 -3
  25. package/lib/encrypter.js +163 -0
  26. package/lib/gridfs-stream/upload.js +1 -0
  27. package/lib/mongo_client.js +123 -172
  28. package/lib/operations/add_user.js +2 -1
  29. package/lib/operations/bulk_write.js +0 -8
  30. package/lib/operations/connect.js +14 -61
  31. package/lib/operations/execute_operation.js +47 -69
  32. package/lib/operations/find.js +3 -0
  33. package/lib/operations/find_one_and_replace.js +8 -2
  34. package/lib/operations/find_one_and_update.js +8 -3
  35. package/lib/operations/insert_many.js +1 -5
  36. package/lib/operations/operation.js +1 -1
  37. package/lib/utils.js +88 -30
  38. package/lib/write_concern.js +5 -1
  39. package/package.json +22 -22
@@ -13,9 +13,9 @@ const ReplSet = require('../topologies/replset');
13
13
  const Server = require('../topologies/server');
14
14
  const ServerSessionPool = require('../core').Sessions.ServerSessionPool;
15
15
  const emitDeprecationWarning = require('../utils').emitDeprecationWarning;
16
+ const emitWarningOnce = require('../utils').emitWarningOnce;
16
17
  const fs = require('fs');
17
18
  const WriteConcern = require('../write_concern');
18
- const BSON = require('../core/connection/utils').retrieveBSON();
19
19
  const CMAP_EVENT_NAMES = require('../cmap/events').CMAP_EVENT_NAMES;
20
20
 
21
21
  let client;
@@ -182,12 +182,12 @@ function validOptions(options) {
182
182
  if (options.validateOptions) {
183
183
  return new MongoError(`option ${name} is not supported`);
184
184
  } else {
185
- console.warn(`the options [${name}] is not supported`);
185
+ emitWarningOnce(`the options [${name}] is not supported`);
186
186
  }
187
187
  }
188
188
 
189
189
  if (legacyOptionNames.indexOf(name) !== -1) {
190
- console.warn(
190
+ emitWarningOnce(
191
191
  `the server/replset/mongos/db options are deprecated, ` +
192
192
  `all their options are supported at the top level of the options object [${validOptionNames}]`
193
193
  );
@@ -257,9 +257,6 @@ function resolveTLSOptions(options) {
257
257
  });
258
258
  }
259
259
 
260
- const emitDeprecationForNonUnifiedTopology = deprecate(() => {},
261
- 'current Server Discovery and Monitoring engine is deprecated, and will be removed in a future version. ' + 'To use the new Server Discover and Monitoring engine, pass option { useUnifiedTopology: true } to the MongoClient constructor.');
262
-
263
260
  function connect(mongoClient, url, options, callback) {
264
261
  options = Object.assign({}, options);
265
262
 
@@ -335,7 +332,9 @@ function connect(mongoClient, url, options, callback) {
335
332
  return createTopology(mongoClient, 'unified', _finalOptions, connectCallback);
336
333
  }
337
334
 
338
- emitDeprecationForNonUnifiedTopology();
335
+ emitWarningOnce(
336
+ 'Current Server Discovery and Monitoring engine is deprecated, and will be removed in a future version. To use the new Server Discover and Monitoring engine, pass option { useUnifiedTopology: true } to the MongoClient constructor.'
337
+ );
339
338
 
340
339
  // Do we have a replicaset then skip discovery and go straight to connectivity
341
340
  if (_finalOptions.replicaSet || _finalOptions.rs_name) {
@@ -496,58 +495,9 @@ function createTopology(mongoClient, topologyType, options, callback) {
496
495
 
497
496
  // determine CSFLE support
498
497
  if (options.autoEncryption != null) {
499
- let AutoEncrypter;
500
- try {
501
- require.resolve('mongodb-client-encryption');
502
- } catch (err) {
503
- callback(
504
- new MongoError(
505
- 'Auto-encryption requested, but the module is not installed. Please add `mongodb-client-encryption` as a dependency of your project'
506
- )
507
- );
508
- return;
509
- }
510
-
511
- try {
512
- let mongodbClientEncryption = require('mongodb-client-encryption');
513
- if (typeof mongodbClientEncryption.extension !== 'function') {
514
- callback(
515
- new MongoError(
516
- 'loaded version of `mongodb-client-encryption` does not have property `extension`. Please make sure you are loading the correct version of `mongodb-client-encryption`'
517
- )
518
- );
519
- }
520
- AutoEncrypter = mongodbClientEncryption.extension(require('../../index')).AutoEncrypter;
521
- } catch (err) {
522
- callback(err);
523
- return;
524
- }
525
-
526
- const mongoCryptOptions = Object.assign(
527
- {
528
- bson:
529
- options.bson ||
530
- new BSON([
531
- BSON.Binary,
532
- BSON.Code,
533
- BSON.DBRef,
534
- BSON.Decimal128,
535
- BSON.Double,
536
- BSON.Int32,
537
- BSON.Long,
538
- BSON.Map,
539
- BSON.MaxKey,
540
- BSON.MinKey,
541
- BSON.ObjectId,
542
- BSON.BSONRegExp,
543
- BSON.Symbol,
544
- BSON.Timestamp
545
- ])
546
- },
547
- options.autoEncryption
548
- );
549
-
550
- options.autoEncrypter = new AutoEncrypter(mongoClient, mongoCryptOptions);
498
+ const Encrypter = require('../encrypter').Encrypter;
499
+ options.encrypter = new Encrypter(mongoClient, options);
500
+ options.autoEncrypter = options.encrypter.autoEncrypter;
551
501
  }
552
502
 
553
503
  // Create the topology
@@ -585,7 +535,10 @@ function createTopology(mongoClient, topologyType, options, callback) {
585
535
  return;
586
536
  }
587
537
 
588
- callback(undefined, topology);
538
+ options.encrypter.connectInternalClient(error => {
539
+ if (error) return callback(error);
540
+ callback(undefined, topology);
541
+ });
589
542
  });
590
543
  });
591
544
 
@@ -616,7 +569,7 @@ function createUnifiedOptions(finalOptions, options) {
616
569
  'mongos_options'
617
570
  ];
618
571
  const noMerge = ['readconcern', 'compression', 'autoencryption'];
619
- const skip = ['w', 'wtimeout', 'j', 'journal', 'fsync', 'writeConcern'];
572
+ const skip = ['w', 'wtimeout', 'j', 'journal', 'fsync', 'writeconcern'];
620
573
 
621
574
  for (const name in options) {
622
575
  if (skip.indexOf(name.toLowerCase()) !== -1) {
@@ -1,5 +1,6 @@
1
1
  'use strict';
2
2
 
3
+ const maybePromise = require('../utils').maybePromise;
3
4
  const MongoError = require('../core/error').MongoError;
4
5
  const Aspect = require('./operation').Aspect;
5
6
  const OperationBase = require('./operation').OperationBase;
@@ -21,7 +22,7 @@ const isUnifiedTopology = require('../core/utils').isUnifiedTopology;
21
22
  * @param {Operation} operation The operation to execute
22
23
  * @param {function} callback The command result callback
23
24
  */
24
- function executeOperation(topology, operation, callback) {
25
+ function executeOperation(topology, operation, cb) {
25
26
  if (topology == null) {
26
27
  throw new TypeError('This method requires a valid topology instance');
27
28
  }
@@ -30,64 +31,57 @@ function executeOperation(topology, operation, callback) {
30
31
  throw new TypeError('This method requires a valid operation instance');
31
32
  }
32
33
 
33
- if (isUnifiedTopology(topology) && topology.shouldCheckForSessionSupport()) {
34
- return selectServerForSessionSupport(topology, operation, callback);
35
- }
36
-
37
- const Promise = topology.s.promiseLibrary;
38
-
39
- // The driver sessions spec mandates that we implicitly create sessions for operations
40
- // that are not explicitly provided with a session.
41
- let session, owner;
42
- if (topology.hasSessionSupport()) {
43
- if (operation.session == null) {
44
- owner = Symbol();
45
- session = topology.startSession({ owner });
46
- operation.session = session;
47
- } else if (operation.session.hasEnded) {
48
- throw new MongoError('Use of expired sessions is not permitted');
34
+ return maybePromise(topology, cb, callback => {
35
+ if (isUnifiedTopology(topology) && topology.shouldCheckForSessionSupport()) {
36
+ // Recursive call to executeOperation after a server selection
37
+ return selectServerForSessionSupport(topology, operation, callback);
49
38
  }
50
- }
51
-
52
- let result;
53
- if (typeof callback !== 'function') {
54
- result = new Promise((resolve, reject) => {
55
- callback = (err, res) => {
56
- if (err) return reject(err);
57
- resolve(res);
58
- };
59
- });
60
- }
61
39
 
62
- function executeCallback(err, result) {
63
- if (session && session.owner === owner) {
64
- session.endSession();
65
- if (operation.session === session) {
66
- operation.clearSession();
40
+ // The driver sessions spec mandates that we implicitly create sessions for operations
41
+ // that are not explicitly provided with a session.
42
+ let session, owner;
43
+ if (topology.hasSessionSupport()) {
44
+ if (operation.session == null) {
45
+ owner = Symbol();
46
+ session = topology.startSession({ owner });
47
+ operation.session = session;
48
+ } else if (operation.session.hasEnded) {
49
+ return callback(new MongoError('Use of expired sessions is not permitted'));
67
50
  }
51
+ } else if (operation.session) {
52
+ // If the user passed an explicit session and we are still, after server selection,
53
+ // trying to run against a topology that doesn't support sessions we error out.
54
+ return callback(new MongoError('Current topology does not support sessions'));
68
55
  }
69
56
 
70
- callback(err, result);
71
- }
72
-
73
- try {
74
- if (operation.hasAspect(Aspect.EXECUTE_WITH_SELECTION)) {
75
- executeWithServerSelection(topology, operation, executeCallback);
76
- } else {
77
- operation.execute(executeCallback);
78
- }
79
- } catch (e) {
80
- if (session && session.owner === owner) {
81
- session.endSession();
82
- if (operation.session === session) {
83
- operation.clearSession();
57
+ function executeCallback(err, result) {
58
+ if (session && session.owner === owner) {
59
+ session.endSession();
60
+ if (operation.session === session) {
61
+ operation.clearSession();
62
+ }
84
63
  }
64
+
65
+ callback(err, result);
85
66
  }
86
67
 
87
- throw e;
88
- }
68
+ try {
69
+ if (operation.hasAspect(Aspect.EXECUTE_WITH_SELECTION)) {
70
+ executeWithServerSelection(topology, operation, executeCallback);
71
+ } else {
72
+ operation.execute(executeCallback);
73
+ }
74
+ } catch (error) {
75
+ if (session && session.owner === owner) {
76
+ session.endSession();
77
+ if (operation.session === session) {
78
+ operation.clearSession();
79
+ }
80
+ }
89
81
 
90
- return result;
82
+ callback(error);
83
+ }
84
+ });
91
85
  }
92
86
 
93
87
  function supportsRetryableReads(server) {
@@ -139,7 +133,6 @@ function executeWithServerSelection(topology, operation, callback) {
139
133
  callback(err, null);
140
134
  return;
141
135
  }
142
-
143
136
  const shouldRetryReads =
144
137
  topology.s.options.retryReads !== false &&
145
138
  operation.session &&
@@ -156,31 +149,16 @@ function executeWithServerSelection(topology, operation, callback) {
156
149
  });
157
150
  }
158
151
 
159
- // TODO: This is only supported for unified topology, it should go away once
160
- // we remove support for legacy topology types.
152
+ // The Unified Topology runs serverSelection before executing every operation
153
+ // Session support is determined by the result of a monitoring check triggered by this selection
161
154
  function selectServerForSessionSupport(topology, operation, callback) {
162
- const Promise = topology.s.promiseLibrary;
163
-
164
- let result;
165
- if (typeof callback !== 'function') {
166
- result = new Promise((resolve, reject) => {
167
- callback = (err, result) => {
168
- if (err) return reject(err);
169
- resolve(result);
170
- };
171
- });
172
- }
173
-
174
155
  topology.selectServer(ReadPreference.primaryPreferred, err => {
175
156
  if (err) {
176
- callback(err);
177
- return;
157
+ return callback(err);
178
158
  }
179
159
 
180
160
  executeOperation(topology, operation, callback);
181
161
  });
182
-
183
- return result;
184
162
  }
185
163
 
186
164
  module.exports = executeOperation;
@@ -20,6 +20,9 @@ class FindOperation extends OperationBase {
20
20
  // copied from `CommandOperationV2`, to be subclassed in the future
21
21
  this.server = server;
22
22
 
23
+ // updates readPreference if setReadPreference was called on the cursor
24
+ this.readPreference = ReadPreference.resolve(this, this.options);
25
+
23
26
  if (typeof this.cmd.allowDiskUse !== 'undefined' && maxWireVersion(server) < 4) {
24
27
  callback(new MongoError('The `allowDiskUse` option is not supported on MongoDB < 3.2'));
25
28
  return;
@@ -1,16 +1,22 @@
1
1
  'use strict';
2
2
 
3
+ const MongoError = require('../core').MongoError;
3
4
  const FindAndModifyOperation = require('./find_and_modify');
4
5
  const hasAtomicOperators = require('../utils').hasAtomicOperators;
5
6
 
6
7
  class FindOneAndReplaceOperation extends FindAndModifyOperation {
7
8
  constructor(collection, filter, replacement, options) {
9
+ if ('returnDocument' in options && 'returnOriginal' in options) {
10
+ throw new MongoError(
11
+ 'findOneAndReplace option returnOriginal is deprecated in favor of returnDocument and cannot be combined'
12
+ );
13
+ }
8
14
  // Final options
9
15
  const finalOptions = Object.assign({}, options);
10
16
  finalOptions.fields = options.projection;
11
17
  finalOptions.update = true;
12
- finalOptions.new = options.returnOriginal !== void 0 ? !options.returnOriginal : false;
13
- finalOptions.upsert = options.upsert !== void 0 ? !!options.upsert : false;
18
+ finalOptions.new = options.returnDocument === 'after' || options.returnOriginal === false;
19
+ finalOptions.upsert = options.upsert === true;
14
20
 
15
21
  if (filter == null || typeof filter !== 'object') {
16
22
  throw new TypeError('Filter parameter must be an object');
@@ -1,17 +1,22 @@
1
1
  'use strict';
2
2
 
3
+ const MongoError = require('../core').MongoError;
3
4
  const FindAndModifyOperation = require('./find_and_modify');
4
5
  const hasAtomicOperators = require('../utils').hasAtomicOperators;
5
6
 
6
7
  class FindOneAndUpdateOperation extends FindAndModifyOperation {
7
8
  constructor(collection, filter, update, options) {
9
+ if ('returnDocument' in options && 'returnOriginal' in options) {
10
+ throw new MongoError(
11
+ 'findOneAndUpdate option returnOriginal is deprecated in favor of returnDocument and cannot be combined'
12
+ );
13
+ }
8
14
  // Final options
9
15
  const finalOptions = Object.assign({}, options);
10
16
  finalOptions.fields = options.projection;
11
17
  finalOptions.update = true;
12
- finalOptions.new =
13
- typeof options.returnOriginal === 'boolean' ? !options.returnOriginal : false;
14
- finalOptions.upsert = typeof options.upsert === 'boolean' ? options.upsert : false;
18
+ finalOptions.new = options.returnDocument === 'after' || options.returnOriginal === false;
19
+ finalOptions.upsert = options.upsert === true;
15
20
 
16
21
  if (filter == null || typeof filter !== 'object') {
17
22
  throw new TypeError('Filter parameter must be an object');
@@ -30,11 +30,7 @@ class InsertManyOperation extends OperationBase {
30
30
  docs = prepareDocs(coll, docs, options);
31
31
 
32
32
  // Generate the bulk write operations
33
- const operations = [
34
- {
35
- insertMany: docs
36
- }
37
- ];
33
+ const operations = docs.map(document => ({ insertOne: { document } }));
38
34
 
39
35
  const bulkWriteOperation = new BulkWriteOperation(coll, operations, options);
40
36
 
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  const Explain = require('../explain').Explain;
4
- const MongoError = require('../core').MongoError;
4
+ const MongoError = require('../core/error').MongoError;
5
5
 
6
6
  const Aspect = {
7
7
  READ_OPERATION: Symbol('READ_OPERATION'),
package/lib/utils.js CHANGED
@@ -40,7 +40,7 @@ var formatSortValue = (exports.formatSortValue = function(sortDirection) {
40
40
  });
41
41
 
42
42
  var formattedOrderClause = (exports.formattedOrderClause = function(sortValue) {
43
- var orderBy = {};
43
+ var orderBy = new Map();
44
44
  if (sortValue == null) return null;
45
45
  if (Array.isArray(sortValue)) {
46
46
  if (sortValue.length === 0) {
@@ -49,15 +49,22 @@ var formattedOrderClause = (exports.formattedOrderClause = function(sortValue) {
49
49
 
50
50
  for (var i = 0; i < sortValue.length; i++) {
51
51
  if (sortValue[i].constructor === String) {
52
- orderBy[sortValue[i]] = 1;
52
+ orderBy.set(`${sortValue[i]}`, 1);
53
53
  } else {
54
- orderBy[sortValue[i][0]] = formatSortValue(sortValue[i][1]);
54
+ orderBy.set(`${sortValue[i][0]}`, formatSortValue(sortValue[i][1]));
55
55
  }
56
56
  }
57
57
  } else if (sortValue != null && typeof sortValue === 'object') {
58
- orderBy = sortValue;
58
+ if (sortValue instanceof Map) {
59
+ orderBy = sortValue;
60
+ } else {
61
+ var sortKeys = Object.keys(sortValue);
62
+ for (var k of sortKeys) {
63
+ orderBy.set(k, sortValue[k]);
64
+ }
65
+ }
59
66
  } else if (typeof sortValue === 'string') {
60
- orderBy[sortValue] = 1;
67
+ orderBy.set(`${sortValue}`, 1);
61
68
  } else {
62
69
  throw new Error(
63
70
  'Illegal sort clause, must be of the form ' +
@@ -287,39 +294,38 @@ var filterOptions = function(options, names) {
287
294
  };
288
295
 
289
296
  // Write concern keys
290
- var writeConcernKeys = ['w', 'j', 'wtimeout', 'fsync'];
291
-
292
- // Merge the write concern options
293
- var mergeOptionsAndWriteConcern = function(targetOptions, sourceOptions, keys, mergeWriteConcern) {
294
- // Mix in any allowed options
295
- for (var i = 0; i < keys.length; i++) {
296
- if (!targetOptions[keys[i]] && sourceOptions[keys[i]] !== undefined) {
297
- targetOptions[keys[i]] = sourceOptions[keys[i]];
298
- }
299
- }
300
-
301
- // No merging of write concern
302
- if (!mergeWriteConcern) return targetOptions;
297
+ const WRITE_CONCERN_KEYS = ['w', 'j', 'wtimeout', 'fsync', 'writeConcern'];
303
298
 
304
- // Found no write Concern options
305
- var found = false;
306
- for (i = 0; i < writeConcernKeys.length; i++) {
307
- if (targetOptions[writeConcernKeys[i]]) {
299
+ /**
300
+ * If there is no WriteConcern related options defined on target then inherit from source.
301
+ * Otherwise, do not inherit **any** options from source.
302
+ * @internal
303
+ * @param {object} target - options object conditionally receiving the writeConcern options
304
+ * @param {object} source - options object containing the potentially inherited writeConcern options
305
+ */
306
+ function conditionallyMergeWriteConcern(target, source) {
307
+ let found = false;
308
+ for (const wcKey of WRITE_CONCERN_KEYS) {
309
+ if (wcKey in target) {
310
+ // Found a writeConcern option
308
311
  found = true;
309
312
  break;
310
313
  }
311
314
  }
312
315
 
313
316
  if (!found) {
314
- for (i = 0; i < writeConcernKeys.length; i++) {
315
- if (sourceOptions[writeConcernKeys[i]]) {
316
- targetOptions[writeConcernKeys[i]] = sourceOptions[writeConcernKeys[i]];
317
+ for (const wcKey of WRITE_CONCERN_KEYS) {
318
+ if (source[wcKey]) {
319
+ if (!('writeConcern' in target)) {
320
+ target.writeConcern = {};
321
+ }
322
+ target.writeConcern[wcKey] = source[wcKey];
317
323
  }
318
324
  }
319
325
  }
320
326
 
321
- return targetOptions;
322
- };
327
+ return target;
328
+ }
323
329
 
324
330
  /**
325
331
  * Executes the given operation with provided arguments.
@@ -534,7 +540,12 @@ function decorateWithExplain(command, explain) {
534
540
  return { explain: command, verbosity: explain.verbosity };
535
541
  }
536
542
 
537
- const emitProcessWarning = msg => process.emitWarning(msg, 'DeprecationWarning');
543
+ const nodejsMajorVersion = +process.version.split('.')[0].substring(1);
544
+ const emitProcessWarning = msg =>
545
+ nodejsMajorVersion <= 6
546
+ ? process.emitWarning(msg, 'DeprecationWarning', MONGODB_WARNING_CODE)
547
+ : process.emitWarning(msg, { type: 'DeprecationWarning', code: MONGODB_WARNING_CODE });
548
+ // eslint-disable-next-line no-console
538
549
  const emitConsoleWarning = msg => console.error(msg);
539
550
  const emitDeprecationWarning = process.emitWarning ? emitProcessWarning : emitConsoleWarning;
540
551
 
@@ -816,6 +827,50 @@ function hasAtomicOperators(doc) {
816
827
  );
817
828
  }
818
829
 
830
+ /**
831
+ * When the driver used emitWarning the code will be equal to this.
832
+ * @public
833
+ *
834
+ * @example
835
+ * ```js
836
+ * process.on('warning', (warning) => {
837
+ * if (warning.code === MONGODB_WARNING_CODE) console.error('Ah an important warning! :)')
838
+ * })
839
+ * ```
840
+ */
841
+ const MONGODB_WARNING_CODE = 'MONGODB DRIVER';
842
+
843
+ /**
844
+ * @internal
845
+ * @param {string} message - message to warn about
846
+ */
847
+ function emitWarning(message) {
848
+ if (process.emitWarning) {
849
+ return nodejsMajorVersion <= 6
850
+ ? process.emitWarning(message, undefined, MONGODB_WARNING_CODE)
851
+ : process.emitWarning(message, { code: MONGODB_WARNING_CODE });
852
+ } else {
853
+ // Approximate the style of print out on node versions pre 8.x
854
+ // eslint-disable-next-line no-console
855
+ return console.error(`[${MONGODB_WARNING_CODE}] Warning:`, message);
856
+ }
857
+ }
858
+
859
+ const emittedWarnings = new Set();
860
+ /**
861
+ * Will emit a warning once for the duration of the application.
862
+ * Uses the message to identify if it has already been emitted
863
+ * so using string interpolation can cause multiple emits
864
+ * @internal
865
+ * @param {string} message - message to warn about
866
+ */
867
+ function emitWarningOnce(message) {
868
+ if (!emittedWarnings.has(message)) {
869
+ emittedWarnings.add(message);
870
+ return emitWarning(message);
871
+ }
872
+ }
873
+
819
874
  module.exports = {
820
875
  filterOptions,
821
876
  mergeOptions,
@@ -832,7 +887,7 @@ module.exports = {
832
887
  isObject,
833
888
  debugOptions,
834
889
  MAX_JS_INT: Number.MAX_SAFE_INTEGER + 1,
835
- mergeOptionsAndWriteConcern,
890
+ conditionallyMergeWriteConcern,
836
891
  executeLegacyOperation,
837
892
  applyRetryableWrites,
838
893
  applyWriteConcern,
@@ -849,5 +904,8 @@ module.exports = {
849
904
  now,
850
905
  calculateDurationInMs,
851
906
  makeInterruptableAsyncInterval,
852
- hasAtomicOperators
907
+ hasAtomicOperators,
908
+ MONGODB_WARNING_CODE,
909
+ emitWarning,
910
+ emitWarningOnce
853
911
  };
@@ -1,6 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  const kWriteConcernKeys = new Set(['w', 'wtimeout', 'j', 'journal', 'fsync']);
4
+ let utils;
4
5
 
5
6
  /**
6
7
  * The **WriteConcern** class is a class that represents a MongoDB WriteConcern.
@@ -75,7 +76,10 @@ class WriteConcern {
75
76
  );
76
77
  }
77
78
 
78
- console.warn(
79
+ // this is down here to prevent circular dependency
80
+ if (!utils) utils = require('./utils');
81
+
82
+ utils.emitWarningOnce(
79
83
  `Top-level use of w, wtimeout, j, and fsync is deprecated. Use writeConcern instead.`
80
84
  );
81
85
  return new WriteConcern(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mongodb",
3
- "version": "3.6.4",
3
+ "version": "3.6.8",
4
4
  "description": "The official MongoDB driver for Node.js",
5
5
  "main": "index.js",
6
6
  "files": [
@@ -16,13 +16,6 @@
16
16
  "driver",
17
17
  "official"
18
18
  ],
19
- "peerOptionalDependencies": {
20
- "kerberos": "^1.1.0",
21
- "mongodb-client-encryption": "^1.0.0",
22
- "mongodb-extjson": "^2.1.2",
23
- "snappy": "^6.3.4",
24
- "bson-ext": "^2.0.0"
25
- },
26
19
  "peerDependenciesMeta": {
27
20
  "kerberos": {
28
21
  "optional": true
@@ -47,33 +40,39 @@
47
40
  "bl": "^2.2.1",
48
41
  "bson": "^1.1.4",
49
42
  "denque": "^1.4.1",
50
- "require_optional": "^1.0.1",
43
+ "optional-require": "^1.0.3",
51
44
  "safe-buffer": "^5.1.2"
52
45
  },
53
46
  "devDependencies": {
47
+ "@types/chai": "^4.2.16",
48
+ "@types/mocha": "^8.2.2",
49
+ "@types/node": "^14.14.37",
50
+ "array-includes": "^3.1.3",
54
51
  "chai": "^4.1.1",
55
52
  "chai-subset": "^1.6.0",
56
53
  "chalk": "^2.4.2",
57
54
  "co": "4.6.0",
58
- "coveralls": "^2.11.6",
59
55
  "eslint": "^7.10.0",
60
56
  "eslint-config-prettier": "^6.11.0",
61
57
  "eslint-plugin-es": "^3.0.1",
62
58
  "eslint-plugin-prettier": "^3.1.3",
63
- "istanbul": "^0.4.5",
64
- "jsdoc": "3.5.5",
59
+ "jsdoc": "^3.5.5",
65
60
  "lodash.camelcase": "^4.3.0",
66
61
  "mocha": "5.2.0",
67
62
  "mocha-sinon": "^2.1.0",
68
63
  "mongodb-extjson": "^2.1.1",
69
64
  "mongodb-mock-server": "^1.0.1",
65
+ "nyc": "^15.1.0",
66
+ "object.entries": "^1.1.3",
70
67
  "prettier": "^1.19.1",
71
68
  "semver": "^5.5.0",
72
69
  "sinon": "^4.3.0",
73
70
  "sinon-chai": "^3.2.0",
74
71
  "snappy": "^6.3.4",
75
72
  "spec-xunit-file": "0.0.1-3",
76
- "standard-version": "^8.0.2",
73
+ "standard-version": "^9.2.0",
74
+ "tslib": "^2.2.0",
75
+ "typescript": "^4.2.4",
77
76
  "util.promisify": "^1.0.1",
78
77
  "worker-farm": "^1.5.0",
79
78
  "wtfnode": "^0.8.0",
@@ -87,18 +86,19 @@
87
86
  "url": "https://github.com/mongodb/node-mongodb-native/issues"
88
87
  },
89
88
  "scripts": {
90
- "atlas": "mocha --opts '{}' ./test/manual/atlas_connectivity.test.js",
89
+ "build:evergreen": "node .evergreen/generate_evergreen_tasks.js",
90
+ "build:unified": "tsc -p test/functional/unified-spec-runner/tsconfig.unified.json",
91
+ "check:atlas": "mocha --opts '{}' ./test/manual/atlas_connectivity.test.js",
92
+ "check:bench": "node test/benchmarks/driverBench/",
93
+ "check:coverage": "nyc npm run check:test",
91
94
  "check:kerberos": "mocha --opts '{}' -t 60000 test/manual/kerberos.test.js",
92
95
  "check:ldap": "mocha --opts '{}' test/manual/ldap.test.js",
96
+ "check:lint": "eslint -v && eslint lib test",
97
+ "check:test": "mocha --recursive test/functional test/unit",
93
98
  "check:tls": "mocha --opts '{}' test/manual/tls_support.test.js",
94
- "test": "npm run lint && mocha --recursive test/functional test/unit",
95
- "test-nolint": "mocha --recursive test/functional test/unit",
96
- "coverage": "istanbul cover mongodb-test-runner -- -t 60000 test/unit test/functional",
97
- "lint": "eslint -v && eslint lib test",
98
- "format": "npm run lint -- --fix",
99
- "bench": "node test/benchmarks/driverBench/",
100
- "generate-evergreen": "node .evergreen/generate_evergreen_tasks.js",
101
- "release": "standard-version -i HISTORY.md"
99
+ "format": "npm run check:lint -- --fix",
100
+ "release": "standard-version -i HISTORY.md",
101
+ "test": "npm run lint && mocha --recursive test/functional test/unit"
102
102
  },
103
103
  "homepage": "https://github.com/mongodb/node-mongodb-native",
104
104
  "optionalDependencies": {