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.
Files changed (90) hide show
  1. package/eslint.config.mjs +198 -0
  2. package/lib/aggregate.js +17 -73
  3. package/lib/cast/bigint.js +1 -1
  4. package/lib/cast/double.js +1 -1
  5. package/lib/cast/uuid.js +5 -48
  6. package/lib/cast.js +2 -2
  7. package/lib/connection.js +0 -1
  8. package/lib/cursor/aggregationCursor.js +14 -24
  9. package/lib/cursor/queryCursor.js +7 -14
  10. package/lib/document.js +125 -121
  11. package/lib/drivers/node-mongodb-native/connection.js +3 -10
  12. package/lib/error/objectParameter.js +1 -2
  13. package/lib/error/validation.js +0 -8
  14. package/lib/helpers/clone.js +1 -1
  15. package/lib/helpers/common.js +1 -1
  16. package/lib/helpers/indexes/isIndexEqual.js +0 -1
  17. package/lib/helpers/model/applyDefaultsToPOJO.js +2 -2
  18. package/lib/helpers/model/applyHooks.js +43 -53
  19. package/lib/helpers/model/applyMethods.js +2 -2
  20. package/lib/helpers/model/applyStaticHooks.js +1 -48
  21. package/lib/helpers/model/castBulkWrite.js +1 -1
  22. package/lib/helpers/parallelLimit.js +18 -36
  23. package/lib/helpers/pluralize.js +3 -3
  24. package/lib/helpers/populate/assignRawDocsToIdStructure.js +1 -8
  25. package/lib/helpers/populate/createPopulateQueryFilter.js +1 -1
  26. package/lib/helpers/populate/getModelsMapForPopulate.js +17 -9
  27. package/lib/helpers/populate/getSchemaTypes.js +5 -5
  28. package/lib/helpers/query/cast$expr.js +8 -10
  29. package/lib/helpers/query/castFilterPath.js +1 -1
  30. package/lib/helpers/query/castUpdate.js +14 -12
  31. package/lib/helpers/query/getEmbeddedDiscriminatorPath.js +1 -1
  32. package/lib/helpers/schema/applyPlugins.js +1 -1
  33. package/lib/helpers/schema/getIndexes.js +1 -7
  34. package/lib/helpers/timestamps/setupTimestamps.js +3 -6
  35. package/lib/helpers/updateValidators.js +57 -111
  36. package/lib/model.js +419 -607
  37. package/lib/mongoose.js +41 -13
  38. package/lib/plugins/saveSubdocs.js +24 -51
  39. package/lib/plugins/sharding.js +5 -4
  40. package/lib/plugins/validateBeforeSave.js +3 -13
  41. package/lib/query.js +101 -145
  42. package/lib/queryHelpers.js +2 -2
  43. package/lib/schema/array.js +41 -84
  44. package/lib/schema/documentArray.js +57 -94
  45. package/lib/schema/documentArrayElement.js +16 -11
  46. package/lib/schema/string.js +1 -1
  47. package/lib/schema/subdocument.js +22 -28
  48. package/lib/schema/uuid.js +0 -21
  49. package/lib/schema.js +81 -39
  50. package/lib/schemaType.js +39 -57
  51. package/lib/types/array/index.js +2 -2
  52. package/lib/types/array/methods/index.js +4 -4
  53. package/lib/types/arraySubdocument.js +1 -1
  54. package/lib/types/buffer.js +10 -10
  55. package/lib/types/decimal128.js +1 -1
  56. package/lib/types/documentArray/index.js +1 -1
  57. package/lib/types/documentArray/methods/index.js +5 -3
  58. package/lib/types/double.js +1 -1
  59. package/lib/types/objectid.js +1 -1
  60. package/lib/types/subdocument.js +15 -43
  61. package/lib/types/uuid.js +1 -1
  62. package/lib/utils.js +1 -8
  63. package/lib/validOptions.js +3 -3
  64. package/package.json +11 -24
  65. package/types/connection.d.ts +20 -11
  66. package/types/document.d.ts +95 -26
  67. package/types/index.d.ts +143 -39
  68. package/types/inferhydrateddoctype.d.ts +115 -0
  69. package/types/inferrawdoctype.d.ts +99 -75
  70. package/types/inferschematype.d.ts +17 -3
  71. package/types/middlewares.d.ts +0 -2
  72. package/types/models.d.ts +131 -199
  73. package/types/mongooseoptions.d.ts +6 -5
  74. package/types/pipelinestage.d.ts +1 -1
  75. package/types/query.d.ts +71 -139
  76. package/types/schemaoptions.d.ts +1 -1
  77. package/types/schematypes.d.ts +14 -10
  78. package/types/types.d.ts +3 -4
  79. package/types/utility.d.ts +68 -48
  80. package/types/validation.d.ts +18 -14
  81. package/browser.js +0 -8
  82. package/dist/browser.umd.js +0 -2
  83. package/lib/browser.js +0 -141
  84. package/lib/browserDocument.js +0 -101
  85. package/lib/documentProvider.js +0 -30
  86. package/lib/drivers/browser/binary.js +0 -14
  87. package/lib/drivers/browser/decimal128.js +0 -7
  88. package/lib/drivers/browser/index.js +0 -13
  89. package/lib/drivers/browser/objectid.js +0 -29
  90. package/lib/helpers/promiseOrCallback.js +0 -54
