mongoose 5.7.4 → 5.7.8
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 +40 -0
- package/lib/aggregate.js +3 -3
- package/lib/cast.js +8 -0
- package/lib/connection.js +29 -17
- package/lib/cursor/AggregationCursor.js +10 -0
- package/lib/document.js +98 -13
- package/lib/error/validation.js +4 -2
- package/lib/helpers/cursor/eachAsync.js +54 -50
- package/lib/helpers/updateValidators.js +3 -0
- package/lib/index.js +9 -0
- package/lib/model.js +9 -7
- package/lib/options/SchemaArrayOptions.js +13 -0
- package/lib/options/SchemaBufferOptions.js +13 -0
- package/lib/options/SchemaDateOptions.js +13 -0
- package/lib/options/SchemaNumberOptions.js +13 -0
- package/lib/options/SchemaObjectIdOptions.js +13 -0
- package/lib/options/SchemaStringOptions.js +39 -0
- package/lib/options/SchemaTypeOptions.js +22 -5
- package/lib/query.js +1 -1
- package/lib/queryhelpers.js +1 -1
- package/lib/schema/SingleNestedPath.js +5 -3
- package/lib/schema/array.js +2 -2
- package/lib/schema/documentarray.js +42 -17
- package/lib/schema/string.js +23 -12
- package/lib/schema.js +7 -13
- package/lib/schematype.js +3 -3
- package/lib/types/core_array.js +4 -1
- package/lib/types/documentarray.js +81 -0
- package/lib/types/subdocument.js +13 -0
- package/package.json +3 -6
|
@@ -2,6 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
const SchemaTypeOptions = require('./SchemaTypeOptions');
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* The options defined on a Number schematype.
|
|
7
|
+
*
|
|
8
|
+
* ####Example:
|
|
9
|
+
*
|
|
10
|
+
* const schema = new Schema({ count: Number });
|
|
11
|
+
* schema.path('count').options; // SchemaNumberOptions instance
|
|
12
|
+
*
|
|
13
|
+
* @api public
|
|
14
|
+
* @inherits SchemaTypeOptions
|
|
15
|
+
* @constructor SchemaNumberOptions
|
|
16
|
+
*/
|
|
17
|
+
|
|
5
18
|
class SchemaNumberOptions extends SchemaTypeOptions {}
|
|
6
19
|
|
|
7
20
|
const opts = {
|
|
@@ -2,6 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
const SchemaTypeOptions = require('./SchemaTypeOptions');
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* The options defined on an ObjectId schematype.
|
|
7
|
+
*
|
|
8
|
+
* ####Example:
|
|
9
|
+
*
|
|
10
|
+
* const schema = new Schema({ testId: mongoose.ObjectId });
|
|
11
|
+
* schema.path('testId').options; // SchemaObjectIdOptions instance
|
|
12
|
+
*
|
|
13
|
+
* @api public
|
|
14
|
+
* @inherits SchemaTypeOptions
|
|
15
|
+
* @constructor SchemaObjectIdOptions
|
|
16
|
+
*/
|
|
17
|
+
|
|
5
18
|
class SchemaObjectIdOptions extends SchemaTypeOptions {}
|
|
6
19
|
|
|
7
20
|
const opts = {
|
|
@@ -2,6 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
const SchemaTypeOptions = require('./SchemaTypeOptions');
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* The options defined on a string schematype.
|
|
7
|
+
*
|
|
8
|
+
* ####Example:
|
|
9
|
+
*
|
|
10
|
+
* const schema = new Schema({ name: String });
|
|
11
|
+
* schema.path('name').options; // SchemaStringOptions instance
|
|
12
|
+
*
|
|
13
|
+
* @api public
|
|
14
|
+
* @inherits SchemaTypeOptions
|
|
15
|
+
* @constructor SchemaStringOptions
|
|
16
|
+
*/
|
|
17
|
+
|
|
5
18
|
class SchemaStringOptions extends SchemaTypeOptions {}
|
|
6
19
|
|
|
7
20
|
const opts = {
|
|
@@ -75,6 +88,32 @@ Object.defineProperty(SchemaStringOptions.prototype, 'trim', opts);
|
|
|
75
88
|
|
|
76
89
|
Object.defineProperty(SchemaStringOptions.prototype, 'uppercase', opts);
|
|
77
90
|
|
|
91
|
+
/**
|
|
92
|
+
* If set, Mongoose will add a custom validator that ensures the given
|
|
93
|
+
* string's `length` is at least the given number.
|
|
94
|
+
*
|
|
95
|
+
* @api public
|
|
96
|
+
* @property minlength
|
|
97
|
+
* @memberOf SchemaStringOptions
|
|
98
|
+
* @type Number
|
|
99
|
+
* @instance
|
|
100
|
+
*/
|
|
101
|
+
|
|
102
|
+
Object.defineProperty(SchemaStringOptions.prototype, 'minlength', opts);
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* If set, Mongoose will add a custom validator that ensures the given
|
|
106
|
+
* string's `length` is at most the given number.
|
|
107
|
+
*
|
|
108
|
+
* @api public
|
|
109
|
+
* @property maxlength
|
|
110
|
+
* @memberOf SchemaStringOptions
|
|
111
|
+
* @type Number
|
|
112
|
+
* @instance
|
|
113
|
+
*/
|
|
114
|
+
|
|
115
|
+
Object.defineProperty(SchemaStringOptions.prototype, 'maxlength', opts);
|
|
116
|
+
|
|
78
117
|
/*!
|
|
79
118
|
* ignore
|
|
80
119
|
*/
|
|
@@ -2,6 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
const utils = require('../utils');
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* The options defined on a schematype.
|
|
7
|
+
*
|
|
8
|
+
* ####Example:
|
|
9
|
+
*
|
|
10
|
+
* const schema = new Schema({ name: String });
|
|
11
|
+
* schema.path('name').options instanceof mongoose.SchemaTypeOptions; // true
|
|
12
|
+
*
|
|
13
|
+
* @api public
|
|
14
|
+
* @constructor SchemaTypeOptions
|
|
15
|
+
*/
|
|
16
|
+
|
|
5
17
|
class SchemaTypeOptions {
|
|
6
18
|
constructor(obj) {
|
|
7
19
|
if (obj == null) {
|
|
@@ -95,7 +107,8 @@ Object.defineProperty(SchemaTypeOptions.prototype, 'ref', opts);
|
|
|
95
107
|
Object.defineProperty(SchemaTypeOptions.prototype, 'select', opts);
|
|
96
108
|
|
|
97
109
|
/**
|
|
98
|
-
* If truthy, Mongoose will
|
|
110
|
+
* If [truthy](https://masteringjs.io/tutorials/fundamentals/truthy), Mongoose will
|
|
111
|
+
* build an index on this path when the model is
|
|
99
112
|
* compiled.
|
|
100
113
|
*
|
|
101
114
|
* @api public
|
|
@@ -108,7 +121,8 @@ Object.defineProperty(SchemaTypeOptions.prototype, 'select', opts);
|
|
|
108
121
|
Object.defineProperty(SchemaTypeOptions.prototype, 'index', opts);
|
|
109
122
|
|
|
110
123
|
/**
|
|
111
|
-
* If truthy, Mongoose
|
|
124
|
+
* If [truthy](https://masteringjs.io/tutorials/fundamentals/truthy), Mongoose
|
|
125
|
+
* will build a unique index on this path when the
|
|
112
126
|
* model is compiled. [The `unique` option is **not** a validator](/docs/validation.html#the-unique-option-is-not-a-validator).
|
|
113
127
|
*
|
|
114
128
|
* @api public
|
|
@@ -121,7 +135,8 @@ Object.defineProperty(SchemaTypeOptions.prototype, 'index', opts);
|
|
|
121
135
|
Object.defineProperty(SchemaTypeOptions.prototype, 'unique', opts);
|
|
122
136
|
|
|
123
137
|
/**
|
|
124
|
-
* If truthy, Mongoose will
|
|
138
|
+
* If [truthy](https://masteringjs.io/tutorials/fundamentals/truthy), Mongoose will
|
|
139
|
+
* disallow changes to this path once the document
|
|
125
140
|
* is saved to the database for the first time. Read more about [immutability in Mongoose here](http://thecodebarbarian.com/whats-new-in-mongoose-5-6-immutable-properties.html).
|
|
126
141
|
*
|
|
127
142
|
* @api public
|
|
@@ -134,7 +149,8 @@ Object.defineProperty(SchemaTypeOptions.prototype, 'unique', opts);
|
|
|
134
149
|
Object.defineProperty(SchemaTypeOptions.prototype, 'immutable', opts);
|
|
135
150
|
|
|
136
151
|
/**
|
|
137
|
-
* If truthy, Mongoose will
|
|
152
|
+
* If [truthy](https://masteringjs.io/tutorials/fundamentals/truthy), Mongoose will
|
|
153
|
+
* build a sparse index on this path.
|
|
138
154
|
*
|
|
139
155
|
* @api public
|
|
140
156
|
* @property sparse
|
|
@@ -146,7 +162,8 @@ Object.defineProperty(SchemaTypeOptions.prototype, 'immutable', opts);
|
|
|
146
162
|
Object.defineProperty(SchemaTypeOptions.prototype, 'sparse', opts);
|
|
147
163
|
|
|
148
164
|
/**
|
|
149
|
-
* If truthy, Mongoose
|
|
165
|
+
* If [truthy](https://masteringjs.io/tutorials/fundamentals/truthy), Mongoose
|
|
166
|
+
* will build a text index on this path.
|
|
150
167
|
*
|
|
151
168
|
* @api public
|
|
152
169
|
* @property text
|
package/lib/query.js
CHANGED
|
@@ -1941,7 +1941,7 @@ Query.prototype._find = wrapThunk(function(callback) {
|
|
|
1941
1941
|
* // Using callbacks
|
|
1942
1942
|
* Movie.find({ year: { $gte: 1980, $lte: 1989 } }, function(err, arr) {});
|
|
1943
1943
|
*
|
|
1944
|
-
* @param {Object} [filter] mongodb selector. If not specified, returns all documents.
|
|
1944
|
+
* @param {Object|ObjectId} [filter] mongodb selector. If not specified, returns all documents.
|
|
1945
1945
|
* @param {Function} [callback]
|
|
1946
1946
|
* @return {Query} this
|
|
1947
1947
|
* @api public
|
package/lib/queryhelpers.js
CHANGED
|
@@ -107,7 +107,7 @@ exports.getDiscriminatorByValue = getDiscriminatorByValue;
|
|
|
107
107
|
* @param {Object} doc
|
|
108
108
|
* @param {Object} fields
|
|
109
109
|
*
|
|
110
|
-
* @return {
|
|
110
|
+
* @return {Document}
|
|
111
111
|
*/
|
|
112
112
|
exports.createModel = function createModel(model, doc, fields, userProvidedFields) {
|
|
113
113
|
model.hooks.execPreSync('createModel', doc);
|
|
@@ -274,17 +274,19 @@ SingleNestedPath.prototype.doValidateSync = function(value, scope, options) {
|
|
|
274
274
|
* const shapeSchema = Schema({ name: String }, { discriminatorKey: 'kind' });
|
|
275
275
|
* const schema = Schema({ shape: shapeSchema });
|
|
276
276
|
*
|
|
277
|
-
* const singleNestedPath = parentSchema.path('
|
|
277
|
+
* const singleNestedPath = parentSchema.path('shape');
|
|
278
278
|
* singleNestedPath.discriminator('Circle', Schema({ radius: Number }));
|
|
279
279
|
*
|
|
280
280
|
* @param {String} name
|
|
281
281
|
* @param {Schema} schema fields to add to the schema for instances of this sub-class
|
|
282
|
+
* @param {String} [value] the string stored in the `discriminatorKey` property. If not specified, Mongoose uses the `name` parameter.
|
|
283
|
+
* @return {Function} the constructor Mongoose will use for creating instances of this discriminator model
|
|
282
284
|
* @see discriminators /docs/discriminators.html
|
|
283
285
|
* @api public
|
|
284
286
|
*/
|
|
285
287
|
|
|
286
|
-
SingleNestedPath.prototype.discriminator = function(name, schema,
|
|
287
|
-
discriminator(this.caster, name, schema,
|
|
288
|
+
SingleNestedPath.prototype.discriminator = function(name, schema, value) {
|
|
289
|
+
discriminator(this.caster, name, schema, value);
|
|
288
290
|
|
|
289
291
|
this.caster.discriminators[name] = _createConstructor(schema, this.caster);
|
|
290
292
|
|
package/lib/schema/array.js
CHANGED
|
@@ -196,8 +196,8 @@ SchemaArray.prototype.checkRequired = function checkRequired(value, doc) {
|
|
|
196
196
|
*/
|
|
197
197
|
|
|
198
198
|
SchemaArray.prototype.enum = function() {
|
|
199
|
-
let arr = this;
|
|
200
|
-
while (true) {
|
|
199
|
+
let arr = this;
|
|
200
|
+
while (true) {
|
|
201
201
|
const instance = get(arr, 'caster.instance');
|
|
202
202
|
if (instance === 'Array') {
|
|
203
203
|
arr = arr.caster;
|
|
@@ -9,6 +9,7 @@ const CastError = require('../error/cast');
|
|
|
9
9
|
const EventEmitter = require('events').EventEmitter;
|
|
10
10
|
const SchemaType = require('../schematype');
|
|
11
11
|
const discriminator = require('../helpers/model/discriminator');
|
|
12
|
+
const get = require('../helpers/get');
|
|
12
13
|
const util = require('util');
|
|
13
14
|
const utils = require('../utils');
|
|
14
15
|
const getConstructor = require('../helpers/discriminator/getConstructor');
|
|
@@ -29,7 +30,7 @@ let Subdocument;
|
|
|
29
30
|
* @api public
|
|
30
31
|
*/
|
|
31
32
|
|
|
32
|
-
function
|
|
33
|
+
function DocumentArrayPath(key, schema, options, schemaOptions) {
|
|
33
34
|
const EmbeddedDocument = _createConstructor(schema, options);
|
|
34
35
|
EmbeddedDocument.prototype.$basePath = key;
|
|
35
36
|
|
|
@@ -54,6 +55,17 @@ function DocumentArray(key, schema, options, schemaOptions) {
|
|
|
54
55
|
return arr;
|
|
55
56
|
});
|
|
56
57
|
}
|
|
58
|
+
|
|
59
|
+
const parentSchemaType = this;
|
|
60
|
+
this.$embeddedSchemaType = new SchemaType(key + '.$', {
|
|
61
|
+
required: get(this, 'schemaOptions.required', false)
|
|
62
|
+
});
|
|
63
|
+
this.$embeddedSchemaType.cast = function(value, doc, init) {
|
|
64
|
+
return parentSchemaType.cast(value, doc, init)[0];
|
|
65
|
+
};
|
|
66
|
+
this.$embeddedSchemaType.$isMongooseDocumentArrayElement = true;
|
|
67
|
+
this.$embeddedSchemaType.caster = this.Constructor;
|
|
68
|
+
this.$embeddedSchemaType.schema = this.schema;
|
|
57
69
|
}
|
|
58
70
|
|
|
59
71
|
/**
|
|
@@ -62,24 +74,23 @@ function DocumentArray(key, schema, options, schemaOptions) {
|
|
|
62
74
|
*
|
|
63
75
|
* @api public
|
|
64
76
|
*/
|
|
65
|
-
|
|
77
|
+
DocumentArrayPath.schemaName = 'DocumentArray';
|
|
66
78
|
|
|
67
79
|
/**
|
|
68
80
|
* Options for all document arrays.
|
|
69
81
|
*
|
|
70
82
|
* - `castNonArrays`: `true` by default. If `false`, Mongoose will throw a CastError when a value isn't an array. If `true`, Mongoose will wrap the provided value in an array before casting.
|
|
71
83
|
*
|
|
72
|
-
* @static options
|
|
73
84
|
* @api public
|
|
74
85
|
*/
|
|
75
86
|
|
|
76
|
-
|
|
87
|
+
DocumentArrayPath.options = { castNonArrays: true };
|
|
77
88
|
|
|
78
89
|
/*!
|
|
79
90
|
* Inherits from ArrayType.
|
|
80
91
|
*/
|
|
81
|
-
|
|
82
|
-
|
|
92
|
+
DocumentArrayPath.prototype = Object.create(ArrayType.prototype);
|
|
93
|
+
DocumentArrayPath.prototype.constructor = DocumentArrayPath;
|
|
83
94
|
|
|
84
95
|
/*!
|
|
85
96
|
* Ignore
|
|
@@ -122,11 +133,25 @@ function _createConstructor(schema, options, baseClass) {
|
|
|
122
133
|
return EmbeddedDocument;
|
|
123
134
|
}
|
|
124
135
|
|
|
125
|
-
|
|
126
|
-
*
|
|
136
|
+
/**
|
|
137
|
+
* Adds a discriminator to this document array.
|
|
138
|
+
*
|
|
139
|
+
* ####Example:
|
|
140
|
+
* const shapeSchema = Schema({ name: String }, { discriminatorKey: 'kind' });
|
|
141
|
+
* const schema = Schema({ shapes: [shapeSchema] });
|
|
142
|
+
*
|
|
143
|
+
* const docArrayPath = parentSchema.path('shapes');
|
|
144
|
+
* docArrayPath.discriminator('Circle', Schema({ radius: Number }));
|
|
145
|
+
*
|
|
146
|
+
* @param {String} name
|
|
147
|
+
* @param {Schema} schema fields to add to the schema for instances of this sub-class
|
|
148
|
+
* @param {String} [value] the string stored in the `discriminatorKey` property. If not specified, Mongoose uses the `name` parameter.
|
|
149
|
+
* @see discriminators /docs/discriminators.html
|
|
150
|
+
* @return {Function} the constructor Mongoose will use for creating instances of this discriminator model
|
|
151
|
+
* @api public
|
|
127
152
|
*/
|
|
128
153
|
|
|
129
|
-
|
|
154
|
+
DocumentArrayPath.prototype.discriminator = function(name, schema, tiedValue) {
|
|
130
155
|
if (typeof name === 'function') {
|
|
131
156
|
name = utils.getFunctionName(name);
|
|
132
157
|
}
|
|
@@ -155,7 +180,7 @@ DocumentArray.prototype.discriminator = function(name, schema, tiedValue) {
|
|
|
155
180
|
* @api private
|
|
156
181
|
*/
|
|
157
182
|
|
|
158
|
-
|
|
183
|
+
DocumentArrayPath.prototype.doValidate = function(array, fn, scope, options) {
|
|
159
184
|
// lazy load
|
|
160
185
|
MongooseDocumentArray || (MongooseDocumentArray = require('../types/documentarray'));
|
|
161
186
|
|
|
@@ -231,7 +256,7 @@ DocumentArray.prototype.doValidate = function(array, fn, scope, options) {
|
|
|
231
256
|
* @api private
|
|
232
257
|
*/
|
|
233
258
|
|
|
234
|
-
|
|
259
|
+
DocumentArrayPath.prototype.doValidateSync = function(array, scope) {
|
|
235
260
|
const schemaTypeError = SchemaType.prototype.doValidateSync.call(this, array, scope);
|
|
236
261
|
if (schemaTypeError != null) {
|
|
237
262
|
schemaTypeError.$isArrayValidatorError = true;
|
|
@@ -277,7 +302,7 @@ DocumentArray.prototype.doValidateSync = function(array, scope) {
|
|
|
277
302
|
* ignore
|
|
278
303
|
*/
|
|
279
304
|
|
|
280
|
-
|
|
305
|
+
DocumentArrayPath.prototype.getDefault = function(scope) {
|
|
281
306
|
let ret = typeof this.defaultValue === 'function'
|
|
282
307
|
? this.defaultValue.call(scope)
|
|
283
308
|
: this.defaultValue;
|
|
@@ -316,7 +341,7 @@ DocumentArray.prototype.getDefault = function(scope) {
|
|
|
316
341
|
* @api private
|
|
317
342
|
*/
|
|
318
343
|
|
|
319
|
-
|
|
344
|
+
DocumentArrayPath.prototype.cast = function(value, doc, init, prev, options) {
|
|
320
345
|
// lazy load
|
|
321
346
|
MongooseDocumentArray || (MongooseDocumentArray = require('../types/documentarray'));
|
|
322
347
|
|
|
@@ -326,7 +351,7 @@ DocumentArray.prototype.cast = function(value, doc, init, prev, options) {
|
|
|
326
351
|
const _opts = { transform: false, virtuals: false };
|
|
327
352
|
|
|
328
353
|
if (!Array.isArray(value)) {
|
|
329
|
-
if (!init && !
|
|
354
|
+
if (!init && !DocumentArrayPath.options.castNonArrays) {
|
|
330
355
|
throw new CastError('DocumentArray', util.inspect(value), this.path);
|
|
331
356
|
}
|
|
332
357
|
// gh-2442 mark whole array as modified if we're initializing a doc from
|
|
@@ -416,7 +441,7 @@ DocumentArray.prototype.cast = function(value, doc, init, prev, options) {
|
|
|
416
441
|
* ignore
|
|
417
442
|
*/
|
|
418
443
|
|
|
419
|
-
|
|
444
|
+
DocumentArrayPath.prototype.clone = function() {
|
|
420
445
|
const options = Object.assign({}, this.options);
|
|
421
446
|
const schematype = new this.constructor(this.path, this.schema, options, this.schemaOptions);
|
|
422
447
|
schematype.validators = this.validators.slice();
|
|
@@ -429,7 +454,7 @@ DocumentArray.prototype.clone = function() {
|
|
|
429
454
|
* Scopes paths selected in a query to this array.
|
|
430
455
|
* Necessary for proper default application of subdocument values.
|
|
431
456
|
*
|
|
432
|
-
* @param {
|
|
457
|
+
* @param {DocumentArrayPath} array - the array to scope `fields` paths
|
|
433
458
|
* @param {Object|undefined} fields - the root fields selected in the query
|
|
434
459
|
* @param {Boolean|undefined} init - if we are being created part of a query result
|
|
435
460
|
*/
|
|
@@ -469,4 +494,4 @@ function scopePaths(array, fields, init) {
|
|
|
469
494
|
* Module exports.
|
|
470
495
|
*/
|
|
471
496
|
|
|
472
|
-
module.exports =
|
|
497
|
+
module.exports = DocumentArrayPath;
|
package/lib/schema/string.js
CHANGED
|
@@ -43,7 +43,12 @@ SchemaString.schemaName = 'String';
|
|
|
43
43
|
*/
|
|
44
44
|
SchemaString.prototype = Object.create(SchemaType.prototype);
|
|
45
45
|
SchemaString.prototype.constructor = SchemaString;
|
|
46
|
-
SchemaString.prototype
|
|
46
|
+
Object.defineProperty(SchemaString.prototype, 'OptionsConstructor', {
|
|
47
|
+
configurable: false,
|
|
48
|
+
enumerable: false,
|
|
49
|
+
writable: false,
|
|
50
|
+
value: SchemaStringOptions
|
|
51
|
+
});
|
|
47
52
|
|
|
48
53
|
/*!
|
|
49
54
|
* ignore
|
|
@@ -574,17 +579,23 @@ function handleArray(val) {
|
|
|
574
579
|
});
|
|
575
580
|
}
|
|
576
581
|
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
582
|
+
const $conditionalHandlers = utils.options(SchemaType.prototype.$conditionalHandlers, {
|
|
583
|
+
$all: handleArray,
|
|
584
|
+
$gt: handleSingle,
|
|
585
|
+
$gte: handleSingle,
|
|
586
|
+
$lt: handleSingle,
|
|
587
|
+
$lte: handleSingle,
|
|
588
|
+
$options: String,
|
|
589
|
+
$regex: handleSingle,
|
|
590
|
+
$not: handleSingle
|
|
591
|
+
});
|
|
592
|
+
|
|
593
|
+
Object.defineProperty(SchemaString.prototype, '$conditionalHandlers', {
|
|
594
|
+
configurable: false,
|
|
595
|
+
enumerable: false,
|
|
596
|
+
writable: false,
|
|
597
|
+
value: Object.freeze($conditionalHandlers)
|
|
598
|
+
});
|
|
588
599
|
|
|
589
600
|
/**
|
|
590
601
|
* Casts contents for queries.
|
package/lib/schema.js
CHANGED
|
@@ -402,7 +402,6 @@ Schema.prototype.add = function add(obj, prefix) {
|
|
|
402
402
|
// the `_id` option. This behavior never worked before 5.4.11 but numerous
|
|
403
403
|
// codebases use it (see gh-7516, gh-7512).
|
|
404
404
|
if (obj._id === false && prefix == null) {
|
|
405
|
-
delete obj._id;
|
|
406
405
|
this.options._id = false;
|
|
407
406
|
}
|
|
408
407
|
|
|
@@ -417,6 +416,10 @@ Schema.prototype.add = function add(obj, prefix) {
|
|
|
417
416
|
throw new TypeError('Invalid value for schema path `' + fullPath +
|
|
418
417
|
'`, got value "' + obj[key] + '"');
|
|
419
418
|
}
|
|
419
|
+
// Retain `_id: false` but don't set it as a path, re: gh-8274.
|
|
420
|
+
if (key === '_id' && obj[key] === false) {
|
|
421
|
+
continue;
|
|
422
|
+
}
|
|
420
423
|
|
|
421
424
|
if (Array.isArray(obj[key]) && obj[key].length === 1 && obj[key][0] == null) {
|
|
422
425
|
throw new TypeError('Invalid value for schema Array path `' + fullPath +
|
|
@@ -1179,16 +1182,7 @@ function getPositionalPathType(self, path) {
|
|
|
1179
1182
|
|
|
1180
1183
|
if (i === last && val && !/\D/.test(subpath)) {
|
|
1181
1184
|
if (val.$isMongooseDocumentArray) {
|
|
1182
|
-
|
|
1183
|
-
val = new SchemaType(subpath, {
|
|
1184
|
-
required: get(val, 'schemaOptions.required', false)
|
|
1185
|
-
});
|
|
1186
|
-
val.cast = function(value, doc, init) {
|
|
1187
|
-
return oldVal.cast(value, doc, init)[0];
|
|
1188
|
-
};
|
|
1189
|
-
val.$isMongooseDocumentArrayElement = true;
|
|
1190
|
-
val.caster = oldVal.caster;
|
|
1191
|
-
val.schema = oldVal.schema;
|
|
1185
|
+
val = val.$embeddedSchemaType;
|
|
1192
1186
|
} else if (val instanceof MongooseTypes.Array) {
|
|
1193
1187
|
// StringSchema, NumberSchema, etc
|
|
1194
1188
|
val = val.caster;
|
|
@@ -1637,8 +1631,8 @@ Schema.prototype.indexes = function() {
|
|
|
1637
1631
|
* @param {String|Model} [options.ref] model name or model instance. Marks this as a [populate virtual](populate.html#populate-virtuals).
|
|
1638
1632
|
* @param {String|Function} [options.localField] Required for populate virtuals. See [populate virtual docs](populate.html#populate-virtuals) for more information.
|
|
1639
1633
|
* @param {String|Function} [options.foreignField] Required for populate virtuals. See [populate virtual docs](populate.html#populate-virtuals) for more information.
|
|
1640
|
-
* @param {Boolean|Function} [options.justOne=false] Only works with populate virtuals. If truthy, will be a single doc or `null`. Otherwise, the populate virtual will be an array.
|
|
1641
|
-
* @param {Boolean} [options.count=false] Only works with populate virtuals. If truthy, this populate virtual will contain the number of documents rather than the documents themselves when you `populate()`.
|
|
1634
|
+
* @param {Boolean|Function} [options.justOne=false] Only works with populate virtuals. If [truthy](https://masteringjs.io/tutorials/fundamentals/truthy), will be a single doc or `null`. Otherwise, the populate virtual will be an array.
|
|
1635
|
+
* @param {Boolean} [options.count=false] Only works with populate virtuals. If [truthy](https://masteringjs.io/tutorials/fundamentals/truthy), this populate virtual will contain the number of documents rather than the documents themselves when you `populate()`.
|
|
1642
1636
|
* @return {VirtualType}
|
|
1643
1637
|
*/
|
|
1644
1638
|
|
package/lib/schematype.js
CHANGED
|
@@ -29,7 +29,7 @@ const ValidatorError = MongooseError.ValidatorError;
|
|
|
29
29
|
* schema.path('name') instanceof SchemaType; // true
|
|
30
30
|
*
|
|
31
31
|
* @param {String} path
|
|
32
|
-
* @param {
|
|
32
|
+
* @param {SchemaTypeOptions} [options] See [SchemaTypeOptions docs](/docs/api/schematypeoptions.html)
|
|
33
33
|
* @param {String} [instance]
|
|
34
34
|
* @api public
|
|
35
35
|
*/
|
|
@@ -664,7 +664,7 @@ SchemaType.prototype.get = function(fn) {
|
|
|
664
664
|
* Product.on('error', handleError);
|
|
665
665
|
*
|
|
666
666
|
* @param {RegExp|Function|Object} obj validator function, or hash describing options
|
|
667
|
-
* @param {Function} [obj.validator] validator function. If the validator function returns `undefined` or a truthy value, validation succeeds. If it returns falsy (except `undefined`) or throws an error, validation fails.
|
|
667
|
+
* @param {Function} [obj.validator] validator function. If the validator function returns `undefined` or a truthy value, validation succeeds. If it returns [falsy](https://masteringjs.io/tutorials/fundamentals/falsy) (except `undefined`) or throws an error, validation fails.
|
|
668
668
|
* @param {String|Function} [obj.message] optional error message. If function, should return the error message as a string
|
|
669
669
|
* @param {Boolean} [obj.propsParameter=false] If true, Mongoose will pass the validator properties object (with the `validator` function, `message`, etc.) as the 2nd arg to the validator function. This is disabled by default because many validators [rely on positional args](https://github.com/chriso/validator.js#validators), so turning this on may cause unpredictable behavior in external validators.
|
|
670
670
|
* @param {String|Function} [errorMsg] optional error message. If function, should return the error message as a string
|
|
@@ -1265,7 +1265,7 @@ SchemaType._isRef = function(self, value, doc, init) {
|
|
|
1265
1265
|
// - setting / pushing values after population
|
|
1266
1266
|
const path = doc.$__fullPath(self.path);
|
|
1267
1267
|
const owner = doc.ownerDocument ? doc.ownerDocument() : doc;
|
|
1268
|
-
ref = owner.populated(path);
|
|
1268
|
+
ref = owner.populated(path) || doc.populated(self.path);
|
|
1269
1269
|
}
|
|
1270
1270
|
|
|
1271
1271
|
if (ref) {
|
package/lib/types/core_array.js
CHANGED
|
@@ -628,8 +628,9 @@ class CoreMongooseArray extends Array {
|
|
|
628
628
|
|
|
629
629
|
_checkManualPopulation(this, arguments);
|
|
630
630
|
|
|
631
|
+
const parent = this[arrayParentSymbol];
|
|
631
632
|
let values = [].map.call(arguments, this._mapCast, this);
|
|
632
|
-
values = this[arraySchemaSymbol].applySetters(values,
|
|
633
|
+
values = this[arraySchemaSymbol].applySetters(values, parent, undefined,
|
|
633
634
|
undefined, { skipDocumentArrayCast: true });
|
|
634
635
|
const ret = [].push.apply(this, values);
|
|
635
636
|
|
|
@@ -723,6 +724,7 @@ class CoreMongooseArray extends Array {
|
|
|
723
724
|
* @api public
|
|
724
725
|
* @method sort
|
|
725
726
|
* @memberOf MongooseArray
|
|
727
|
+
* @see https://masteringjs.io/tutorials/fundamentals/array-sort
|
|
726
728
|
*/
|
|
727
729
|
|
|
728
730
|
sort() {
|
|
@@ -741,6 +743,7 @@ class CoreMongooseArray extends Array {
|
|
|
741
743
|
* @api public
|
|
742
744
|
* @method splice
|
|
743
745
|
* @memberOf MongooseArray
|
|
746
|
+
* @see https://masteringjs.io/tutorials/fundamentals/array-splice
|
|
744
747
|
*/
|
|
745
748
|
|
|
746
749
|
splice() {
|
|
@@ -172,6 +172,64 @@ class CoreDocumentArray extends CoreMongooseArray {
|
|
|
172
172
|
}));
|
|
173
173
|
}
|
|
174
174
|
|
|
175
|
+
/**
|
|
176
|
+
* Wraps [`Array#push`](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/push) with proper change tracking.
|
|
177
|
+
*
|
|
178
|
+
* @param {Object} [args...]
|
|
179
|
+
* @api public
|
|
180
|
+
* @method push
|
|
181
|
+
* @memberOf MongooseDocumentArray
|
|
182
|
+
*/
|
|
183
|
+
|
|
184
|
+
push() {
|
|
185
|
+
const ret = super.push.apply(this, arguments);
|
|
186
|
+
|
|
187
|
+
_updateParentPopulated(this);
|
|
188
|
+
|
|
189
|
+
return ret;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Pulls items from the array atomically.
|
|
194
|
+
*
|
|
195
|
+
* @param {Object} [args...]
|
|
196
|
+
* @api public
|
|
197
|
+
* @method pull
|
|
198
|
+
* @memberOf MongooseDocumentArray
|
|
199
|
+
*/
|
|
200
|
+
|
|
201
|
+
pull() {
|
|
202
|
+
const ret = super.pull.apply(this, arguments);
|
|
203
|
+
|
|
204
|
+
_updateParentPopulated(this);
|
|
205
|
+
|
|
206
|
+
return ret;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Wraps [`Array#shift`](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/unshift) with proper change tracking.
|
|
211
|
+
*/
|
|
212
|
+
|
|
213
|
+
shift() {
|
|
214
|
+
const ret = super.shift.apply(this, arguments);
|
|
215
|
+
|
|
216
|
+
_updateParentPopulated(this);
|
|
217
|
+
|
|
218
|
+
return ret;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Wraps [`Array#splice`](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/splice) with proper change tracking and casting.
|
|
223
|
+
*/
|
|
224
|
+
|
|
225
|
+
splice() {
|
|
226
|
+
const ret = super.splice.apply(this, arguments);
|
|
227
|
+
|
|
228
|
+
_updateParentPopulated(this);
|
|
229
|
+
|
|
230
|
+
return ret;
|
|
231
|
+
}
|
|
232
|
+
|
|
175
233
|
/**
|
|
176
234
|
* Helper for console.log
|
|
177
235
|
*
|
|
@@ -254,6 +312,29 @@ if (util.inspect.custom) {
|
|
|
254
312
|
CoreDocumentArray.prototype.inspect;
|
|
255
313
|
}
|
|
256
314
|
|
|
315
|
+
/*!
|
|
316
|
+
* If this is a document array, each element may contain single
|
|
317
|
+
* populated paths, so we need to modify the top-level document's
|
|
318
|
+
* populated cache. See gh-8247, gh-8265.
|
|
319
|
+
*/
|
|
320
|
+
|
|
321
|
+
function _updateParentPopulated(arr) {
|
|
322
|
+
const parent = arr[arrayParentSymbol];
|
|
323
|
+
if (parent.$__.populated != null) {
|
|
324
|
+
const populatedPaths = Object.keys(parent.$__.populated).
|
|
325
|
+
filter(p => p.startsWith(arr[arrayPathSymbol] + '.'));
|
|
326
|
+
|
|
327
|
+
for (const path of populatedPaths) {
|
|
328
|
+
const remnant = path.slice((arr[arrayPathSymbol] + '.').length);
|
|
329
|
+
if (!Array.isArray(parent.$__.populated[path].value)) {
|
|
330
|
+
continue;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
parent.$__.populated[path].value = arr.map(val => val.populated(remnant));
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
257
338
|
/**
|
|
258
339
|
* DocumentArray constructor
|
|
259
340
|
*
|
package/lib/types/subdocument.js
CHANGED
|
@@ -115,6 +115,19 @@ Subdocument.prototype.markModified = function(path) {
|
|
|
115
115
|
}
|
|
116
116
|
};
|
|
117
117
|
|
|
118
|
+
Subdocument.prototype.isModified = function(paths, modifiedPaths) {
|
|
119
|
+
if (this.$parent && this.$basePath) {
|
|
120
|
+
if (Array.isArray(paths) || typeof paths === 'string') {
|
|
121
|
+
paths = (Array.isArray(paths) ? paths : paths.split(' '));
|
|
122
|
+
paths = paths.map(p => [this.$basePath, p].join('.'));
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return this.$parent.isModified(paths, modifiedPaths);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return Document.prototype.isModified(paths, modifiedPaths);
|
|
129
|
+
};
|
|
130
|
+
|
|
118
131
|
/**
|
|
119
132
|
* Marks a path as valid, removing existing validation errors.
|
|
120
133
|
*
|