mongoose 6.1.9 → 6.2.2
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/.eslintrc.json +154 -0
- package/CHANGELOG.md +59 -0
- package/dist/browser.umd.js +233 -222
- package/index.js +5 -1
- package/lib/aggregate.js +23 -28
- package/lib/browserDocument.js +1 -1
- package/lib/cast/number.js +2 -3
- package/lib/cast.js +9 -7
- package/lib/connection.js +76 -24
- package/lib/cursor/AggregationCursor.js +12 -7
- package/lib/cursor/QueryCursor.js +11 -6
- package/lib/document.js +107 -107
- package/lib/drivers/node-mongodb-native/collection.js +12 -4
- package/lib/drivers/node-mongodb-native/connection.js +11 -0
- package/lib/error/cast.js +3 -2
- package/lib/error/index.js +11 -0
- package/lib/error/syncIndexes.js +30 -0
- package/lib/helpers/clone.js +51 -29
- package/lib/helpers/common.js +2 -2
- package/lib/helpers/cursor/eachAsync.js +18 -15
- package/lib/helpers/document/compile.js +7 -4
- package/lib/helpers/getFunctionName.js +6 -4
- package/lib/helpers/isMongooseObject.js +9 -8
- package/lib/helpers/isObject.js +4 -4
- package/lib/helpers/model/discriminator.js +2 -1
- package/lib/helpers/path/parentPaths.js +10 -5
- package/lib/helpers/populate/assignRawDocsToIdStructure.js +4 -2
- package/lib/helpers/populate/assignVals.js +8 -4
- package/lib/helpers/populate/getModelsMapForPopulate.js +4 -4
- package/lib/helpers/populate/markArraySubdocsPopulated.js +3 -1
- package/lib/helpers/populate/modelNamesFromRefPath.js +4 -3
- package/lib/helpers/printJestWarning.js +2 -2
- package/lib/helpers/projection/applyProjection.js +77 -0
- package/lib/helpers/projection/hasIncludedChildren.js +36 -0
- package/lib/helpers/projection/isExclusive.js +5 -2
- package/lib/helpers/projection/isInclusive.js +5 -1
- package/lib/helpers/query/cast$expr.js +279 -0
- package/lib/helpers/query/castUpdate.js +6 -2
- package/lib/helpers/query/isOperator.js +5 -2
- package/lib/helpers/schema/applyPlugins.js +11 -0
- package/lib/helpers/schema/getPath.js +4 -2
- package/lib/helpers/timestamps/setupTimestamps.js +3 -8
- package/lib/index.js +28 -26
- package/lib/internal.js +1 -1
- package/lib/model.js +161 -122
- package/lib/options/SchemaTypeOptions.js +1 -1
- package/lib/plugins/trackTransaction.js +5 -4
- package/lib/query.js +159 -146
- package/lib/queryhelpers.js +10 -10
- package/lib/schema/SubdocumentPath.js +4 -3
- package/lib/schema/array.js +30 -21
- package/lib/schema/buffer.js +1 -1
- package/lib/schema/date.js +1 -1
- package/lib/schema/decimal128.js +1 -1
- package/lib/schema/documentarray.js +9 -11
- package/lib/schema/number.js +1 -1
- package/lib/schema/objectid.js +2 -2
- package/lib/schema/string.js +4 -4
- package/lib/schema.js +9 -8
- package/lib/schematype.js +77 -30
- package/lib/types/ArraySubdocument.js +2 -1
- package/lib/types/DocumentArray/index.js +10 -27
- package/lib/types/DocumentArray/isMongooseDocumentArray.js +5 -0
- package/lib/types/DocumentArray/methods/index.js +15 -3
- package/lib/types/array/index.js +22 -21
- package/lib/types/array/isMongooseArray.js +5 -0
- package/lib/types/array/methods/index.js +22 -23
- package/lib/types/buffer.js +3 -3
- package/lib/types/map.js +2 -3
- package/lib/utils.js +10 -7
- package/package.json +19 -151
- package/tools/repl.js +1 -1
- package/tsconfig.json +8 -0
- package/types/PipelineStage.d.ts +272 -0
- package/{index.d.ts → types/index.d.ts} +156 -357
- package/lib/types/array/ArrayWrapper.js +0 -981
package/lib/queryhelpers.js
CHANGED
|
@@ -26,9 +26,9 @@ exports.preparePopulationOptions = function preparePopulationOptions(query, opti
|
|
|
26
26
|
|
|
27
27
|
// lean options should trickle through all queries
|
|
28
28
|
if (options.lean != null) {
|
|
29
|
-
pop
|
|
30
|
-
filter(p =>
|
|
31
|
-
forEach(makeLean(options.lean));
|
|
29
|
+
pop
|
|
30
|
+
.filter(p => (p && p.options && p.options.lean) == null)
|
|
31
|
+
.forEach(makeLean(options.lean));
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
pop.forEach(opts => {
|
|
@@ -53,12 +53,12 @@ exports.preparePopulationOptionsMQ = function preparePopulationOptionsMQ(query,
|
|
|
53
53
|
|
|
54
54
|
// lean options should trickle through all queries
|
|
55
55
|
if (options.lean != null) {
|
|
56
|
-
pop
|
|
57
|
-
filter(p =>
|
|
58
|
-
forEach(makeLean(options.lean));
|
|
56
|
+
pop
|
|
57
|
+
.filter(p => (p && p.options && p.options.lean) == null)
|
|
58
|
+
.forEach(makeLean(options.lean));
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
-
const session =
|
|
61
|
+
const session = query && query.options && query.options.session || null;
|
|
62
62
|
if (session != null) {
|
|
63
63
|
pop.forEach(path => {
|
|
64
64
|
if (path.options == null) {
|
|
@@ -212,7 +212,7 @@ exports.applyPaths = function applyPaths(fields, schema) {
|
|
|
212
212
|
|
|
213
213
|
let addedPath = analyzePath(path, type);
|
|
214
214
|
// arrays
|
|
215
|
-
if (addedPath == null && type.$isMongooseArray && !type.$isMongooseDocumentArray) {
|
|
215
|
+
if (addedPath == null && !Array.isArray(type) && type.$isMongooseArray && !type.$isMongooseDocumentArray) {
|
|
216
216
|
addedPath = analyzePath(path, type.caster);
|
|
217
217
|
}
|
|
218
218
|
if (addedPath != null) {
|
|
@@ -272,7 +272,7 @@ exports.applyPaths = function applyPaths(fields, schema) {
|
|
|
272
272
|
// Special case: if user has included a parent path of a discriminator key,
|
|
273
273
|
// don't explicitly project in the discriminator key because that will
|
|
274
274
|
// project out everything else under the parent path
|
|
275
|
-
if (!exclude &&
|
|
275
|
+
if (!exclude && (type && type.options && type.options.$skipDiscriminatorCheck || false)) {
|
|
276
276
|
let cur = '';
|
|
277
277
|
for (let i = 0; i < pieces.length; ++i) {
|
|
278
278
|
cur += (cur.length === 0 ? '' : '.') + pieces[i];
|
|
@@ -319,7 +319,7 @@ exports.handleDeleteWriteOpResult = function handleDeleteWriteOpResult(callback)
|
|
|
319
319
|
return callback(error);
|
|
320
320
|
}
|
|
321
321
|
const mongooseResult = Object.assign({}, res.result);
|
|
322
|
-
if (
|
|
322
|
+
if ((res && res.result && res.result.n || null) != null) {
|
|
323
323
|
mongooseResult.deletedCount = res.result.n;
|
|
324
324
|
}
|
|
325
325
|
if (res.deletedCount != null) {
|
|
@@ -13,7 +13,6 @@ const $exists = require('./operators/exists');
|
|
|
13
13
|
const castToNumber = require('./operators/helpers').castToNumber;
|
|
14
14
|
const discriminator = require('../helpers/model/discriminator');
|
|
15
15
|
const geospatial = require('./operators/geospatial');
|
|
16
|
-
const get = require('../helpers/get');
|
|
17
16
|
const getConstructor = require('../helpers/discriminator/getConstructor');
|
|
18
17
|
const handleIdOption = require('../helpers/schema/handleIdOption');
|
|
19
18
|
const internalToObjectOptions = require('../options').internalToObjectOptions;
|
|
@@ -164,7 +163,7 @@ SubdocumentPath.prototype.cast = function(val, doc, init, priorVal, options) {
|
|
|
164
163
|
let subdoc;
|
|
165
164
|
|
|
166
165
|
// Only pull relevant selected paths and pull out the base path
|
|
167
|
-
const parentSelected =
|
|
166
|
+
const parentSelected = doc && doc.$__ && doc.$__.selected || {};
|
|
168
167
|
const path = this.path;
|
|
169
168
|
const selected = Object.keys(parentSelected).reduce((obj, key) => {
|
|
170
169
|
if (key.startsWith(path + '.')) {
|
|
@@ -301,7 +300,9 @@ SubdocumentPath.prototype.doValidateSync = function(value, scope, options) {
|
|
|
301
300
|
SubdocumentPath.prototype.discriminator = function(name, schema, options) {
|
|
302
301
|
options = options || {};
|
|
303
302
|
const value = utils.isPOJO(options) ? options.value : options;
|
|
304
|
-
const clone =
|
|
303
|
+
const clone = typeof options.clone === 'boolean'
|
|
304
|
+
? options.clone
|
|
305
|
+
: true;
|
|
305
306
|
|
|
306
307
|
if (schema.instanceOfSchema && clone) {
|
|
307
308
|
schema = schema.clone();
|
package/lib/schema/array.js
CHANGED
|
@@ -13,7 +13,6 @@ const CastError = SchemaType.CastError;
|
|
|
13
13
|
const Mixed = require('./mixed');
|
|
14
14
|
const arrayDepth = require('../helpers/arrayDepth');
|
|
15
15
|
const cast = require('../cast');
|
|
16
|
-
const get = require('../helpers/get');
|
|
17
16
|
const isOperator = require('../helpers/query/isOperator');
|
|
18
17
|
const util = require('util');
|
|
19
18
|
const utils = require('../utils');
|
|
@@ -112,14 +111,12 @@ function SchemaArray(key, cast, options, schemaOptions) {
|
|
|
112
111
|
|
|
113
112
|
if (!('defaultValue' in this) || this.defaultValue !== void 0) {
|
|
114
113
|
const defaultFn = function() {
|
|
115
|
-
let arr = [];
|
|
116
|
-
if (fn) {
|
|
117
|
-
arr = defaultArr.call(this);
|
|
118
|
-
} else if (defaultArr != null) {
|
|
119
|
-
arr = arr.concat(defaultArr);
|
|
120
|
-
}
|
|
121
114
|
// Leave it up to `cast()` to convert the array
|
|
122
|
-
return
|
|
115
|
+
return fn
|
|
116
|
+
? defaultArr.call(this)
|
|
117
|
+
: defaultArr != null
|
|
118
|
+
? [].concat(defaultArr)
|
|
119
|
+
: [];
|
|
123
120
|
};
|
|
124
121
|
defaultFn.$runBeforeSetters = !fn;
|
|
125
122
|
this.default(defaultFn);
|
|
@@ -220,7 +217,7 @@ SchemaArray.prototype.checkRequired = function checkRequired(value, doc) {
|
|
|
220
217
|
|
|
221
218
|
// `require('util').inherits()` does **not** copy static properties, and
|
|
222
219
|
// plugins like mongoose-float use `inherits()` for pre-ES6.
|
|
223
|
-
const _checkRequired = typeof this.constructor.checkRequired
|
|
220
|
+
const _checkRequired = typeof this.constructor.checkRequired === 'function' ?
|
|
224
221
|
this.constructor.checkRequired() :
|
|
225
222
|
SchemaArray.checkRequired();
|
|
226
223
|
|
|
@@ -238,7 +235,9 @@ SchemaArray.prototype.checkRequired = function checkRequired(value, doc) {
|
|
|
238
235
|
SchemaArray.prototype.enum = function() {
|
|
239
236
|
let arr = this;
|
|
240
237
|
while (true) {
|
|
241
|
-
const instance =
|
|
238
|
+
const instance = arr &&
|
|
239
|
+
arr.caster &&
|
|
240
|
+
arr.caster.instance;
|
|
242
241
|
if (instance === 'Array') {
|
|
243
242
|
arr = arr.caster;
|
|
244
243
|
continue;
|
|
@@ -275,7 +274,7 @@ SchemaArray.prototype.applyGetters = function(value, scope) {
|
|
|
275
274
|
|
|
276
275
|
const ret = SchemaType.prototype.applyGetters.call(this, value, scope);
|
|
277
276
|
if (Array.isArray(ret)) {
|
|
278
|
-
const rawValue = ret
|
|
277
|
+
const rawValue = utils.isMongooseArray(ret) ? ret.__array : ret;
|
|
279
278
|
const len = rawValue.length;
|
|
280
279
|
for (let i = 0; i < len; ++i) {
|
|
281
280
|
rawValue[i] = this.caster.applyGetters(rawValue[i], scope);
|
|
@@ -299,7 +298,7 @@ SchemaArray.prototype._applySetters = function(value, scope, init, priorVal) {
|
|
|
299
298
|
}
|
|
300
299
|
|
|
301
300
|
// No need to wrap empty arrays
|
|
302
|
-
if (value != null && value.length
|
|
301
|
+
if (value != null && value.length !== 0) {
|
|
303
302
|
const valueDepth = arrayDepth(value);
|
|
304
303
|
if (valueDepth.min === valueDepth.max && valueDepth.max < depth && valueDepth.containsNonArrayItem) {
|
|
305
304
|
for (let i = valueDepth.max; i < depth; ++i) {
|
|
@@ -357,7 +356,7 @@ SchemaArray.prototype.cast = function(value, doc, init, prev, options) {
|
|
|
357
356
|
|
|
358
357
|
options = options || emptyOpts;
|
|
359
358
|
|
|
360
|
-
let rawValue = value
|
|
359
|
+
let rawValue = utils.isMongooseArray(value) ? value.__array : value;
|
|
361
360
|
value = MongooseArray(rawValue, options.path || this._arrayPath || this.path, doc, this);
|
|
362
361
|
rawValue = value.__array;
|
|
363
362
|
|
|
@@ -557,12 +556,16 @@ function cast$all(val) {
|
|
|
557
556
|
}
|
|
558
557
|
|
|
559
558
|
val = val.map(function(v) {
|
|
560
|
-
if (utils.isObject(v)) {
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
559
|
+
if (!utils.isObject(v)) {
|
|
560
|
+
return v;
|
|
561
|
+
}
|
|
562
|
+
if (v.$elemMatch != null) {
|
|
563
|
+
return { $elemMatch: cast(this.casterConstructor.schema, v.$elemMatch) };
|
|
564
564
|
}
|
|
565
|
-
|
|
565
|
+
|
|
566
|
+
const o = {};
|
|
567
|
+
o[this.path] = v;
|
|
568
|
+
return cast(this.casterConstructor.schema, o)[this.path];
|
|
566
569
|
}, this);
|
|
567
570
|
|
|
568
571
|
return this.castForQuery(val);
|
|
@@ -581,9 +584,15 @@ function cast$elemMatch(val) {
|
|
|
581
584
|
|
|
582
585
|
// Is this an embedded discriminator and is the discriminator key set?
|
|
583
586
|
// If so, use the discriminator schema. See gh-7449
|
|
584
|
-
const discriminatorKey =
|
|
585
|
-
|
|
586
|
-
|
|
587
|
+
const discriminatorKey = this &&
|
|
588
|
+
this.casterConstructor &&
|
|
589
|
+
this.casterConstructor.schema &&
|
|
590
|
+
this.casterConstructor.schema.options &&
|
|
591
|
+
this.casterConstructor.schema.options.discriminatorKey;
|
|
592
|
+
const discriminators = this &&
|
|
593
|
+
this.casterConstructor &&
|
|
594
|
+
this.casterConstructor.schema &&
|
|
595
|
+
this.casterConstructor.schema.discriminators || {};
|
|
587
596
|
if (discriminatorKey != null &&
|
|
588
597
|
val[discriminatorKey] != null &&
|
|
589
598
|
discriminators[val[discriminatorKey]] != null) {
|
package/lib/schema/buffer.js
CHANGED
|
@@ -202,7 +202,7 @@ SchemaBuffer.prototype.cast = function(value, doc, init) {
|
|
|
202
202
|
|
|
203
203
|
/**
|
|
204
204
|
* Sets the default [subtype](https://studio3t.com/whats-new/best-practices-uuid-mongodb/)
|
|
205
|
-
* for this buffer. You can find a [list of allowed subtypes here](
|
|
205
|
+
* for this buffer. You can find a [list of allowed subtypes here](https://api.mongodb.com/python/current/api/bson/binary.html).
|
|
206
206
|
*
|
|
207
207
|
* ####Example:
|
|
208
208
|
*
|
package/lib/schema/date.js
CHANGED
|
@@ -201,7 +201,7 @@ SchemaDate.prototype.checkRequired = function(value, doc) {
|
|
|
201
201
|
|
|
202
202
|
// `require('util').inherits()` does **not** copy static properties, and
|
|
203
203
|
// plugins like mongoose-float use `inherits()` for pre-ES6.
|
|
204
|
-
const _checkRequired = typeof this.constructor.checkRequired
|
|
204
|
+
const _checkRequired = typeof this.constructor.checkRequired === 'function' ?
|
|
205
205
|
this.constructor.checkRequired() :
|
|
206
206
|
SchemaDate.checkRequired();
|
|
207
207
|
return _checkRequired(value);
|
package/lib/schema/decimal128.js
CHANGED
|
@@ -146,7 +146,7 @@ Decimal128.prototype.checkRequired = function checkRequired(value, doc) {
|
|
|
146
146
|
|
|
147
147
|
// `require('util').inherits()` does **not** copy static properties, and
|
|
148
148
|
// plugins like mongoose-float use `inherits()` for pre-ES6.
|
|
149
|
-
const _checkRequired = typeof this.constructor.checkRequired
|
|
149
|
+
const _checkRequired = typeof this.constructor.checkRequired === 'function' ?
|
|
150
150
|
this.constructor.checkRequired() :
|
|
151
151
|
Decimal128.checkRequired();
|
|
152
152
|
|
|
@@ -11,7 +11,6 @@ const SchemaDocumentArrayOptions =
|
|
|
11
11
|
require('../options/SchemaDocumentArrayOptions');
|
|
12
12
|
const SchemaType = require('../schematype');
|
|
13
13
|
const discriminator = require('../helpers/model/discriminator');
|
|
14
|
-
const get = require('../helpers/get');
|
|
15
14
|
const handleIdOption = require('../helpers/schema/handleIdOption');
|
|
16
15
|
const util = require('util');
|
|
17
16
|
const utils = require('../utils');
|
|
@@ -68,7 +67,9 @@ function DocumentArrayPath(key, schema, options, schemaOptions) {
|
|
|
68
67
|
|
|
69
68
|
const parentSchemaType = this;
|
|
70
69
|
this.$embeddedSchemaType = new SchemaType(key + '.$', {
|
|
71
|
-
required:
|
|
70
|
+
required: this &&
|
|
71
|
+
this.schemaOptions &&
|
|
72
|
+
this.schemaOptions.required || false
|
|
72
73
|
});
|
|
73
74
|
this.$embeddedSchemaType.cast = function(value, doc, init) {
|
|
74
75
|
return parentSchemaType.cast(value, doc, init)[0];
|
|
@@ -173,7 +174,7 @@ DocumentArrayPath.prototype.discriminator = function(name, schema, options) {
|
|
|
173
174
|
|
|
174
175
|
options = options || {};
|
|
175
176
|
const tiedValue = utils.isPOJO(options) ? options.value : options;
|
|
176
|
-
const clone =
|
|
177
|
+
const clone = typeof options.clone === 'boolean' ? options.clone : true;
|
|
177
178
|
|
|
178
179
|
if (schema.instanceOfSchema && clone) {
|
|
179
180
|
schema = schema.clone();
|
|
@@ -228,7 +229,7 @@ DocumentArrayPath.prototype.doValidate = function(array, fn, scope, options) {
|
|
|
228
229
|
if (options && options.updateValidator) {
|
|
229
230
|
return fn();
|
|
230
231
|
}
|
|
231
|
-
if (!
|
|
232
|
+
if (!utils.isMongooseDocumentArray(array)) {
|
|
232
233
|
array = new MongooseDocumentArray(array, _this.path, scope);
|
|
233
234
|
}
|
|
234
235
|
|
|
@@ -398,12 +399,9 @@ DocumentArrayPath.prototype.cast = function(value, doc, init, prev, options) {
|
|
|
398
399
|
return this.cast([value], doc, init, prev, options);
|
|
399
400
|
}
|
|
400
401
|
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
} else if (value && value.isMongooseDocumentArray) {
|
|
405
|
-
// We need to create a new array, otherwise change tracking will
|
|
406
|
-
// update the old doc (gh-4449)
|
|
402
|
+
// We need to create a new array, otherwise change tracking will
|
|
403
|
+
// update the old doc (gh-4449)
|
|
404
|
+
if (!options.skipDocumentArrayCast || utils.isMongooseDocumentArray(value)) {
|
|
407
405
|
value = new MongooseDocumentArray(value, this.path, doc);
|
|
408
406
|
}
|
|
409
407
|
|
|
@@ -415,7 +413,7 @@ DocumentArrayPath.prototype.cast = function(value, doc, init, prev, options) {
|
|
|
415
413
|
value[arrayPathSymbol] = this.path + '.' + options.arrayPathIndex;
|
|
416
414
|
}
|
|
417
415
|
|
|
418
|
-
const rawArray = value
|
|
416
|
+
const rawArray = utils.isMongooseDocumentArray(value) ? value.__array : value;
|
|
419
417
|
|
|
420
418
|
const len = rawArray.length;
|
|
421
419
|
const initDocumentOptions = { skipId: true, willInit: true };
|
package/lib/schema/number.js
CHANGED
|
@@ -170,7 +170,7 @@ SchemaNumber.prototype.checkRequired = function checkRequired(value, doc) {
|
|
|
170
170
|
|
|
171
171
|
// `require('util').inherits()` does **not** copy static properties, and
|
|
172
172
|
// plugins like mongoose-float use `inherits()` for pre-ES6.
|
|
173
|
-
const _checkRequired = typeof this.constructor.checkRequired
|
|
173
|
+
const _checkRequired = typeof this.constructor.checkRequired === 'function' ?
|
|
174
174
|
this.constructor.checkRequired() :
|
|
175
175
|
SchemaNumber.checkRequired();
|
|
176
176
|
|
package/lib/schema/objectid.js
CHANGED
|
@@ -204,7 +204,7 @@ ObjectId.prototype.checkRequired = function checkRequired(value, doc) {
|
|
|
204
204
|
|
|
205
205
|
// `require('util').inherits()` does **not** copy static properties, and
|
|
206
206
|
// plugins like mongoose-float use `inherits()` for pre-ES6.
|
|
207
|
-
const _checkRequired = typeof this.constructor.checkRequired
|
|
207
|
+
const _checkRequired = typeof this.constructor.checkRequired === 'function' ?
|
|
208
208
|
this.constructor.checkRequired() :
|
|
209
209
|
ObjectId.checkRequired();
|
|
210
210
|
|
|
@@ -281,7 +281,7 @@ function resetId(v) {
|
|
|
281
281
|
|
|
282
282
|
if (this instanceof Document) {
|
|
283
283
|
if (v === void 0) {
|
|
284
|
-
const _v = new oid;
|
|
284
|
+
const _v = new oid();
|
|
285
285
|
this.$__._id = _v;
|
|
286
286
|
return _v;
|
|
287
287
|
}
|
package/lib/schema/string.js
CHANGED
|
@@ -253,7 +253,7 @@ SchemaString.prototype.enum = function() {
|
|
|
253
253
|
};
|
|
254
254
|
|
|
255
255
|
/**
|
|
256
|
-
* Adds a lowercase [setter](
|
|
256
|
+
* Adds a lowercase [setter](https://mongoosejs.com/docs/api.html#schematype_SchemaType-set).
|
|
257
257
|
*
|
|
258
258
|
* ####Example:
|
|
259
259
|
*
|
|
@@ -291,7 +291,7 @@ SchemaString.prototype.lowercase = function(shouldApply) {
|
|
|
291
291
|
};
|
|
292
292
|
|
|
293
293
|
/**
|
|
294
|
-
* Adds an uppercase [setter](
|
|
294
|
+
* Adds an uppercase [setter](https://mongoosejs.com/docs/api.html#schematype_SchemaType-set).
|
|
295
295
|
*
|
|
296
296
|
* ####Example:
|
|
297
297
|
*
|
|
@@ -327,7 +327,7 @@ SchemaString.prototype.uppercase = function(shouldApply) {
|
|
|
327
327
|
};
|
|
328
328
|
|
|
329
329
|
/**
|
|
330
|
-
* Adds a trim [setter](
|
|
330
|
+
* Adds a trim [setter](https://mongoosejs.com/docs/api.html#schematype_SchemaType-set).
|
|
331
331
|
*
|
|
332
332
|
* The string value will be [trimmed](https://masteringjs.io/tutorials/fundamentals/trim-string) when set.
|
|
333
333
|
*
|
|
@@ -566,7 +566,7 @@ SchemaString.prototype.checkRequired = function checkRequired(value, doc) {
|
|
|
566
566
|
|
|
567
567
|
// `require('util').inherits()` does **not** copy static properties, and
|
|
568
568
|
// plugins like mongoose-float use `inherits()` for pre-ES6.
|
|
569
|
-
const _checkRequired = typeof this.constructor.checkRequired
|
|
569
|
+
const _checkRequired = typeof this.constructor.checkRequired === 'function' ?
|
|
570
570
|
this.constructor.checkRequired() :
|
|
571
571
|
SchemaString.checkRequired();
|
|
572
572
|
|
package/lib/schema.js
CHANGED
|
@@ -75,6 +75,7 @@ let id = 0;
|
|
|
75
75
|
* - [selectPopulatedPaths](/docs/guide.html#selectPopulatedPaths): boolean - defaults to `true`
|
|
76
76
|
* - [skipVersioning](/docs/guide.html#skipVersioning): object - paths to exclude from versioning
|
|
77
77
|
* - [timestamps](/docs/guide.html#timestamps): object or boolean - defaults to `false`. If true, Mongoose adds `createdAt` and `updatedAt` properties to your schema and manages those properties for you.
|
|
78
|
+
* - [pluginTags](/docs/guide.html#pluginTags): array of strings - defaults to `undefined`. If set and plugin called with `tags` option, will only apply that plugin to schemas with a matching tag.
|
|
78
79
|
*
|
|
79
80
|
* ####Options for Nested Schemas:
|
|
80
81
|
* - `excludeIndexes`: bool - defaults to `false`. If `true`, skip building indexes on this schema's paths.
|
|
@@ -85,7 +86,7 @@ let id = 0;
|
|
|
85
86
|
*
|
|
86
87
|
* @param {Object|Schema|Array} [definition] Can be one of: object describing schema paths, or schema to copy, or array of objects and schemas
|
|
87
88
|
* @param {Object} [options]
|
|
88
|
-
* @inherits NodeJS EventEmitter
|
|
89
|
+
* @inherits NodeJS EventEmitter https://nodejs.org/api/events.html#events_class_events_eventemitter
|
|
89
90
|
* @event `init`: Emitted after the schema is compiled into a `Model`.
|
|
90
91
|
* @api public
|
|
91
92
|
*/
|
|
@@ -424,7 +425,7 @@ Schema.prototype.pick = function(paths, options) {
|
|
|
424
425
|
|
|
425
426
|
Schema.prototype.defaultOptions = function(options) {
|
|
426
427
|
this._userProvidedOptions = options == null ? {} : utils.clone(options);
|
|
427
|
-
const baseOptions =
|
|
428
|
+
const baseOptions = this.base && this.base.options || {};
|
|
428
429
|
|
|
429
430
|
const strict = 'strict' in baseOptions ? baseOptions.strict : true;
|
|
430
431
|
options = utils.options({
|
|
@@ -518,7 +519,7 @@ Schema.prototype.add = function add(obj, prefix) {
|
|
|
518
519
|
if (key === '_id' && val === false) {
|
|
519
520
|
continue;
|
|
520
521
|
}
|
|
521
|
-
if (val instanceof VirtualType ||
|
|
522
|
+
if (val instanceof VirtualType || (val.constructor && val.constructor.name || null) === 'VirtualType') {
|
|
522
523
|
this.virtual(val);
|
|
523
524
|
continue;
|
|
524
525
|
}
|
|
@@ -1035,7 +1036,7 @@ Schema.prototype.interpretAsType = function(path, obj, options) {
|
|
|
1035
1036
|
if (!MongooseTypes.hasOwnProperty(name)) {
|
|
1036
1037
|
throw new TypeError('Invalid schema configuration: ' +
|
|
1037
1038
|
`\`${name}\` is not a valid type within the array \`${path}\`.` +
|
|
1038
|
-
'See
|
|
1039
|
+
'See https://bit.ly/mongoose-schematypes for a list of valid schema types.');
|
|
1039
1040
|
}
|
|
1040
1041
|
}
|
|
1041
1042
|
|
|
@@ -1075,7 +1076,7 @@ Schema.prototype.interpretAsType = function(path, obj, options) {
|
|
|
1075
1076
|
if (MongooseTypes[name] == null) {
|
|
1076
1077
|
throw new TypeError(`Invalid schema configuration: \`${name}\` is not ` +
|
|
1077
1078
|
`a valid type at path \`${path}\`. See ` +
|
|
1078
|
-
'
|
|
1079
|
+
'https://bit.ly/mongoose-schematypes for a list of valid schema types.');
|
|
1079
1080
|
}
|
|
1080
1081
|
|
|
1081
1082
|
const schemaType = new MongooseTypes[name](path, obj);
|
|
@@ -1470,8 +1471,8 @@ Schema.prototype.pre = function(name) {
|
|
|
1470
1471
|
* @param {Boolean} [options.document] If `name` is a hook for both document and query middleware, set to `true` to run on document middleware.
|
|
1471
1472
|
* @param {Boolean} [options.query] If `name` is a hook for both document and query middleware, set to `true` to run on query middleware.
|
|
1472
1473
|
* @param {Function} fn callback
|
|
1473
|
-
* @see middleware
|
|
1474
|
-
* @see kareem
|
|
1474
|
+
* @see middleware https://mongoosejs.com/docs/middleware.html
|
|
1475
|
+
* @see kareem https://npmjs.org/package/kareem
|
|
1475
1476
|
* @api public
|
|
1476
1477
|
*/
|
|
1477
1478
|
|
|
@@ -1618,7 +1619,7 @@ Schema.prototype.static = function(name, fn) {
|
|
|
1618
1619
|
* schema.index({ first: 1, last: -1 })
|
|
1619
1620
|
*
|
|
1620
1621
|
* @param {Object} fields
|
|
1621
|
-
* @param {Object} [options] Options to pass to [MongoDB driver's `createIndex()` function](
|
|
1622
|
+
* @param {Object} [options] Options to pass to [MongoDB driver's `createIndex()` function](https://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#createIndex)
|
|
1622
1623
|
* @param {String | number} [options.expires=null] Mongoose-specific syntactic sugar, uses [ms](https://www.npmjs.com/package/ms) to convert `expires` option into seconds for the `expireAfterSeconds` in the above link.
|
|
1623
1624
|
* @api public
|
|
1624
1625
|
*/
|
package/lib/schematype.js
CHANGED
|
@@ -8,7 +8,6 @@ const MongooseError = require('./error/index');
|
|
|
8
8
|
const SchemaTypeOptions = require('./options/SchemaTypeOptions');
|
|
9
9
|
const $exists = require('./schema/operators/exists');
|
|
10
10
|
const $type = require('./schema/operators/type');
|
|
11
|
-
const get = require('./helpers/get');
|
|
12
11
|
const handleImmutable = require('./helpers/schematype/handleImmutable');
|
|
13
12
|
const isAsyncFunction = require('./helpers/isAsyncFunction');
|
|
14
13
|
const immediate = require('./helpers/immediate');
|
|
@@ -128,6 +127,51 @@ function SchemaType(path, options, instance) {
|
|
|
128
127
|
|
|
129
128
|
SchemaType.prototype.OptionsConstructor = SchemaTypeOptions;
|
|
130
129
|
|
|
130
|
+
/**
|
|
131
|
+
* The path to this SchemaType in a Schema.
|
|
132
|
+
*
|
|
133
|
+
* ####Example:
|
|
134
|
+
* const schema = new Schema({ name: String });
|
|
135
|
+
* schema.path('name').path; // 'name'
|
|
136
|
+
*
|
|
137
|
+
* @property path
|
|
138
|
+
* @api public
|
|
139
|
+
* @memberOf SchemaType
|
|
140
|
+
*/
|
|
141
|
+
|
|
142
|
+
SchemaType.prototype.path;
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* The validators that Mongoose should run to validate properties at this SchemaType's path.
|
|
146
|
+
*
|
|
147
|
+
* ####Example:
|
|
148
|
+
* const schema = new Schema({ name: { type: String, required: true } });
|
|
149
|
+
* schema.path('name').validators.length; // 1, the `required` validator
|
|
150
|
+
*
|
|
151
|
+
* @property validators
|
|
152
|
+
* @api public
|
|
153
|
+
* @memberOf SchemaType
|
|
154
|
+
*/
|
|
155
|
+
|
|
156
|
+
SchemaType.prototype.validators;
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* True if this SchemaType has a required validator. False otherwise.
|
|
160
|
+
*
|
|
161
|
+
* ####Example:
|
|
162
|
+
* const schema = new Schema({ name: { type: String, required: true } });
|
|
163
|
+
* schema.path('name').isRequired; // true
|
|
164
|
+
*
|
|
165
|
+
* schema.path('name').required(false);
|
|
166
|
+
* schema.path('name').isRequired; // false
|
|
167
|
+
*
|
|
168
|
+
* @property isRequired
|
|
169
|
+
* @api public
|
|
170
|
+
* @memberOf SchemaType
|
|
171
|
+
*/
|
|
172
|
+
|
|
173
|
+
SchemaType.prototype.validators;
|
|
174
|
+
|
|
131
175
|
/*!
|
|
132
176
|
* ignore
|
|
133
177
|
*/
|
|
@@ -743,7 +787,7 @@ SchemaType.prototype.get = function(fn) {
|
|
|
743
787
|
*
|
|
744
788
|
* // make sure every value is equal to "something"
|
|
745
789
|
* function validator (val) {
|
|
746
|
-
* return val
|
|
790
|
+
* return val === 'something';
|
|
747
791
|
* }
|
|
748
792
|
* new Schema({ name: { type: String, validate: validator }});
|
|
749
793
|
*
|
|
@@ -871,7 +915,7 @@ SchemaType.prototype.validate = function(obj, message, type) {
|
|
|
871
915
|
if (!utils.isPOJO(arg)) {
|
|
872
916
|
const msg = 'Invalid validator. Received (' + typeof arg + ') '
|
|
873
917
|
+ arg
|
|
874
|
-
+ '. See
|
|
918
|
+
+ '. See https://mongoosejs.com/docs/api.html#schematype_SchemaType-validate';
|
|
875
919
|
|
|
876
920
|
throw new Error(msg);
|
|
877
921
|
}
|
|
@@ -981,7 +1025,7 @@ SchemaType.prototype.required = function(required, message) {
|
|
|
981
1025
|
this.isRequired = true;
|
|
982
1026
|
|
|
983
1027
|
this.requiredValidator = function(v) {
|
|
984
|
-
const cachedRequired =
|
|
1028
|
+
const cachedRequired = this && this.$__ && this.$__.cachedRequired;
|
|
985
1029
|
|
|
986
1030
|
// no validation when this path wasn't selected in the query.
|
|
987
1031
|
if (cachedRequired != null && !this.$__isSelected(_this.path) && !this[documentIsModified](_this.path)) {
|
|
@@ -1080,7 +1124,7 @@ SchemaType.prototype.getDefault = function(scope, init) {
|
|
|
1080
1124
|
}
|
|
1081
1125
|
|
|
1082
1126
|
const casted = this.applySetters(ret, scope, init);
|
|
1083
|
-
if (casted && casted.$isSingleNested) {
|
|
1127
|
+
if (casted && !Array.isArray(casted) && casted.$isSingleNested) {
|
|
1084
1128
|
casted.$__parent = scope;
|
|
1085
1129
|
}
|
|
1086
1130
|
return casted;
|
|
@@ -1283,6 +1327,16 @@ SchemaType.prototype.doValidate = function(value, fn, scope, options) {
|
|
|
1283
1327
|
}
|
|
1284
1328
|
};
|
|
1285
1329
|
|
|
1330
|
+
|
|
1331
|
+
function _validate(ok, validatorProperties) {
|
|
1332
|
+
if (ok !== undefined && !ok) {
|
|
1333
|
+
const ErrorConstructor = validatorProperties.ErrorConstructor || ValidatorError;
|
|
1334
|
+
const err = new ErrorConstructor(validatorProperties);
|
|
1335
|
+
err[validatorErrorSymbol] = true;
|
|
1336
|
+
return err;
|
|
1337
|
+
}
|
|
1338
|
+
}
|
|
1339
|
+
|
|
1286
1340
|
/**
|
|
1287
1341
|
* Performs a validation of `value` using the validators declared for this SchemaType.
|
|
1288
1342
|
*
|
|
@@ -1306,7 +1360,7 @@ SchemaType.prototype.doValidateSync = function(value, scope, options) {
|
|
|
1306
1360
|
|
|
1307
1361
|
let validators = this.validators;
|
|
1308
1362
|
if (value === void 0) {
|
|
1309
|
-
if (this.validators.length
|
|
1363
|
+
if (this.validators.length !== 0 && this.validators[0].type === 'required') {
|
|
1310
1364
|
validators = [this.validators[0]];
|
|
1311
1365
|
} else {
|
|
1312
1366
|
return null;
|
|
@@ -1314,34 +1368,35 @@ SchemaType.prototype.doValidateSync = function(value, scope, options) {
|
|
|
1314
1368
|
}
|
|
1315
1369
|
|
|
1316
1370
|
let err = null;
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1371
|
+
let i = 0;
|
|
1372
|
+
const len = validators.length;
|
|
1373
|
+
for (i = 0; i < len; ++i) {
|
|
1374
|
+
|
|
1375
|
+
const v = validators[i];
|
|
1321
1376
|
|
|
1322
1377
|
if (v == null || typeof v !== 'object') {
|
|
1323
|
-
|
|
1378
|
+
continue;
|
|
1324
1379
|
}
|
|
1325
1380
|
|
|
1326
1381
|
const validator = v.validator;
|
|
1327
1382
|
const validatorProperties = utils.clone(v);
|
|
1328
1383
|
validatorProperties.path = options && options.path ? options.path : path;
|
|
1329
1384
|
validatorProperties.value = value;
|
|
1330
|
-
let ok;
|
|
1385
|
+
let ok = false;
|
|
1331
1386
|
|
|
1332
1387
|
// Skip any explicit async validators. Validators that return a promise
|
|
1333
1388
|
// will still run, but won't trigger any errors.
|
|
1334
1389
|
if (isAsyncFunction(validator)) {
|
|
1335
|
-
|
|
1390
|
+
continue;
|
|
1336
1391
|
}
|
|
1337
1392
|
|
|
1338
1393
|
if (validator instanceof RegExp) {
|
|
1339
|
-
|
|
1340
|
-
|
|
1394
|
+
err = _validate(validator.test(value), validatorProperties);
|
|
1395
|
+
continue;
|
|
1341
1396
|
}
|
|
1342
1397
|
|
|
1343
1398
|
if (typeof validator !== 'function') {
|
|
1344
|
-
|
|
1399
|
+
continue;
|
|
1345
1400
|
}
|
|
1346
1401
|
|
|
1347
1402
|
try {
|
|
@@ -1358,23 +1413,15 @@ SchemaType.prototype.doValidateSync = function(value, scope, options) {
|
|
|
1358
1413
|
// Skip any validators that return a promise, we can't handle those
|
|
1359
1414
|
// synchronously
|
|
1360
1415
|
if (ok != null && typeof ok.then === 'function') {
|
|
1361
|
-
|
|
1416
|
+
continue;
|
|
1362
1417
|
}
|
|
1363
|
-
|
|
1364
|
-
});
|
|
1365
|
-
|
|
1366
|
-
return err;
|
|
1367
|
-
|
|
1368
|
-
function validate(ok, validatorProperties) {
|
|
1418
|
+
err = _validate(ok, validatorProperties);
|
|
1369
1419
|
if (err) {
|
|
1370
|
-
|
|
1371
|
-
}
|
|
1372
|
-
if (ok !== undefined && !ok) {
|
|
1373
|
-
const ErrorConstructor = validatorProperties.ErrorConstructor || ValidatorError;
|
|
1374
|
-
err = new ErrorConstructor(validatorProperties);
|
|
1375
|
-
err[validatorErrorSymbol] = true;
|
|
1420
|
+
break;
|
|
1376
1421
|
}
|
|
1377
1422
|
}
|
|
1423
|
+
|
|
1424
|
+
return err;
|
|
1378
1425
|
};
|
|
1379
1426
|
|
|
1380
1427
|
/**
|
|
@@ -1585,7 +1632,7 @@ SchemaType.prototype._castForQuery = function(val) {
|
|
|
1585
1632
|
*/
|
|
1586
1633
|
|
|
1587
1634
|
SchemaType.checkRequired = function(fn) {
|
|
1588
|
-
if (arguments.length
|
|
1635
|
+
if (arguments.length !== 0) {
|
|
1589
1636
|
this._checkRequired = fn;
|
|
1590
1637
|
}
|
|
1591
1638
|
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
const EventEmitter = require('events').EventEmitter;
|
|
8
8
|
const Subdocument = require('./subdocument');
|
|
9
|
+
const utils = require('../utils');
|
|
9
10
|
|
|
10
11
|
const documentArrayParent = require('../helpers/symbols').documentArrayParent;
|
|
11
12
|
|
|
@@ -20,7 +21,7 @@ const documentArrayParent = require('../helpers/symbols').documentArrayParent;
|
|
|
20
21
|
*/
|
|
21
22
|
|
|
22
23
|
function ArraySubdocument(obj, parentArr, skipId, fields, index) {
|
|
23
|
-
if (
|
|
24
|
+
if (utils.isMongooseDocumentArray(parentArr)) {
|
|
24
25
|
this.__parentArray = parentArr;
|
|
25
26
|
this[documentArrayParent] = parentArr.$parent();
|
|
26
27
|
} else {
|