@@ -50,9 +50,9 @@ function SchemaSubdocument(schema, path, options, parentSchema) {
50
50
 
51
51
  schema = handleIdOption(schema, options);
52
52
 
53
- this.caster = _createConstructor(schema, null, options);
54
- this.caster.path = path;
55
- this.caster.prototype.$basePath = path;
53
+ this.Constructor = _createConstructor(schema, null, options);
54
+ this.Constructor.path = path;
55
+ this.Constructor.prototype.$basePath = path;
56
56
  this.schema = schema;
57
57
  this.$isSingleNested = true;
58
58
  this.base = schema.base;
@@ -181,13 +181,13 @@ SchemaSubdocument.prototype.cast = function(val, doc, init, priorVal, options) {
181
181
  return val;
182
182
  }
183
183
 
184
- if (val != null && (typeof val !== 'object' || Array.isArray(val))) {
184
+ if (!init && val != null && (typeof val !== 'object' || Array.isArray(val))) {
185
185
  throw new ObjectExpectedError(this.path, val);
186
186
  }
187
187
 
188
188
  const discriminatorKeyPath = this.schema.path(this.schema.options.discriminatorKey);
189
189
  const defaultDiscriminatorValue = discriminatorKeyPath == null ? null : discriminatorKeyPath.getDefault(doc);
190
- const Constructor = getConstructor(this.caster, val, defaultDiscriminatorValue);
190
+ const Constructor = getConstructor(this.Constructor, val, defaultDiscriminatorValue);
191
191
 
192
192
  let subdoc;
193
193
 
@@ -202,7 +202,7 @@ SchemaSubdocument.prototype.cast = function(val, doc, init, priorVal, options) {
202
202
  return obj;
203
203
  }, null);
204
204
  if (init) {
205
- subdoc = new Constructor(void 0, selected, doc, false, { defaults: false });
205
+ subdoc = new Constructor(void 0, selected, doc, { defaults: false });
206
206
  delete subdoc.$__.defaults;
207
207
  // Don't pass `path` to $init - it's only for the subdocument itself, not its fields.
208
208
  // For change tracking, subdocuments use relative paths internally.
@@ -217,10 +217,10 @@ SchemaSubdocument.prototype.cast = function(val, doc, init, priorVal, options) {
217
217
  } else {
218
218
  options = Object.assign({}, options, { priorDoc: priorVal });
219
219
  if (Object.keys(val).length === 0) {
220
- return new Constructor({}, selected, doc, undefined, options);
220
+ return new Constructor({}, selected, doc, options);
221
221
  }
222
222
 
223
- return new Constructor(val, selected, doc, undefined, options);
223
+ return new Constructor(val, selected, doc, options);
224
224
  }
225
225
 
226
226
  return subdoc;
@@ -247,7 +247,7 @@ SchemaSubdocument.prototype.castForQuery = function($conditional, val, context,
247
247
  return val;
248
248
  }
249
249
 
250
- const Constructor = getConstructor(this.caster, val);
250
+ const Constructor = getConstructor(this.Constructor, val);
251
251
  if (val instanceof Constructor) {
252
252
  return val;
253
253
  }
@@ -275,11 +275,11 @@ SchemaSubdocument.prototype.castForQuery = function($conditional, val, context,
275
275
  /**
276
276
  * Async validation on this single nested doc.
277
277
  *
278
- * @api private
278
+ * @api public
279
279
  */
280
280
 
281
- SchemaSubdocument.prototype.doValidate = function(value, fn, scope, options) {
282
- const Constructor = getConstructor(this.caster, value);
281
+ SchemaSubdocument.prototype.doValidate = async function doValidate(value, scope, options) {
282
+ const Constructor = getConstructor(this.Constructor, value);
283
283
 
284
284
  if (value && !(value instanceof Constructor)) {
285
285
  value = new Constructor(value, null, (scope != null && scope.$__ != null) ? scope : null);
@@ -287,21 +287,15 @@ SchemaSubdocument.prototype.doValidate = function(value, fn, scope, options) {
287
287
 
288
288
  if (options && options.skipSchemaValidators) {
289
289
  if (!value) {
290
- return fn(null);
290
+ return;
291
291
  }
292
- return value.validate().then(() => fn(null), err => fn(err));
292
+ return value.validate();
293
293
  }
294
294
 
295
- SchemaType.prototype.doValidate.call(this, value, function(error) {
296
- if (error) {
297
- return fn(error);
298
- }
299
- if (!value) {
300
- return fn(null);
301
- }
302
-
303
- value.validate().then(() => fn(null), err => fn(err));
304
- }, scope, options);
295
+ await SchemaType.prototype.doValidate.call(this, value, scope, options);
296
+ if (value != null) {
297
+ await value.validate();
298
+ }
305
299
  };
306
300
 
307
301
  /**
@@ -355,11 +349,11 @@ SchemaSubdocument.prototype.discriminator = function(name, schema, options) {
355
349
  schema = schema.clone();
356
350
  }
357
351
 
358
- schema = discriminator(this.caster, name, schema, value, null, null, options.overwriteExisting);
352
+ schema = discriminator(this.Constructor, name, schema, value, null, null, options.overwriteExisting);
359
353
 
360
- this.caster.discriminators[name] = _createConstructor(schema, this.caster);
354
+ this.Constructor.discriminators[name] = _createConstructor(schema, this.Constructor);
361
355
 
362
- return this.caster.discriminators[name];
356
+ return this.Constructor.discriminators[name];
363
357
  };
364
358
 
365
359
  /*!
@@ -423,7 +417,7 @@ SchemaSubdocument.prototype.clone = function() {
423
417
  if (this.requiredValidator !== undefined) {
424
418
  schematype.requiredValidator = this.requiredValidator;
425
419
  }
426
- schematype.caster.discriminators = Object.assign({}, this.caster.discriminators);
420
+ schematype.Constructor.discriminators = Object.assign({}, this.Constructor.discriminators);
427
421
  schematype._appliedDiscriminators = this._appliedDiscriminators;
428
422
  return schematype;
429
423
  };
@@ -4,7 +4,6 @@
4
4
 
5
5
  'use strict';
6
6
 
7
- const MongooseBuffer = require('../types/buffer');
8
7
  const SchemaType = require('../schemaType');
9
8
  const CastError = SchemaType.CastError;
10
9
  const castUUID = require('../cast/uuid');
@@ -13,7 +12,6 @@ const utils = require('../utils');
13
12
  const handleBitwiseOperator = require('./operators/bitwise');
14
13
 
15
14
  const UUID_FORMAT = castUUID.UUID_FORMAT;
16
- const Binary = MongooseBuffer.Binary;
17
15
 
18
16
  /**
19
17
  * Convert binary to a uuid string
@@ -45,21 +43,6 @@ function binaryToString(uuidBin) {
45
43
 
46
44
  function SchemaUUID(key, options, _schemaOptions, parentSchema) {
47
45
  SchemaType.call(this, key, options, 'UUID', parentSchema);
48
- this.getters.push(function(value) {
49
- // For populated
50
- if (value != null && value.$__ != null) {
51
- return value;
52
- }
53
- if (Buffer.isBuffer(value)) {
54
- return binaryToString(value);
55
- } else if (value instanceof Binary) {
56
- return binaryToString(value.buffer);
57
- } else if (utils.isPOJO(value) && value.type === 'Buffer' && Array.isArray(value.data)) {
58
- // Cloned buffers look like `{ type: 'Buffer', data: [5, 224, ...] }`
59
- return binaryToString(Buffer.from(value.data));
60
- }
61
- return value;
62
- });
63
46
  }
64
47
 
65
48
  /**
@@ -251,11 +234,7 @@ const $conditionalHandlers = {
251
234
  $bitsAllSet: handleBitwiseOperator,
252
235
  $bitsAnySet: handleBitwiseOperator,
253
236
  $all: handleArray,
254
- $gt: handleSingle,
255
- $gte: handleSingle,
256
237
  $in: handleArray,
257
- $lt: handleSingle,
258
- $lte: handleSingle,
259
238
  $ne: handleSingle,
260
239
  $nin: handleArray
261
240
  };
package/lib/schema.js CHANGED
@@ -23,6 +23,7 @@ const merge = require('./helpers/schema/merge');
23
23
  const mpath = require('mpath');
24
24
  const setPopulatedVirtualValue = require('./helpers/populate/setPopulatedVirtualValue');
25
25
  const setupTimestamps = require('./helpers/timestamps/setupTimestamps');
26
+ const symbols = require('./schema/symbols');
26
27
  const utils = require('./utils');
27
28
  const validateRef = require('./helpers/populate/validateRef');
28
29
 
@@ -31,7 +32,7 @@ const hasNumericSubpathRegex = /\.\d+(\.|$)/;
31
32
  let MongooseTypes;
32
33
 
33
34
  const queryHooks = require('./constants').queryMiddlewareFunctions;
34
- const documentHooks = require('./helpers/model/applyHooks').middlewareFunctions;
35
+ const documentHooks = require('./constants').documentMiddlewareFunctions;
35
36
  const hookNames = queryHooks.concat(documentHooks).
36
37
  reduce((s, hook) => s.add(hook), new Set());
37
38
 
@@ -372,6 +373,29 @@ Schema.prototype.paths;
372
373
 
373
374
  Schema.prototype.tree;
374
375
 
376
+ /**
377
+ * Creates a new schema with the given definition and options. Equivalent to `new Schema(definition, options)`.
378
+ *
379
+ * `Schema.create()` is primarily useful for automatic schema type inference in TypeScript.
380
+ *
381
+ * #### Example:
382
+ *
383
+ * const schema = Schema.create({ name: String }, { toObject: { virtuals: true } });
384
+ * // Equivalent:
385
+ * const schema2 = new Schema({ name: String }, { toObject: { virtuals: true } });
386
+ *
387
+ * @param {Object} definition
388
+ * @param {Object} [options]
389
+ * @return {Schema} the new schema
390
+ * @api public
391
+ * @memberOf Schema
392
+ * @static
393
+ */
394
+
395
+ Schema.create = function create(definition, options) {
396
+ return new Schema(definition, options);
397
+ };
398
+
375
399
  /**
376
400
  * Returns a deep copy of the schema
377
401
  *
@@ -660,6 +684,33 @@ Schema.prototype.discriminator = function(name, schema, options) {
660
684
  return this;
661
685
  };
662
686
 
687
+ /*!
688
+ * Get the document middleware for this schema, filtering out any hooks that are specific to queries.
689
+ */
690
+ Schema.prototype._getDocumentMiddleware = function _getDocumentMiddleware() {
691
+ return this.s.hooks.
692
+ filter(hook => {
693
+ if (hook.name === 'updateOne' || hook.name === 'deleteOne') {
694
+ return !!hook['document'];
695
+ }
696
+ if (hook.name === 'remove' || hook.name === 'init') {
697
+ return hook['document'] == null || !!hook['document'];
698
+ }
699
+ if (hook.query != null || hook.document != null) {
700
+ return hook.document !== false;
701
+ }
702
+ return true;
703
+ }).
704
+ filter(hook => {
705
+ // If user has overwritten the method, don't apply built-in middleware
706
+ if (this.methods[hook.name]) {
707
+ return !hook.fn[symbols.builtInMiddleware];
708
+ }
709
+
710
+ return true;
711
+ });
712
+ };
713
+
663
714
  /*!
664
715
  * Get this schema's default toObject/toJSON options, including Mongoose global
665
716
  * options.
@@ -1300,7 +1351,7 @@ Schema.prototype.path = function(path, obj) {
1300
1351
  if (schemaType.$__schemaType.$isSingleNested) {
1301
1352
  this.childSchemas.push({
1302
1353
  schema: schemaType.$__schemaType.schema,
1303
- model: schemaType.$__schemaType.caster,
1354
+ model: schemaType.$__schemaType.Constructor,
1304
1355
  path: path
1305
1356
  });
1306
1357
  }
@@ -1329,10 +1380,10 @@ Schema.prototype.path = function(path, obj) {
1329
1380
  value: this.base
1330
1381
  });
1331
1382
 
1332
- schemaType.caster.base = this.base;
1383
+ schemaType.Constructor.base = this.base;
1333
1384
  this.childSchemas.push({
1334
1385
  schema: schemaType.schema,
1335
- model: schemaType.caster,
1386
+ model: schemaType.Constructor,
1336
1387
  path: path
1337
1388
  });
1338
1389
  } else if (schemaType.$isMongooseDocumentArray) {
@@ -1343,15 +1394,15 @@ Schema.prototype.path = function(path, obj) {
1343
1394
  value: this.base
1344
1395
  });
1345
1396
 
1346
- schemaType.casterConstructor.base = this.base;
1397
+ schemaType.Constructor.base = this.base;
1347
1398
  this.childSchemas.push({
1348
1399
  schema: schemaType.schema,
1349
- model: schemaType.casterConstructor,
1400
+ model: schemaType.Constructor,
1350
1401
  path: path
1351
1402
  });
1352
1403
  }
1353
1404
 
1354
- if (schemaType.$isMongooseArray && schemaType.caster instanceof SchemaType) {
1405
+ if (schemaType.$isMongooseArray && !schemaType.$isMongooseDocumentArray) {
1355
1406
  let arrayPath = path;
1356
1407
  let _schemaType = schemaType;
1357
1408
 
@@ -1359,16 +1410,9 @@ Schema.prototype.path = function(path, obj) {
1359
1410
  while (_schemaType.$isMongooseArray) {
1360
1411
  arrayPath = arrayPath + '.$';
1361
1412
 
1362
- // Skip arrays of document arrays
1363
- if (_schemaType.$isMongooseDocumentArray) {
1364
- _schemaType.$embeddedSchemaType._arrayPath = arrayPath;
1365
- _schemaType.$embeddedSchemaType._arrayParentPath = path;
1366
- _schemaType = _schemaType.$embeddedSchemaType;
1367
- } else {
1368
- _schemaType.caster._arrayPath = arrayPath;
1369
- _schemaType.caster._arrayParentPath = path;
1370
- _schemaType = _schemaType.caster;
1371
- }
1413
+ _schemaType.embeddedSchemaType._arrayPath = arrayPath;
1414
+ _schemaType.embeddedSchemaType._arrayParentPath = path;
1415
+ _schemaType = _schemaType.embeddedSchemaType;
1372
1416
 
1373
1417
  this.subpaths[arrayPath] = _schemaType;
1374
1418
  }
@@ -1420,13 +1464,13 @@ Schema.prototype._gatherChildSchemas = function _gatherChildSchemas() {
1420
1464
  if (schematype.$isMongooseDocumentArray || schematype.$isSingleNested) {
1421
1465
  childSchemas.push({
1422
1466
  schema: schematype.schema,
1423
- model: schematype.caster,
1467
+ model: schematype.Constructor,
1424
1468
  path: path
1425
1469
  });
1426
1470
  } else if (schematype.$isSchemaMap && schematype.$__schemaType.$isSingleNested) {
1427
1471
  childSchemas.push({
1428
1472
  schema: schematype.$__schemaType.schema,
1429
- model: schematype.$__schemaType.caster,
1473
+ model: schematype.$__schemaType.Constructor,
1430
1474
  path: path
1431
1475
  });
1432
1476
  }
@@ -1945,10 +1989,10 @@ function getPositionalPathType(self, path, cleanPath) {
1945
1989
 
1946
1990
  if (i === last && val && !/\D/.test(subpath)) {
1947
1991
  if (val.$isMongooseDocumentArray) {
1948
- val = val.$embeddedSchemaType;
1992
+ val = val.embeddedSchemaType;
1949
1993
  } else if (val instanceof MongooseTypes.Array) {
1950
1994
  // StringSchema, NumberSchema, etc
1951
- val = val.caster;
1995
+ val = val.embeddedSchemaType;
1952
1996
  } else {
1953
1997
  val = undefined;
1954
1998
  }
@@ -1959,7 +2003,7 @@ function getPositionalPathType(self, path, cleanPath) {
1959
2003
  if (!/\D/.test(subpath)) {
1960
2004
  // Nested array
1961
2005
  if (val instanceof MongooseTypes.Array && i !== last) {
1962
- val = val.caster;
2006
+ val = val.embeddedSchemaType;
1963
2007
  }
1964
2008
  continue;
1965
2009
  }
@@ -2022,23 +2066,21 @@ Schema.prototype.queue = function(name, args) {
2022
2066
  *
2023
2067
  * const toySchema = new Schema({ name: String, created: Date });
2024
2068
  *
2025
- * toySchema.pre('save', function(next) {
2069
+ * toySchema.pre('save', function() {
2026
2070
  * if (!this.created) this.created = new Date;
2027
- * next();
2028
2071
  * });
2029
2072
  *
2030
- * toySchema.pre('validate', function(next) {
2073
+ * toySchema.pre('validate', function() {
2031
2074
  * if (this.name !== 'Woody') this.name = 'Woody';
2032
- * next();
2033
2075
  * });
2034
2076
  *
2035
2077
  * // Equivalent to calling `pre()` on `find`, `findOne`, `findOneAndUpdate`.
2036
- * toySchema.pre(/^find/, function(next) {
2078
+ * toySchema.pre(/^find/, function() {
2037
2079
  * console.log(this.getFilter());
2038
2080
  * });
2039
2081
  *
2040
2082
  * // Equivalent to calling `pre()` on `updateOne`, `findOneAndUpdate`.
2041
- * toySchema.pre(['updateOne', 'findOneAndUpdate'], function(next) {
2083
+ * toySchema.pre(['updateOne', 'findOneAndUpdate'], function() {
2042
2084
  * console.log(this.getFilter());
2043
2085
  * });
2044
2086
  *
@@ -2455,8 +2497,8 @@ Object.defineProperty(Schema, 'indexTypes', {
2455
2497
  * registeredAt: { type: Date, index: true }
2456
2498
  * });
2457
2499
  *
2458
- * // [ [ { email: 1 }, { unique: true, background: true } ],
2459
- * // [ { registeredAt: 1 }, { background: true } ] ]
2500
+ * // [ [ { email: 1 }, { unique: true } ],
2501
+ * // [ { registeredAt: 1 }, {} ] ]
2460
2502
  * userSchema.indexes();
2461
2503
  *
2462
2504
  * [Plugins](https://mongoosejs.com/docs/plugins.html) can use the return value of this function to modify a schema's indexes.
@@ -2854,11 +2896,11 @@ Schema.prototype._getSchema = function(path) {
2854
2896
  if (foundschema) {
2855
2897
  resultPath.push(trypath);
2856
2898
 
2857
- if (foundschema.caster) {
2899
+ if (foundschema.embeddedSchemaType || foundschema.Constructor) {
2858
2900
  // array of Mixed?
2859
- if (foundschema.caster instanceof MongooseTypes.Mixed) {
2860
- foundschema.caster.$fullPath = resultPath.join('.');
2861
- return foundschema.caster;
2901
+ if (foundschema.embeddedSchemaType instanceof MongooseTypes.Mixed) {
2902
+ foundschema.embeddedSchemaType.$fullPath = resultPath.join('.');
2903
+ return foundschema.embeddedSchemaType;
2862
2904
  }
2863
2905
 
2864
2906
  // Now that we found the array, we need to check if there
@@ -2868,8 +2910,8 @@ Schema.prototype._getSchema = function(path) {
2868
2910
  // If there is no foundschema.schema we are dealing with
2869
2911
  // a path like array.$
2870
2912
  if (p !== parts.length) {
2871
- if (p + 1 === parts.length && foundschema.$embeddedSchemaType && (parts[p] === '$' || isArrayFilter(parts[p]))) {
2872
- return foundschema.$embeddedSchemaType;
2913
+ if (p + 1 === parts.length && foundschema.embeddedSchemaType && (parts[p] === '$' || isArrayFilter(parts[p]))) {
2914
+ return foundschema.embeddedSchemaType;
2873
2915
  }
2874
2916
 
2875
2917
  if (foundschema.schema) {
@@ -2877,7 +2919,7 @@ Schema.prototype._getSchema = function(path) {
2877
2919
  if (parts[p] === '$' || isArrayFilter(parts[p])) {
2878
2920
  if (p + 1 === parts.length) {
2879
2921
  // comments.$
2880
- return foundschema.$embeddedSchemaType;
2922
+ return foundschema.embeddedSchemaType;
2881
2923
  }
2882
2924
  // comments.$.comments.$.title
2883
2925
  ret = search(parts.slice(p + 1), foundschema.schema);
@@ -2957,9 +2999,9 @@ Schema.prototype._getPathType = function(path) {
2957
2999
  trypath = parts.slice(0, p).join('.');
2958
3000
  foundschema = schema.path(trypath);
2959
3001
  if (foundschema) {
2960
- if (foundschema.caster) {
3002
+ if (foundschema.embeddedSchemaType || foundschema.Constructor) {
2961
3003
  // array of Mixed?
2962
- if (foundschema.caster instanceof MongooseTypes.Mixed) {
3004
+ if (foundschema.embeddedSchemaType instanceof MongooseTypes.Mixed) {
2963
3005
  return { schema: foundschema, pathType: 'mixed' };
2964
3006
  }
2965
3007
 
package/lib/schemaType.js CHANGED
@@ -12,7 +12,6 @@ const clone = require('./helpers/clone');
12
12
  const handleImmutable = require('./helpers/schematype/handleImmutable');
13
13
  const isAsyncFunction = require('./helpers/isAsyncFunction');
14
14
  const isSimpleValidator = require('./helpers/isSimpleValidator');
15
- const immediate = require('./helpers/immediate');
16
15
  const schemaTypeSymbol = require('./helpers/symbols').schemaTypeSymbol;
17
16
  const utils = require('./utils');
18
17
  const validatorErrorSymbol = require('./helpers/symbols').validatorErrorSymbol;
@@ -445,13 +444,6 @@ SchemaType.prototype.default = function(val) {
445
444
  * s.path('my.date').index({ expires: 60 });
446
445
  * s.path('my.path').index({ unique: true, sparse: true });
447
446
  *
448
- * #### Note:
449
- *
450
- * _Indexes are created [in the background](https://www.mongodb.com/docs/manual/core/index-creation/#index-creation-background)
451
- * by default. If `background` is set to `false`, MongoDB will not execute any
452
- * read/write operations you send until the index build.
453
- * Specify `background: false` to override Mongoose's default._
454
- *
455
447
  * @param {Object|Boolean|String|Number} options
456
448
  * @return {SchemaType} this
457
449
  * @api public
@@ -1341,7 +1333,6 @@ SchemaType.prototype.select = function select(val) {
1341
1333
  * Performs a validation of `value` using the validators declared for this SchemaType.
1342
1334
  *
1343
1335
  * @param {Any} value
1344
- * @param {Function} callback
1345
1336
  * @param {Object} scope
1346
1337
  * @param {Object} [options]
1347
1338
  * @param {String} [options.path]
@@ -1349,28 +1340,20 @@ SchemaType.prototype.select = function select(val) {
1349
1340
  * @api public
1350
1341
  */
1351
1342
 
1352
- SchemaType.prototype.doValidate = function(value, fn, scope, options) {
1343
+ SchemaType.prototype.doValidate = async function doValidate(value, scope, options) {
1353
1344
  let err = false;
1354
1345
  const path = this.path;
1355
- if (typeof fn !== 'function') {
1356
- throw new TypeError(`Must pass callback function to doValidate(), got ${typeof fn}`);
1357
- }
1358
1346
 
1359
1347
  // Avoid non-object `validators`
1360
1348
  const validators = this.validators.
1361
1349
  filter(v => typeof v === 'object' && v !== null);
1362
1350
 
1363
- let count = validators.length;
1364
-
1365
- if (!count) {
1366
- return fn(null);
1351
+ if (!validators.length) {
1352
+ return;
1367
1353
  }
1368
1354
 
1355
+ const promises = [];
1369
1356
  for (let i = 0, len = validators.length; i < len; ++i) {
1370
- if (err) {
1371
- break;
1372
- }
1373
-
1374
1357
  const v = validators[i];
1375
1358
  const validator = v.validator;
1376
1359
  let ok;
@@ -1386,17 +1369,19 @@ SchemaType.prototype.doValidate = function(value, fn, scope, options) {
1386
1369
  }
1387
1370
  }
1388
1371
 
1389
- if (validator instanceof RegExp) {
1390
- validate(validator.test(value), validatorProperties, scope);
1372
+ if (value === undefined && validator !== this.requiredValidator) {
1391
1373
  continue;
1392
1374
  }
1393
-
1394
- if (typeof validator !== 'function') {
1375
+ if (validator instanceof RegExp) {
1376
+ ok = validator.test(value);
1377
+ if (ok === false) {
1378
+ const ErrorConstructor = validatorProperties.ErrorConstructor || ValidatorError;
1379
+ err = new ErrorConstructor(validatorProperties, scope);
1380
+ err[validatorErrorSymbol] = true;
1381
+ throw err;
1382
+ }
1395
1383
  continue;
1396
- }
1397
-
1398
- if (value === undefined && validator !== this.requiredValidator) {
1399
- validate(true, validatorProperties, scope);
1384
+ } else if (typeof validator !== 'function') {
1400
1385
  continue;
1401
1386
  }
1402
1387
 
@@ -1415,38 +1400,35 @@ SchemaType.prototype.doValidate = function(value, fn, scope, options) {
1415
1400
  }
1416
1401
 
1417
1402
  if (ok != null && typeof ok.then === 'function') {
1418
- ok.then(
1419
- function(ok) { validate(ok, validatorProperties, scope); },
1420
- function(error) {
1421
- validatorProperties.reason = error;
1422
- validatorProperties.message = error.message;
1423
- ok = false;
1424
- validate(ok, validatorProperties, scope);
1425
- });
1426
- } else {
1427
- validate(ok, validatorProperties, scope);
1428
- }
1429
- }
1430
-
1431
- function validate(ok, validatorProperties, scope) {
1432
- if (err) {
1433
- return;
1434
- }
1435
- if (ok === undefined || ok) {
1436
- if (--count <= 0) {
1437
- immediate(function() {
1438
- fn(null);
1439
- });
1440
- }
1441
- } else {
1403
+ promises.push(
1404
+ ok.then(
1405
+ function(ok) {
1406
+ if (ok === false) {
1407
+ const ErrorConstructor = validatorProperties.ErrorConstructor || ValidatorError;
1408
+ err = new ErrorConstructor(validatorProperties, scope);
1409
+ err[validatorErrorSymbol] = true;
1410
+ throw err;
1411
+ }
1412
+ },
1413
+ function(error) {
1414
+ validatorProperties.reason = error;
1415
+ validatorProperties.message = error.message;
1416
+ ok = false;
1417
+ const ErrorConstructor = validatorProperties.ErrorConstructor || ValidatorError;
1418
+ err = new ErrorConstructor(validatorProperties, scope);
1419
+ err[validatorErrorSymbol] = true;
1420
+ throw err;
1421
+ })
1422
+ );
1423
+ } else if (ok !== undefined && !ok) {
1442
1424
  const ErrorConstructor = validatorProperties.ErrorConstructor || ValidatorError;
1443
1425
  err = new ErrorConstructor(validatorProperties, scope);
1444
1426
  err[validatorErrorSymbol] = true;
1445
- immediate(function() {
1446
- fn(err);
1447
- });
1427
+ throw err;
1448
1428
  }
1449
1429
  }
1430
+
1431
+ await Promise.all(promises);
1450
1432
  };
1451
1433
 
1452
1434
 
@@ -1811,7 +1793,7 @@ SchemaType.prototype.clone = function() {
1811
1793
  */
1812
1794
 
1813
1795
  SchemaType.prototype.getEmbeddedSchemaType = function getEmbeddedSchemaType() {
1814
- return this.$embeddedSchemaType;
1796
+ return this.embeddedSchemaType;
1815
1797
  };
1816
1798
 
1817
1799
  /*!
@@ -88,8 +88,8 @@ function MongooseArray(values, path, doc, schematype) {
88
88
  if (schematype && schematype.virtuals && schematype.virtuals.hasOwnProperty(prop)) {
89
89
  return schematype.virtuals[prop].applyGetters(undefined, target);
90
90
  }
91
- if (typeof prop === 'string' && numberRE.test(prop) && schematype?.$embeddedSchemaType != null) {
92
- return schematype.$embeddedSchemaType.applyGetters(__array[prop], doc);
91
+ if (typeof prop === 'string' && numberRE.test(prop) && schematype?.embeddedSchemaType != null) {
92
+ return schematype.embeddedSchemaType.applyGetters(__array[prop], doc);
93
93
  }
94
94
 
95
95
  return __array[prop];
@@ -251,10 +251,10 @@ const methods = {
251
251
  if (!isDisc) {
252
252
  value = new Model(value);
253
253
  }
254
- return this[arraySchemaSymbol].caster.applySetters(value, parent, true);
254
+ return this[arraySchemaSymbol].embeddedSchemaType.applySetters(value, parent, true);
255
255
  }
256
256
 
257
- return this[arraySchemaSymbol].caster.applySetters(value, parent, false);
257
+ return this[arraySchemaSymbol].embeddedSchemaType.applySetters(value, parent, false);
258
258
  },
259
259
 
260
260
  /**
@@ -1007,7 +1007,7 @@ function _minimizePath(obj, parts, i) {
1007
1007
  function _checkManualPopulation(arr, docs) {
1008
1008
  const ref = arr == null ?
1009
1009
  null :
1010
- arr[arraySchemaSymbol] && arr[arraySchemaSymbol].caster && arr[arraySchemaSymbol].caster.options && arr[arraySchemaSymbol].caster.options.ref || null;
1010
+ arr[arraySchemaSymbol]?.embeddedSchemaType?.options?.ref || null;
1011
1011
  if (arr.length === 0 &&
1012
1012
  docs.length !== 0) {
1013
1013
  if (_isAllSubdocs(docs, ref)) {
@@ -1025,7 +1025,7 @@ function _checkManualPopulation(arr, docs) {
1025
1025
  function _depopulateIfNecessary(arr, docs) {
1026
1026
  const ref = arr == null ?
1027
1027
  null :
1028
- arr[arraySchemaSymbol] && arr[arraySchemaSymbol].caster && arr[arraySchemaSymbol].caster.options && arr[arraySchemaSymbol].caster.options.ref || null;
1028
+ arr[arraySchemaSymbol]?.embeddedSchemaType?.options?.ref || null;
1029
1029
  const parentDoc = arr[arrayParentSymbol];
1030
1030
  const path = arr[arrayPathSymbol];
1031
1031
  if (!ref || !parentDoc.populated(path)) {
@@ -41,7 +41,7 @@ function ArraySubdocument(obj, parentArr, skipId, fields, index) {
41
41
  options = { isNew: true };
42
42
  }
43
43
 
44
- Subdocument.call(this, obj, fields, this[documentArrayParent], skipId, options);
44
+ Subdocument.call(this, obj, fields, this[documentArrayParent], options);
45
45
  }
46
46
 
47
47
  /*!