mongodb 3.6.4 → 3.6.5
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.
- package/HISTORY.md +10 -0
- package/README.md +63 -67
- package/lib/collection.js +3 -2
- package/lib/core/auth/scram.js +2 -1
- package/lib/core/connection/logger.js +1 -0
- package/lib/core/connection/msg.js +3 -1
- package/lib/core/sdam/topology.js +2 -1
- package/lib/core/sdam/topology_description.js +24 -6
- package/lib/core/tools/smoke_plugin.js +1 -0
- package/lib/core/topologies/read_preference.js +2 -1
- package/lib/core/uri_parser.js +2 -1
- package/lib/core/wireprotocol/kill_cursors.js +2 -1
- package/lib/db.js +9 -3
- package/lib/mongo_client.js +0 -4
- package/lib/operations/add_user.js +2 -1
- package/lib/operations/connect.js +6 -6
- package/lib/operations/execute_operation.js +47 -69
- package/lib/operations/operation.js +1 -1
- package/lib/utils.js +76 -25
- package/lib/write_concern.js +5 -1
- package/package.json +1 -1
package/HISTORY.md
CHANGED
|
@@ -2,6 +2,16 @@
|
|
|
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.5](https://github.com/mongodb/node-mongodb-native/compare/v3.6.4...v3.6.5) (2021-03-16)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
* MongoError circular dependency warning ([#2734](https://github.com/mongodb/node-mongodb-native/issues/2734)) ([d67ffa7](https://github.com/mongodb/node-mongodb-native/commit/d67ffa7a2e3f86734c7e9b6944aab1d765b9e75e))
|
|
11
|
+
* move session support check to operation layer ([#2739](https://github.com/mongodb/node-mongodb-native/issues/2739)) ([8b370a7](https://github.com/mongodb/node-mongodb-native/commit/8b370a7ad784f5759c964cdfaec62e06c896dc95))
|
|
12
|
+
* session support detection spec compliance ([#2732](https://github.com/mongodb/node-mongodb-native/issues/2732)) ([9baec71](https://github.com/mongodb/node-mongodb-native/commit/9baec7128f612f2d9c290c85d24e33602f911499))
|
|
13
|
+
* use emitWarning API for internal messages ([#2743](https://github.com/mongodb/node-mongodb-native/issues/2743)) ([8bd9777](https://github.com/mongodb/node-mongodb-native/commit/8bd9777b0aedd56b81675c3e79fae63432319982))
|
|
14
|
+
|
|
5
15
|
### [3.6.4](https://github.com/mongodb/node-mongodb-native/compare/v3.6.3...v3.6.4) (2021-02-02)
|
|
6
16
|
|
|
7
17
|
|
package/README.md
CHANGED
|
@@ -1,21 +1,24 @@
|
|
|
1
|
-
|
|
1
|
+
# MongoDB NodeJS Driver
|
|
2
2
|
|
|
3
|
-
[](https://nodei.co/npm/mongodb/)
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
The official [MongoDB](https://www.mongodb.com/) driver for Node.js.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
**NOTE: v3.x released with breaking API changes. You can find a list of changes [here](CHANGES_3.0.0.md).**
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
## Version 4.0
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
**Looking for the latest?** We're working on the next major version of the driver, now in beta.
|
|
12
|
+
Check out our [beta version 4.0 here](https://github.com/mongodb/node-mongodb-native/tree/4.0), which includes a full migration of the driver to TypeScript.
|
|
12
13
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
|
16
|
-
|
|
|
17
|
-
|
|
|
18
|
-
|
|
|
14
|
+
## Quick Links
|
|
15
|
+
|
|
16
|
+
| what | where |
|
|
17
|
+
| ------------- | ---------------------------------------------------- |
|
|
18
|
+
| documentation | http://mongodb.github.io/node-mongodb-native |
|
|
19
|
+
| api-doc | http://mongodb.github.io/node-mongodb-native/3.6/api |
|
|
20
|
+
| source | https://github.com/mongodb/node-mongodb-native |
|
|
21
|
+
| mongodb | http://www.mongodb.org |
|
|
19
22
|
|
|
20
23
|
### Bugs / Feature Requests
|
|
21
24
|
|
|
@@ -41,12 +44,12 @@ Change history can be found in [`HISTORY.md`](HISTORY.md).
|
|
|
41
44
|
|
|
42
45
|
For version compatibility matrices, please refer to the following links:
|
|
43
46
|
|
|
44
|
-
|
|
45
|
-
|
|
47
|
+
- [MongoDB](https://docs.mongodb.com/ecosystem/drivers/driver-compatibility-reference/#reference-compatibility-mongodb-node)
|
|
48
|
+
- [NodeJS](https://docs.mongodb.com/ecosystem/drivers/driver-compatibility-reference/#reference-compatibility-language-node)
|
|
46
49
|
|
|
47
|
-
|
|
50
|
+
## Installation
|
|
48
51
|
|
|
49
|
-
The recommended way to get started using the Node.js
|
|
52
|
+
The recommended way to get started using the Node.js driver is by using `npm` (Node Package Manager) to install the dependency in your project.
|
|
50
53
|
|
|
51
54
|
## MongoDB Driver
|
|
52
55
|
|
|
@@ -64,10 +67,10 @@ You can also use the [Yarn](https://yarnpkg.com/en) package manager.
|
|
|
64
67
|
|
|
65
68
|
The MongoDB driver depends on several other packages. These are:
|
|
66
69
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
70
|
+
- [bson](https://github.com/mongodb/js-bson)
|
|
71
|
+
- [bson-ext](https://github.com/mongodb-js/bson-ext)
|
|
72
|
+
- [kerberos](https://github.com/mongodb-js/kerberos)
|
|
73
|
+
- [mongodb-client-encryption](https://github.com/mongodb/libmongocrypt#readme)
|
|
71
74
|
|
|
72
75
|
The `kerberos` package is a C++ extension that requires a build environment to be installed on your system. You must be able to build Node.js itself in order to compile and install the `kerberos` module. Furthermore, the `kerberos` module requires the MIT Kerberos package to correctly compile on UNIX operating systems. Consult your UNIX operation system package manager for what libraries to install.
|
|
73
76
|
|
|
@@ -108,9 +111,9 @@ This will print out all the steps npm is performing while trying to install the
|
|
|
108
111
|
|
|
109
112
|
A compiler tool chain known to work for compiling `kerberos` on Windows is the following.
|
|
110
113
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
+
- Visual Studio C++ 2010 (do not use higher versions)
|
|
115
|
+
- Windows 7 64bit SDK
|
|
116
|
+
- Python 2.7 or higher
|
|
114
117
|
|
|
115
118
|
Open the Visual Studio command prompt. Ensure `node.exe` is in your path and install `node-gyp`.
|
|
116
119
|
|
|
@@ -168,7 +171,7 @@ For complete MongoDB installation instructions, see [the manual](https://docs.mo
|
|
|
168
171
|
|
|
169
172
|
1. Download the right MongoDB version from [MongoDB](https://www.mongodb.org/downloads)
|
|
170
173
|
2. Create a database directory (in this case under **/data**).
|
|
171
|
-
3. Install and start a
|
|
174
|
+
3. Install and start a `mongod` process.
|
|
172
175
|
|
|
173
176
|
```bash
|
|
174
177
|
mongod --dbpath=/data
|
|
@@ -192,11 +195,11 @@ const url = 'mongodb://localhost:27017';
|
|
|
192
195
|
|
|
193
196
|
// Database Name
|
|
194
197
|
const dbName = 'myproject';
|
|
195
|
-
|
|
198
|
+
const client = new MongoClient(url);
|
|
196
199
|
// Use connect method to connect to the server
|
|
197
|
-
|
|
200
|
+
client.connect(function(err) {
|
|
198
201
|
assert.equal(null, err);
|
|
199
|
-
console.log(
|
|
202
|
+
console.log('Connected successfully to server');
|
|
200
203
|
|
|
201
204
|
const db = client.db(dbName);
|
|
202
205
|
|
|
@@ -222,23 +225,21 @@ const insertDocuments = function(db, callback) {
|
|
|
222
225
|
// Get the documents collection
|
|
223
226
|
const collection = db.collection('documents');
|
|
224
227
|
// Insert some documents
|
|
225
|
-
collection.insertMany([
|
|
226
|
-
{a : 1}, {a : 2}, {a : 3}
|
|
227
|
-
], function(err, result) {
|
|
228
|
+
collection.insertMany([{ a: 1 }, { a: 2 }, { a: 3 }], function(err, result) {
|
|
228
229
|
assert.equal(err, null);
|
|
229
230
|
assert.equal(3, result.result.n);
|
|
230
231
|
assert.equal(3, result.ops.length);
|
|
231
|
-
console.log(
|
|
232
|
+
console.log('Inserted 3 documents into the collection');
|
|
232
233
|
callback(result);
|
|
233
234
|
});
|
|
234
|
-
}
|
|
235
|
+
};
|
|
235
236
|
```
|
|
236
237
|
|
|
237
238
|
The **insert** command returns an object with the following fields:
|
|
238
239
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
240
|
+
- **result** Contains the result document from MongoDB
|
|
241
|
+
- **ops** Contains the documents inserted with added **\_id** fields
|
|
242
|
+
- **connection** Contains the connection used to perform the insert
|
|
242
243
|
|
|
243
244
|
Add the following code to call the **insertDocuments** function:
|
|
244
245
|
|
|
@@ -255,7 +256,7 @@ const dbName = 'myproject';
|
|
|
255
256
|
// Use connect method to connect to the server
|
|
256
257
|
MongoClient.connect(url, function(err, client) {
|
|
257
258
|
assert.equal(null, err);
|
|
258
|
-
console.log(
|
|
259
|
+
console.log('Connected successfully to server');
|
|
259
260
|
|
|
260
261
|
const db = client.db(dbName);
|
|
261
262
|
|
|
@@ -289,11 +290,11 @@ const findDocuments = function(db, callback) {
|
|
|
289
290
|
// Find some documents
|
|
290
291
|
collection.find({}).toArray(function(err, docs) {
|
|
291
292
|
assert.equal(err, null);
|
|
292
|
-
console.log(
|
|
293
|
-
console.log(docs)
|
|
293
|
+
console.log('Found the following records');
|
|
294
|
+
console.log(docs);
|
|
294
295
|
callback(docs);
|
|
295
296
|
});
|
|
296
|
-
}
|
|
297
|
+
};
|
|
297
298
|
```
|
|
298
299
|
|
|
299
300
|
This query returns all the documents in the **documents** collection. Add the **findDocument** method to the **MongoClient.connect** callback:
|
|
@@ -311,7 +312,7 @@ const dbName = 'myproject';
|
|
|
311
312
|
// Use connect method to connect to the server
|
|
312
313
|
MongoClient.connect(url, function(err, client) {
|
|
313
314
|
assert.equal(null, err);
|
|
314
|
-
console.log(
|
|
315
|
+
console.log('Connected correctly to server');
|
|
315
316
|
|
|
316
317
|
const db = client.db(dbName);
|
|
317
318
|
|
|
@@ -332,16 +333,16 @@ const findDocuments = function(db, callback) {
|
|
|
332
333
|
// Get the documents collection
|
|
333
334
|
const collection = db.collection('documents');
|
|
334
335
|
// Find some documents
|
|
335
|
-
collection.find({
|
|
336
|
+
collection.find({ a: 3 }).toArray(function(err, docs) {
|
|
336
337
|
assert.equal(err, null);
|
|
337
|
-
console.log(
|
|
338
|
+
console.log('Found the following records');
|
|
338
339
|
console.log(docs);
|
|
339
340
|
callback(docs);
|
|
340
341
|
});
|
|
341
|
-
}
|
|
342
|
+
};
|
|
342
343
|
```
|
|
343
344
|
|
|
344
|
-
Only the documents which match
|
|
345
|
+
Only the documents which match `'a' : 3` should be returned.
|
|
345
346
|
|
|
346
347
|
### Update a document
|
|
347
348
|
|
|
@@ -352,14 +353,13 @@ const updateDocument = function(db, callback) {
|
|
|
352
353
|
// Get the documents collection
|
|
353
354
|
const collection = db.collection('documents');
|
|
354
355
|
// Update document where a is 2, set b equal to 1
|
|
355
|
-
collection.updateOne({ a
|
|
356
|
-
, { $set: { b : 1 } }, function(err, result) {
|
|
356
|
+
collection.updateOne({ a: 2 }, { $set: { b: 1 } }, function(err, result) {
|
|
357
357
|
assert.equal(err, null);
|
|
358
358
|
assert.equal(1, result.result.n);
|
|
359
|
-
console.log(
|
|
359
|
+
console.log('Updated the document with the field a equal to 2');
|
|
360
360
|
callback(result);
|
|
361
361
|
});
|
|
362
|
-
}
|
|
362
|
+
};
|
|
363
363
|
```
|
|
364
364
|
|
|
365
365
|
The method updates the first document where the field **a** is equal to **2** by adding a new field **b** to the document set to **1**. Next, update the callback function from **MongoClient.connect** to include the update method.
|
|
@@ -377,7 +377,7 @@ const dbName = 'myproject';
|
|
|
377
377
|
// Use connect method to connect to the server
|
|
378
378
|
MongoClient.connect(url, function(err, client) {
|
|
379
379
|
assert.equal(null, err);
|
|
380
|
-
console.log(
|
|
380
|
+
console.log('Connected successfully to server');
|
|
381
381
|
|
|
382
382
|
const db = client.db(dbName);
|
|
383
383
|
|
|
@@ -398,13 +398,13 @@ const removeDocument = function(db, callback) {
|
|
|
398
398
|
// Get the documents collection
|
|
399
399
|
const collection = db.collection('documents');
|
|
400
400
|
// Delete document where a is 3
|
|
401
|
-
collection.deleteOne({ a
|
|
401
|
+
collection.deleteOne({ a: 3 }, function(err, result) {
|
|
402
402
|
assert.equal(err, null);
|
|
403
403
|
assert.equal(1, result.result.n);
|
|
404
|
-
console.log(
|
|
404
|
+
console.log('Removed the document with the field a equal to 3');
|
|
405
405
|
callback(result);
|
|
406
406
|
});
|
|
407
|
-
}
|
|
407
|
+
};
|
|
408
408
|
```
|
|
409
409
|
|
|
410
410
|
Add the new method to the **MongoClient.connect** callback function.
|
|
@@ -422,7 +422,7 @@ const dbName = 'myproject';
|
|
|
422
422
|
// Use connect method to connect to the server
|
|
423
423
|
MongoClient.connect(url, function(err, client) {
|
|
424
424
|
assert.equal(null, err);
|
|
425
|
-
console.log(
|
|
425
|
+
console.log('Connected successfully to server');
|
|
426
426
|
|
|
427
427
|
const db = client.db(dbName);
|
|
428
428
|
|
|
@@ -444,18 +444,14 @@ performance. The following function creates an index on the **a** field in the
|
|
|
444
444
|
|
|
445
445
|
```js
|
|
446
446
|
const indexCollection = function(db, callback) {
|
|
447
|
-
db.collection('documents').createIndex(
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
console.log(results);
|
|
452
|
-
callback();
|
|
453
|
-
}
|
|
454
|
-
);
|
|
447
|
+
db.collection('documents').createIndex({ a: 1 }, null, function(err, results) {
|
|
448
|
+
console.log(results);
|
|
449
|
+
callback();
|
|
450
|
+
});
|
|
455
451
|
};
|
|
456
452
|
```
|
|
457
453
|
|
|
458
|
-
Add the
|
|
454
|
+
Add the `indexCollection` method to your app:
|
|
459
455
|
|
|
460
456
|
```js
|
|
461
457
|
const MongoClient = require('mongodb').MongoClient;
|
|
@@ -469,7 +465,7 @@ const dbName = 'myproject';
|
|
|
469
465
|
// Use connect method to connect to the server
|
|
470
466
|
MongoClient.connect(url, function(err, client) {
|
|
471
467
|
assert.equal(null, err);
|
|
472
|
-
console.log(
|
|
468
|
+
console.log('Connected successfully to server');
|
|
473
469
|
|
|
474
470
|
const db = client.db(dbName);
|
|
475
471
|
|
|
@@ -485,13 +481,13 @@ For more detailed information, see the [tutorials](docs/reference/content/tutori
|
|
|
485
481
|
|
|
486
482
|
## Next Steps
|
|
487
483
|
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
484
|
+
- [MongoDB Documentation](http://mongodb.org)
|
|
485
|
+
- [Read about Schemas](http://learnmongodbthehardway.com)
|
|
486
|
+
- [Star us on GitHub](https://github.com/mongodb/node-mongodb-native)
|
|
491
487
|
|
|
492
488
|
## License
|
|
493
489
|
|
|
494
490
|
[Apache 2.0](LICENSE.md)
|
|
495
491
|
|
|
496
|
-
© 2009-2012 Christian Amor Kvalheim
|
|
492
|
+
© 2009-2012 Christian Amor Kvalheim
|
|
497
493
|
© 2012-present MongoDB [Contributors](CONTRIBUTORS.md)
|
package/lib/collection.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const deprecate = require('util').deprecate;
|
|
4
4
|
const deprecateOptions = require('./utils').deprecateOptions;
|
|
5
|
+
const emitWarningOnce = require('./utils').emitWarningOnce;
|
|
5
6
|
const checkCollectionName = require('./utils').checkCollectionName;
|
|
6
7
|
const ObjectID = require('./core').BSON.ObjectID;
|
|
7
8
|
const MongoError = require('./core').MongoError;
|
|
@@ -323,7 +324,7 @@ Collection.prototype.find = deprecateOptions(
|
|
|
323
324
|
function(query, options, callback) {
|
|
324
325
|
if (typeof callback === 'object') {
|
|
325
326
|
// TODO(MAJOR): throw in the future
|
|
326
|
-
|
|
327
|
+
emitWarningOnce('Third parameter to `find()` must be a callback or undefined');
|
|
327
328
|
}
|
|
328
329
|
|
|
329
330
|
let selector = query;
|
|
@@ -1092,7 +1093,7 @@ Collection.prototype.findOne = deprecateOptions(
|
|
|
1092
1093
|
function(query, options, callback) {
|
|
1093
1094
|
if (typeof callback === 'object') {
|
|
1094
1095
|
// TODO(MAJOR): throw in the future
|
|
1095
|
-
|
|
1096
|
+
emitWarningOnce('Third parameter to `findOne()` must be a callback or undefined');
|
|
1096
1097
|
}
|
|
1097
1098
|
|
|
1098
1099
|
if (typeof query === 'function') (callback = query), (query = {}), (options = {});
|
package/lib/core/auth/scram.js
CHANGED
|
@@ -4,6 +4,7 @@ const Buffer = require('safe-buffer').Buffer;
|
|
|
4
4
|
const retrieveBSON = require('../connection/utils').retrieveBSON;
|
|
5
5
|
const MongoError = require('../error').MongoError;
|
|
6
6
|
const AuthProvider = require('./auth_provider').AuthProvider;
|
|
7
|
+
const emitWarningOnce = require('../../utils').emitWarning;
|
|
7
8
|
|
|
8
9
|
const BSON = retrieveBSON();
|
|
9
10
|
const Binary = BSON.Binary;
|
|
@@ -24,7 +25,7 @@ class ScramSHA extends AuthProvider {
|
|
|
24
25
|
prepare(handshakeDoc, authContext, callback) {
|
|
25
26
|
const cryptoMethod = this.cryptoMethod;
|
|
26
27
|
if (cryptoMethod === 'sha256' && saslprep == null) {
|
|
27
|
-
|
|
28
|
+
emitWarningOnce('Warning: no saslprep library specified. Passwords will not be sanitized');
|
|
28
29
|
}
|
|
29
30
|
|
|
30
31
|
crypto.randomBytes(24, (err, nonce) => {
|
|
@@ -31,6 +31,7 @@ const Buffer = require('safe-buffer').Buffer;
|
|
|
31
31
|
const opcodes = require('../wireprotocol/shared').opcodes;
|
|
32
32
|
const databaseNamespace = require('../wireprotocol/shared').databaseNamespace;
|
|
33
33
|
const ReadPreference = require('../topologies/read_preference');
|
|
34
|
+
const MongoError = require('../../core/error').MongoError;
|
|
34
35
|
|
|
35
36
|
// Incrementing request id
|
|
36
37
|
let _requestId = 0;
|
|
@@ -196,7 +197,8 @@ class BinMsg {
|
|
|
196
197
|
while (this.index < this.data.length) {
|
|
197
198
|
const payloadType = this.data.readUInt8(this.index++);
|
|
198
199
|
if (payloadType === 1) {
|
|
199
|
-
|
|
200
|
+
// It was decided that no driver makes use of payload type 1
|
|
201
|
+
throw new MongoError('OP_MSG Payload Type 1 detected unsupported protocol');
|
|
200
202
|
} else if (payloadType === 0) {
|
|
201
203
|
const bsonSize = this.data.readUInt32LE(this.index);
|
|
202
204
|
const bin = this.data.slice(this.index, this.index + bsonSize);
|
|
@@ -27,6 +27,7 @@ const ServerSessionPool = require('../sessions').ServerSessionPool;
|
|
|
27
27
|
const makeClientMetadata = require('../utils').makeClientMetadata;
|
|
28
28
|
const CMAP_EVENT_NAMES = require('../../cmap/events').CMAP_EVENT_NAMES;
|
|
29
29
|
const compareTopologyVersion = require('./server_description').compareTopologyVersion;
|
|
30
|
+
const emitWarning = require('../../utils').emitWarning;
|
|
30
31
|
|
|
31
32
|
const common = require('./common');
|
|
32
33
|
const drainTimerQueue = common.drainTimerQueue;
|
|
@@ -739,7 +740,7 @@ class Topology extends EventEmitter {
|
|
|
739
740
|
}
|
|
740
741
|
|
|
741
742
|
unref() {
|
|
742
|
-
|
|
743
|
+
emitWarning('not implemented: `unref`');
|
|
743
744
|
}
|
|
744
745
|
|
|
745
746
|
// NOTE: There are many places in code where we explicitly check the last isMaster
|
|
@@ -72,12 +72,30 @@ class TopologyDescription {
|
|
|
72
72
|
// value among ServerDescriptions of all data-bearing server types. If any have a null
|
|
73
73
|
// logicalSessionTimeoutMinutes, then TopologyDescription.logicalSessionTimeoutMinutes MUST be
|
|
74
74
|
// set to null.
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
if (
|
|
79
|
-
|
|
80
|
-
|
|
75
|
+
this.logicalSessionTimeoutMinutes = null;
|
|
76
|
+
for (const addressServerTuple of this.servers) {
|
|
77
|
+
const server = addressServerTuple[1];
|
|
78
|
+
if (server.isReadable) {
|
|
79
|
+
if (server.logicalSessionTimeoutMinutes == null) {
|
|
80
|
+
// If any of the servers have a null logicalSessionsTimeout, then the whole topology does
|
|
81
|
+
this.logicalSessionTimeoutMinutes = null;
|
|
82
|
+
break;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (this.logicalSessionTimeoutMinutes == null) {
|
|
86
|
+
// First server with a non null logicalSessionsTimeout
|
|
87
|
+
this.logicalSessionTimeoutMinutes = server.logicalSessionTimeoutMinutes;
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Always select the smaller of the:
|
|
92
|
+
// current server logicalSessionsTimeout and the topologies logicalSessionsTimeout
|
|
93
|
+
this.logicalSessionTimeoutMinutes = Math.min(
|
|
94
|
+
this.logicalSessionTimeoutMinutes,
|
|
95
|
+
server.logicalSessionTimeoutMinutes
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
81
99
|
}
|
|
82
100
|
|
|
83
101
|
/**
|
|
@@ -52,6 +52,7 @@ exports.attachToRunner = function(runner, outputFile) {
|
|
|
52
52
|
fs.writeFileSync(outputFile, JSON.stringify(smokeOutput));
|
|
53
53
|
|
|
54
54
|
// Standard NodeJS uncaught exception handler
|
|
55
|
+
// eslint-disable-next-line no-console
|
|
55
56
|
console.error(err.stack);
|
|
56
57
|
process.exit(1);
|
|
57
58
|
});
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
'use strict';
|
|
2
|
+
const emitWarningOnce = require('../../utils').emitWarningOnce;
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* The **ReadPreference** class is a class that represents a MongoDB ReadPreference and is
|
|
@@ -20,7 +21,7 @@ const ReadPreference = function(mode, tags, options) {
|
|
|
20
21
|
|
|
21
22
|
// TODO(major): tags MUST be an array of tagsets
|
|
22
23
|
if (tags && !Array.isArray(tags)) {
|
|
23
|
-
|
|
24
|
+
emitWarningOnce(
|
|
24
25
|
'ReadPreference tags must be an array, this will change in the next major version'
|
|
25
26
|
);
|
|
26
27
|
|
package/lib/core/uri_parser.js
CHANGED
|
@@ -4,6 +4,7 @@ const qs = require('querystring');
|
|
|
4
4
|
const dns = require('dns');
|
|
5
5
|
const MongoParseError = require('./error').MongoParseError;
|
|
6
6
|
const ReadPreference = require('./topologies/read_preference');
|
|
7
|
+
const emitWarningOnce = require('../utils').emitWarningOnce;
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
10
|
* The following regular expression validates a connection string and breaks the
|
|
@@ -438,7 +439,7 @@ function parseQueryString(query, options) {
|
|
|
438
439
|
// special cases for known deprecated options
|
|
439
440
|
if (result.wtimeout && result.wtimeoutms) {
|
|
440
441
|
delete result.wtimeout;
|
|
441
|
-
|
|
442
|
+
emitWarningOnce('Unsupported option `wtimeout` specified');
|
|
442
443
|
}
|
|
443
444
|
|
|
444
445
|
return Object.keys(result).length ? result : null;
|
|
@@ -5,6 +5,7 @@ const MongoError = require('../error').MongoError;
|
|
|
5
5
|
const MongoNetworkError = require('../error').MongoNetworkError;
|
|
6
6
|
const collectionNamespace = require('./shared').collectionNamespace;
|
|
7
7
|
const maxWireVersion = require('../utils').maxWireVersion;
|
|
8
|
+
const emitWarning = require('../utils').emitWarning;
|
|
8
9
|
const command = require('./command');
|
|
9
10
|
|
|
10
11
|
function killCursors(server, ns, cursorState, callback) {
|
|
@@ -31,7 +32,7 @@ function killCursors(server, ns, cursorState, callback) {
|
|
|
31
32
|
if (typeof callback === 'function') {
|
|
32
33
|
callback(err, null);
|
|
33
34
|
} else {
|
|
34
|
-
|
|
35
|
+
emitWarning(err);
|
|
35
36
|
}
|
|
36
37
|
}
|
|
37
38
|
}
|
package/lib/db.js
CHANGED
|
@@ -12,7 +12,7 @@ const MongoError = require('./core').MongoError;
|
|
|
12
12
|
const ObjectID = require('./core').ObjectID;
|
|
13
13
|
const Logger = require('./core').Logger;
|
|
14
14
|
const Collection = require('./collection');
|
|
15
|
-
const
|
|
15
|
+
const conditionallyMergeWriteConcern = require('./utils').conditionallyMergeWriteConcern;
|
|
16
16
|
const executeLegacyOperation = require('./utils').executeLegacyOperation;
|
|
17
17
|
const ChangeStream = require('./change_stream');
|
|
18
18
|
const deprecate = require('util').deprecate;
|
|
@@ -382,7 +382,7 @@ Db.prototype.admin = function() {
|
|
|
382
382
|
* @param {AggregationCursor} cursor The cursor if the aggregation command was executed successfully.
|
|
383
383
|
*/
|
|
384
384
|
|
|
385
|
-
const
|
|
385
|
+
const COLLECTION_OPTION_KEYS = [
|
|
386
386
|
'pkFactory',
|
|
387
387
|
'readPreference',
|
|
388
388
|
'serializeFunctions',
|
|
@@ -433,8 +433,14 @@ Db.prototype.collection = function(name, options, callback) {
|
|
|
433
433
|
options.ignoreUndefined = this.s.options.ignoreUndefined;
|
|
434
434
|
}
|
|
435
435
|
|
|
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];
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
|
|
436
442
|
// Merge in all needed options and ensure correct writeConcern merging from db level
|
|
437
|
-
options =
|
|
443
|
+
options = conditionallyMergeWriteConcern(options, this.s.options);
|
|
438
444
|
|
|
439
445
|
// Execute
|
|
440
446
|
if (options == null || !options.strict) {
|
package/lib/mongo_client.js
CHANGED
|
@@ -457,10 +457,6 @@ MongoClient.prototype.startSession = function(options) {
|
|
|
457
457
|
throw new MongoError('Must connect to a server before calling this method');
|
|
458
458
|
}
|
|
459
459
|
|
|
460
|
-
if (!this.topology.hasSessionSupport()) {
|
|
461
|
-
throw new MongoError('Current topology does not support sessions');
|
|
462
|
-
}
|
|
463
|
-
|
|
464
460
|
return this.topology.startSession(options, this.s.options);
|
|
465
461
|
};
|
|
466
462
|
|
|
@@ -6,6 +6,7 @@ const defineAspects = require('./operation').defineAspects;
|
|
|
6
6
|
const crypto = require('crypto');
|
|
7
7
|
const handleCallback = require('../utils').handleCallback;
|
|
8
8
|
const toError = require('../utils').toError;
|
|
9
|
+
const emitWarning = require('../utils').emitWarning;
|
|
9
10
|
|
|
10
11
|
class AddUserOperation extends CommandOperation {
|
|
11
12
|
constructor(db, username, password, options) {
|
|
@@ -29,7 +30,7 @@ class AddUserOperation extends CommandOperation {
|
|
|
29
30
|
// If not roles defined print deprecated message
|
|
30
31
|
// TODO: handle deprecation properly
|
|
31
32
|
if (roles.length === 0) {
|
|
32
|
-
|
|
33
|
+
emitWarning('Creating a user without roles is deprecated in MongoDB >= 2.6');
|
|
33
34
|
}
|
|
34
35
|
|
|
35
36
|
// Check the db name and add roles if needed
|
|
@@ -13,6 +13,7 @@ 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
19
|
const BSON = require('../core/connection/utils').retrieveBSON();
|
|
@@ -182,12 +183,12 @@ function validOptions(options) {
|
|
|
182
183
|
if (options.validateOptions) {
|
|
183
184
|
return new MongoError(`option ${name} is not supported`);
|
|
184
185
|
} else {
|
|
185
|
-
|
|
186
|
+
emitWarningOnce(`the options [${name}] is not supported`);
|
|
186
187
|
}
|
|
187
188
|
}
|
|
188
189
|
|
|
189
190
|
if (legacyOptionNames.indexOf(name) !== -1) {
|
|
190
|
-
|
|
191
|
+
emitWarningOnce(
|
|
191
192
|
`the server/replset/mongos/db options are deprecated, ` +
|
|
192
193
|
`all their options are supported at the top level of the options object [${validOptionNames}]`
|
|
193
194
|
);
|
|
@@ -257,9 +258,6 @@ function resolveTLSOptions(options) {
|
|
|
257
258
|
});
|
|
258
259
|
}
|
|
259
260
|
|
|
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
261
|
function connect(mongoClient, url, options, callback) {
|
|
264
262
|
options = Object.assign({}, options);
|
|
265
263
|
|
|
@@ -335,7 +333,9 @@ function connect(mongoClient, url, options, callback) {
|
|
|
335
333
|
return createTopology(mongoClient, 'unified', _finalOptions, connectCallback);
|
|
336
334
|
}
|
|
337
335
|
|
|
338
|
-
|
|
336
|
+
emitWarningOnce(
|
|
337
|
+
'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.'
|
|
338
|
+
);
|
|
339
339
|
|
|
340
340
|
// Do we have a replicaset then skip discovery and go straight to connectivity
|
|
341
341
|
if (_finalOptions.replicaSet || _finalOptions.rs_name) {
|
|
@@ -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,
|
|
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
|
-
|
|
34
|
-
|
|
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
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
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
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
//
|
|
160
|
-
//
|
|
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;
|
package/lib/utils.js
CHANGED
|
@@ -287,39 +287,38 @@ var filterOptions = function(options, names) {
|
|
|
287
287
|
};
|
|
288
288
|
|
|
289
289
|
// Write concern keys
|
|
290
|
-
|
|
290
|
+
const WRITE_CONCERN_KEYS = ['w', 'j', 'wtimeout', 'fsync', 'writeConcern'];
|
|
291
291
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
// Found no write Concern options
|
|
305
|
-
var found = false;
|
|
306
|
-
for (i = 0; i < writeConcernKeys.length; i++) {
|
|
307
|
-
if (targetOptions[writeConcernKeys[i]]) {
|
|
292
|
+
/**
|
|
293
|
+
* If there is no WriteConcern related options defined on target then inherit from source.
|
|
294
|
+
* Otherwise, do not inherit **any** options from source.
|
|
295
|
+
* @internal
|
|
296
|
+
* @param {object} target - options object conditionally receiving the writeConcern options
|
|
297
|
+
* @param {object} source - options object containing the potentially inherited writeConcern options
|
|
298
|
+
*/
|
|
299
|
+
function conditionallyMergeWriteConcern(target, source) {
|
|
300
|
+
let found = false;
|
|
301
|
+
for (const wcKey of WRITE_CONCERN_KEYS) {
|
|
302
|
+
if (wcKey in target) {
|
|
303
|
+
// Found a writeConcern option
|
|
308
304
|
found = true;
|
|
309
305
|
break;
|
|
310
306
|
}
|
|
311
307
|
}
|
|
312
308
|
|
|
313
309
|
if (!found) {
|
|
314
|
-
for (
|
|
315
|
-
if (
|
|
316
|
-
|
|
310
|
+
for (const wcKey of WRITE_CONCERN_KEYS) {
|
|
311
|
+
if (source[wcKey]) {
|
|
312
|
+
if (!('writeConcern' in target)) {
|
|
313
|
+
target.writeConcern = {};
|
|
314
|
+
}
|
|
315
|
+
target.writeConcern[wcKey] = source[wcKey];
|
|
317
316
|
}
|
|
318
317
|
}
|
|
319
318
|
}
|
|
320
319
|
|
|
321
|
-
return
|
|
322
|
-
}
|
|
320
|
+
return target;
|
|
321
|
+
}
|
|
323
322
|
|
|
324
323
|
/**
|
|
325
324
|
* Executes the given operation with provided arguments.
|
|
@@ -534,7 +533,12 @@ function decorateWithExplain(command, explain) {
|
|
|
534
533
|
return { explain: command, verbosity: explain.verbosity };
|
|
535
534
|
}
|
|
536
535
|
|
|
537
|
-
const
|
|
536
|
+
const nodejsMajorVersion = +process.version.split('.')[0].substring(1);
|
|
537
|
+
const emitProcessWarning = msg =>
|
|
538
|
+
nodejsMajorVersion <= 6
|
|
539
|
+
? process.emitWarning(msg, 'DeprecationWarning', MONGODB_WARNING_CODE)
|
|
540
|
+
: process.emitWarning(msg, { type: 'DeprecationWarning', code: MONGODB_WARNING_CODE });
|
|
541
|
+
// eslint-disable-next-line no-console
|
|
538
542
|
const emitConsoleWarning = msg => console.error(msg);
|
|
539
543
|
const emitDeprecationWarning = process.emitWarning ? emitProcessWarning : emitConsoleWarning;
|
|
540
544
|
|
|
@@ -816,6 +820,50 @@ function hasAtomicOperators(doc) {
|
|
|
816
820
|
);
|
|
817
821
|
}
|
|
818
822
|
|
|
823
|
+
/**
|
|
824
|
+
* When the driver used emitWarning the code will be equal to this.
|
|
825
|
+
* @public
|
|
826
|
+
*
|
|
827
|
+
* @example
|
|
828
|
+
* ```js
|
|
829
|
+
* process.on('warning', (warning) => {
|
|
830
|
+
* if (warning.code === MONGODB_WARNING_CODE) console.error('Ah an important warning! :)')
|
|
831
|
+
* })
|
|
832
|
+
* ```
|
|
833
|
+
*/
|
|
834
|
+
const MONGODB_WARNING_CODE = 'MONGODB DRIVER';
|
|
835
|
+
|
|
836
|
+
/**
|
|
837
|
+
* @internal
|
|
838
|
+
* @param {string} message - message to warn about
|
|
839
|
+
*/
|
|
840
|
+
function emitWarning(message) {
|
|
841
|
+
if (process.emitWarning) {
|
|
842
|
+
return nodejsMajorVersion <= 6
|
|
843
|
+
? process.emitWarning(message, undefined, MONGODB_WARNING_CODE)
|
|
844
|
+
: process.emitWarning(message, { code: MONGODB_WARNING_CODE });
|
|
845
|
+
} else {
|
|
846
|
+
// Approximate the style of print out on node versions pre 8.x
|
|
847
|
+
// eslint-disable-next-line no-console
|
|
848
|
+
return console.error(`[${MONGODB_WARNING_CODE}] Warning:`, message);
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
const emittedWarnings = new Set();
|
|
853
|
+
/**
|
|
854
|
+
* Will emit a warning once for the duration of the application.
|
|
855
|
+
* Uses the message to identify if it has already been emitted
|
|
856
|
+
* so using string interpolation can cause multiple emits
|
|
857
|
+
* @internal
|
|
858
|
+
* @param {string} message - message to warn about
|
|
859
|
+
*/
|
|
860
|
+
function emitWarningOnce(message) {
|
|
861
|
+
if (!emittedWarnings.has(message)) {
|
|
862
|
+
emittedWarnings.add(message);
|
|
863
|
+
return emitWarning(message);
|
|
864
|
+
}
|
|
865
|
+
}
|
|
866
|
+
|
|
819
867
|
module.exports = {
|
|
820
868
|
filterOptions,
|
|
821
869
|
mergeOptions,
|
|
@@ -832,7 +880,7 @@ module.exports = {
|
|
|
832
880
|
isObject,
|
|
833
881
|
debugOptions,
|
|
834
882
|
MAX_JS_INT: Number.MAX_SAFE_INTEGER + 1,
|
|
835
|
-
|
|
883
|
+
conditionallyMergeWriteConcern,
|
|
836
884
|
executeLegacyOperation,
|
|
837
885
|
applyRetryableWrites,
|
|
838
886
|
applyWriteConcern,
|
|
@@ -849,5 +897,8 @@ module.exports = {
|
|
|
849
897
|
now,
|
|
850
898
|
calculateDurationInMs,
|
|
851
899
|
makeInterruptableAsyncInterval,
|
|
852
|
-
hasAtomicOperators
|
|
900
|
+
hasAtomicOperators,
|
|
901
|
+
MONGODB_WARNING_CODE,
|
|
902
|
+
emitWarning,
|
|
903
|
+
emitWarningOnce
|
|
853
904
|
};
|
package/lib/write_concern.js
CHANGED
|
@@ -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
|
-
|
|
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(
|