mongoose 5.2.3 → 5.2.7
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/.eslintignore +1 -0
- package/.travis.yml +1 -1
- package/History.md +58 -0
- package/README.md +6 -6
- package/lib/aggregate.js +22 -0
- package/lib/browser.js +2 -0
- package/lib/cast/boolean.js +5 -6
- package/lib/cast/number.js +49 -0
- package/lib/collection.js +2 -5
- package/lib/connection.js +22 -3
- package/lib/document.js +31 -3
- package/lib/driver.js +15 -0
- package/lib/drivers/browser/index.js +3 -0
- package/lib/drivers/node-mongodb-native/collection.js +23 -9
- package/lib/drivers/node-mongodb-native/index.js +1 -0
- package/lib/helpers/immediate.js +10 -0
- package/lib/helpers/populate/getSchemaTypes.js +80 -62
- package/lib/helpers/populate/getVirtual.js +2 -5
- package/lib/helpers/query/applyQueryMiddleware.js +37 -0
- package/lib/helpers/query/castUpdate.js +34 -12
- package/lib/index.js +6 -4
- package/lib/model.js +98 -100
- package/lib/query.js +125 -25
- package/lib/queryhelpers.js +21 -2
- package/lib/schema/boolean.js +40 -0
- package/lib/schema/documentarray.js +18 -5
- package/lib/schema/embedded.js +7 -2
- package/lib/schema/number.js +11 -31
- package/lib/schema/objectid.js +1 -4
- package/lib/schema.js +1 -1
- package/lib/schematype.js +35 -19
- package/lib/types/buffer.js +2 -2
- package/lib/types/decimal128.js +1 -1
- package/lib/types/documentarray.js +2 -2
- package/lib/types/embedded.js +2 -1
- package/lib/types/map.js +4 -0
- package/lib/types/objectid.js +1 -1
- package/lib/types/subdocument.js +2 -1
- package/lib/utils.js +17 -16
- package/migrating_to_5.md +1 -1
- package/package.json +4 -6
- package/tools/checkNodeVersion.js +7 -0
- package/tools/sharded.js +4 -1
- package/website.js +2 -1
- package/lib/drivers/index.js +0 -20
- package/lib/drivers/index.web.js +0 -5
package/.eslintignore
CHANGED
package/.travis.yml
CHANGED
|
@@ -16,6 +16,6 @@ before_script:
|
|
|
16
16
|
- ./mongodb-linux-x86_64-3.6.4/bin/mongod --fork --nopreallocj --dbpath ./data/db/27017 --syslog --port 27017
|
|
17
17
|
script:
|
|
18
18
|
- npm test
|
|
19
|
-
- npm run lint
|
|
19
|
+
- node tools/checkNodeVersion.js "4.x || 5.x" || npm run lint
|
|
20
20
|
notifications:
|
|
21
21
|
email: false
|
package/History.md
CHANGED
|
@@ -1,3 +1,61 @@
|
|
|
1
|
+
5.2.7 / 2018-08-06
|
|
2
|
+
==================
|
|
3
|
+
* fix(model): check `expireAfterSeconds` option when diffing indexes in syncIndexes() #6820 #6819 [christopherhex](https://github.com/christopherhex)
|
|
4
|
+
* chore: fix some common test flakes in travis #6816 [Fonger](https://github.com/Fonger)
|
|
5
|
+
* chore: bump eslint and webpack to avoid bad versions of eslint-scope #6814
|
|
6
|
+
* test(model): add delay to session tests to improve pass rate #6811 [Fonger](https://github.com/Fonger)
|
|
7
|
+
* fix(model): support options in `deleteMany` #6810 [Fonger](https://github.com/Fonger)
|
|
8
|
+
* fix(query): don't use $each when pushing an array into an array #6809 [lineus](https://github.com/lineus)
|
|
9
|
+
* chore: bump mquery so eslint isn't a prod dependency #6800
|
|
10
|
+
* fix(populate): correctly get schema type when calling `populate()` on already populated path #6798
|
|
11
|
+
* fix(populate): propagate readConcern options in populate from parent query #6792 #6785 [Fonger](https://github.com/Fonger)
|
|
12
|
+
* docs(connection): add description of useNewUrlParser option #6789
|
|
13
|
+
* fix(query): make select('+path') a no-op if no select prop in schema #6785
|
|
14
|
+
* docs(schematype+validation): document using function syntax for custom validator message #6772
|
|
15
|
+
* fix(update): throw CastError if updating with `$inc: null` #6770
|
|
16
|
+
* fix(connection): throw helpful error when calling `createConnection(undefined)` #6763
|
|
17
|
+
|
|
18
|
+
5.2.6 / 2018-07-30
|
|
19
|
+
==================
|
|
20
|
+
* fix(document): don't double-call deeply nested custom getters when using `get()` #6779 #6637
|
|
21
|
+
* fix(query): upgrade mquery for readConcern() helper #6777
|
|
22
|
+
* docs(schematypes): clean up typos #6773 [sajadtorkamani](https://github.com/sajadtorkamani)
|
|
23
|
+
* refactor(browser): fix webpack warnings #6771 #6705
|
|
24
|
+
* fix(populate): make error reported when no `localField` specified catchable #6767
|
|
25
|
+
* docs(connection): use correct form in createConnection example #6766 [lineus](https://github.com/lineus)
|
|
26
|
+
* fix(connection): throw helpful error when using legacy `mongoose.connect()` syntax #6756
|
|
27
|
+
* fix(document): handle overwriting `$session` in `execPopulate()` #6754
|
|
28
|
+
* fix(query): propagate top-level session down to `populate()` #6754
|
|
29
|
+
* fix(aggregate): add `session()` helper for consistency with query api #6752
|
|
30
|
+
* fix(map): avoid infinite recursion when update overwrites a map #6750
|
|
31
|
+
* fix(model): be consistent about passing noop callback to mongoose.model() `init()` as well as db.model() #6707
|
|
32
|
+
|
|
33
|
+
5.2.5 / 2018-07-23
|
|
34
|
+
==================
|
|
35
|
+
* fix(boolean): expose `convertToTrue` and `convertToFalse` for custom boolean casting #6758
|
|
36
|
+
* docs(schematypes): add note about what values are converted to booleans #6758
|
|
37
|
+
* fix(document): fix(document): report castError when setting single nested doc to array #6753
|
|
38
|
+
* docs: prefix mongoose.Schema call with new operator #6751 [sajadtorkamani](https://github.com/sajadtorkamani)
|
|
39
|
+
* docs(query): add examples and links to schema writeConcern option for writeConcern helpers #6748
|
|
40
|
+
* docs(middleware): clarify that init middleware is sync #6747
|
|
41
|
+
* perf(model): create error rather than modifying stack for source map perf #6735
|
|
42
|
+
* fix(model): throw helpful error when passing object to aggregate() #6732
|
|
43
|
+
* fix(model): pass Model instance as context to applyGetters when calling getters for virtual populate #6726 [lineus](https://github.com/lineus)
|
|
44
|
+
* fix(documentarray): remove `isNew` and `save` listeners on CastError because otherwise they never get removed #6723
|
|
45
|
+
* docs(model+query): clarify when to use `countDocuments()` vs `estimatedDocumentCount()` #6713
|
|
46
|
+
* fix(populate): correctly set virtual nestedSchemaPath when calling populate() multiple times #6644
|
|
47
|
+
* docs(connections): add note about the `family` option for IPv4 vs IPv6 and add port to example URIs #6566
|
|
48
|
+
|
|
49
|
+
5.2.4 / 2018-07-16
|
|
50
|
+
==================
|
|
51
|
+
* docs: Model.insertMany rawResult option in api docs #6724 [lineus](https://github.com/lineus)
|
|
52
|
+
* docs: fix typo on migrating to 5 guide #6722 [iagowp](https://github.com/iagowp)
|
|
53
|
+
* docs: update doc about keepalive #6719 #6718 [simllll](https://github.com/simllll)
|
|
54
|
+
* fix: ensure debug mode doesn't crash with sessions #6712
|
|
55
|
+
* fix(document): report castError when setting single nested doc to primitive value #6710
|
|
56
|
+
* fix(connection): throw helpful error if using `new db.model(foo)(bar)` #6698
|
|
57
|
+
* fix(model): throw readable error with better stack trace when non-cb passed to $wrapCallback() #6640
|
|
58
|
+
|
|
1
59
|
5.2.3 / 2018-07-11
|
|
2
60
|
==================
|
|
3
61
|
* fix(populate): if a getter is defined on the localField, use it when populating #6702 #6618 [lineus](https://github.com/lineus)
|
package/README.md
CHANGED
|
@@ -80,14 +80,14 @@ Once connected, the `open` event is fired on the `Connection` instance. If you'r
|
|
|
80
80
|
Models are defined through the `Schema` interface.
|
|
81
81
|
|
|
82
82
|
```js
|
|
83
|
-
const Schema = mongoose.Schema
|
|
84
|
-
|
|
83
|
+
const Schema = mongoose.Schema;
|
|
84
|
+
const ObjectId = Schema.ObjectId;
|
|
85
85
|
|
|
86
86
|
const BlogPost = new Schema({
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
87
|
+
author: ObjectId,
|
|
88
|
+
title: String,
|
|
89
|
+
body: String,
|
|
90
|
+
date: Date
|
|
91
91
|
});
|
|
92
92
|
```
|
|
93
93
|
|
package/lib/aggregate.js
CHANGED
|
@@ -633,6 +633,27 @@ Aggregate.prototype.hint = function(value) {
|
|
|
633
633
|
return this;
|
|
634
634
|
};
|
|
635
635
|
|
|
636
|
+
/**
|
|
637
|
+
* Sets the session for this aggregation. Useful for [transactions](/docs/transactions.html).
|
|
638
|
+
*
|
|
639
|
+
* ####Example:
|
|
640
|
+
*
|
|
641
|
+
* const session = await Model.startSession();
|
|
642
|
+
* await Model.aggregate(..).session(session);
|
|
643
|
+
*
|
|
644
|
+
* @param {ClientSession} session
|
|
645
|
+
* @see mongodb http://docs.mongodb.org/manual/reference/command/aggregate/
|
|
646
|
+
*/
|
|
647
|
+
|
|
648
|
+
Aggregate.prototype.session = function(session) {
|
|
649
|
+
if (session == null) {
|
|
650
|
+
delete this.options.session;
|
|
651
|
+
return;
|
|
652
|
+
}
|
|
653
|
+
this.options.session = session;
|
|
654
|
+
return this;
|
|
655
|
+
};
|
|
656
|
+
|
|
636
657
|
/**
|
|
637
658
|
* Lets you set arbitrary options, for middleware or plugins.
|
|
638
659
|
*
|
|
@@ -645,6 +666,7 @@ Aggregate.prototype.hint = function(value) {
|
|
|
645
666
|
* @param [options.maxTimeMS] number limits the time this aggregation will run, see [MongoDB docs on `maxTimeMS`](https://docs.mongodb.com/manual/reference/operator/meta/maxTimeMS/)
|
|
646
667
|
* @param [options.allowDiskUse] boolean if true, the MongoDB server will use the hard drive to store data during this aggregation
|
|
647
668
|
* @param [options.collation] object see [`Aggregate.prototype.collation()`](./docs/api.html#aggregate_Aggregate-collation)
|
|
669
|
+
* @param [options.session] ClientSession see [`Aggregate.prototype.session()`](./docs/api.html#aggregate_Aggregate-session)
|
|
648
670
|
* @see mongodb http://docs.mongodb.org/manual/reference/command/aggregate/
|
|
649
671
|
* @return {Aggregate} this
|
|
650
672
|
* @api public
|
package/lib/browser.js
CHANGED
package/lib/cast/boolean.js
CHANGED
|
@@ -2,9 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
const CastError = require('../error/cast');
|
|
4
4
|
|
|
5
|
-
const convertToTrue = [true, 'true', 1, '1', 'yes'];
|
|
6
|
-
const convertToFalse = [false, 'false', 0, '0', 'no'];
|
|
7
|
-
|
|
8
5
|
/*!
|
|
9
6
|
* Given a value, cast it to a boolean, or throw a `CastError` if the value
|
|
10
7
|
* cannot be casted. `null` and `undefined` are considered valid.
|
|
@@ -21,12 +18,14 @@ module.exports = function castBoolean(value, path) {
|
|
|
21
18
|
return value;
|
|
22
19
|
}
|
|
23
20
|
|
|
24
|
-
|
|
25
|
-
if (convertToTrue.indexOf(value) !== -1) {
|
|
21
|
+
if (module.exports.convertToTrue.has(value)) {
|
|
26
22
|
return true;
|
|
27
23
|
}
|
|
28
|
-
if (convertToFalse.
|
|
24
|
+
if (module.exports.convertToFalse.has(value)) {
|
|
29
25
|
return false;
|
|
30
26
|
}
|
|
31
27
|
throw new CastError('boolean', value, path);
|
|
32
28
|
};
|
|
29
|
+
|
|
30
|
+
module.exports.convertToTrue = new Set([true, 'true', 1, '1', 'yes']);
|
|
31
|
+
module.exports.convertToFalse = new Set([false, 'false', 0, '0', 'no']);
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const CastError = require('../error/cast');
|
|
4
|
+
|
|
5
|
+
/*!
|
|
6
|
+
* Given a value, cast it to a number, or throw a `CastError` if the value
|
|
7
|
+
* cannot be casted. `null` and `undefined` are considered valid.
|
|
8
|
+
*
|
|
9
|
+
* @param {Any} value
|
|
10
|
+
* @param {String} [path] optional the path to set on the CastError
|
|
11
|
+
* @return {Boolean|null|undefined}
|
|
12
|
+
* @throws {CastError} if `value` is not one of the allowed values
|
|
13
|
+
* @api private
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
module.exports = function castNumber(val, path) {
|
|
17
|
+
if (isNaN(val)) {
|
|
18
|
+
throw new CastError('number', val, path);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (val == null) {
|
|
22
|
+
return val;
|
|
23
|
+
}
|
|
24
|
+
if (val === '') {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (typeof val === 'string' || typeof val === 'boolean') {
|
|
29
|
+
val = Number(val);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (isNaN(val)) {
|
|
33
|
+
throw new CastError('number', val, path);
|
|
34
|
+
}
|
|
35
|
+
if (val instanceof Number) {
|
|
36
|
+
return val;
|
|
37
|
+
}
|
|
38
|
+
if (typeof val === 'number') {
|
|
39
|
+
return val;
|
|
40
|
+
}
|
|
41
|
+
if (!Array.isArray(val) && typeof val.valueOf === 'function') {
|
|
42
|
+
return Number(val.valueOf());
|
|
43
|
+
}
|
|
44
|
+
if (val.toString && !Array.isArray(val) && val.toString() == Number(val)) {
|
|
45
|
+
return new Number(val);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
throw new CastError('number', val, path);
|
|
49
|
+
};
|
package/lib/collection.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
const EventEmitter = require('events').EventEmitter;
|
|
8
8
|
const STATES = require('./connectionstate');
|
|
9
|
-
const
|
|
9
|
+
const immediate = require('./helpers/immediate');
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* Abstract Collection constructor
|
|
@@ -83,10 +83,7 @@ Collection.prototype.conn;
|
|
|
83
83
|
|
|
84
84
|
Collection.prototype.onOpen = function() {
|
|
85
85
|
this.buffer = false;
|
|
86
|
-
|
|
87
|
-
utils.immediate(function() {
|
|
88
|
-
_this.doQueue();
|
|
89
|
-
});
|
|
86
|
+
immediate(() => this.doQueue());
|
|
90
87
|
};
|
|
91
88
|
|
|
92
89
|
/**
|
package/lib/connection.js
CHANGED
|
@@ -5,9 +5,8 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
const EventEmitter = require('events').EventEmitter;
|
|
8
|
-
const driver = global.MONGOOSE_DRIVER_PATH || './drivers/node-mongodb-native';
|
|
9
8
|
const Schema = require('./schema');
|
|
10
|
-
const Collection = require(driver
|
|
9
|
+
const Collection = require('./driver').get().Collection;
|
|
11
10
|
const STATES = require('./connectionstate');
|
|
12
11
|
const MongooseError = require('./error');
|
|
13
12
|
const PromiseProvider = require('./promise_provider');
|
|
@@ -414,6 +413,19 @@ Connection.prototype.openUri = function(uri, options, callback) {
|
|
|
414
413
|
options = null;
|
|
415
414
|
}
|
|
416
415
|
|
|
416
|
+
if (['string', 'number'].indexOf(typeof options) !== -1) {
|
|
417
|
+
throw new MongooseError('Mongoose 5.x no longer supports ' +
|
|
418
|
+
'`mongoose.connect(host, dbname, port)` or ' +
|
|
419
|
+
'`mongoose.createConnection(host, dbname, port)`. See ' +
|
|
420
|
+
'http://mongoosejs.com/docs/connections.html for supported connection syntax');
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
if (typeof uri !== 'string') {
|
|
424
|
+
throw new MongooseError('The `uri` parameter to `openUri()` must be a ' +
|
|
425
|
+
`string, got "${typeof uri}". Make sure the first parameter to ` +
|
|
426
|
+
'`mongoose.connect()` or `mongoose.createConnection()` is a string.');
|
|
427
|
+
}
|
|
428
|
+
|
|
417
429
|
const Promise = PromiseProvider.get();
|
|
418
430
|
const _this = this;
|
|
419
431
|
|
|
@@ -710,6 +722,12 @@ Connection.prototype.collection = function(name, options) {
|
|
|
710
722
|
*/
|
|
711
723
|
|
|
712
724
|
Connection.prototype.model = function(name, schema, collection) {
|
|
725
|
+
if (!(this instanceof Connection)) {
|
|
726
|
+
throw new MongooseError('`connection.model()` should not be run with ' +
|
|
727
|
+
'`new`. If you are doing `new db.model(foo)(bar)`, use ' +
|
|
728
|
+
'`db.model(foo)(bar)` instead');
|
|
729
|
+
}
|
|
730
|
+
|
|
713
731
|
let fn;
|
|
714
732
|
if (typeof name === 'function') {
|
|
715
733
|
fn = name;
|
|
@@ -752,7 +770,8 @@ Connection.prototype.model = function(name, schema, collection) {
|
|
|
752
770
|
}
|
|
753
771
|
|
|
754
772
|
// Errors handled internally, so safe to ignore error
|
|
755
|
-
model.init(()
|
|
773
|
+
model.init(function $modelInitNoop() {});
|
|
774
|
+
|
|
756
775
|
return model;
|
|
757
776
|
}
|
|
758
777
|
|
package/lib/document.js
CHANGED
|
@@ -396,7 +396,11 @@ Document.prototype.toBSON = function() {
|
|
|
396
396
|
/**
|
|
397
397
|
* Initializes the document without setters or marking anything modified.
|
|
398
398
|
*
|
|
399
|
-
* Called internally after a document is returned from mongodb.
|
|
399
|
+
* Called internally after a document is returned from mongodb. Normally,
|
|
400
|
+
* you do **not** need to call this function on your own.
|
|
401
|
+
*
|
|
402
|
+
* This function triggers `init` [middleware](/docs/middleware.html).
|
|
403
|
+
* Note that `init` hooks are [synchronous](/docs/middleware.html#synchronous).
|
|
400
404
|
*
|
|
401
405
|
* @param {Object} doc document returned by mongo
|
|
402
406
|
* @api public
|
|
@@ -1111,6 +1115,8 @@ Document.prototype.get = function(path, type, options) {
|
|
|
1111
1115
|
obj = void 0;
|
|
1112
1116
|
} else if (obj instanceof Map) {
|
|
1113
1117
|
obj = obj.get(pieces[i]);
|
|
1118
|
+
} else if (i === l - 1) {
|
|
1119
|
+
obj = utils.getValue(pieces[i], obj);
|
|
1114
1120
|
} else {
|
|
1115
1121
|
obj = obj[pieces[i]];
|
|
1116
1122
|
}
|
|
@@ -2358,8 +2364,8 @@ Document.prototype.$toObject = function(options, json) {
|
|
|
2358
2364
|
*
|
|
2359
2365
|
* ####Options:
|
|
2360
2366
|
*
|
|
2361
|
-
* - `getters` apply all getters (path and virtual getters)
|
|
2362
|
-
* - `virtuals` apply virtual getters (can override `getters` option)
|
|
2367
|
+
* - `getters` apply all getters (path and virtual getters), defaults to false
|
|
2368
|
+
* - `virtuals` apply virtual getters (can override `getters` option), defaults to false
|
|
2363
2369
|
* - `minimize` remove empty objects (defaults to true)
|
|
2364
2370
|
* - `transform` a transform function to apply to the resulting document before returning
|
|
2365
2371
|
* - `depopulate` depopulate any populated paths, replacing them with their original refs (defaults to false)
|
|
@@ -2462,6 +2468,12 @@ Document.prototype.$toObject = function(options, json) {
|
|
|
2462
2468
|
* _During save, no custom options are applied to the document before being sent to the database._
|
|
2463
2469
|
*
|
|
2464
2470
|
* @param {Object} [options]
|
|
2471
|
+
* @param {Boolean} [options.getters=false] if true, apply all getters, including virtuals
|
|
2472
|
+
* @param {Boolean} [options.virtuals=false] if true, apply virtuals. Use `{ getters: true, virtuals: false }` to just apply getters, not virtuals
|
|
2473
|
+
* @param {Boolean} [options.minimize=true] if true, omit any empty objects from the output
|
|
2474
|
+
* @param {Function|null} [options.transform=null] if set, mongoose will call this function to allow you to transform the returned object
|
|
2475
|
+
* @param {Boolean} [options.depopulate=false] if true, replace any conventionally populated paths with the original id in the output. Has no affect on virtual populated paths.
|
|
2476
|
+
* @param {Boolean} [options.versionKey=true] if false, exclude the version key (`__v` by default) from the output
|
|
2465
2477
|
* @return {Object} js object
|
|
2466
2478
|
* @see mongodb.Binary http://mongodb.github.com/node-mongodb-native/api-bson-generated/binary.html
|
|
2467
2479
|
* @api public
|
|
@@ -2753,6 +2765,22 @@ Document.prototype.populate = function populate() {
|
|
|
2753
2765
|
populateOptions.path = nestedPath + '.' + populateOptions.path;
|
|
2754
2766
|
});
|
|
2755
2767
|
}
|
|
2768
|
+
|
|
2769
|
+
// Use `$session()` by default if the document has an associated session
|
|
2770
|
+
// See gh-6754
|
|
2771
|
+
if (this.$session() != null) {
|
|
2772
|
+
const session = this.$session();
|
|
2773
|
+
paths.forEach(path => {
|
|
2774
|
+
if (path.options == null) {
|
|
2775
|
+
path.options = { session: session };
|
|
2776
|
+
return;
|
|
2777
|
+
}
|
|
2778
|
+
if (!('session' in path.options)) {
|
|
2779
|
+
path.options.session = session;
|
|
2780
|
+
}
|
|
2781
|
+
});
|
|
2782
|
+
}
|
|
2783
|
+
|
|
2756
2784
|
topLevelModel.populate(this, paths, fn);
|
|
2757
2785
|
}
|
|
2758
2786
|
|
package/lib/driver.js
ADDED
|
@@ -3,6 +3,9 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
exports.Binary = require('./binary');
|
|
6
|
+
exports.Collection = function() {
|
|
7
|
+
throw new Error('Cannot create a collection from browser library');
|
|
8
|
+
};
|
|
6
9
|
exports.Decimal128 = require('./decimal128');
|
|
7
10
|
exports.ObjectId = require('./objectid');
|
|
8
11
|
exports.ReadPreference = require('./ReadPreference');
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
const MongooseCollection = require('../../collection');
|
|
8
8
|
const Collection = require('mongodb').Collection;
|
|
9
9
|
const get = require('lodash.get');
|
|
10
|
-
const
|
|
10
|
+
const sliced = require('sliced');
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* A [node-mongodb-native](https://github.com/mongodb/node-mongodb-native) collection implementation.
|
|
@@ -72,7 +72,7 @@ NativeCollection.prototype.onOpen = function() {
|
|
|
72
72
|
}
|
|
73
73
|
} else {
|
|
74
74
|
// create
|
|
75
|
-
|
|
75
|
+
const opts = Object.assign({}, _this.opts.capped);
|
|
76
76
|
opts.capped = true;
|
|
77
77
|
_this.conn.db.createCollection(_this.name, opts, callback);
|
|
78
78
|
}
|
|
@@ -132,7 +132,7 @@ function iter(i) {
|
|
|
132
132
|
if (debug) {
|
|
133
133
|
if (typeof debug === 'function') {
|
|
134
134
|
debug.apply(_this,
|
|
135
|
-
[_this.name, i].concat(
|
|
135
|
+
[_this.name, i].concat(sliced(args, 0, args.length - 1)));
|
|
136
136
|
} else {
|
|
137
137
|
this.$print(_this.name, i, args);
|
|
138
138
|
}
|
|
@@ -224,7 +224,7 @@ function format(obj, sub) {
|
|
|
224
224
|
return obj;
|
|
225
225
|
}
|
|
226
226
|
|
|
227
|
-
var x = utils.clone(obj, {transform: false});
|
|
227
|
+
var x = require('../../utils').clone(obj, {transform: false});
|
|
228
228
|
var representation;
|
|
229
229
|
|
|
230
230
|
if (x.constructor.name === 'Binary') {
|
|
@@ -242,8 +242,17 @@ function format(obj, sub) {
|
|
|
242
242
|
for (var i = 0; i < numKeys; ++i) {
|
|
243
243
|
key = keys[i];
|
|
244
244
|
if (x[key]) {
|
|
245
|
+
let error;
|
|
245
246
|
if (typeof x[key].toBSON === 'function') {
|
|
246
|
-
|
|
247
|
+
try {
|
|
248
|
+
// `session.toBSON()` throws an error. This means we throw errors
|
|
249
|
+
// in debug mode when using transactions, see gh-6712. As a
|
|
250
|
+
// workaround, catch `toBSON()` errors, try to serialize without
|
|
251
|
+
// `toBSON()`, and rethrow if serialization still fails.
|
|
252
|
+
x[key] = x[key].toBSON();
|
|
253
|
+
} catch (_error) {
|
|
254
|
+
error = _error;
|
|
255
|
+
}
|
|
247
256
|
}
|
|
248
257
|
if (x[key].constructor.name === 'Binary') {
|
|
249
258
|
x[key] = 'BinData(' + x[key].sub_type + ', "' +
|
|
@@ -260,6 +269,11 @@ function format(obj, sub) {
|
|
|
260
269
|
x[key] = {inspect: function() { return representation; }};
|
|
261
270
|
} else if (Array.isArray(x[key])) {
|
|
262
271
|
x[key] = x[key].map(map);
|
|
272
|
+
} else if (error != null) {
|
|
273
|
+
// If there was an error with `toBSON()` and the object wasn't
|
|
274
|
+
// already converted to a string representation, rethrow it.
|
|
275
|
+
// Open to better ideas on how to handle this.
|
|
276
|
+
throw error;
|
|
263
277
|
}
|
|
264
278
|
}
|
|
265
279
|
}
|
|
@@ -268,10 +282,10 @@ function format(obj, sub) {
|
|
|
268
282
|
return x;
|
|
269
283
|
}
|
|
270
284
|
|
|
271
|
-
return require('util')
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
285
|
+
return require('util').
|
|
286
|
+
inspect(x, false, 10, true).
|
|
287
|
+
replace(/\n/g, '').
|
|
288
|
+
replace(/\s{2,}/g, ' ');
|
|
275
289
|
}
|
|
276
290
|
|
|
277
291
|
/**
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Centralize this so we can more easily work around issues with people
|
|
3
|
+
* stubbing out `process.nextTick()` in tests using sinon:
|
|
4
|
+
* https://github.com/sinonjs/lolex#automatically-incrementing-mocked-time
|
|
5
|
+
* See gh-6074
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
module.exports = function immediate(cb) {
|
|
9
|
+
return process.nextTick(cb);
|
|
10
|
+
};
|
|
@@ -4,8 +4,9 @@
|
|
|
4
4
|
* ignore
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
const Mixed = require('../../schema/mixed');
|
|
8
|
+
const get = require('lodash.get');
|
|
9
|
+
const mpath = require('mpath');
|
|
9
10
|
|
|
10
11
|
/*!
|
|
11
12
|
* @param {Schema} schema
|
|
@@ -28,79 +29,96 @@ module.exports = function getSchemaTypes(schema, doc, path) {
|
|
|
28
29
|
while (p--) {
|
|
29
30
|
trypath = parts.slice(0, p).join('.');
|
|
30
31
|
foundschema = schema.path(trypath);
|
|
31
|
-
if (foundschema) {
|
|
32
|
-
if (foundschema.caster) {
|
|
33
|
-
// array of Mixed?
|
|
34
|
-
if (foundschema.caster instanceof Mixed) {
|
|
35
|
-
return foundschema.caster;
|
|
36
|
-
}
|
|
37
32
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
const discriminatorKeyPath = trypath + '.' +
|
|
42
|
-
foundschema.schema.options.discriminatorKey;
|
|
43
|
-
const keys = mpath.get(discriminatorKeyPath, subdoc) || [];
|
|
44
|
-
schemas = Object.keys(discriminators).
|
|
45
|
-
reduce(function(cur, discriminator) {
|
|
46
|
-
if (keys.indexOf(discriminator) !== -1) {
|
|
47
|
-
cur.push(discriminators[discriminator]);
|
|
48
|
-
}
|
|
49
|
-
return cur;
|
|
50
|
-
}, []);
|
|
51
|
-
}
|
|
33
|
+
if (foundschema == null) {
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
52
36
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
// a path like array.$
|
|
59
|
-
if (p !== parts.length && foundschema.schema) {
|
|
60
|
-
let ret;
|
|
61
|
-
if (parts[p] === '$') {
|
|
62
|
-
if (p + 1 === parts.length) {
|
|
63
|
-
// comments.$
|
|
64
|
-
return foundschema;
|
|
65
|
-
}
|
|
66
|
-
// comments.$.comments.$.title
|
|
67
|
-
ret = search(parts.slice(p + 1), schema, mpath.get(trypath, subdoc));
|
|
68
|
-
if (ret) {
|
|
69
|
-
ret.$isUnderneathDocArray = ret.$isUnderneathDocArray ||
|
|
70
|
-
!foundschema.schema.$isSingleNested;
|
|
71
|
-
}
|
|
72
|
-
return ret;
|
|
73
|
-
}
|
|
37
|
+
if (foundschema.caster) {
|
|
38
|
+
// array of Mixed?
|
|
39
|
+
if (foundschema.caster instanceof Mixed) {
|
|
40
|
+
return foundschema.caster;
|
|
41
|
+
}
|
|
74
42
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
ret.push(_ret);
|
|
86
|
-
}
|
|
43
|
+
let schemas = null;
|
|
44
|
+
if (doc != null && foundschema.schema != null && foundschema.schema.discriminators != null) {
|
|
45
|
+
const discriminators = foundschema.schema.discriminators;
|
|
46
|
+
const discriminatorKeyPath = trypath + '.' +
|
|
47
|
+
foundschema.schema.options.discriminatorKey;
|
|
48
|
+
const keys = mpath.get(discriminatorKeyPath, subdoc) || [];
|
|
49
|
+
schemas = Object.keys(discriminators).
|
|
50
|
+
reduce(function(cur, discriminator) {
|
|
51
|
+
if (keys.indexOf(discriminator) !== -1) {
|
|
52
|
+
cur.push(discriminators[discriminator]);
|
|
87
53
|
}
|
|
88
|
-
return
|
|
89
|
-
}
|
|
90
|
-
|
|
54
|
+
return cur;
|
|
55
|
+
}, []);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Now that we found the array, we need to check if there
|
|
59
|
+
// are remaining document paths to look up for casting.
|
|
60
|
+
// Also we need to handle array.$.path since schema.path
|
|
61
|
+
// doesn't work for that.
|
|
62
|
+
// If there is no foundschema.schema we are dealing with
|
|
63
|
+
// a path like array.$
|
|
64
|
+
if (p !== parts.length && foundschema.schema) {
|
|
65
|
+
let ret;
|
|
66
|
+
if (parts[p] === '$') {
|
|
67
|
+
if (p + 1 === parts.length) {
|
|
68
|
+
// comments.$
|
|
69
|
+
return foundschema;
|
|
70
|
+
}
|
|
71
|
+
// comments.$.comments.$.title
|
|
72
|
+
ret = search(parts.slice(p + 1), schema, mpath.get(trypath, subdoc));
|
|
73
|
+
if (ret) {
|
|
74
|
+
ret.$isUnderneathDocArray = ret.$isUnderneathDocArray ||
|
|
75
|
+
!foundschema.schema.$isSingleNested;
|
|
76
|
+
}
|
|
77
|
+
return ret;
|
|
78
|
+
}
|
|
91
79
|
|
|
92
|
-
|
|
93
|
-
|
|
80
|
+
if (schemas != null && schemas.length > 0) {
|
|
81
|
+
ret = [];
|
|
82
|
+
for (var i = 0; i < schemas.length; ++i) {
|
|
83
|
+
let _ret = search(parts.slice(p), schemas[i], mpath.get(trypath, subdoc));
|
|
84
|
+
if (_ret != null) {
|
|
85
|
+
_ret.$isUnderneathDocArray = _ret.$isUnderneathDocArray ||
|
|
94
86
|
!foundschema.schema.$isSingleNested;
|
|
87
|
+
if (_ret.$isUnderneathDocArray) {
|
|
88
|
+
ret.$isUnderneathDocArray = true;
|
|
89
|
+
}
|
|
90
|
+
ret.push(_ret);
|
|
95
91
|
}
|
|
92
|
+
}
|
|
93
|
+
return ret;
|
|
94
|
+
} else {
|
|
95
|
+
ret = search(parts.slice(p), foundschema.schema, mpath.get(trypath, subdoc));
|
|
96
96
|
|
|
97
|
-
|
|
97
|
+
if (ret) {
|
|
98
|
+
ret.$isUnderneathDocArray = ret.$isUnderneathDocArray ||
|
|
99
|
+
!foundschema.schema.$isSingleNested;
|
|
98
100
|
}
|
|
101
|
+
|
|
102
|
+
return ret;
|
|
99
103
|
}
|
|
100
104
|
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (doc.$__ && doc.populated(trypath)) {
|
|
108
|
+
const schema = get(doc.$__.populated[trypath], 'options.model.schema');
|
|
109
|
+
if (schema != null) {
|
|
110
|
+
const ret = search(parts.slice(p), schema, mpath.get(trypath, subdoc));
|
|
111
|
+
|
|
112
|
+
if (ret) {
|
|
113
|
+
ret.$isUnderneathDocArray = ret.$isUnderneathDocArray ||
|
|
114
|
+
!schema.$isSingleNested;
|
|
115
|
+
}
|
|
101
116
|
|
|
102
|
-
|
|
117
|
+
return ret;
|
|
118
|
+
}
|
|
103
119
|
}
|
|
120
|
+
|
|
121
|
+
return foundschema;
|
|
104
122
|
}
|
|
105
123
|
}
|
|
106
124
|
|