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
package/HISTORY.md CHANGED
@@ -2,6 +2,40 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
+ ### [3.6.11](https://github.com/mongodb/node-mongodb-native/compare/v3.6.10...v3.6.11) (2021-08-05)
6
+
7
+
8
+ ### Bug Fixes
9
+
10
+ * **NODE-1843:** bulk operations ignoring provided sessions [PORT] ([#2898](https://github.com/mongodb/node-mongodb-native/issues/2898)) ([9244b17](https://github.com/mongodb/node-mongodb-native/commit/9244b1771e538f7b685fd6d4aa83d9da84b20093))
11
+ * **NODE-3199:** unable to bundle driver due to uncaught require ([#2903](https://github.com/mongodb/node-mongodb-native/issues/2903)) ([60efe9d](https://github.com/mongodb/node-mongodb-native/commit/60efe9d0030477da462d326c2e2ddc5fe6c0ffff))
12
+
13
+ ### [3.6.10](https://github.com/mongodb/node-mongodb-native/compare/v3.6.9...v3.6.10) (2021-07-06)
14
+
15
+
16
+ ### Bug Fixes
17
+
18
+ * **NODE-2035:** Exceptions thrown from awaited cursor forEach do not propagate ([#2852](https://github.com/mongodb/node-mongodb-native/issues/2852)) ([a917dfa](https://github.com/mongodb/node-mongodb-native/commit/a917dfada67859412344ed238796cf3bee243f5f))
19
+ * **NODE-3150:** added bsonRegExp option for v3.6 ([#2843](https://github.com/mongodb/node-mongodb-native/issues/2843)) ([e4a9a57](https://github.com/mongodb/node-mongodb-native/commit/e4a9a572427666fd1a89576dadf50b9c452e1659))
20
+ * **NODE-3358:** Command monitoring objects hold internal state references ([#2858](https://github.com/mongodb/node-mongodb-native/issues/2858)) ([750760c](https://github.com/mongodb/node-mongodb-native/commit/750760c324ddedb72491befde9f7aff1ceec009c))
21
+ * **NODE-3380:** perform retryable write checks against server ([#2861](https://github.com/mongodb/node-mongodb-native/issues/2861)) ([621677a](https://github.com/mongodb/node-mongodb-native/commit/621677a42772e0b26aa13883f57d7e42f86df43f))
22
+ * **NODE-3397:** report more helpful error with unsupported authMechanism in initial handshake ([#2876](https://github.com/mongodb/node-mongodb-native/issues/2876)) ([3ce148d](https://github.com/mongodb/node-mongodb-native/commit/3ce148d8fb37faea1ee056f6e9331e5282e65cd0))
23
+
24
+ ### [3.6.9](https://github.com/mongodb/node-mongodb-native/compare/v3.6.8...v3.6.9) (2021-05-26)
25
+
26
+
27
+ ### Bug Fixes
28
+
29
+ * **NODE-3309:** remove redundant iteration of bulk write result ([#2815](https://github.com/mongodb/node-mongodb-native/issues/2815)) ([fac9610](https://github.com/mongodb/node-mongodb-native/commit/fac961086eafa0f7437576fd6af900e1f9fe22ed))
30
+ * fix url parsing for a mongodb+srv url that has commas in the database name ([#2789](https://github.com/mongodb/node-mongodb-native/issues/2789)) ([58c4e69](https://github.com/mongodb/node-mongodb-native/commit/58c4e693cc3a717254144d5f9bdddd8414217e97))
31
+
32
+ ### [3.6.8](https://github.com/mongodb/node-mongodb-native/compare/v3.6.7...v3.6.8) (2021-05-21)
33
+
34
+
35
+ ### Bug Fixes
36
+
37
+ * **cmap:** undo flipping of `beforeHandshake` flag for timeout errors ([#2813](https://github.com/mongodb/node-mongodb-native/issues/2813)) ([6e3bab3](https://github.com/mongodb/node-mongodb-native/commit/6e3bab32204ea905ab9b949edccb68556b50d382))
38
+
5
39
  ### [3.6.7](https://github.com/mongodb/node-mongodb-native/compare/v3.6.6...v3.6.7) (2021-05-18)
6
40
 
7
41
 
package/README.md CHANGED
@@ -15,10 +15,10 @@ Check out our [beta version 4.0 here](https://github.com/mongodb/node-mongodb-na
15
15
 
16
16
  | what | where |
17
17
  | ------------- | ---------------------------------------------------- |
18
- | documentation | http://mongodb.github.io/node-mongodb-native |
19
- | api-doc | http://mongodb.github.io/node-mongodb-native/3.6/api |
18
+ | documentation | https://mongodb.github.io/node-mongodb-native |
19
+ | api-doc | https://mongodb.github.io/node-mongodb-native/3.6/api |
20
20
  | source | https://github.com/mongodb/node-mongodb-native |
21
- | mongodb | http://www.mongodb.org |
21
+ | mongodb | https://www.mongodb.org |
22
22
 
23
23
  ### Bugs / Feature Requests
24
24
 
@@ -481,7 +481,7 @@ For more detailed information, see the [tutorials](docs/reference/content/tutori
481
481
 
482
482
  ## Next Steps
483
483
 
484
- - [MongoDB Documentation](http://mongodb.org)
484
+ - [MongoDB Documentation](https://mongodb.org)
485
485
  - [Read about Schemas](http://learnmongodbthehardway.com)
486
486
  - [Star us on GitHub](https://github.com/mongodb/node-mongodb-native)
487
487
 
@@ -57,6 +57,9 @@ class Batch {
57
57
  }
58
58
  }
59
59
 
60
+ const kUpsertedIds = Symbol('upsertedIds');
61
+ const kInsertedIds = Symbol('insertedIds');
62
+
60
63
  /**
61
64
  * @classdesc
62
65
  * The result of a bulk write.
@@ -69,6 +72,8 @@ class BulkWriteResult {
69
72
  */
70
73
  constructor(bulkResult) {
71
74
  this.result = bulkResult;
75
+ this[kUpsertedIds] = undefined;
76
+ this[kInsertedIds] = undefined;
72
77
  }
73
78
 
74
79
  /** Number of documents inserted. */
@@ -94,20 +99,33 @@ class BulkWriteResult {
94
99
 
95
100
  /** Upserted document generated Id's, hash key is the index of the originating operation */
96
101
  get upsertedIds() {
97
- const upserted = {};
98
- for (const doc of !this.result.upserted ? [] : this.result.upserted) {
99
- upserted[doc.index] = doc._id;
102
+ if (this[kUpsertedIds]) {
103
+ return this[kUpsertedIds];
104
+ }
105
+
106
+ this[kUpsertedIds] = {};
107
+ for (const doc of this.result.upserted || []) {
108
+ this[kUpsertedIds][doc.index] = doc._id;
100
109
  }
101
- return upserted;
110
+ return this[kUpsertedIds];
102
111
  }
103
112
 
104
113
  /** Inserted document generated Id's, hash key is the index of the originating operation */
105
114
  get insertedIds() {
106
- const inserted = {};
107
- for (const doc of !this.result.insertedIds ? [] : this.result.insertedIds) {
108
- inserted[doc.index] = doc._id;
115
+ if (this[kInsertedIds]) {
116
+ return this[kInsertedIds];
117
+ }
118
+
119
+ this[kInsertedIds] = {};
120
+ for (const doc of this.result.insertedIds || []) {
121
+ this[kInsertedIds][doc.index] = doc._id;
109
122
  }
110
- return inserted;
123
+ return this[kInsertedIds];
124
+ }
125
+
126
+ /** The number of inserted documents @type {number} */
127
+ get n() {
128
+ return this.result.insertedCount;
111
129
  }
112
130
 
113
131
  /**
@@ -1158,8 +1176,11 @@ class BulkOperationBase {
1158
1176
  * @param {function} callback
1159
1177
  */
1160
1178
  bulkExecute(_writeConcern, options, callback) {
1161
- if (typeof options === 'function') (callback = options), (options = {});
1162
- options = options || {};
1179
+ if (typeof options === 'function') {
1180
+ callback = options;
1181
+ }
1182
+
1183
+ const finalOptions = Object.assign({}, this.s.options, options);
1163
1184
 
1164
1185
  if (typeof _writeConcern === 'function') {
1165
1186
  callback = _writeConcern;
@@ -1185,7 +1206,7 @@ class BulkOperationBase {
1185
1206
  const emptyBatchError = toError('Invalid Operation, no operations specified');
1186
1207
  return this._handleEarlyError(emptyBatchError, callback);
1187
1208
  }
1188
- return { options, callback };
1209
+ return { options: finalOptions, callback };
1189
1210
  }
1190
1211
 
1191
1212
  /**
@@ -1370,5 +1391,6 @@ module.exports = {
1370
1391
  INSERT: INSERT,
1371
1392
  UPDATE: UPDATE,
1372
1393
  REMOVE: REMOVE,
1373
- BulkWriteError
1394
+ BulkWriteError,
1395
+ BulkWriteResult
1374
1396
  };
@@ -122,7 +122,7 @@ class Connection extends EventEmitter {
122
122
  if (issue.isTimeout) {
123
123
  op.cb(
124
124
  new MongoNetworkTimeoutError(`connection ${this.id} to ${this.address} timed out`, {
125
- beforeHandshake: !!this[kIsMaster]
125
+ beforeHandshake: this.ismaster == null
126
126
  })
127
127
  );
128
128
  } else if (issue.isClose) {
@@ -317,6 +317,7 @@ function write(command, options, callback) {
317
317
  promoteLongs: typeof options.promoteLongs === 'boolean' ? options.promoteLongs : true,
318
318
  promoteValues: typeof options.promoteValues === 'boolean' ? options.promoteValues : true,
319
319
  promoteBuffers: typeof options.promoteBuffers === 'boolean' ? options.promoteBuffers : false,
320
+ bsonRegExp: typeof options.bsonRegExp === 'boolean' ? options.bsonRegExp : false,
320
321
  raw: typeof options.raw === 'boolean' ? options.raw : false
321
322
  };
322
323
 
package/lib/collection.js CHANGED
@@ -120,6 +120,8 @@ function Collection(db, topology, dbName, name, pkFactory, options) {
120
120
  options == null || options.promoteBuffers == null
121
121
  ? db.s.options.promoteBuffers
122
122
  : options.promoteBuffers;
123
+ const bsonRegExp =
124
+ options == null || options.bsonRegExp == null ? db.s.options.bsonRegExp : options.bsonRegExp;
123
125
  const collectionHint = null;
124
126
 
125
127
  const namespace = new MongoDBNamespace(dbName, name);
@@ -156,6 +158,8 @@ function Collection(db, topology, dbName, name, pkFactory, options) {
156
158
  promoteValues: promoteValues,
157
159
  // promoteBuffers
158
160
  promoteBuffers: promoteBuffers,
161
+ // bsonRegExp
162
+ bsonRegExp: bsonRegExp,
159
163
  // internalHint
160
164
  internalHint: internalHint,
161
165
  // collectionHint
@@ -303,6 +307,7 @@ const DEPRECATED_FIND_OPTIONS = ['maxScan', 'fields', 'snapshot', 'oplogReplay']
303
307
  * @param {boolean} [options.promoteLongs=true] Promotes Long values to number if they fit inside the 53 bits resolution.
304
308
  * @param {boolean} [options.promoteValues=true] Promotes BSON values to native types where possible, set to false to only receive wrapper types.
305
309
  * @param {boolean} [options.promoteBuffers=false] Promotes Binary BSON values to native Node Buffers.
310
+ * @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.
306
311
  * @param {(ReadPreference|string)} [options.readPreference] The preferred read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
307
312
  * @param {boolean} [options.partial=false] Specify if the cursor should return partial results when querying against a sharded system
308
313
  * @param {number} [options.maxTimeMS] Number of milliseconds to wait before aborting the query.
@@ -451,6 +456,8 @@ Collection.prototype.find = deprecateOptions(
451
456
  newOptions.promoteValues = this.s.promoteValues;
452
457
  if (newOptions.promoteBuffers == null && typeof this.s.promoteBuffers === 'boolean')
453
458
  newOptions.promoteBuffers = this.s.promoteBuffers;
459
+ if (newOptions.bsonRegExp == null && typeof this.s.bsonRegExp === 'boolean')
460
+ newOptions.bsonRegExp = this.s.bsonRegExp;
454
461
 
455
462
  // Sort options
456
463
  if (findCommand.sort) {
@@ -1075,6 +1082,7 @@ Collection.prototype.save = deprecate(function(doc, options, callback) {
1075
1082
  * @param {boolean} [options.promoteLongs=true] Promotes Long values to number if they fit inside the 53 bits resolution.
1076
1083
  * @param {boolean} [options.promoteValues=true] Promotes BSON values to native types where possible, set to false to only receive wrapper types.
1077
1084
  * @param {boolean} [options.promoteBuffers=false] Promotes Binary BSON values to native Node Buffers.
1085
+ * @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.
1078
1086
  * @param {(ReadPreference|string)} [options.readPreference] The preferred read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
1079
1087
  * @param {boolean} [options.partial=false] Specify if the cursor should return partial results when querying against a sharded system
1080
1088
  * @param {number} [options.maxTimeMS] Number of milliseconds to wait before aborting the query.
@@ -1899,6 +1907,7 @@ Collection.prototype.findAndRemove = deprecate(function(query, sort, options, ca
1899
1907
  * @param {boolean} [options.promoteLongs=true] Promotes Long values to number if they fit inside the 53 bits resolution.
1900
1908
  * @param {boolean} [options.promoteValues=true] Promotes BSON values to native types where possible, set to false to only receive wrapper types.
1901
1909
  * @param {boolean} [options.promoteBuffers=false] Promotes Binary BSON values to native Node Buffers.
1910
+ * @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.
1902
1911
  * @param {object} [options.collation] Specify collation settings for operation. See {@link https://docs.mongodb.com/manual/reference/command/aggregate|aggregation documentation}.
1903
1912
  * @param {string} [options.comment] Add a comment to an aggregation command
1904
1913
  * @param {string|object} [options.hint] Add an index selection hint to an aggregation command
@@ -0,0 +1,124 @@
1
+ 'use strict';
2
+ const Msg = require('./core/connection/msg').Msg;
3
+ const KillCursor = require('./core/connection/commands').KillCursor;
4
+ const GetMore = require('./core/connection/commands').GetMore;
5
+ const deepCopy = require('./utils').deepCopy;
6
+
7
+ /** Commands that we want to redact because of the sensitive nature of their contents */
8
+ const SENSITIVE_COMMANDS = new Set([
9
+ 'authenticate',
10
+ 'saslStart',
11
+ 'saslContinue',
12
+ 'getnonce',
13
+ 'createUser',
14
+ 'updateUser',
15
+ 'copydbgetnonce',
16
+ 'copydbsaslstart',
17
+ 'copydb'
18
+ ]);
19
+
20
+ const HELLO_COMMANDS = new Set(['hello', 'ismaster', 'isMaster']);
21
+
22
+ const LEGACY_FIND_QUERY_MAP = {
23
+ $query: 'filter',
24
+ $orderby: 'sort',
25
+ $hint: 'hint',
26
+ $comment: 'comment',
27
+ $maxScan: 'maxScan',
28
+ $max: 'max',
29
+ $min: 'min',
30
+ $returnKey: 'returnKey',
31
+ $showDiskLoc: 'showRecordId',
32
+ $maxTimeMS: 'maxTimeMS',
33
+ $snapshot: 'snapshot'
34
+ };
35
+
36
+ const LEGACY_FIND_OPTIONS_MAP = {
37
+ numberToSkip: 'skip',
38
+ numberToReturn: 'batchSize',
39
+ returnFieldsSelector: 'projection'
40
+ };
41
+
42
+ const OP_QUERY_KEYS = [
43
+ 'tailable',
44
+ 'oplogReplay',
45
+ 'noCursorTimeout',
46
+ 'awaitData',
47
+ 'partial',
48
+ 'exhaust'
49
+ ];
50
+
51
+ const collectionName = command => command.ns.split('.')[1];
52
+
53
+ const shouldRedactCommand = (commandName, cmd) =>
54
+ SENSITIVE_COMMANDS.has(commandName) ||
55
+ (HELLO_COMMANDS.has(commandName) && !!cmd.speculativeAuthenticate);
56
+
57
+ /**
58
+ * Extract the actual command from the query, possibly upconverting if it's a legacy
59
+ * format
60
+ *
61
+ * @param {Object} command the command
62
+ */
63
+ const extractCommand = command => {
64
+ let extractedCommand;
65
+ if (command instanceof GetMore) {
66
+ extractedCommand = {
67
+ getMore: deepCopy(command.cursorId),
68
+ collection: collectionName(command),
69
+ batchSize: command.numberToReturn
70
+ };
71
+ } else if (command instanceof KillCursor) {
72
+ extractedCommand = {
73
+ killCursors: collectionName(command),
74
+ cursors: deepCopy(command.cursorIds)
75
+ };
76
+ } else if (command instanceof Msg) {
77
+ extractedCommand = deepCopy(command.command);
78
+ } else if (command.query && command.query.$query) {
79
+ let result;
80
+ if (command.ns === 'admin.$cmd') {
81
+ // upconvert legacy command
82
+ result = Object.assign({}, command.query.$query);
83
+ } else {
84
+ // upconvert legacy find command
85
+ result = { find: collectionName(command) };
86
+ Object.keys(LEGACY_FIND_QUERY_MAP).forEach(key => {
87
+ if (typeof command.query[key] !== 'undefined')
88
+ result[LEGACY_FIND_QUERY_MAP[key]] = deepCopy(command.query[key]);
89
+ });
90
+ }
91
+
92
+ Object.keys(LEGACY_FIND_OPTIONS_MAP).forEach(key => {
93
+ if (typeof command[key] !== 'undefined')
94
+ result[LEGACY_FIND_OPTIONS_MAP[key]] = deepCopy(command[key]);
95
+ });
96
+
97
+ OP_QUERY_KEYS.forEach(key => {
98
+ if (command[key]) result[key] = command[key];
99
+ });
100
+
101
+ if (typeof command.pre32Limit !== 'undefined') {
102
+ result.limit = command.pre32Limit;
103
+ }
104
+
105
+ if (command.query.$explain) {
106
+ extractedCommand = { explain: result };
107
+ } else {
108
+ extractedCommand = result;
109
+ }
110
+ } else {
111
+ extractedCommand = deepCopy(command.query || command);
112
+ }
113
+
114
+ const commandName = Object.keys(extractedCommand)[0];
115
+ return {
116
+ cmd: extractedCommand,
117
+ name: commandName,
118
+ shouldRedact: shouldRedactCommand(commandName, extractedCommand)
119
+ };
120
+ };
121
+
122
+ module.exports = {
123
+ extractCommand
124
+ };
@@ -9,6 +9,7 @@ const url = require('url');
9
9
 
10
10
  let aws4;
11
11
  try {
12
+ // Ensure you always wrap an optional require in the try block NODE-3199
12
13
  aws4 = require('aws4');
13
14
  } catch (e) {
14
15
  // don't do anything;
@@ -11,6 +11,7 @@ const Binary = BSON.Binary;
11
11
 
12
12
  let saslprep;
13
13
  try {
14
+ // Ensure you always wrap an optional require in the try block NODE-3199
14
15
  saslprep = require('saslprep');
15
16
  } catch (e) {
16
17
  // don't do anything;
@@ -1,123 +1,16 @@
1
1
  'use strict';
2
- const Msg = require('../connection/msg').Msg;
3
2
  const KillCursor = require('../connection/commands').KillCursor;
4
3
  const GetMore = require('../connection/commands').GetMore;
5
4
  const calculateDurationInMs = require('../../utils').calculateDurationInMs;
6
-
7
- /** Commands that we want to redact because of the sensitive nature of their contents */
8
- const SENSITIVE_COMMANDS = new Set([
9
- 'authenticate',
10
- 'saslStart',
11
- 'saslContinue',
12
- 'getnonce',
13
- 'createUser',
14
- 'updateUser',
15
- 'copydbgetnonce',
16
- 'copydbsaslstart',
17
- 'copydb'
18
- ]);
5
+ const extractCommand = require('../../command_utils').extractCommand;
19
6
 
20
7
  // helper methods
21
- const extractCommandName = commandDoc => Object.keys(commandDoc)[0];
22
8
  const namespace = command => command.ns;
23
9
  const databaseName = command => command.ns.split('.')[0];
24
- const collectionName = command => command.ns.split('.')[1];
25
10
  const generateConnectionId = pool =>
26
11
  pool.options ? `${pool.options.host}:${pool.options.port}` : pool.address;
27
- const maybeRedact = (commandName, result) => (SENSITIVE_COMMANDS.has(commandName) ? {} : result);
28
12
  const isLegacyPool = pool => pool.s && pool.queue;
29
13
 
30
- const LEGACY_FIND_QUERY_MAP = {
31
- $query: 'filter',
32
- $orderby: 'sort',
33
- $hint: 'hint',
34
- $comment: 'comment',
35
- $maxScan: 'maxScan',
36
- $max: 'max',
37
- $min: 'min',
38
- $returnKey: 'returnKey',
39
- $showDiskLoc: 'showRecordId',
40
- $maxTimeMS: 'maxTimeMS',
41
- $snapshot: 'snapshot'
42
- };
43
-
44
- const LEGACY_FIND_OPTIONS_MAP = {
45
- numberToSkip: 'skip',
46
- numberToReturn: 'batchSize',
47
- returnFieldsSelector: 'projection'
48
- };
49
-
50
- const OP_QUERY_KEYS = [
51
- 'tailable',
52
- 'oplogReplay',
53
- 'noCursorTimeout',
54
- 'awaitData',
55
- 'partial',
56
- 'exhaust'
57
- ];
58
-
59
- /**
60
- * Extract the actual command from the query, possibly upconverting if it's a legacy
61
- * format
62
- *
63
- * @param {Object} command the command
64
- */
65
- const extractCommand = command => {
66
- if (command instanceof GetMore) {
67
- return {
68
- getMore: command.cursorId,
69
- collection: collectionName(command),
70
- batchSize: command.numberToReturn
71
- };
72
- }
73
-
74
- if (command instanceof KillCursor) {
75
- return {
76
- killCursors: collectionName(command),
77
- cursors: command.cursorIds
78
- };
79
- }
80
-
81
- if (command instanceof Msg) {
82
- return command.command;
83
- }
84
-
85
- if (command.query && command.query.$query) {
86
- let result;
87
- if (command.ns === 'admin.$cmd') {
88
- // upconvert legacy command
89
- result = Object.assign({}, command.query.$query);
90
- } else {
91
- // upconvert legacy find command
92
- result = { find: collectionName(command) };
93
- Object.keys(LEGACY_FIND_QUERY_MAP).forEach(key => {
94
- if (typeof command.query[key] !== 'undefined')
95
- result[LEGACY_FIND_QUERY_MAP[key]] = command.query[key];
96
- });
97
- }
98
-
99
- Object.keys(LEGACY_FIND_OPTIONS_MAP).forEach(key => {
100
- if (typeof command[key] !== 'undefined') result[LEGACY_FIND_OPTIONS_MAP[key]] = command[key];
101
- });
102
-
103
- OP_QUERY_KEYS.forEach(key => {
104
- if (command[key]) result[key] = command[key];
105
- });
106
-
107
- if (typeof command.pre32Limit !== 'undefined') {
108
- result.limit = command.pre32Limit;
109
- }
110
-
111
- if (command.query.$explain) {
112
- return { explain: result };
113
- }
114
-
115
- return result;
116
- }
117
-
118
- return command.query ? command.query : command;
119
- };
120
-
121
14
  const extractReply = (command, reply) => {
122
15
  if (command instanceof GetMore) {
123
16
  return {
@@ -177,21 +70,15 @@ class CommandStartedEvent {
177
70
  * @param {Object} command the command
178
71
  */
179
72
  constructor(pool, command) {
180
- const cmd = extractCommand(command);
181
- const commandName = extractCommandName(cmd);
73
+ const extractedCommand = extractCommand(command);
74
+ const commandName = extractedCommand.name;
182
75
  const connectionDetails = extractConnectionDetails(pool);
183
76
 
184
- // NOTE: remove in major revision, this is not spec behavior
185
- if (SENSITIVE_COMMANDS.has(commandName)) {
186
- this.commandObj = {};
187
- this.commandObj[commandName] = true;
188
- }
189
-
190
77
  Object.assign(this, connectionDetails, {
191
78
  requestId: command.requestId,
192
79
  databaseName: databaseName(command),
193
80
  commandName,
194
- command: cmd
81
+ command: extractedCommand.shouldRedact ? {} : extractedCommand.cmd
195
82
  });
196
83
  }
197
84
  }
@@ -207,15 +94,15 @@ class CommandSucceededEvent {
207
94
  * @param {Array} started a high resolution tuple timestamp of when the command was first sent, to calculate duration
208
95
  */
209
96
  constructor(pool, command, reply, started) {
210
- const cmd = extractCommand(command);
211
- const commandName = extractCommandName(cmd);
97
+ const extractedCommand = extractCommand(command);
98
+ const commandName = extractedCommand.name;
212
99
  const connectionDetails = extractConnectionDetails(pool);
213
100
 
214
101
  Object.assign(this, connectionDetails, {
215
102
  requestId: command.requestId,
216
103
  commandName,
217
104
  duration: calculateDurationInMs(started),
218
- reply: maybeRedact(commandName, extractReply(command, reply))
105
+ reply: extractedCommand.shouldRedact ? {} : extractReply(command, reply)
219
106
  });
220
107
  }
221
108
  }
@@ -231,15 +118,15 @@ class CommandFailedEvent {
231
118
  * @param {Array} started a high resolution tuple timestamp of when the command was first sent, to calculate duration
232
119
  */
233
120
  constructor(pool, command, error, started) {
234
- const cmd = extractCommand(command);
235
- const commandName = extractCommandName(cmd);
121
+ const extractedCommand = extractCommand(command);
122
+ const commandName = extractedCommand.name;
236
123
  const connectionDetails = extractConnectionDetails(pool);
237
124
 
238
125
  Object.assign(this, connectionDetails, {
239
126
  requestId: command.requestId,
240
127
  commandName,
241
128
  duration: calculateDurationInMs(started),
242
- failure: maybeRedact(commandName, error)
129
+ failure: extractedCommand.shouldRedact ? {} : error
243
130
  });
244
131
  }
245
132
  }
@@ -398,7 +398,12 @@ KillCursor.prototype.toBin = function() {
398
398
  };
399
399
 
400
400
  var Response = function(bson, message, msgHeader, msgBody, opts) {
401
- opts = opts || { promoteLongs: true, promoteValues: true, promoteBuffers: false };
401
+ opts = opts || {
402
+ promoteLongs: true,
403
+ promoteValues: true,
404
+ promoteBuffers: false,
405
+ bsonRegExp: false
406
+ };
402
407
  this.parsed = false;
403
408
  this.raw = message;
404
409
  this.data = msgBody;
@@ -429,6 +434,7 @@ var Response = function(bson, message, msgHeader, msgBody, opts) {
429
434
  this.promoteLongs = typeof opts.promoteLongs === 'boolean' ? opts.promoteLongs : true;
430
435
  this.promoteValues = typeof opts.promoteValues === 'boolean' ? opts.promoteValues : true;
431
436
  this.promoteBuffers = typeof opts.promoteBuffers === 'boolean' ? opts.promoteBuffers : false;
437
+ this.bsonRegExp = typeof opts.bsonRegExp === 'boolean' ? opts.bsonRegExp : false;
432
438
  };
433
439
 
434
440
  Response.prototype.isParsed = function() {
@@ -449,13 +455,16 @@ Response.prototype.parse = function(options) {
449
455
  typeof options.promoteValues === 'boolean' ? options.promoteValues : this.opts.promoteValues;
450
456
  var promoteBuffers =
451
457
  typeof options.promoteBuffers === 'boolean' ? options.promoteBuffers : this.opts.promoteBuffers;
458
+ var bsonRegExp =
459
+ typeof options.bsonRegExp === 'boolean' ? options.bsonRegExp : this.opts.bsonRegExp;
452
460
  var bsonSize, _options;
453
461
 
454
462
  // Set up the options
455
463
  _options = {
456
464
  promoteLongs: promoteLongs,
457
465
  promoteValues: promoteValues,
458
- promoteBuffers: promoteBuffers
466
+ promoteBuffers: promoteBuffers,
467
+ bsonRegExp: bsonRegExp
459
468
  };
460
469
 
461
470
  // Position within OP_REPLY at which documents start
@@ -179,6 +179,9 @@ function prepareHandshakeDocument(authContext, callback) {
179
179
  }
180
180
 
181
181
  const authProvider = AUTH_PROVIDERS[credentials.mechanism];
182
+ if (authProvider == null) {
183
+ return callback(new MongoError(`No AuthProvider for ${credentials.mechanism} defined.`));
184
+ }
182
185
  authProvider.prepare(handshakeDoc, authContext, callback);
183
186
  return;
184
187
  }
@@ -38,6 +38,7 @@ const DEBUG_FIELDS = [
38
38
  'promoteLongs',
39
39
  'promoteValues',
40
40
  'promoteBuffers',
41
+ 'bsonRegExp',
41
42
  'checkServerIdentity'
42
43
  ];
43
44
 
@@ -73,6 +74,7 @@ class Connection extends EventEmitter {
73
74
  * @param {boolean} [options.promoteLongs] Convert Long values from the db into Numbers if they fit into 53 bits
74
75
  * @param {boolean} [options.promoteValues] Promotes BSON values to native types where possible, set to false to only receive wrapper types.
75
76
  * @param {boolean} [options.promoteBuffers] Promotes Binary BSON values to native Node Buffers.
77
+ * @param {boolean} [options.bsonRegExp] By default, regex returned from MDB will be native to the language. Setting to true will ensure that a BSON.BSONRegExp object is returned.
76
78
  * @param {number} [options.maxBsonMessageSize=0x4000000] Largest possible size of a BSON message (for legacy purposes)
77
79
  */
78
80
  constructor(socket, options) {
@@ -117,7 +119,8 @@ class Connection extends EventEmitter {
117
119
  this.responseOptions = {
118
120
  promoteLongs: typeof options.promoteLongs === 'boolean' ? options.promoteLongs : true,
119
121
  promoteValues: typeof options.promoteValues === 'boolean' ? options.promoteValues : true,
120
- promoteBuffers: typeof options.promoteBuffers === 'boolean' ? options.promoteBuffers : false
122
+ promoteBuffers: typeof options.promoteBuffers === 'boolean' ? options.promoteBuffers : false,
123
+ bsonRegExp: typeof options.bsonRegExp === 'boolean' ? options.bsonRegExp : false
121
124
  };
122
125
 
123
126
  // Flushing
@@ -254,10 +257,10 @@ class Connection extends EventEmitter {
254
257
  // Debug Log
255
258
  if (this.logger.isDebug()) {
256
259
  if (!Array.isArray(buffer)) {
257
- this.logger.debug(`writing buffer [${buffer.toString('hex')}] to ${this.address}`);
260
+ this.logger.debug(`writing buffer [ ${buffer.length} ] to ${this.address}`);
258
261
  } else {
259
262
  for (let i = 0; i < buffer.length; i++)
260
- this.logger.debug(`writing buffer [${buffer[i].toString('hex')}] to ${this.address}`);
263
+ this.logger.debug(`writing buffer [ ${buffer[i].length} ] to ${this.address}`);
261
264
  }
262
265
  }
263
266