mongodb 3.6.7 → 3.6.11

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 (42) hide show
  1. package/HISTORY.md +34 -0
  2. package/README.md +4 -4
  3. package/lib/bulk/common.js +34 -12
  4. package/lib/cmap/connection.js +2 -1
  5. package/lib/collection.js +9 -0
  6. package/lib/command_utils.js +124 -0
  7. package/lib/core/auth/mongodb_aws.js +1 -0
  8. package/lib/core/auth/scram.js +1 -0
  9. package/lib/core/connection/apm.js +10 -123
  10. package/lib/core/connection/commands.js +11 -2
  11. package/lib/core/connection/connect.js +3 -0
  12. package/lib/core/connection/connection.js +6 -3
  13. package/lib/core/connection/msg.js +11 -2
  14. package/lib/core/connection/pool.js +6 -2
  15. package/lib/core/cursor.js +7 -0
  16. package/lib/core/error.js +2 -2
  17. package/lib/core/index.js +1 -0
  18. package/lib/core/sdam/monitor.js +2 -1
  19. package/lib/core/sdam/server.js +8 -1
  20. package/lib/core/sdam/topology.js +24 -14
  21. package/lib/core/topologies/mongos.js +1 -0
  22. package/lib/core/topologies/replset.js +1 -0
  23. package/lib/core/topologies/server.js +7 -2
  24. package/lib/core/uri_parser.js +3 -1
  25. package/lib/core/utils.js +1 -0
  26. package/lib/core/wireprotocol/constants.js +2 -2
  27. package/lib/core/wireprotocol/shared.js +1 -0
  28. package/lib/cursor.js +12 -2
  29. package/lib/db.js +82 -72
  30. package/lib/encrypter.js +8 -3
  31. package/lib/mongo_client.js +1 -0
  32. package/lib/operations/bulk_write.js +0 -17
  33. package/lib/operations/command.js +4 -1
  34. package/lib/operations/command_v2.js +7 -1
  35. package/lib/operations/connect.js +1 -0
  36. package/lib/operations/db_ops.js +6 -2
  37. package/lib/topologies/mongos.js +1 -0
  38. package/lib/topologies/replset.js +1 -0
  39. package/lib/topologies/server.js +1 -0
  40. package/lib/url_parser.js +2 -1
  41. package/lib/utils.js +78 -1
  42. package/package.json +6 -2
