mongoose 5.0.18 → 5.1.0
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/.travis.yml +4 -3
- package/History.md +16 -0
- package/lib/document.js +68 -12
- package/lib/drivers/browser/objectid.js +12 -0
- package/lib/drivers/node-mongodb-native/collection.js +10 -3
- package/lib/error/version.js +3 -2
- package/lib/index.js +10 -5
- package/lib/internal.js +1 -0
- package/lib/model.js +239 -36
- package/lib/plugins/saveSubdocs.js +1 -1
- package/lib/query.js +191 -97
- package/lib/queryhelpers.js +25 -23
- package/lib/schema/array.js +6 -3
- package/lib/schema/embedded.js +15 -9
- package/lib/schema/index.js +2 -0
- package/lib/schema/map.js +29 -0
- package/lib/schema/objectid.js +0 -20
- package/lib/schema.js +47 -9
- package/lib/schematype.js +19 -1
- package/lib/services/model/applyMethods.js +14 -4
- package/lib/services/query/completeMany.js +47 -0
- package/lib/types/embedded.js +33 -1
- package/lib/types/index.js +2 -0
- package/lib/types/map.js +144 -0
- package/lib/types/objectid.js +12 -0
- package/lib/types/subdocument.js +30 -1
- package/lib/utils.js +5 -3
- package/package.json +1 -1
package/lib/schema.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
1
3
|
/*!
|
|
2
4
|
* Module dependencies.
|
|
3
5
|
*/
|
|
@@ -72,6 +74,7 @@ function Schema(obj, options) {
|
|
|
72
74
|
this.callQueue = [];
|
|
73
75
|
this._indexes = [];
|
|
74
76
|
this.methods = {};
|
|
77
|
+
this.methodOptions = {};
|
|
75
78
|
this.statics = {};
|
|
76
79
|
this.tree = {};
|
|
77
80
|
this.query = {};
|
|
@@ -239,6 +242,7 @@ Schema.prototype.clone = function() {
|
|
|
239
242
|
s.options = utils.clone(this.options);
|
|
240
243
|
s.callQueue = this.callQueue.map(function(f) { return f; });
|
|
241
244
|
s.methods = utils.clone(this.methods);
|
|
245
|
+
s.methodOptions = utils.clone(this.methodOptions);
|
|
242
246
|
s.statics = utils.clone(this.statics);
|
|
243
247
|
s.query = utils.clone(this.query);
|
|
244
248
|
s.plugins = Array.prototype.slice.call(this.plugins);
|
|
@@ -381,6 +385,7 @@ Schema.prototype.add = function add(obj, prefix) {
|
|
|
381
385
|
*/
|
|
382
386
|
|
|
383
387
|
Schema.reserved = Object.create(null);
|
|
388
|
+
Schema.prototype.reserved = Schema.reserved;
|
|
384
389
|
var reserved = Schema.reserved;
|
|
385
390
|
// Core object
|
|
386
391
|
reserved['prototype'] =
|
|
@@ -443,6 +448,17 @@ Schema.prototype.path = function(path, obj) {
|
|
|
443
448
|
return this.singleNestedPaths[path];
|
|
444
449
|
}
|
|
445
450
|
|
|
451
|
+
// Look for maps
|
|
452
|
+
for (let _path of Object.keys(this.paths)) {
|
|
453
|
+
if (!_path.includes('.$*')) {
|
|
454
|
+
continue;
|
|
455
|
+
}
|
|
456
|
+
const re = new RegExp('^' + _path.replace(/\.\$\*/g, '.[^.]+') + '$');
|
|
457
|
+
if (re.test(path)) {
|
|
458
|
+
return this.paths[_path];
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
|
|
446
462
|
// subpaths?
|
|
447
463
|
return /\.\d+\.?.*$/.test(path)
|
|
448
464
|
? getPositionalPath(this, path)
|
|
@@ -459,16 +475,16 @@ Schema.prototype.path = function(path, obj) {
|
|
|
459
475
|
}
|
|
460
476
|
|
|
461
477
|
// update the tree
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
478
|
+
const subpaths = path.split(/\./);
|
|
479
|
+
let last = subpaths.pop();
|
|
480
|
+
let branch = this.tree;
|
|
465
481
|
|
|
466
482
|
subpaths.forEach(function(sub, i) {
|
|
467
483
|
if (!branch[sub]) {
|
|
468
484
|
branch[sub] = {};
|
|
469
485
|
}
|
|
470
486
|
if (typeof branch[sub] !== 'object') {
|
|
471
|
-
|
|
487
|
+
const msg = 'Cannot set nested path `' + path + '`. '
|
|
472
488
|
+ 'Parent path `'
|
|
473
489
|
+ subpaths.slice(0, i).concat([sub]).join('.')
|
|
474
490
|
+ '` already set to type ' + branch[sub].name
|
|
@@ -478,17 +494,26 @@ Schema.prototype.path = function(path, obj) {
|
|
|
478
494
|
branch = branch[sub];
|
|
479
495
|
});
|
|
480
496
|
|
|
481
|
-
|
|
482
497
|
branch[last] = utils.clone(obj);
|
|
483
498
|
|
|
484
499
|
this.paths[path] = Schema.interpretAsType(path, obj, this.options);
|
|
485
500
|
|
|
501
|
+
if (this.paths[path].$isSchemaMap) {
|
|
502
|
+
// Maps can have arbitrary keys, so `$*` is internal shorthand for "any key"
|
|
503
|
+
// The '$' is to imply this path should never be stored in MongoDB so we
|
|
504
|
+
// can easily build a regexp out of this path, and '*' to imply "any key."
|
|
505
|
+
const mapPath = path + '.$*';
|
|
506
|
+
this.paths[path + '.$*'] = Schema.interpretAsType(mapPath,
|
|
507
|
+
obj.of || { type: {} }, this.options);
|
|
508
|
+
this.paths[path].$__schemaType = this.paths[path + '.$*'];
|
|
509
|
+
}
|
|
510
|
+
|
|
486
511
|
if (this.paths[path].$isSingleNested) {
|
|
487
|
-
for (
|
|
512
|
+
for (let key in this.paths[path].schema.paths) {
|
|
488
513
|
this.singleNestedPaths[path + '.' + key] =
|
|
489
514
|
this.paths[path].schema.paths[key];
|
|
490
515
|
}
|
|
491
|
-
for (key in this.paths[path].schema.singleNestedPaths) {
|
|
516
|
+
for (let key in this.paths[path].schema.singleNestedPaths) {
|
|
492
517
|
this.singleNestedPaths[path + '.' + key] =
|
|
493
518
|
this.paths[path].schema.singleNestedPaths[key];
|
|
494
519
|
}
|
|
@@ -722,6 +747,17 @@ Schema.prototype.pathType = function(path) {
|
|
|
722
747
|
return 'real';
|
|
723
748
|
}
|
|
724
749
|
|
|
750
|
+
// Look for maps
|
|
751
|
+
for (let _path of Object.keys(this.paths)) {
|
|
752
|
+
if (!_path.includes('.$*')) {
|
|
753
|
+
continue;
|
|
754
|
+
}
|
|
755
|
+
const re = new RegExp('^' + _path.replace(/\.\$\*/g, '.[^.]+') + '$');
|
|
756
|
+
if (re.test(path)) {
|
|
757
|
+
return this.paths[_path];
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
|
|
725
761
|
if (/\.\d+\.|\.\d+$/.test(path)) {
|
|
726
762
|
return getPositionalPathType(this, path);
|
|
727
763
|
}
|
|
@@ -1183,13 +1219,15 @@ Schema.prototype.plugin = function(fn, opts) {
|
|
|
1183
1219
|
* @api public
|
|
1184
1220
|
*/
|
|
1185
1221
|
|
|
1186
|
-
Schema.prototype.method = function(name, fn) {
|
|
1222
|
+
Schema.prototype.method = function(name, fn, options) {
|
|
1187
1223
|
if (typeof name !== 'string') {
|
|
1188
|
-
for (
|
|
1224
|
+
for (const i in name) {
|
|
1189
1225
|
this.methods[i] = name[i];
|
|
1226
|
+
this.methodOptions[i] = utils.clone(options);
|
|
1190
1227
|
}
|
|
1191
1228
|
} else {
|
|
1192
1229
|
this.methods[name] = fn;
|
|
1230
|
+
this.methodOptions[name] = utils.clone(options);
|
|
1193
1231
|
}
|
|
1194
1232
|
return this;
|
|
1195
1233
|
};
|
package/lib/schematype.js
CHANGED
|
@@ -1035,6 +1035,24 @@ function handleArray(val) {
|
|
|
1035
1035
|
});
|
|
1036
1036
|
}
|
|
1037
1037
|
|
|
1038
|
+
/*!
|
|
1039
|
+
* Just like handleArray, except also allows `[]` because surprisingly
|
|
1040
|
+
* `$in: [1, []]` works fine
|
|
1041
|
+
*/
|
|
1042
|
+
|
|
1043
|
+
function handle$in(val) {
|
|
1044
|
+
var _this = this;
|
|
1045
|
+
if (!Array.isArray(val)) {
|
|
1046
|
+
return [this.castForQuery(val)];
|
|
1047
|
+
}
|
|
1048
|
+
return val.map(function(m) {
|
|
1049
|
+
if (Array.isArray(m) && m.length === 0) {
|
|
1050
|
+
return m;
|
|
1051
|
+
}
|
|
1052
|
+
return _this.castForQuery(m);
|
|
1053
|
+
});
|
|
1054
|
+
}
|
|
1055
|
+
|
|
1038
1056
|
/*!
|
|
1039
1057
|
* ignore
|
|
1040
1058
|
*/
|
|
@@ -1042,7 +1060,7 @@ function handleArray(val) {
|
|
|
1042
1060
|
SchemaType.prototype.$conditionalHandlers = {
|
|
1043
1061
|
$all: handleArray,
|
|
1044
1062
|
$eq: handleSingle,
|
|
1045
|
-
$in:
|
|
1063
|
+
$in: handle$in,
|
|
1046
1064
|
$ne: handleSingle,
|
|
1047
1065
|
$nin: handleArray,
|
|
1048
1066
|
$exists: $exists,
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const get = require('lodash.get');
|
|
4
|
+
|
|
3
5
|
/*!
|
|
4
6
|
* Register methods for this model
|
|
5
7
|
*
|
|
@@ -20,13 +22,21 @@ module.exports = function applyMethods(model, schema) {
|
|
|
20
22
|
configurable: true
|
|
21
23
|
});
|
|
22
24
|
}
|
|
23
|
-
for (
|
|
25
|
+
for (const method of Object.keys(schema.methods)) {
|
|
26
|
+
const fn = schema.methods[method];
|
|
24
27
|
if (schema.tree.hasOwnProperty(method)) {
|
|
25
28
|
throw new Error('You have a method and a property in your schema both ' +
|
|
26
29
|
'named "' + method + '"');
|
|
27
30
|
}
|
|
28
|
-
if (
|
|
29
|
-
|
|
31
|
+
if (schema.reserved[method] &&
|
|
32
|
+
!get(schema, `methodOptions.${method}.suppressWarning`, false)) {
|
|
33
|
+
console.warn(`mongoose: the method name "${method}" is used by mongoose ` +
|
|
34
|
+
'internally, overwriting it may cause bugs. If you\'re sure you know ' +
|
|
35
|
+
'what you\'re doing, you can suppress this error by using ' +
|
|
36
|
+
`\`schema.method('${method}', fn, { suppressWarning: true })\`.`);
|
|
37
|
+
}
|
|
38
|
+
if (typeof fn === 'function') {
|
|
39
|
+
model.prototype[method] = fn;
|
|
30
40
|
} else {
|
|
31
41
|
apply(method, schema);
|
|
32
42
|
}
|
|
@@ -34,7 +44,7 @@ module.exports = function applyMethods(model, schema) {
|
|
|
34
44
|
|
|
35
45
|
// Recursively call `applyMethods()` on child schemas
|
|
36
46
|
model.$appliedMethods = true;
|
|
37
|
-
for (
|
|
47
|
+
for (let i = 0; i < schema.childSchemas.length; ++i) {
|
|
38
48
|
if (schema.childSchemas[i].model.$appliedMethods) {
|
|
39
49
|
continue;
|
|
40
50
|
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const helpers = require('../../queryhelpers');
|
|
4
|
+
|
|
5
|
+
module.exports = completeMany;
|
|
6
|
+
|
|
7
|
+
/*!
|
|
8
|
+
* Given a model and an array of docs, hydrates all the docs to be instances
|
|
9
|
+
* of the model. Used to initialize docs returned from the db from `find()`
|
|
10
|
+
*
|
|
11
|
+
* @param {Model} model
|
|
12
|
+
* @param {Array} docs
|
|
13
|
+
* @param {Object} fields the projection used, including `select` from schemas
|
|
14
|
+
* @param {Object} userProvidedFields the user-specified projection
|
|
15
|
+
* @param {Object} opts
|
|
16
|
+
* @param {Array} [opts.populated]
|
|
17
|
+
* @param {ClientSession} [opts.session]
|
|
18
|
+
* @param {Function} callback
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
function completeMany(model, docs, fields, userProvidedFields, opts, callback) {
|
|
22
|
+
const arr = [];
|
|
23
|
+
let count = docs.length;
|
|
24
|
+
const len = count;
|
|
25
|
+
let error = null;
|
|
26
|
+
|
|
27
|
+
function init(_error) {
|
|
28
|
+
if (_error != null) {
|
|
29
|
+
error = error || _error;
|
|
30
|
+
}
|
|
31
|
+
if (error != null) {
|
|
32
|
+
--count || process.nextTick(() => callback(error));
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
--count || process.nextTick(() => callback(error, arr));
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
for (let i = 0; i < len; ++i) {
|
|
39
|
+
arr[i] = helpers.createModel(model, docs[i], fields, userProvidedFields);
|
|
40
|
+
try {
|
|
41
|
+
arr[i].init(docs[i], opts, init);
|
|
42
|
+
} catch (error) {
|
|
43
|
+
init(error);
|
|
44
|
+
}
|
|
45
|
+
arr[i].$session(opts.session);
|
|
46
|
+
}
|
|
47
|
+
}
|
package/lib/types/embedded.js
CHANGED
|
@@ -107,7 +107,20 @@ EmbeddedDocument.prototype.populate = function() {
|
|
|
107
107
|
* @api private
|
|
108
108
|
*/
|
|
109
109
|
|
|
110
|
-
EmbeddedDocument.prototype.save = function(fn) {
|
|
110
|
+
EmbeddedDocument.prototype.save = function(options, fn) {
|
|
111
|
+
if (typeof options === 'function') {
|
|
112
|
+
fn = options;
|
|
113
|
+
options = {};
|
|
114
|
+
}
|
|
115
|
+
options = options || {};
|
|
116
|
+
|
|
117
|
+
if (!options.suppressWarning) {
|
|
118
|
+
console.warn('mongoose: calling `save()` on a subdoc does **not** save ' +
|
|
119
|
+
'the document to MongoDB, it only runs save middleware. ' +
|
|
120
|
+
'Use `subdoc.save({ suppressWarning: true })` to hide this warning ' +
|
|
121
|
+
'if you\'re sure this behavior is right for your app.');
|
|
122
|
+
}
|
|
123
|
+
|
|
111
124
|
return utils.promiseOrCallback(fn, cb => {
|
|
112
125
|
this.$__save(cb);
|
|
113
126
|
});
|
|
@@ -274,6 +287,25 @@ EmbeddedDocument.prototype.$markValid = function(path) {
|
|
|
274
287
|
}
|
|
275
288
|
};
|
|
276
289
|
|
|
290
|
+
/*!
|
|
291
|
+
* ignore
|
|
292
|
+
*/
|
|
293
|
+
|
|
294
|
+
EmbeddedDocument.prototype.$ignore = function(path) {
|
|
295
|
+
Document.prototype.$ignore.call(this, path);
|
|
296
|
+
|
|
297
|
+
if (!this.__parent) {
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
var index = this.__index;
|
|
302
|
+
if (typeof index !== 'undefined') {
|
|
303
|
+
var parentPath = this.__parentArray._path;
|
|
304
|
+
var fullPath = [parentPath, index, path].join('.');
|
|
305
|
+
this.__parent.$ignore(fullPath);
|
|
306
|
+
}
|
|
307
|
+
};
|
|
308
|
+
|
|
277
309
|
/**
|
|
278
310
|
* Checks if a path is invalid
|
|
279
311
|
*
|
package/lib/types/index.js
CHANGED
package/lib/types/map.js
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/*!
|
|
4
|
+
* ignore
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
class MongooseMap extends Map {
|
|
8
|
+
constructor(v, path, doc, schemaType) {
|
|
9
|
+
if (v != null && v.constructor.name === 'Object') {
|
|
10
|
+
v = Object.keys(v).reduce((arr, key) => arr.concat([[key, v[key]]]), []);
|
|
11
|
+
}
|
|
12
|
+
super(v);
|
|
13
|
+
|
|
14
|
+
this.$__parent = doc;
|
|
15
|
+
this.$__path = path;
|
|
16
|
+
this.$__schemaType = schemaType;
|
|
17
|
+
|
|
18
|
+
this.$__runDeferred();
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
$init(key, value) {
|
|
22
|
+
if (key.startsWith('$')) {
|
|
23
|
+
throw new Error('Mongoose maps do not support keys that start with ' +
|
|
24
|
+
'`$`, got "' + key + '"');
|
|
25
|
+
}
|
|
26
|
+
if (key.indexOf('.') !== -1) {
|
|
27
|
+
throw new Error('Mongoose maps do not support keys that contain `.`, ' +
|
|
28
|
+
'got "' + key + '"');
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
super.set(key, value);
|
|
32
|
+
|
|
33
|
+
if (value != null && value.$isSingleNested) {
|
|
34
|
+
value.$basePath = this.$__path + '.' + key;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
set(key, value) {
|
|
39
|
+
if (key.startsWith('$')) {
|
|
40
|
+
throw new Error('Mongoose maps do not support keys that start with ' +
|
|
41
|
+
'`$`, got "' + key + '"');
|
|
42
|
+
}
|
|
43
|
+
if (key.indexOf('.') !== -1) {
|
|
44
|
+
throw new Error('Mongoose maps do not support keys that contain `.`, ' +
|
|
45
|
+
'got "' + key + '"');
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Weird, but because you can't assign to `this` before calling `super()`
|
|
49
|
+
// you can't get access to `$__schemaType` to cast in the initial call to
|
|
50
|
+
// `set()` from the `super()` constructor.
|
|
51
|
+
|
|
52
|
+
if (this.$__schemaType == null) {
|
|
53
|
+
this.$__deferred = this.$__deferred || [];
|
|
54
|
+
this.$__deferred.push({ key: key, value: value });
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const fullPath = this.$__path + '.' + key;
|
|
59
|
+
const populated = this.$__parent != null && this.$__parent.$__ ?
|
|
60
|
+
this.$__parent.populated(fullPath) || this.$__parent.populated(this.$__path) :
|
|
61
|
+
null;
|
|
62
|
+
|
|
63
|
+
if (populated != null) {
|
|
64
|
+
if (value.$__ == null) {
|
|
65
|
+
value = new populated.options.model(value);
|
|
66
|
+
}
|
|
67
|
+
value.$__.wasPopulated = true;
|
|
68
|
+
} else {
|
|
69
|
+
try {
|
|
70
|
+
value = this.$__schemaType.
|
|
71
|
+
applySetters(value, this.$__parent, false, this.get(key));
|
|
72
|
+
} catch (error) {
|
|
73
|
+
this.$__parent.invalidate(fullPath, error);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
super.set(key, value);
|
|
79
|
+
|
|
80
|
+
if (value != null && value.$isSingleNested) {
|
|
81
|
+
value.$basePath = this.$__path + '.' + key;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (this.$__parent != null && this.$__parent.$__) {
|
|
85
|
+
this.$__parent.markModified(this.$__path + '.' + key);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
toBSON() {
|
|
90
|
+
return new Map(this);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
toJSON() {
|
|
94
|
+
return new Map(this);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
inspect() {
|
|
98
|
+
return new Map(this);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
$__runDeferred() {
|
|
102
|
+
if (!this.$__deferred) {
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
for (let i = 0; i < this.$__deferred.length; ++i) {
|
|
106
|
+
this.set(this.$__deferred[i].key, this.$__deferred[i].value);
|
|
107
|
+
}
|
|
108
|
+
this.$__deferred = null;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
Object.defineProperty(MongooseMap.prototype, '$__parent', {
|
|
113
|
+
enumerable: false,
|
|
114
|
+
writable: true,
|
|
115
|
+
configurable: false
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
Object.defineProperty(MongooseMap.prototype, '$__path', {
|
|
119
|
+
enumerable: false,
|
|
120
|
+
writable: true,
|
|
121
|
+
configurable: false
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
Object.defineProperty(MongooseMap.prototype, '$__schemaType', {
|
|
125
|
+
enumerable: false,
|
|
126
|
+
writable: true,
|
|
127
|
+
configurable: false
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
Object.defineProperty(MongooseMap.prototype, '$isMongooseMap', {
|
|
131
|
+
enumerable: false,
|
|
132
|
+
writable: false,
|
|
133
|
+
configurable: false,
|
|
134
|
+
value: true
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
Object.defineProperty(MongooseMap.prototype, '$__deferredCalls', {
|
|
138
|
+
enumerable: false,
|
|
139
|
+
writable: false,
|
|
140
|
+
configurable: false,
|
|
141
|
+
value: true
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
module.exports = MongooseMap;
|
package/lib/types/objectid.js
CHANGED
|
@@ -10,4 +10,16 @@
|
|
|
10
10
|
|
|
11
11
|
var ObjectId = require('../drivers').ObjectId;
|
|
12
12
|
|
|
13
|
+
/*!
|
|
14
|
+
* Getter for convenience with populate, see gh-6115
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
Object.defineProperty(ObjectId.prototype, '_id', {
|
|
18
|
+
enumerable: false,
|
|
19
|
+
configurable: true,
|
|
20
|
+
get: function() {
|
|
21
|
+
return this;
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
|
|
13
25
|
module.exports = ObjectId;
|
package/lib/types/subdocument.js
CHANGED
|
@@ -36,7 +36,20 @@ Subdocument.prototype.toBSON = function() {
|
|
|
36
36
|
* @api private
|
|
37
37
|
*/
|
|
38
38
|
|
|
39
|
-
Subdocument.prototype.save = function(fn) {
|
|
39
|
+
Subdocument.prototype.save = function(options, fn) {
|
|
40
|
+
if (typeof options === 'function') {
|
|
41
|
+
fn = options;
|
|
42
|
+
options = {};
|
|
43
|
+
}
|
|
44
|
+
options = options || {};
|
|
45
|
+
|
|
46
|
+
if (!options.suppressWarning) {
|
|
47
|
+
console.warn('mongoose: calling `save()` on a subdoc does **not** save ' +
|
|
48
|
+
'the document to MongoDB, it only runs save middleware. ' +
|
|
49
|
+
'Use `subdoc.save({ suppressWarning: true })` to hide this warning ' +
|
|
50
|
+
'if you\'re sure this behavior is right for your app.');
|
|
51
|
+
}
|
|
52
|
+
|
|
40
53
|
return utils.promiseOrCallback(fn, cb => {
|
|
41
54
|
this.$__save(cb);
|
|
42
55
|
});
|
|
@@ -67,6 +80,7 @@ Subdocument.prototype.$isValid = function(path) {
|
|
|
67
80
|
|
|
68
81
|
Subdocument.prototype.markModified = function(path) {
|
|
69
82
|
Document.prototype.markModified.call(this, path);
|
|
83
|
+
|
|
70
84
|
if (this.$parent && this.$basePath) {
|
|
71
85
|
if (this.$parent.isDirectModified(this.$basePath)) {
|
|
72
86
|
return;
|
|
@@ -82,6 +96,10 @@ Subdocument.prototype.$markValid = function(path) {
|
|
|
82
96
|
}
|
|
83
97
|
};
|
|
84
98
|
|
|
99
|
+
/*!
|
|
100
|
+
* ignore
|
|
101
|
+
*/
|
|
102
|
+
|
|
85
103
|
Subdocument.prototype.invalidate = function(path, err, val) {
|
|
86
104
|
// Hack: array subdocuments' validationError is equal to the owner doc's,
|
|
87
105
|
// so validating an array subdoc gives the top-level doc back. Temporary
|
|
@@ -97,6 +115,17 @@ Subdocument.prototype.invalidate = function(path, err, val) {
|
|
|
97
115
|
}
|
|
98
116
|
};
|
|
99
117
|
|
|
118
|
+
/*!
|
|
119
|
+
* ignore
|
|
120
|
+
*/
|
|
121
|
+
|
|
122
|
+
Subdocument.prototype.$ignore = function(path) {
|
|
123
|
+
Document.prototype.$ignore.call(this, path);
|
|
124
|
+
if (this.$parent && this.$basePath) {
|
|
125
|
+
this.$parent.$ignore([this.$basePath, path].join('.'));
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
|
|
100
129
|
/**
|
|
101
130
|
* Returns the top level document of this sub-document.
|
|
102
131
|
*
|
package/lib/utils.js
CHANGED
|
@@ -446,9 +446,11 @@ exports.isMongooseObject = function(v) {
|
|
|
446
446
|
MongooseArray || (MongooseArray = require('./types').Array);
|
|
447
447
|
MongooseBuffer || (MongooseBuffer = require('./types').Buffer);
|
|
448
448
|
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
449
|
+
if (v == null) {
|
|
450
|
+
return false;
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
return v.$__ != null || v.isMongooseArray || v.isMongooseBuffer;
|
|
452
454
|
};
|
|
453
455
|
var isMongooseObject = exports.isMongooseObject;
|
|
454
456
|
|