mongoose 8.20.0 → 9.0.0-rc1
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/eslint.config.mjs +198 -0
- package/lib/aggregate.js +17 -73
- package/lib/cast/bigint.js +1 -1
- package/lib/cast/double.js +1 -1
- package/lib/cast/uuid.js +5 -48
- package/lib/cast.js +2 -2
- package/lib/connection.js +0 -1
- package/lib/cursor/aggregationCursor.js +14 -24
- package/lib/cursor/queryCursor.js +7 -14
- package/lib/document.js +125 -121
- package/lib/drivers/node-mongodb-native/connection.js +3 -10
- package/lib/error/objectParameter.js +1 -2
- package/lib/error/validation.js +0 -8
- package/lib/helpers/clone.js +1 -1
- package/lib/helpers/common.js +1 -1
- package/lib/helpers/indexes/isIndexEqual.js +0 -1
- package/lib/helpers/model/applyDefaultsToPOJO.js +2 -2
- package/lib/helpers/model/applyHooks.js +43 -53
- package/lib/helpers/model/applyMethods.js +2 -2
- package/lib/helpers/model/applyStaticHooks.js +1 -48
- package/lib/helpers/model/castBulkWrite.js +1 -1
- package/lib/helpers/parallelLimit.js +18 -36
- package/lib/helpers/pluralize.js +3 -3
- package/lib/helpers/populate/assignRawDocsToIdStructure.js +1 -8
- package/lib/helpers/populate/createPopulateQueryFilter.js +1 -1
- package/lib/helpers/populate/getModelsMapForPopulate.js +17 -9
- package/lib/helpers/populate/getSchemaTypes.js +5 -5
- package/lib/helpers/query/cast$expr.js +8 -10
- package/lib/helpers/query/castFilterPath.js +1 -1
- package/lib/helpers/query/castUpdate.js +14 -12
- package/lib/helpers/query/getEmbeddedDiscriminatorPath.js +1 -1
- package/lib/helpers/schema/applyPlugins.js +1 -1
- package/lib/helpers/schema/getIndexes.js +1 -7
- package/lib/helpers/timestamps/setupTimestamps.js +3 -6
- package/lib/helpers/updateValidators.js +57 -111
- package/lib/model.js +419 -607
- package/lib/mongoose.js +41 -13
- package/lib/plugins/saveSubdocs.js +24 -51
- package/lib/plugins/sharding.js +5 -4
- package/lib/plugins/validateBeforeSave.js +3 -13
- package/lib/query.js +101 -145
- package/lib/queryHelpers.js +2 -2
- package/lib/schema/array.js +41 -84
- package/lib/schema/documentArray.js +57 -94
- package/lib/schema/documentArrayElement.js +16 -11
- package/lib/schema/string.js +1 -1
- package/lib/schema/subdocument.js +22 -28
- package/lib/schema/uuid.js +0 -21
- package/lib/schema.js +81 -39
- package/lib/schemaType.js +39 -57
- package/lib/types/array/index.js +2 -2
- package/lib/types/array/methods/index.js +4 -4
- package/lib/types/arraySubdocument.js +1 -1
- package/lib/types/buffer.js +10 -10
- package/lib/types/decimal128.js +1 -1
- package/lib/types/documentArray/index.js +1 -1
- package/lib/types/documentArray/methods/index.js +5 -3
- package/lib/types/double.js +1 -1
- package/lib/types/objectid.js +1 -1
- package/lib/types/subdocument.js +15 -43
- package/lib/types/uuid.js +1 -1
- package/lib/utils.js +1 -8
- package/lib/validOptions.js +3 -3
- package/package.json +11 -24
- package/types/connection.d.ts +20 -11
- package/types/document.d.ts +95 -26
- package/types/index.d.ts +143 -39
- package/types/inferhydrateddoctype.d.ts +115 -0
- package/types/inferrawdoctype.d.ts +99 -75
- package/types/inferschematype.d.ts +17 -3
- package/types/middlewares.d.ts +0 -2
- package/types/models.d.ts +131 -199
- package/types/mongooseoptions.d.ts +6 -5
- package/types/pipelinestage.d.ts +1 -1
- package/types/query.d.ts +71 -139
- package/types/schemaoptions.d.ts +1 -1
- package/types/schematypes.d.ts +14 -10
- package/types/types.d.ts +3 -4
- package/types/utility.d.ts +68 -48
- package/types/validation.d.ts +18 -14
- package/browser.js +0 -8
- package/dist/browser.umd.js +0 -2
- package/lib/browser.js +0 -141
- package/lib/browserDocument.js +0 -101
- package/lib/documentProvider.js +0 -30
- package/lib/drivers/browser/binary.js +0 -14
- package/lib/drivers/browser/decimal128.js +0 -7
- package/lib/drivers/browser/index.js +0 -13
- package/lib/drivers/browser/objectid.js +0 -29
- package/lib/helpers/promiseOrCallback.js +0 -54
package/lib/schema/array.js
CHANGED
|
@@ -28,7 +28,6 @@ const getDiscriminatorByValue = require('../helpers/discriminator/getDiscriminat
|
|
|
28
28
|
let MongooseArray;
|
|
29
29
|
let EmbeddedDoc;
|
|
30
30
|
|
|
31
|
-
const isNestedArraySymbol = Symbol('mongoose#isNestedArray');
|
|
32
31
|
const emptyOpts = Object.freeze({});
|
|
33
32
|
|
|
34
33
|
/**
|
|
@@ -81,31 +80,21 @@ function SchemaArray(key, cast, options, schemaOptions, parentSchema) {
|
|
|
81
80
|
: utils.getFunctionName(cast);
|
|
82
81
|
|
|
83
82
|
const Types = require('./index.js');
|
|
84
|
-
const
|
|
83
|
+
const schemaTypeDefinition = Types.hasOwnProperty(name) ? Types[name] : cast;
|
|
85
84
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
this.casterConstructor[isNestedArraySymbol] = true;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
if (typeof caster === 'function' &&
|
|
93
|
-
!caster.$isArraySubdocument &&
|
|
94
|
-
!caster.$isSchemaMap) {
|
|
95
|
-
const path = this.caster instanceof EmbeddedDoc ? null : key;
|
|
96
|
-
if (caster === SchemaArray) {
|
|
97
|
-
this.caster = new caster(path, castOptions, schemaOptions, null, parentSchema);
|
|
85
|
+
if (typeof schemaTypeDefinition === 'function') {
|
|
86
|
+
if (schemaTypeDefinition === SchemaArray) {
|
|
87
|
+
this.embeddedSchemaType = new schemaTypeDefinition(key, castOptions, schemaOptions, null, parentSchema);
|
|
98
88
|
} else {
|
|
99
|
-
this.
|
|
89
|
+
this.embeddedSchemaType = new schemaTypeDefinition(key, castOptions, schemaOptions, parentSchema);
|
|
100
90
|
}
|
|
101
|
-
} else {
|
|
102
|
-
this.
|
|
103
|
-
if (!(this.
|
|
104
|
-
this.
|
|
91
|
+
} else if (schemaTypeDefinition instanceof SchemaType) {
|
|
92
|
+
this.embeddedSchemaType = schemaTypeDefinition;
|
|
93
|
+
if (!(this.embeddedSchemaType instanceof EmbeddedDoc)) {
|
|
94
|
+
this.embeddedSchemaType.path = key;
|
|
105
95
|
}
|
|
106
96
|
}
|
|
107
97
|
|
|
108
|
-
this.$embeddedSchemaType = this.caster;
|
|
109
98
|
}
|
|
110
99
|
|
|
111
100
|
this.$isMongooseArray = true;
|
|
@@ -267,10 +256,10 @@ SchemaArray.prototype.enum = function() {
|
|
|
267
256
|
let arr = this;
|
|
268
257
|
while (true) {
|
|
269
258
|
const instance = arr &&
|
|
270
|
-
arr.
|
|
271
|
-
arr.
|
|
259
|
+
arr.embeddedSchemaType &&
|
|
260
|
+
arr.embeddedSchemaType.instance;
|
|
272
261
|
if (instance === 'Array') {
|
|
273
|
-
arr = arr.
|
|
262
|
+
arr = arr.embeddedSchemaType;
|
|
274
263
|
continue;
|
|
275
264
|
}
|
|
276
265
|
if (instance !== 'String' && instance !== 'Number') {
|
|
@@ -285,7 +274,7 @@ SchemaArray.prototype.enum = function() {
|
|
|
285
274
|
enumArray = utils.object.vals(enumArray);
|
|
286
275
|
}
|
|
287
276
|
|
|
288
|
-
arr.
|
|
277
|
+
arr.embeddedSchemaType.enum.apply(arr.embeddedSchemaType, enumArray);
|
|
289
278
|
return this;
|
|
290
279
|
};
|
|
291
280
|
|
|
@@ -308,9 +297,8 @@ SchemaArray.prototype.applyGetters = function(value, scope) {
|
|
|
308
297
|
};
|
|
309
298
|
|
|
310
299
|
SchemaArray.prototype._applySetters = function(value, scope, init, priorVal) {
|
|
311
|
-
if (this.
|
|
312
|
-
SchemaArray.options.castNonArrays
|
|
313
|
-
!this[isNestedArraySymbol]) {
|
|
300
|
+
if (this.embeddedSchemaType.$isMongooseArray &&
|
|
301
|
+
SchemaArray.options.castNonArrays) {
|
|
314
302
|
// Check nesting levels and wrap in array if necessary
|
|
315
303
|
let depth = 0;
|
|
316
304
|
let arr = this;
|
|
@@ -318,7 +306,7 @@ SchemaArray.prototype._applySetters = function(value, scope, init, priorVal) {
|
|
|
318
306
|
arr.$isMongooseArray &&
|
|
319
307
|
!arr.$isMongooseDocumentArray) {
|
|
320
308
|
++depth;
|
|
321
|
-
arr = arr.
|
|
309
|
+
arr = arr.embeddedSchemaType;
|
|
322
310
|
}
|
|
323
311
|
|
|
324
312
|
// No need to wrap empty arrays
|
|
@@ -392,9 +380,9 @@ SchemaArray.prototype.cast = function(value, doc, init, prev, options) {
|
|
|
392
380
|
return value;
|
|
393
381
|
}
|
|
394
382
|
|
|
395
|
-
const caster = this.
|
|
383
|
+
const caster = this.embeddedSchemaType;
|
|
396
384
|
const isMongooseArray = caster.$isMongooseArray;
|
|
397
|
-
if (caster && this.
|
|
385
|
+
if (caster && this.embeddedSchemaType.constructor !== Mixed) {
|
|
398
386
|
try {
|
|
399
387
|
const len = rawValue.length;
|
|
400
388
|
for (i = 0; i < len; i++) {
|
|
@@ -449,19 +437,18 @@ SchemaArray.prototype._castForPopulate = function _castForPopulate(value, doc) {
|
|
|
449
437
|
const rawValue = value.__array ? value.__array : value;
|
|
450
438
|
const len = rawValue.length;
|
|
451
439
|
|
|
452
|
-
|
|
453
|
-
if (caster && this.casterConstructor !== Mixed) {
|
|
440
|
+
if (this.embeddedSchemaType && this.embeddedSchemaType.constructor !== Mixed) {
|
|
454
441
|
try {
|
|
455
442
|
for (i = 0; i < len; i++) {
|
|
456
443
|
const opts = {};
|
|
457
444
|
// Perf: creating `arrayPath` is expensive for large arrays.
|
|
458
445
|
// We only need `arrayPath` if this is a nested array, so
|
|
459
446
|
// skip if possible.
|
|
460
|
-
if (
|
|
447
|
+
if (this.embeddedSchemaType.$isMongooseArray && this.embeddedSchemaType._arrayParentPath != null) {
|
|
461
448
|
opts.arrayPathIndex = i;
|
|
462
449
|
}
|
|
463
450
|
|
|
464
|
-
rawValue[i] =
|
|
451
|
+
rawValue[i] = this.embeddedSchemaType.cast(rawValue[i], doc, false, void 0, opts);
|
|
465
452
|
}
|
|
466
453
|
} catch (e) {
|
|
467
454
|
// rethrow
|
|
@@ -484,11 +471,10 @@ SchemaArray.prototype.$toObject = SchemaArray.prototype.toObject;
|
|
|
484
471
|
SchemaArray.prototype.discriminator = function(...args) {
|
|
485
472
|
let arr = this;
|
|
486
473
|
while (arr.$isMongooseArray && !arr.$isMongooseDocumentArray) {
|
|
487
|
-
arr = arr.
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
}
|
|
474
|
+
arr = arr.embeddedSchemaType;
|
|
475
|
+
}
|
|
476
|
+
if (!arr.$isMongooseDocumentArray) {
|
|
477
|
+
throw new MongooseError('You can only add an embedded discriminator on a document array, ' + this.path + ' is a plain array');
|
|
492
478
|
}
|
|
493
479
|
return arr.discriminator(...args);
|
|
494
480
|
};
|
|
@@ -499,7 +485,7 @@ SchemaArray.prototype.discriminator = function(...args) {
|
|
|
499
485
|
|
|
500
486
|
SchemaArray.prototype.clone = function() {
|
|
501
487
|
const options = Object.assign({}, this.options);
|
|
502
|
-
const schematype = new this.constructor(this.path, this.
|
|
488
|
+
const schematype = new this.constructor(this.path, this.embeddedSchemaType, options, this.schemaOptions, this.parentSchema);
|
|
503
489
|
schematype.validators = this.validators.slice();
|
|
504
490
|
if (this.requiredValidator !== undefined) {
|
|
505
491
|
schematype.requiredValidator = this.requiredValidator;
|
|
@@ -508,30 +494,21 @@ SchemaArray.prototype.clone = function() {
|
|
|
508
494
|
};
|
|
509
495
|
|
|
510
496
|
SchemaArray.prototype._castForQuery = function(val, context) {
|
|
511
|
-
let
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
if (typeof val[Constructor.schema.options.discriminatorKey] === 'string' &&
|
|
519
|
-
Constructor.discriminators[val[Constructor.schema.options.discriminatorKey]]) {
|
|
520
|
-
Constructor = Constructor.discriminators[val[Constructor.schema.options.discriminatorKey]];
|
|
497
|
+
let embeddedSchemaType = this.embeddedSchemaType;
|
|
498
|
+
const discriminatorKey = embeddedSchemaType?.schema?.options?.discriminatorKey;
|
|
499
|
+
const discriminators = embeddedSchemaType?.discriminators;
|
|
500
|
+
|
|
501
|
+
if (val && discriminators && typeof discriminatorKey === 'string') {
|
|
502
|
+
if (discriminators[val[discriminatorKey]]) {
|
|
503
|
+
embeddedSchemaType = discriminators[val[discriminatorKey]];
|
|
521
504
|
} else {
|
|
522
|
-
const constructorByValue = getDiscriminatorByValue(
|
|
505
|
+
const constructorByValue = getDiscriminatorByValue(discriminators, val[discriminatorKey]);
|
|
523
506
|
if (constructorByValue) {
|
|
524
|
-
|
|
507
|
+
embeddedSchemaType = constructorByValue;
|
|
525
508
|
}
|
|
526
509
|
}
|
|
527
510
|
}
|
|
528
511
|
|
|
529
|
-
const proto = this.casterConstructor.prototype;
|
|
530
|
-
const protoCastForQuery = proto && proto.castForQuery;
|
|
531
|
-
const protoCast = proto && proto.cast;
|
|
532
|
-
const constructorCastForQuery = Constructor.castForQuery;
|
|
533
|
-
const caster = this.caster;
|
|
534
|
-
|
|
535
512
|
if (Array.isArray(val)) {
|
|
536
513
|
this.setters.reverse().forEach(setter => {
|
|
537
514
|
val = setter.call(this, val, this);
|
|
@@ -540,30 +517,10 @@ SchemaArray.prototype._castForQuery = function(val, context) {
|
|
|
540
517
|
if (utils.isObject(v) && v.$elemMatch) {
|
|
541
518
|
return v;
|
|
542
519
|
}
|
|
543
|
-
|
|
544
|
-
v = protoCastForQuery.call(caster, null, v, context);
|
|
545
|
-
return v;
|
|
546
|
-
} else if (protoCast) {
|
|
547
|
-
v = protoCast.call(caster, v);
|
|
548
|
-
return v;
|
|
549
|
-
} else if (constructorCastForQuery) {
|
|
550
|
-
v = constructorCastForQuery.call(caster, null, v, context);
|
|
551
|
-
return v;
|
|
552
|
-
}
|
|
553
|
-
if (v != null) {
|
|
554
|
-
v = new Constructor(v);
|
|
555
|
-
return v;
|
|
556
|
-
}
|
|
557
|
-
return v;
|
|
520
|
+
return embeddedSchemaType.castForQuery(null, v, context);
|
|
558
521
|
});
|
|
559
|
-
} else
|
|
560
|
-
val =
|
|
561
|
-
} else if (protoCast) {
|
|
562
|
-
val = protoCast.call(caster, val);
|
|
563
|
-
} else if (constructorCastForQuery) {
|
|
564
|
-
val = constructorCastForQuery.call(caster, null, val, context);
|
|
565
|
-
} else if (val != null) {
|
|
566
|
-
val = new Constructor(val);
|
|
522
|
+
} else {
|
|
523
|
+
val = embeddedSchemaType.castForQuery(null, val, context);
|
|
567
524
|
}
|
|
568
525
|
|
|
569
526
|
return val;
|
|
@@ -629,12 +586,12 @@ function cast$all(val, context) {
|
|
|
629
586
|
return v;
|
|
630
587
|
}
|
|
631
588
|
if (v.$elemMatch != null) {
|
|
632
|
-
return { $elemMatch: cast(this.
|
|
589
|
+
return { $elemMatch: cast(this.embeddedSchemaType.schema, v.$elemMatch, null, this && this.$$context) };
|
|
633
590
|
}
|
|
634
591
|
|
|
635
592
|
const o = {};
|
|
636
593
|
o[this.path] = v;
|
|
637
|
-
return cast(this.
|
|
594
|
+
return cast(this.embeddedSchemaType.schema, o, null, this && this.$$context)[this.path];
|
|
638
595
|
}, this);
|
|
639
596
|
|
|
640
597
|
return this.castForQuery(null, val, context);
|
|
@@ -682,7 +639,7 @@ function createLogicalQueryOperatorHandler(op) {
|
|
|
682
639
|
|
|
683
640
|
const ret = [];
|
|
684
641
|
for (const obj of val) {
|
|
685
|
-
ret.push(cast(this.
|
|
642
|
+
ret.push(cast(this.embeddedSchemaType.schema ?? context.schema, obj, null, this && this.$$context));
|
|
686
643
|
}
|
|
687
644
|
|
|
688
645
|
return ret;
|
|
@@ -57,18 +57,26 @@ function SchemaDocumentArray(key, schema, options, schemaOptions, parentSchema)
|
|
|
57
57
|
schema = handleIdOption(schema, options);
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
const
|
|
61
|
-
|
|
60
|
+
const Constructor = _createConstructor(schema, options);
|
|
61
|
+
Constructor.prototype.$basePath = key;
|
|
62
|
+
Constructor.path = key;
|
|
62
63
|
|
|
63
|
-
|
|
64
|
+
const $parentSchemaType = this;
|
|
65
|
+
const embeddedSchemaType = new DocumentArrayElement(key + '.$', schema, {
|
|
66
|
+
...(schemaOptions || {}),
|
|
67
|
+
$parentSchemaType,
|
|
68
|
+
Constructor
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
SchemaArray.call(this, key, embeddedSchemaType, options, null, parentSchema);
|
|
64
72
|
|
|
65
73
|
this.schema = schema;
|
|
66
74
|
// EmbeddedDocument schematype options
|
|
67
75
|
this.schemaOptions = schemaOptions || {};
|
|
68
76
|
this.$isMongooseDocumentArray = true;
|
|
69
|
-
this.Constructor =
|
|
77
|
+
this.Constructor = Constructor;
|
|
70
78
|
|
|
71
|
-
|
|
79
|
+
Constructor.base = schema.base;
|
|
72
80
|
|
|
73
81
|
const fn = this.defaultValue;
|
|
74
82
|
|
|
@@ -82,20 +90,6 @@ function SchemaDocumentArray(key, schema, options, schemaOptions, parentSchema)
|
|
|
82
90
|
return arr;
|
|
83
91
|
});
|
|
84
92
|
}
|
|
85
|
-
|
|
86
|
-
const $parentSchemaType = this;
|
|
87
|
-
this.$embeddedSchemaType = new DocumentArrayElement(
|
|
88
|
-
key + '.$',
|
|
89
|
-
{
|
|
90
|
-
...(schemaOptions || {}),
|
|
91
|
-
$parentSchemaType
|
|
92
|
-
},
|
|
93
|
-
schemaOptions,
|
|
94
|
-
parentSchema
|
|
95
|
-
);
|
|
96
|
-
|
|
97
|
-
this.$embeddedSchemaType.caster = this.Constructor;
|
|
98
|
-
this.$embeddedSchemaType.schema = this.schema;
|
|
99
93
|
}
|
|
100
94
|
|
|
101
95
|
/**
|
|
@@ -218,93 +212,62 @@ SchemaDocumentArray.prototype.discriminator = function(name, schema, options) {
|
|
|
218
212
|
schema = schema.clone();
|
|
219
213
|
}
|
|
220
214
|
|
|
221
|
-
schema = discriminator(this.
|
|
215
|
+
schema = discriminator(this.Constructor, name, schema, tiedValue, null, null, options?.overwriteExisting);
|
|
222
216
|
|
|
223
|
-
const EmbeddedDocument = _createConstructor(schema, null, this.
|
|
224
|
-
EmbeddedDocument.baseCasterConstructor = this.
|
|
217
|
+
const EmbeddedDocument = _createConstructor(schema, null, this.Constructor);
|
|
218
|
+
EmbeddedDocument.baseCasterConstructor = this.Constructor;
|
|
225
219
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
});
|
|
230
|
-
} catch (error) {
|
|
231
|
-
// Ignore error, only happens on old versions of node
|
|
232
|
-
}
|
|
220
|
+
Object.defineProperty(EmbeddedDocument, 'name', {
|
|
221
|
+
value: name
|
|
222
|
+
});
|
|
233
223
|
|
|
234
|
-
this.
|
|
224
|
+
this.Constructor.discriminators[name] = EmbeddedDocument;
|
|
235
225
|
|
|
236
|
-
return this.
|
|
226
|
+
return this.Constructor.discriminators[name];
|
|
237
227
|
};
|
|
238
228
|
|
|
239
229
|
/**
|
|
240
230
|
* Performs local validations first, then validations on each embedded doc
|
|
241
231
|
*
|
|
242
|
-
* @api
|
|
232
|
+
* @api public
|
|
243
233
|
*/
|
|
244
234
|
|
|
245
|
-
SchemaDocumentArray.prototype.doValidate = function(array,
|
|
235
|
+
SchemaDocumentArray.prototype.doValidate = async function doValidate(array, scope, options) {
|
|
246
236
|
// lazy load
|
|
247
237
|
MongooseDocumentArray || (MongooseDocumentArray = require('../types/documentArray'));
|
|
248
238
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
}
|
|
253
|
-
|
|
239
|
+
await SchemaType.prototype.doValidate.call(this, array, scope);
|
|
240
|
+
if (options?.updateValidator) {
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
if (!utils.isMongooseDocumentArray(array)) {
|
|
244
|
+
array = new MongooseDocumentArray(array, this.path, scope);
|
|
254
245
|
}
|
|
255
246
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
return fn(err);
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
let count = array && array.length;
|
|
262
|
-
let error;
|
|
263
|
-
|
|
264
|
-
if (!count) {
|
|
265
|
-
return fn();
|
|
266
|
-
}
|
|
267
|
-
if (options && options.updateValidator) {
|
|
268
|
-
return fn();
|
|
269
|
-
}
|
|
270
|
-
if (!utils.isMongooseDocumentArray(array)) {
|
|
271
|
-
array = new MongooseDocumentArray(array, _this.path, scope);
|
|
272
|
-
}
|
|
273
|
-
|
|
247
|
+
const promises = [];
|
|
248
|
+
for (let i = 0; i < array.length; ++i) {
|
|
274
249
|
// handle sparse arrays, do not use array.forEach which does not
|
|
275
250
|
// iterate over sparse elements yet reports array.length including
|
|
276
251
|
// them :(
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
252
|
+
let doc = array[i];
|
|
253
|
+
if (doc == null) {
|
|
254
|
+
continue;
|
|
255
|
+
}
|
|
256
|
+
// If you set the array index directly, the doc might not yet be
|
|
257
|
+
// a full fledged mongoose subdoc, so make it into one.
|
|
258
|
+
if (!(doc instanceof Subdocument)) {
|
|
259
|
+
const Constructor = getConstructor(this.Constructor, array[i]);
|
|
260
|
+
doc = array[i] = new Constructor(doc, array, undefined, undefined, i);
|
|
283
261
|
}
|
|
284
262
|
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
let doc = array[i];
|
|
288
|
-
if (doc == null) {
|
|
289
|
-
--count || fn(error);
|
|
290
|
-
continue;
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
// If you set the array index directly, the doc might not yet be
|
|
294
|
-
// a full fledged mongoose subdoc, so make it into one.
|
|
295
|
-
if (!(doc instanceof Subdocument)) {
|
|
296
|
-
const Constructor = getConstructor(_this.casterConstructor, array[i]);
|
|
297
|
-
doc = array[i] = new Constructor(doc, array, undefined, undefined, i);
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
if (options != null && options.validateModifiedOnly && !doc.$isModified()) {
|
|
301
|
-
--count || fn(error);
|
|
302
|
-
continue;
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
doc.$__validate(null, options, callback);
|
|
263
|
+
if (options != null && options.validateModifiedOnly && !doc.$isModified()) {
|
|
264
|
+
continue;
|
|
306
265
|
}
|
|
266
|
+
|
|
267
|
+
promises.push(doc.$__validate(null, options));
|
|
307
268
|
}
|
|
269
|
+
|
|
270
|
+
await Promise.all(promises);
|
|
308
271
|
};
|
|
309
272
|
|
|
310
273
|
/**
|
|
@@ -345,7 +308,7 @@ SchemaDocumentArray.prototype.doValidateSync = function(array, scope, options) {
|
|
|
345
308
|
// If you set the array index directly, the doc might not yet be
|
|
346
309
|
// a full fledged mongoose subdoc, so make it into one.
|
|
347
310
|
if (!(doc instanceof Subdocument)) {
|
|
348
|
-
const Constructor = getConstructor(this.
|
|
311
|
+
const Constructor = getConstructor(this.Constructor, array[i]);
|
|
349
312
|
doc = array[i] = new Constructor(doc, array, undefined, undefined, i);
|
|
350
313
|
}
|
|
351
314
|
|
|
@@ -390,7 +353,7 @@ SchemaDocumentArray.prototype.getDefault = function(scope, init, options) {
|
|
|
390
353
|
ret = new MongooseDocumentArray(ret, this.path, scope);
|
|
391
354
|
|
|
392
355
|
for (let i = 0; i < ret.length; ++i) {
|
|
393
|
-
const Constructor = getConstructor(this.
|
|
356
|
+
const Constructor = getConstructor(this.Constructor, ret[i]);
|
|
394
357
|
const _subdoc = new Constructor({}, ret, undefined,
|
|
395
358
|
undefined, i);
|
|
396
359
|
_subdoc.$init(ret[i]);
|
|
@@ -468,7 +431,7 @@ SchemaDocumentArray.prototype.cast = function(value, doc, init, prev, options) {
|
|
|
468
431
|
continue;
|
|
469
432
|
}
|
|
470
433
|
|
|
471
|
-
const Constructor = getConstructor(this.
|
|
434
|
+
const Constructor = getConstructor(this.Constructor, rawArray[i]);
|
|
472
435
|
|
|
473
436
|
const spreadDoc = handleSpreadDoc(rawArray[i], true);
|
|
474
437
|
if (rawArray[i] !== spreadDoc) {
|
|
@@ -659,21 +622,21 @@ function cast$elemMatch(val, context) {
|
|
|
659
622
|
// Is this an embedded discriminator and is the discriminator key set?
|
|
660
623
|
// If so, use the discriminator schema. See gh-7449
|
|
661
624
|
const discriminatorKey = this &&
|
|
662
|
-
this.
|
|
663
|
-
this.
|
|
664
|
-
this.
|
|
665
|
-
this.
|
|
625
|
+
this.Constructor &&
|
|
626
|
+
this.Constructor.schema &&
|
|
627
|
+
this.Constructor.schema.options &&
|
|
628
|
+
this.Constructor.schema.options.discriminatorKey;
|
|
666
629
|
const discriminators = this &&
|
|
667
|
-
this.
|
|
668
|
-
this.
|
|
669
|
-
this.
|
|
630
|
+
this.Constructor &&
|
|
631
|
+
this.Constructor.schema &&
|
|
632
|
+
this.Constructor.schema.discriminators || {};
|
|
670
633
|
if (discriminatorKey != null &&
|
|
671
634
|
val[discriminatorKey] != null &&
|
|
672
635
|
discriminators[val[discriminatorKey]] != null) {
|
|
673
636
|
return cast(discriminators[val[discriminatorKey]], val, null, this && this.$$context);
|
|
674
637
|
}
|
|
675
638
|
|
|
676
|
-
const schema = this.
|
|
639
|
+
const schema = this.Constructor.schema ?? context.schema;
|
|
677
640
|
return cast(schema, val, null, this && this.$$context);
|
|
678
641
|
}
|
|
679
642
|
|
|
@@ -10,17 +10,22 @@ const SchemaSubdocument = require('./subdocument');
|
|
|
10
10
|
const getConstructor = require('../helpers/discriminator/getConstructor');
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
|
-
* DocumentArrayElement SchemaType constructor.
|
|
13
|
+
* DocumentArrayElement SchemaType constructor. Mongoose calls this internally when you define a new document array in your schema.
|
|
14
|
+
*
|
|
15
|
+
* #### Example:
|
|
16
|
+
* const schema = new Schema({ users: [{ name: String }] });
|
|
17
|
+
* schema.path('users.$'); // SchemaDocumentArrayElement with schema `new Schema({ name: String })`
|
|
14
18
|
*
|
|
15
19
|
* @param {String} path
|
|
20
|
+
* @param {Schema} schema
|
|
21
|
+
* @param {Object} options
|
|
16
22
|
* @param {Object} options
|
|
17
|
-
* @param {Object} schemaOptions
|
|
18
23
|
* @param {Schema} parentSchema
|
|
19
24
|
* @inherits SchemaType
|
|
20
25
|
* @api public
|
|
21
26
|
*/
|
|
22
27
|
|
|
23
|
-
function SchemaDocumentArrayElement(path,
|
|
28
|
+
function SchemaDocumentArrayElement(path, schema, options, parentSchema) {
|
|
24
29
|
this.$parentSchemaType = options && options.$parentSchemaType;
|
|
25
30
|
if (!this.$parentSchemaType) {
|
|
26
31
|
throw new MongooseError('Cannot create DocumentArrayElement schematype without a parent');
|
|
@@ -30,6 +35,8 @@ function SchemaDocumentArrayElement(path, options, _schemaOptions, parentSchema)
|
|
|
30
35
|
SchemaType.call(this, path, options, 'DocumentArrayElement', parentSchema);
|
|
31
36
|
|
|
32
37
|
this.$isMongooseDocumentArrayElement = true;
|
|
38
|
+
this.Constructor = options && options.Constructor;
|
|
39
|
+
this.schema = schema;
|
|
33
40
|
}
|
|
34
41
|
|
|
35
42
|
/**
|
|
@@ -60,21 +67,19 @@ SchemaDocumentArrayElement.prototype.cast = function(...args) {
|
|
|
60
67
|
};
|
|
61
68
|
|
|
62
69
|
/**
|
|
63
|
-
*
|
|
70
|
+
* Async validation on this individual array element
|
|
64
71
|
*
|
|
65
|
-
* @
|
|
66
|
-
* @param {any} [val]
|
|
67
|
-
* @api private
|
|
72
|
+
* @api public
|
|
68
73
|
*/
|
|
69
74
|
|
|
70
|
-
SchemaDocumentArrayElement.prototype.doValidate = function(value,
|
|
71
|
-
const Constructor = getConstructor(this.
|
|
75
|
+
SchemaDocumentArrayElement.prototype.doValidate = async function doValidate(value, scope, options) {
|
|
76
|
+
const Constructor = getConstructor(this.Constructor, value);
|
|
72
77
|
|
|
73
78
|
if (value && !(value instanceof Constructor)) {
|
|
74
79
|
value = new Constructor(value, scope, null, null, options && options.index != null ? options.index : null);
|
|
75
80
|
}
|
|
76
81
|
|
|
77
|
-
return SchemaSubdocument.prototype.doValidate.call(this, value,
|
|
82
|
+
return SchemaSubdocument.prototype.doValidate.call(this, value, scope, options);
|
|
78
83
|
};
|
|
79
84
|
|
|
80
85
|
/**
|
|
@@ -89,7 +94,7 @@ SchemaDocumentArrayElement.prototype.clone = function() {
|
|
|
89
94
|
const ret = SchemaType.prototype.clone.apply(this, arguments);
|
|
90
95
|
delete this.options.$parentSchemaType;
|
|
91
96
|
|
|
92
|
-
ret.
|
|
97
|
+
ret.Constructor = this.Constructor;
|
|
93
98
|
ret.schema = this.schema;
|
|
94
99
|
|
|
95
100
|
return ret;
|
package/lib/schema/string.js
CHANGED