@@ -139,7 +139,12 @@ Msg.getRequestId = function() {
139
139
 
140
140
  class BinMsg {
141
141
  constructor(bson, message, msgHeader, msgBody, opts) {
142
- opts = opts || { promoteLongs: true, promoteValues: true, promoteBuffers: false };
142
+ opts = opts || {
143
+ promoteLongs: true,
144
+ promoteValues: true,
145
+ promoteBuffers: false,
146
+ bsonRegExp: false
147
+ };
143
148
  this.parsed = false;
144
149
  this.raw = message;
145
150
  this.data = msgBody;
@@ -161,6 +166,7 @@ class BinMsg {
161
166
  this.promoteLongs = typeof opts.promoteLongs === 'boolean' ? opts.promoteLongs : true;
162
167
  this.promoteValues = typeof opts.promoteValues === 'boolean' ? opts.promoteValues : true;
163
168
  this.promoteBuffers = typeof opts.promoteBuffers === 'boolean' ? opts.promoteBuffers : false;
169
+ this.bsonRegExp = typeof opts.bsonRegExp === 'boolean' ? opts.bsonRegExp : false;
164
170
 
165
171
  this.documents = [];
166
172
  }
@@ -186,12 +192,15 @@ class BinMsg {
186
192
  typeof options.promoteBuffers === 'boolean'
187
193
  ? options.promoteBuffers
188
194
  : this.opts.promoteBuffers;
195
+ const bsonRegExp =
196
+ typeof options.bsonRegExp === 'boolean' ? options.bsonRegExp : this.opts.bsonRegExp;
189
197
 
190
198
  // Set up the options
191
199
  const _options = {
192
200
  promoteLongs: promoteLongs,
193
201
  promoteValues: promoteValues,
194
- promoteBuffers: promoteBuffers
202
+ promoteBuffers: promoteBuffers,
203
+ bsonRegExp: bsonRegExp
195
204
  };
196
205
 
197
206
  while (this.index < this.data.length) {
@@ -76,6 +76,7 @@ var _id = 0;
76
76
  * @param {boolean} [options.promoteLongs=true] Convert Long values from the db into Numbers if they fit into 53 bits
77
77
  * @param {boolean} [options.promoteValues=true] Promotes BSON values to native types where possible, set to false to only receive wrapper types.
78
78
  * @param {boolean} [options.promoteBuffers=false] Promotes Binary BSON values to native Node Buffers.
79
+ * @param {boolean} [options.bsonRegExp=false] By default, regex returned from MDB will be native to the language. Setting to true will ensure that a BSON.BSONRegExp object is returned.
79
80
  * @param {boolean} [options.domainsEnabled=false] Enable the wrapping of the callback in the current domain, disabled by default to avoid perf hit.
80
81
  * @fires Pool#connect
81
82
  * @fires Pool#close
@@ -127,6 +128,7 @@ var Pool = function(topology, options) {
127
128
  promoteLongs: true,
128
129
  promoteValues: true,
129
130
  promoteBuffers: false,
131
+ bsonRegExp: false,
130
132
  // Reconnection options
131
133
  reconnect: true,
132
134
  reconnectInterval: 1000,
@@ -390,8 +392,8 @@ function messageHandler(self) {
390
392
  if (self.logger.isDebug()) {
391
393
  self.logger.debug(
392
394
  f(
393
- 'message [%s] received from %s:%s',
394
- message.raw.toString('hex'),
395
+ 'message [ %s ] received from %s:%s',
396
+ message.raw.length,
395
397
  self.options.host,
396
398
  self.options.port
397
399
  )
@@ -870,6 +872,7 @@ Pool.prototype.write = function(command, options, cb) {
870
872
  promoteLongs: true,
871
873
  promoteValues: true,
872
874
  promoteBuffers: false,
875
+ bsonRegExp: false,
873
876
  fullResult: false
874
877
  };
875
878
 
@@ -879,6 +882,7 @@ Pool.prototype.write = function(command, options, cb) {
879
882
  typeof options.promoteValues === 'boolean' ? options.promoteValues : true;
880
883
  operation.promoteBuffers =
881
884
  typeof options.promoteBuffers === 'boolean' ? options.promoteBuffers : false;
885
+ operation.bsonRegExp = typeof options.bsonRegExp === 'boolean' ? options.bsonRegExp : false;
882
886
  operation.raw = typeof options.raw === 'boolean' ? options.raw : false;
883
887
  operation.immediateRelease =
884
888
  typeof options.immediateRelease === 'boolean' ? options.immediateRelease : false;
@@ -146,6 +146,13 @@ class CoreCursor extends Readable {
146
146
  this.cursorState.promoteBuffers = options.promoteBuffers;
147
147
  }
148
148
 
149
+ // Add bsonRegExp to cursor state
150
+ if (typeof topologyOptions.bsonRegExp === 'boolean') {
151
+ this.cursorState.bsonRegExp = topologyOptions.bsonRegExp;
152
+ } else if (typeof options.bsonRegExp === 'boolean') {
153
+ this.cursorState.bsonRegExp = options.bsonRegExp;
154
+ }
155
+
149
156
  if (topologyOptions.reconnect) {
150
157
  this.cursorState.reconnect = topologyOptions.reconnect;
151
158
  }
package/lib/core/error.js CHANGED
@@ -102,8 +102,8 @@ class MongoNetworkError extends MongoError {
102
102
  super(message);
103
103
  this.name = 'MongoNetworkError';
104
104
 
105
- if (options && options.beforeHandshake === true) {
106
- this[kBeforeHandshake] = true;
105
+ if (options && typeof options.beforeHandshake === 'boolean') {
106
+ this[kBeforeHandshake] = options.beforeHandshake;
107
107
  }
108
108
  }
109
109
  }
package/lib/core/index.js CHANGED
@@ -5,6 +5,7 @@ const require_optional = require('optional-require')(require);
5
5
  const EJSON = require('./utils').retrieveEJSON();
6
6
 
7
7
  try {
8
+ // Ensure you always wrap an optional require in the try block NODE-3199
8
9
  // Attempt to grab the native BSON parser
9
10
  const BSONNative = require_optional('bson-ext');
10
11
  // If we got the native parser, use it instead of the
@@ -85,7 +85,8 @@ class Monitor extends EventEmitter {
85
85
  raw: false,
86
86
  promoteLongs: true,
87
87
  promoteValues: true,
88
- promoteBuffers: true
88
+ promoteBuffers: true,
89
+ bsonRegExp: true
89
90
  }
90
91
  );
91
92
 
@@ -20,6 +20,7 @@ const isNodeShuttingDownError = require('../error').isNodeShuttingDownError;
20
20
  const isNetworkErrorBeforeHandshake = require('../error').isNetworkErrorBeforeHandshake;
21
21
  const maxWireVersion = require('../utils').maxWireVersion;
22
22
  const makeStateMachine = require('../utils').makeStateMachine;
23
+ const extractCommand = require('../../command_utils').extractCommand;
23
24
  const common = require('./common');
24
25
  const ServerType = common.ServerType;
25
26
  const isTransactionCommand = require('../transactions').isTransactionCommand;
@@ -49,6 +50,7 @@ const DEBUG_FIELDS = [
49
50
  'promoteLongs',
50
51
  'promoteValues',
51
52
  'promoteBuffers',
53
+ 'bsonRegExp',
52
54
  'servername'
53
55
  ];
54
56
 
@@ -166,6 +168,10 @@ class Server extends EventEmitter {
166
168
  return this.s.description;
167
169
  }
168
170
 
171
+ get supportsRetryableWrites() {
172
+ return supportsRetryableWrites(this);
173
+ }
174
+
169
175
  get name() {
170
176
  return this.s.description.address;
171
177
  }
@@ -261,10 +267,11 @@ class Server extends EventEmitter {
261
267
 
262
268
  // Debug log
263
269
  if (this.s.logger.isDebug()) {
270
+ const extractedCommand = extractCommand(cmd);
264
271
  this.s.logger.debug(
265
272
  `executing command [${JSON.stringify({
266
273
  ns,
267
- cmd,
274
+ cmd: extractedCommand.shouldRedact ? `${extractedCommand.name} details REDACTED` : cmd,
268
275
  options: debugOptions(DEBUG_FIELDS, options)
269
276
  })}] against ${this.name}`
270
277
  );
@@ -9,7 +9,6 @@ const events = require('./events');
9
9
  const Server = require('./server').Server;
10
10
  const relayEvents = require('../utils').relayEvents;
11
11
  const ReadPreference = require('../topologies/read_preference');
12
- const isRetryableWritesSupported = require('../topologies/shared').isRetryableWritesSupported;
13
12
  const CoreCursor = require('../cursor').CoreCursor;
14
13
  const deprecate = require('util').deprecate;
15
14
  const BSON = require('../connection/utils').retrieveBSON();
@@ -669,12 +668,17 @@ class Topology extends EventEmitter {
669
668
  return;
670
669
  }
671
670
 
671
+ const notAlreadyRetrying = !options.retrying;
672
+ const retryWrites = !!options.retryWrites;
673
+ const hasSession = !!options.session;
674
+ const supportsRetryableWrites = server.supportsRetryableWrites;
675
+ const notInTransaction = !hasSession || !options.session.inTransaction();
672
676
  const willRetryWrite =
673
- !options.retrying &&
674
- !!options.retryWrites &&
675
- options.session &&
676
- isRetryableWritesSupported(this) &&
677
- !options.session.inTransaction() &&
677
+ notAlreadyRetrying &&
678
+ retryWrites &&
679
+ hasSession &&
680
+ supportsRetryableWrites &&
681
+ notInTransaction &&
678
682
  isWriteCommand(cmd);
679
683
 
680
684
  const cb = (err, result) => {
@@ -925,20 +929,26 @@ function executeWriteOperation(args, options, callback) {
925
929
  const ns = args.ns;
926
930
  const ops = args.ops;
927
931
 
928
- const willRetryWrite =
929
- !args.retrying &&
930
- !!options.retryWrites &&
931
- options.session &&
932
- isRetryableWritesSupported(topology) &&
933
- !options.session.inTransaction() &&
934
- options.explain === undefined;
935
-
936
932
  topology.selectServer(writableServerSelector(), options, (err, server) => {
937
933
  if (err) {
938
934
  callback(err, null);
939
935
  return;
940
936
  }
941
937
 
938
+ const notAlreadyRetrying = !args.retrying;
939
+ const retryWrites = !!options.retryWrites;
940
+ const hasSession = !!options.session;
941
+ const supportsRetryableWrites = server.supportsRetryableWrites;
942
+ const notInTransaction = !hasSession || !options.session.inTransaction();
943
+ const notExplaining = options.explain === undefined;
944
+ const willRetryWrite =
945
+ notAlreadyRetrying &&
946
+ retryWrites &&
947
+ hasSession &&
948
+ supportsRetryableWrites &&
949
+ notInTransaction &&
950
+ notExplaining;
951
+
942
952
  const handler = (err, result) => {
943
953
  if (!err) return callback(null, result);
944
954
  if (!shouldRetryOperation(err)) {
@@ -88,6 +88,7 @@ var handlers = ['connect', 'close', 'error', 'timeout', 'parseError'];
88
88
  * @param {boolean} [options.promoteLongs=true] Convert Long values from the db into Numbers if they fit into 53 bits
89
89
  * @param {boolean} [options.promoteValues=true] Promotes BSON values to native types where possible, set to false to only receive wrapper types.
90
90
  * @param {boolean} [options.promoteBuffers=false] Promotes Binary BSON values to native Node Buffers.
91
+ * @param {boolean} [options.bsonRegExp=false] By default, regex returned from MDB will be native to the language. Setting to true will ensure that a BSON.BSONRegExp object is returned.
91
92
  * @param {boolean} [options.domainsEnabled=false] Enable the wrapping of the callback in the current domain, disabled by default to avoid perf hit.
92
93
  * @param {boolean} [options.monitorCommands=false] Enable command monitoring for this topology
93
94
  * @return {Mongos} A cursor instance
@@ -88,6 +88,7 @@ var handlers = ['connect', 'close', 'error', 'timeout', 'parseError'];
88
88
  * @param {boolean} [options.promoteLongs=true] Convert Long values from the db into Numbers if they fit into 53 bits
89
89
  * @param {boolean} [options.promoteValues=true] Promotes BSON values to native types where possible, set to false to only receive wrapper types.
90
90
  * @param {boolean} [options.promoteBuffers=false] Promotes Binary BSON values to native Node Buffers.
91
+ * @param {boolean} [options.bsonRegExp=false] By default, regex returned from MDB will be native to the language. Setting to true will ensure that a BSON.BSONRegExp object is returned.
91
92
  * @param {number} [options.pingInterval=5000] Ping interval to check the response time to the different servers
92
93
  * @param {number} [options.localThresholdMS=15] Cutoff latency point in MS for Replicaset member selection
93
94
  * @param {boolean} [options.domainsEnabled=false] Enable the wrapping of the callback in the current domain, disabled by default to avoid perf hit.
@@ -16,6 +16,7 @@ var inherits = require('util').inherits,
16
16
  createCompressionInfo = require('./shared').createCompressionInfo,
17
17
  resolveClusterTime = require('./shared').resolveClusterTime,
18
18
  SessionMixins = require('./shared').SessionMixins,
19
+ extractCommand = require('../../command_utils').extractCommand,
19
20
  relayEvents = require('../utils').relayEvents;
20
21
 
21
22
  const collationNotSupported = require('../utils').collationNotSupported;
@@ -46,6 +47,7 @@ var debugFields = [
46
47
  'promoteLongs',
47
48
  'promoteValues',
48
49
  'promoteBuffers',
50
+ 'bsonRegExp',
49
51
  'servername'
50
52
  ];
51
53
 
@@ -88,6 +90,7 @@ function topologyId(server) {
88
90
  * @param {boolean} [options.promoteLongs=true] Convert Long values from the db into Numbers if they fit into 53 bits
89
91
  * @param {boolean} [options.promoteValues=true] Promotes BSON values to native types where possible, set to false to only receive wrapper types.
90
92
  * @param {boolean} [options.promoteBuffers=false] Promotes Binary BSON values to native Node Buffers.
93
+ * @param {boolean} [options.bsonRegExp=false] By default, regex returned from MDB will be native to the language. Setting to true will ensure that a BSON.BSONRegExp object is returned.
91
94
  * @param {string} [options.appname=null] Application name, passed in on ismaster call and logged in mongod server logs. Maximum size 128 bytes.
92
95
  * @param {boolean} [options.domainsEnabled=false] Enable the wrapping of the callback in the current domain, disabled by default to avoid perf hit.
93
96
  * @param {boolean} [options.monitorCommands=false] Enable command monitoring for this topology
@@ -608,18 +611,20 @@ Server.prototype.command = function(ns, cmd, options, callback) {
608
611
  options = Object.assign({}, options, { wireProtocolCommand: false });
609
612
 
610
613
  // Debug log
611
- if (self.s.logger.isDebug())
614
+ if (self.s.logger.isDebug()) {
615
+ const extractedCommand = extractCommand(cmd);
612
616
  self.s.logger.debug(
613
617
  f(
614
618
  'executing command [%s] against %s',
615
619
  JSON.stringify({
616
620
  ns: ns,
617
- cmd: cmd,
621
+ cmd: extractedCommand.shouldRedact ? `${extractedCommand.name} details REDACTED` : cmd,
618
622
  options: debugOptions(debugFields, options)
619
623
  }),
620
624
  self.name
621
625
  )
622
626
  );
627
+ }
623
628
 
624
629
  // If we are not connected or have a disconnectHandler specified
625
630
  if (disconnectHandler(self, 'command', ns, cmd, options, callback)) return;
@@ -52,7 +52,9 @@ function parseSrvConnectionString(uri, options, callback) {
52
52
  }
53
53
 
54
54
  result.domainLength = result.hostname.split('.').length;
55
- if (result.pathname && result.pathname.match(',')) {
55
+
56
+ const hostname = uri.substring('mongodb+srv://'.length).split('/')[0];
57
+ if (hostname.match(',')) {
56
58
  return callback(new MongoParseError('Invalid URI, cannot contain multiple hostnames'));
57
59
  }
58
60
 
package/lib/core/utils.js CHANGED
@@ -27,6 +27,7 @@ function retrieveKerberos() {
27
27
  let kerberos;
28
28
 
29
29
  try {
30
+ // Ensure you always wrap an optional require in the try block NODE-3199
30
31
  kerberos = requireOptional('kerberos');
31
32
  } catch (err) {
32
33
  if (err.code === 'MODULE_NOT_FOUND') {
@@ -1,9 +1,9 @@
1
1
  'use strict';
2
2
 
3
3
  const MIN_SUPPORTED_SERVER_VERSION = '2.6';
4
- const MAX_SUPPORTED_SERVER_VERSION = '4.4';
4
+ const MAX_SUPPORTED_SERVER_VERSION = '5.0';
5
5
  const MIN_SUPPORTED_WIRE_VERSION = 2;
6
- const MAX_SUPPORTED_WIRE_VERSION = 9;
6
+ const MAX_SUPPORTED_WIRE_VERSION = 13;
7
7
 
8
8
  module.exports = {
9
9
  MIN_SUPPORTED_SERVER_VERSION,
@@ -57,6 +57,7 @@ function applyCommonQueryOptions(queryOptions, options) {
57
57
  promoteLongs: typeof options.promoteLongs === 'boolean' ? options.promoteLongs : true,
58
58
  promoteValues: typeof options.promoteValues === 'boolean' ? options.promoteValues : true,
59
59
  promoteBuffers: typeof options.promoteBuffers === 'boolean' ? options.promoteBuffers : false,
60
+ bsonRegExp: typeof options.bsonRegExp === 'boolean' ? options.bsonRegExp : false,
60
61
  monitoring: typeof options.monitoring === 'boolean' ? options.monitoring : false,
61
62
  fullResult: typeof options.fullResult === 'boolean' ? options.fullResult : false
62
63
  });
package/lib/cursor.js CHANGED
@@ -742,7 +742,12 @@ class Cursor extends CoreCursor {
742
742
  return false;
743
743
  }
744
744
  if (doc != null) {
745
- iterator(doc);
745
+ try {
746
+ iterator(doc);
747
+ } catch (error) {
748
+ callback(error);
749
+ return false;
750
+ }
746
751
  return true;
747
752
  }
748
753
  if (doc == null && callback) {
@@ -762,7 +767,12 @@ class Cursor extends CoreCursor {
762
767
  fulfill(null);
763
768
  return false;
764
769
  } else {
765
- iterator(doc);
770
+ try {
771
+ iterator(doc);
772
+ } catch (error) {
773
+ reject(error);
774
+ return false;
775
+ }
766
776
  return true;
767
777
  }
768
778
  });
package/lib/db.js CHANGED
@@ -83,7 +83,6 @@ const legalOptionNames = [
83
83
  'bufferMaxEntries',
84
84
  'authSource',
85
85
  'ignoreUndefined',
86
- 'promoteLongs',
87
86
  'promiseLibrary',
88
87
  'readConcern',
89
88
  'retryMiliSeconds',
@@ -95,6 +94,7 @@ const legalOptionNames = [
95
94
  'promoteBuffers',
96
95
  'promoteLongs',
97
96
  'promoteValues',
97
+ 'bsonRegExp',
98
98
  'compression',
99
99
  'retryWrites'
100
100
  ];
@@ -117,6 +117,7 @@ const legalOptionNames = [
117
117
  * @param {boolean} [options.promoteLongs=true] Promotes Long values to number if they fit inside the 53 bits resolution.
118
118
  * @param {boolean} [options.promoteBuffers=false] Promotes Binary BSON values to native Node Buffers.
119
119
  * @param {boolean} [options.promoteValues=true] Promotes BSON values to native types where possible, set to false to only receive wrapper types.
120
+ * @param {boolean} [options.bsonRegExp=false] By default, regex returned from MDB will be native to the language. Setting to true will ensure that a BSON.BSONRegExp object is returned.
120
121
  * @param {number} [options.bufferMaxEntries=-1] Sets a cap on how many operations the driver will buffer up before giving up on getting a working connection, default is -1 which is unlimited.
121
122
  * @param {(ReadPreference|string)} [options.readPreference] The preferred read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
122
123
  * @param {object} [options.pkFactory] A primary key factory object for generation of custom _id keys.
@@ -323,6 +324,7 @@ Db.prototype.command = function(command, options, callback) {
323
324
  * @param {boolean} [options.promoteLongs=true] Promotes Long values to number if they fit inside the 53 bits resolution.
324
325
  * @param {boolean} [options.promoteValues=true] Promotes BSON values to native types where possible, set to false to only receive wrapper types.
325
326
  * @param {boolean} [options.promoteBuffers=false] Promotes Binary BSON values to native Node Buffers.
327
+ * @param {boolean} [options.bsonRegExp=false] By default, regex returned from MDB will be native to the language. Setting to true will ensure that a BSON.BSONRegExp object is returned.
326
328
  * @param {object} [options.collation] Specify collation (MongoDB 3.4 or higher) settings for update operation (see 3.4 documentation for available fields).
327
329
  * @param {string} [options.comment] Add a comment to an aggregation command
328
330
  * @param {string|object} [options.hint] Add an index selection hint to an aggregation command
@@ -391,7 +393,8 @@ const COLLECTION_OPTION_KEYS = [
391
393
  'ignoreUndefined',
392
394
  'promoteValues',
393
395
  'promoteBuffers',
394
- 'promoteLongs'
396
+ 'promoteLongs',
397
+ 'bsonRegExp'
395
398
  ];
396
399
 
397
400
  /**
@@ -409,91 +412,98 @@ const COLLECTION_OPTION_KEYS = [
409
412
  * @param {object} [options.pkFactory] A primary key factory object for generation of custom _id keys.
410
413
  * @param {(ReadPreference|string)} [options.readPreference] The preferred read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
411
414
  * @param {boolean} [options.serializeFunctions=false] Serialize functions on any object.
412
- * @param {boolean} [options.strict=false] Returns an error if the collection does not exist
415
+ * @param {boolean} [options.strict=false] **Deprecated** Returns an error if the collection does not exist
413
416
  * @param {object} [options.readConcern] Specify a read concern for the collection. (only MongoDB 3.2 or higher supported)
414
417
  * @param {ReadConcernLevel} [options.readConcern.level='local'] Specify a read concern level for the collection operations (only MongoDB 3.2 or higher supported)
415
418
  * @param {Db~collectionResultCallback} [callback] The collection result callback
416
419
  * @return {Collection} return the new Collection instance if not in strict mode
417
420
  */
418
- Db.prototype.collection = function(name, options, callback) {
419
- if (typeof options === 'function') (callback = options), (options = {});
420
- options = options || {};
421
- options = Object.assign({}, options);
422
-
423
- // Set the promise library
424
- options.promiseLibrary = this.s.promiseLibrary;
421
+ Db.prototype.collection = deprecateOptions(
422
+ {
423
+ name: 'Db.collection',
424
+ deprecatedOptions: ['strict'],
425
+ optionsIndex: 1
426
+ },
427
+ function(name, options, callback) {
428
+ if (typeof options === 'function') (callback = options), (options = {});
429
+ options = options || {};
430
+ options = Object.assign({}, options);
425
431
 
426
- // If we have not set a collection level readConcern set the db level one
427
- options.readConcern = options.readConcern
428
- ? new ReadConcern(options.readConcern.level)
429
- : this.readConcern;
432
+ // Set the promise library
433
+ options.promiseLibrary = this.s.promiseLibrary;
430
434
 
431
- // Do we have ignoreUndefined set
432
- if (this.s.options.ignoreUndefined) {
433
- options.ignoreUndefined = this.s.options.ignoreUndefined;
434
- }
435
+ // If we have not set a collection level readConcern set the db level one
436
+ options.readConcern = options.readConcern
437
+ ? new ReadConcern(options.readConcern.level)
438
+ : this.readConcern;
435
439
 
436
- for (const collectionOptionKey of COLLECTION_OPTION_KEYS) {
437
- if (!(collectionOptionKey in options) && this.s.options[collectionOptionKey] !== undefined) {
438
- options[collectionOptionKey] = this.s.options[collectionOptionKey];
440
+ // Do we have ignoreUndefined set
441
+ if (this.s.options.ignoreUndefined) {
442
+ options.ignoreUndefined = this.s.options.ignoreUndefined;
439
443
  }
440
- }
441
444
 
442
- // Merge in all needed options and ensure correct writeConcern merging from db level
443
- options = conditionallyMergeWriteConcern(options, this.s.options);
444
-
445
- // Execute
446
- if (options == null || !options.strict) {
447
- try {
448
- const collection = new Collection(
449
- this,
450
- this.s.topology,
451
- this.databaseName,
452
- name,
453
- this.s.pkFactory,
454
- options
455
- );
456
- if (callback) callback(null, collection);
457
- return collection;
458
- } catch (err) {
459
- if (err instanceof MongoError && callback) return callback(err);
460
- throw err;
445
+ for (const collectionOptionKey of COLLECTION_OPTION_KEYS) {
446
+ if (!(collectionOptionKey in options) && this.s.options[collectionOptionKey] !== undefined) {
447
+ options[collectionOptionKey] = this.s.options[collectionOptionKey];
448
+ }
461
449
  }
462
- }
463
450
 
464
- // Strict mode
465
- if (typeof callback !== 'function') {
466
- throw toError(`A callback is required in strict mode. While getting collection ${name}`);
467
- }
451
+ // Merge in all needed options and ensure correct writeConcern merging from db level
452
+ options = conditionallyMergeWriteConcern(options, this.s.options);
453
+
454
+ // Execute
455
+ if (options == null || !options.strict) {
456
+ try {
457
+ const collection = new Collection(
458
+ this,
459
+ this.s.topology,
460
+ this.databaseName,
461
+ name,
462
+ this.s.pkFactory,
463
+ options
464
+ );
465
+ if (callback) callback(null, collection);
466
+ return collection;
467
+ } catch (err) {
468
+ if (err instanceof MongoError && callback) return callback(err);
469
+ throw err;
470
+ }
471
+ }
468
472
 
469
- // Did the user destroy the topology
470
- if (this.serverConfig && this.serverConfig.isDestroyed()) {
471
- return callback(new MongoError('topology was destroyed'));
472
- }
473
+ // Strict mode
474
+ if (typeof callback !== 'function') {
475
+ throw toError(`A callback is required in strict mode. While getting collection ${name}`);
476
+ }
473
477
 
474
- const listCollectionOptions = Object.assign({}, options, { nameOnly: true });
475
-
476
- // Strict mode
477
- this.listCollections({ name: name }, listCollectionOptions).toArray((err, collections) => {
478
- if (err != null) return handleCallback(callback, err, null);
479
- if (collections.length === 0)
480
- return handleCallback(
481
- callback,
482
- toError(`Collection ${name} does not exist. Currently in strict mode.`),
483
- null
484
- );
485
-
486
- try {
487
- return handleCallback(
488
- callback,
489
- null,
490
- new Collection(this, this.s.topology, this.databaseName, name, this.s.pkFactory, options)
491
- );
492
- } catch (err) {
493
- return handleCallback(callback, err, null);
478
+ // Did the user destroy the topology
479
+ if (this.serverConfig && this.serverConfig.isDestroyed()) {
480
+ return callback(new MongoError('topology was destroyed'));
494
481
  }
495
- });
496
- };
482
+
483
+ const listCollectionOptions = Object.assign({}, options, { nameOnly: true });
484
+
485
+ // Strict mode
486
+ this.listCollections({ name: name }, listCollectionOptions).toArray((err, collections) => {
487
+ if (err != null) return handleCallback(callback, err, null);
488
+ if (collections.length === 0)
489
+ return handleCallback(
490
+ callback,
491
+ toError(`Collection ${name} does not exist. Currently in strict mode.`),
492
+ null
493
+ );
494
+
495
+ try {
496
+ return handleCallback(
497
+ callback,
498
+ null,
499
+ new Collection(this, this.s.topology, this.databaseName, name, this.s.pkFactory, options)
500
+ );
501
+ } catch (err) {
502
+ return handleCallback(callback, err, null);
503
+ }
504
+ });
505
+ }
506
+ );
497
507
 
498
508
  /**
499
509
  * Create a new collection on a server with the specified options. Use this to create capped collections.
package/lib/encrypter.js CHANGED
@@ -3,8 +3,10 @@ const MongoClient = require('./mongo_client');
3
3
  const BSON = require('./core/connection/utils').retrieveBSON();
4
4
  const MongoError = require('./core/error').MongoError;
5
5
 
6
+ let mongodbClientEncryption = undefined;
6
7
  try {
7
- require.resolve('mongodb-client-encryption');
8
+ // Ensure you always wrap an optional require in the try block NODE-3199
9
+ mongodbClientEncryption = require('mongodb-client-encryption');
8
10
  } catch (err) {
9
11
  throw new MongoError(
10
12
  'Auto-encryption requested, but the module is not installed. ' +
@@ -12,13 +14,16 @@ try {
12
14
  );
13
15
  }
14
16
 
15
- const mongodbClientEncryption = require('mongodb-client-encryption');
16
- if (typeof mongodbClientEncryption.extension !== 'function') {
17
+ if (
18
+ mongodbClientEncryption === undefined ||
19
+ typeof mongodbClientEncryption.extension !== 'function'
20
+ ) {
17
21
  throw new MongoError(
18
22
  'loaded version of `mongodb-client-encryption` does not have property `extension`. ' +
19
23
  'Please make sure you are loading the correct version of `mongodb-client-encryption`'
20
24
  );
21
25
  }
26
+
22
27
  const AutoEncrypter = mongodbClientEncryption.extension(require('../index')).AutoEncrypter;
23
28
 
24
29
  const kInternalClient = Symbol('internalClient');
@@ -144,6 +144,7 @@ const validOptions = require('./operations/connect').validOptions;
144
144
  * @property {boolean} [promoteValues] (**default**: true) Promotes BSON values to native types where possible, set to false to only receive wrapper types
145
145
  * @property {boolean} [promoteBuffers] (**default**: false) Promotes Binary BSON values to native Node Buffers
146
146
  * @property {boolean} [promoteLongs] (**default**: true) Promotes long values to number if they fit inside the 53 bits resolution
147
+ * * @param {boolean} [bsonRegExp] (**default**: false) By default, regex returned from MDB will be native to the language. Setting to true will ensure that a BSON.BSONRegExp object is returned.
147
148
  * @property {boolean} [domainsEnabled] (**default**: false) Enable the wrapping of the callback in the current domain, disabled by default to avoid perf hit
148
149
  * @property {object} [validateOptions] (**default**: false) Validate MongoClient passed in options for correctness
149
150
  * @property {string} [appname] (**default**: undefined) The name of the application that created this MongoClient instance. MongoDB 3.4 and newer will print this value in the server log upon establishing each connection. It is also recorded in the slow query log and profile collections
@@ -70,23 +70,6 @@ class BulkWriteOperation extends OperationBase {
70
70
  return callback(err, null);
71
71
  }
72
72
 
73
- // Update the n
74
- r.n = r.insertedCount;
75
-
76
- // Inserted documents
77
- const inserted = r.getInsertedIds();
78
- // Map inserted ids
79
- for (let i = 0; i < inserted.length; i++) {
80
- r.insertedIds[inserted[i].index] = inserted[i]._id;
81
- }
82
-
83
- // Upserted documents
84
- const upserted = r.getUpsertedIds();
85
- // Map upserted ids
86
- for (let i = 0; i < upserted.length; i++) {
87
- r.upsertedIds[upserted[i].index] = upserted[i]._id;
88
- }
89
-
90
73
  // Return the results
91
74
  callback(null, r);
92
75
  });