mongoose 8.19.4 → 9.0.0-rc0

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 (105) 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 +3 -3
  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/divergentArray.js +2 -2
  13. package/lib/error/objectParameter.js +1 -2
  14. package/lib/error/validation.js +0 -8
  15. package/lib/helpers/clone.js +1 -1
  16. package/lib/helpers/common.js +1 -1
  17. package/lib/helpers/discriminator/mergeDiscriminatorSchema.js +10 -0
  18. package/lib/helpers/indexes/isIndexEqual.js +0 -1
  19. package/lib/helpers/model/applyDefaultsToPOJO.js +2 -2
  20. package/lib/helpers/model/applyHooks.js +43 -53
  21. package/lib/helpers/model/applyMethods.js +2 -2
  22. package/lib/helpers/model/applyStaticHooks.js +1 -48
  23. package/lib/helpers/model/castBulkWrite.js +1 -1
  24. package/lib/helpers/parallelLimit.js +18 -36
  25. package/lib/helpers/pluralize.js +3 -3
  26. package/lib/helpers/populate/assignRawDocsToIdStructure.js +1 -8
  27. package/lib/helpers/populate/createPopulateQueryFilter.js +1 -1
  28. package/lib/helpers/populate/getModelsMapForPopulate.js +17 -9
  29. package/lib/helpers/populate/getSchemaTypes.js +5 -5
  30. package/lib/helpers/query/cast$expr.js +8 -10
  31. package/lib/helpers/query/castFilterPath.js +1 -1
  32. package/lib/helpers/query/castUpdate.js +15 -13
  33. package/lib/helpers/query/getEmbeddedDiscriminatorPath.js +1 -1
  34. package/lib/helpers/schema/applyPlugins.js +1 -1
  35. package/lib/helpers/schema/getIndexes.js +1 -7
  36. package/lib/helpers/timestamps/setupTimestamps.js +3 -6
  37. package/lib/helpers/updateValidators.js +57 -111
  38. package/lib/model.js +419 -607
  39. package/lib/mongoose.js +41 -13
  40. package/lib/plugins/saveSubdocs.js +24 -51
  41. package/lib/plugins/sharding.js +5 -4
  42. package/lib/plugins/validateBeforeSave.js +3 -13
  43. package/lib/query.js +101 -145
  44. package/lib/queryHelpers.js +2 -2
  45. package/lib/schema/array.js +46 -84
  46. package/lib/schema/bigint.js +4 -2
  47. package/lib/schema/boolean.js +4 -2
  48. package/lib/schema/buffer.js +4 -2
  49. package/lib/schema/date.js +4 -2
  50. package/lib/schema/decimal128.js +4 -2
  51. package/lib/schema/documentArray.js +66 -91
  52. package/lib/schema/documentArrayElement.js +18 -11
  53. package/lib/schema/double.js +4 -2
  54. package/lib/schema/int32.js +4 -2
  55. package/lib/schema/map.js +87 -6
  56. package/lib/schema/mixed.js +4 -2
  57. package/lib/schema/number.js +4 -2
  58. package/lib/schema/objectId.js +4 -2
  59. package/lib/schema/string.js +5 -3
  60. package/lib/schema/subdocument.js +27 -31
  61. package/lib/schema/union.js +11 -3
  62. package/lib/schema/uuid.js +4 -23
  63. package/lib/schema.js +91 -91
  64. package/lib/schemaType.js +67 -59
  65. package/lib/types/array/index.js +2 -2
  66. package/lib/types/array/methods/index.js +4 -4
  67. package/lib/types/arraySubdocument.js +1 -1
  68. package/lib/types/buffer.js +10 -10
  69. package/lib/types/decimal128.js +1 -1
  70. package/lib/types/documentArray/index.js +1 -1
  71. package/lib/types/documentArray/methods/index.js +32 -18
  72. package/lib/types/double.js +1 -1
  73. package/lib/types/map.js +1 -2
  74. package/lib/types/objectid.js +1 -1
  75. package/lib/types/subdocument.js +15 -43
  76. package/lib/types/uuid.js +1 -1
  77. package/lib/utils.js +1 -8
  78. package/lib/validOptions.js +3 -3
  79. package/package.json +11 -24
  80. package/types/connection.d.ts +20 -11
  81. package/types/document.d.ts +96 -27
  82. package/types/index.d.ts +143 -39
  83. package/types/inferhydrateddoctype.d.ts +115 -0
  84. package/types/inferrawdoctype.d.ts +99 -75
  85. package/types/inferschematype.d.ts +17 -3
  86. package/types/middlewares.d.ts +0 -2
  87. package/types/models.d.ts +131 -199
  88. package/types/mongooseoptions.d.ts +6 -5
  89. package/types/pipelinestage.d.ts +1 -1
  90. package/types/query.d.ts +71 -139
  91. package/types/schemaoptions.d.ts +1 -1
  92. package/types/schematypes.d.ts +14 -10
  93. package/types/types.d.ts +3 -4
  94. package/types/utility.d.ts +68 -48
  95. package/types/validation.d.ts +18 -14
  96. package/browser.js +0 -8
  97. package/dist/browser.umd.js +0 -2
  98. package/lib/browser.js +0 -141
  99. package/lib/browserDocument.js +0 -101
  100. package/lib/documentProvider.js +0 -30
  101. package/lib/drivers/browser/binary.js +0 -14
  102. package/lib/drivers/browser/decimal128.js +0 -7
  103. package/lib/drivers/browser/index.js +0 -13
  104. package/lib/drivers/browser/objectid.js +0 -29
  105. package/lib/helpers/promiseOrCallback.js +0 -54
@@ -1,8 +1,5 @@
1
1
  'use strict';
2
2
 
3
- const symbols = require('../../schema/symbols');
4
- const promiseOrCallback = require('../promiseOrCallback');
5
-
6
3
  /*!
7
4
  * ignore
8
5
  */
@@ -15,10 +12,10 @@ module.exports = applyHooks;
15
12
 
16
13
  applyHooks.middlewareFunctions = [
17
14
  'deleteOne',
18
- 'save',
19
- 'validate',
20
15
  'remove',
16
+ 'save',
21
17
  'updateOne',
18
+ 'validate',
22
19
  'init'
23
20
  ];
24
21
 
@@ -47,15 +44,15 @@ function applyHooks(model, schema, options) {
47
44
  contextParameter: true
48
45
  };
49
46
  const objToDecorate = options.decorateDoc ? model : model.prototype;
50
-
51
47
  model.$appliedHooks = true;
52
48
  for (const key of Object.keys(schema.paths)) {
53
- const type = schema.paths[key];
49
+ let type = schema.paths[key];
54
50
  let childModel = null;
55
- if (type.$isSingleNested) {
56
- childModel = type.caster;
57
- } else if (type.$isMongooseDocumentArray) {
58
- childModel = type.Constructor;
51
+
52
+ const result = findChildModel(type);
53
+ if (result) {
54
+ childModel = result.childModel;
55
+ type = result.type;
59
56
  } else {
60
57
  continue;
61
58
  }
@@ -64,7 +61,11 @@ function applyHooks(model, schema, options) {
64
61
  continue;
65
62
  }
66
63
 
67
- applyHooks(childModel, type.schema, { ...options, isChildSchema: true });
64
+ applyHooks(childModel, type.schema, {
65
+ ...options,
66
+ decorateDoc: false,
67
+ isChildSchema: true
68
+ });
68
69
  if (childModel.discriminators != null) {
69
70
  const keys = Object.keys(childModel.discriminators);
70
71
  for (const key of keys) {
@@ -78,39 +79,10 @@ function applyHooks(model, schema, options) {
78
79
  // promises and make it so that `doc.save.toString()` provides meaningful
79
80
  // information.
80
81
 
81
- const middleware = schema.s.hooks.
82
- filter(hook => {
83
- if (hook.name === 'updateOne' || hook.name === 'deleteOne') {
84
- return !!hook['document'];
85
- }
86
- if (hook.name === 'remove' || hook.name === 'init') {
87
- return hook['document'] == null || !!hook['document'];
88
- }
89
- if (hook.query != null || hook.document != null) {
90
- return hook.document !== false;
91
- }
92
- return true;
93
- }).
94
- filter(hook => {
95
- // If user has overwritten the method, don't apply built-in middleware
96
- if (schema.methods[hook.name]) {
97
- return !hook.fn[symbols.builtInMiddleware];
98
- }
99
-
100
- return true;
101
- });
82
+ const middleware = schema._getDocumentMiddleware();
102
83
 
103
84
  model._middleware = middleware;
104
85
 
105
- objToDecorate.$__originalValidate = objToDecorate.$__originalValidate || objToDecorate.$__validate;
106
-
107
- const internalMethodsToWrap = options && options.isChildSchema ? ['save', 'validate', 'deleteOne'] : ['save', 'validate'];
108
- for (const method of internalMethodsToWrap) {
109
- const toWrap = method === 'validate' ? '$__originalValidate' : `$__${method}`;
110
- const wrapped = middleware.
111
- createWrapper(method, objToDecorate[toWrap], null, kareemOptions);
112
- objToDecorate[`$__${method}`] = wrapped;
113
- }
114
86
  objToDecorate.$__init = middleware.
115
87
  createWrapperSync('init', objToDecorate.$__init, null, kareemOptions);
116
88
 
@@ -134,17 +106,35 @@ function applyHooks(model, schema, options) {
134
106
  continue;
135
107
  }
136
108
  const originalMethod = objToDecorate[method];
137
- objToDecorate[method] = function() {
138
- const args = Array.prototype.slice.call(arguments);
139
- const cb = args.slice(-1).pop();
140
- const argsWithoutCallback = typeof cb === 'function' ?
141
- args.slice(0, args.length - 1) : args;
142
- return promiseOrCallback(cb, callback => {
143
- return this[`$__${method}`].apply(this,
144
- argsWithoutCallback.concat([callback]));
145
- }, model.events);
146
- };
147
- objToDecorate[`$__${method}`] = middleware.
109
+ objToDecorate[`$__${method}`] = objToDecorate[method];
110
+ objToDecorate[method] = middleware.
148
111
  createWrapper(method, originalMethod, null, customMethodOptions);
149
112
  }
150
113
  }
114
+
115
+ /**
116
+ * Check if there is an embedded schematype in the given schematype. Handles drilling down into primitive
117
+ * arrays and maps in case of array of array of subdocs or map of subdocs.
118
+ *
119
+ * @param {SchemaType} curType
120
+ * @returns {{ childModel: Model | typeof Subdocument, curType: SchemaType } | null}
121
+ */
122
+
123
+ function findChildModel(curType) {
124
+ if (curType.$isSingleNested || curType.$isMongooseDocumentArray) {
125
+ return { childModel: curType.Constructor, type: curType };
126
+ }
127
+ if (curType.instance === 'Array') {
128
+ const embedded = curType.getEmbeddedSchemaType();
129
+ if (embedded) {
130
+ return findChildModel(embedded);
131
+ }
132
+ }
133
+ if (curType.instance === 'Map') {
134
+ const mapType = curType.getEmbeddedSchemaType();
135
+ if (mapType) {
136
+ return findChildModel(mapType);
137
+ }
138
+ }
139
+ return null;
140
+ }
@@ -60,8 +60,8 @@ module.exports = function applyMethods(model, schema) {
60
60
  model.$appliedMethods = true;
61
61
  for (const key of Object.keys(schema.paths)) {
62
62
  const type = schema.paths[key];
63
- if (type.$isSingleNested && !type.caster.$appliedMethods) {
64
- applyMethods(type.caster, type.schema);
63
+ if (type.$isSingleNested && !type.Constructor.$appliedMethods) {
64
+ applyMethods(type.Constructor, type.schema);
65
65
  }
66
66
  if (type.$isMongooseDocumentArray && !type.Constructor.$appliedMethods) {
67
67
  applyMethods(type.Constructor, type.schema);
@@ -1,6 +1,5 @@
1
1
  'use strict';
2
2
 
3
- const promiseOrCallback = require('../promiseOrCallback');
4
3
  const { queryMiddlewareFunctions, aggregateMiddlewareFunctions, modelMiddlewareFunctions, documentMiddlewareFunctions } = require('../../constants');
5
4
 
6
5
  const middlewareFunctions = Array.from(
@@ -13,14 +12,6 @@ const middlewareFunctions = Array.from(
13
12
  );
14
13
 
15
14
  module.exports = function applyStaticHooks(model, hooks, statics) {
16
- const kareemOptions = {
17
- useErrorHandlers: true,
18
- numCallbackParams: 1
19
- };
20
-
21
- model.$__insertMany = hooks.createWrapper('insertMany',
22
- model.$__insertMany, model, kareemOptions);
23
-
24
15
  hooks = hooks.filter(hook => {
25
16
  // If the custom static overwrites an existing middleware, don't apply
26
17
  // middleware to it by default. This avoids a potential backwards breaking
@@ -36,45 +27,7 @@ module.exports = function applyStaticHooks(model, hooks, statics) {
36
27
  if (hooks.hasHooks(key)) {
37
28
  const original = model[key];
38
29
 
39
- model[key] = function() {
40
- const numArgs = arguments.length;
41
- const lastArg = numArgs > 0 ? arguments[numArgs - 1] : null;
42
- const cb = typeof lastArg === 'function' ? lastArg : null;
43
- const args = Array.prototype.slice.
44
- call(arguments, 0, cb == null ? numArgs : numArgs - 1);
45
- // Special case: can't use `Kareem#wrap()` because it doesn't currently
46
- // support wrapped functions that return a promise.
47
- return promiseOrCallback(cb, callback => {
48
- hooks.execPre(key, model, args, function(err) {
49
- if (err != null) {
50
- return callback(err);
51
- }
52
-
53
- let postCalled = 0;
54
- const ret = original.apply(model, args.concat(post));
55
- if (ret != null && typeof ret.then === 'function') {
56
- ret.then(res => post(null, res), err => post(err));
57
- }
58
-
59
- function post(error, res) {
60
- if (postCalled++ > 0) {
61
- return;
62
- }
63
-
64
- if (error != null) {
65
- return callback(error);
66
- }
67
-
68
- hooks.execPost(key, model, [res], function(error) {
69
- if (error != null) {
70
- return callback(error);
71
- }
72
- callback(null, res);
73
- });
74
- }
75
- });
76
- }, model.events);
77
- };
30
+ model[key] = hooks.createWrapper(key, original);
78
31
  }
79
32
  }
80
33
  };
@@ -224,7 +224,7 @@ module.exports.castReplaceOne = async function castReplaceOne(originalModel, rep
224
224
  });
225
225
 
226
226
  // set `skipId`, otherwise we get "_id field cannot be changed"
227
- const doc = new model(replaceOne['replacement'], strict, true);
227
+ const doc = new model(replaceOne['replacement'], strict, { skipId: true });
228
228
  if (model.schema.options.timestamps && getTimestampsOpt(replaceOne, options)) {
229
229
  doc.initializeTimestamps();
230
230
  }
@@ -6,50 +6,32 @@ module.exports = parallelLimit;
6
6
  * ignore
7
7
  */
8
8
 
9
- function parallelLimit(fns, limit, callback) {
10
- let numInProgress = 0;
11
- let numFinished = 0;
12
- let error = null;
13
-
9
+ async function parallelLimit(params, fn, limit) {
14
10
  if (limit <= 0) {
15
11
  throw new Error('Limit must be positive');
16
12
  }
17
13
 
18
- if (fns.length === 0) {
19
- return callback(null, []);
14
+ if (params.length === 0) {
15
+ return [];
20
16
  }
21
17
 
22
- for (let i = 0; i < fns.length && i < limit; ++i) {
23
- _start();
24
- }
18
+ const results = [];
19
+ const executing = new Set();
25
20
 
26
- function _start() {
27
- fns[numFinished + numInProgress](_done(numFinished + numInProgress));
28
- ++numInProgress;
29
- }
21
+ for (let index = 0; index < params.length; index++) {
22
+ const param = params[index];
23
+ const p = fn(param, index);
24
+ results.push(p);
30
25
 
31
- const results = [];
26
+ executing.add(p);
27
+
28
+ const clean = () => executing.delete(p);
29
+ p.then(clean).catch(clean);
32
30
 
33
- function _done(index) {
34
- return (err, res) => {
35
- --numInProgress;
36
- ++numFinished;
37
-
38
- if (error != null) {
39
- return;
40
- }
41
- if (err != null) {
42
- error = err;
43
- return callback(error);
44
- }
45
-
46
- results[index] = res;
47
-
48
- if (numFinished === fns.length) {
49
- return callback(null, results);
50
- } else if (numFinished + numInProgress < fns.length) {
51
- _start();
52
- }
53
- };
31
+ if (executing.size >= limit) {
32
+ await Promise.race(executing);
33
+ }
54
34
  }
35
+
36
+ return Promise.all(results);
55
37
  }
@@ -8,13 +8,13 @@ module.exports = pluralize;
8
8
 
9
9
  exports.pluralization = [
10
10
  [/human$/gi, 'humans'],
11
- [/(m)an$/gi, '$1en'],
11
+ [/(m|wom)an$/gi, '$1en'],
12
12
  [/(pe)rson$/gi, '$1ople'],
13
13
  [/(child)$/gi, '$1ren'],
14
14
  [/^(ox)$/gi, '$1en'],
15
15
  [/(ax|test)is$/gi, '$1es'],
16
- [/(octop|vir)us$/gi, '$1i'],
17
- [/(alias|status)$/gi, '$1es'],
16
+ [/(octop|cact|foc|fung|nucle)us$/gi, '$1i'],
17
+ [/(alias|status|virus)$/gi, '$1es'],
18
18
  [/(bu)s$/gi, '$1ses'],
19
19
  [/(buffal|tomat|potat)o$/gi, '$1oes'],
20
20
  [/([ti])um$/gi, '$1a'],
@@ -78,14 +78,7 @@ function assignRawDocsToIdStructure(rawIds, resultDocs, resultOrder, options, re
78
78
  continue;
79
79
  }
80
80
 
81
- if (id?.constructor?.name === 'Binary' && id.sub_type === 4 && typeof id.toUUID === 'function') {
82
- // Workaround for gh-15315 because Mongoose UUIDs don't use BSON UUIDs yet.
83
- sid = String(id.toUUID());
84
- } else if (id?.constructor?.name === 'Buffer' && id._subtype === 4 && typeof id.toUUID === 'function') {
85
- sid = String(id.toUUID());
86
- } else {
87
- sid = String(id);
88
- }
81
+ sid = String(id);
89
82
  doc = resultDocs[sid];
90
83
  // If user wants separate copies of same doc, use this option
91
84
  if (options.clone && doc != null) {
@@ -73,7 +73,7 @@ function _filterInvalidIds(ids, foreignSchemaType, skipInvalidIds) {
73
73
  try {
74
74
  foreignSchemaType.cast(id);
75
75
  return true;
76
- } catch (err) {
76
+ } catch {
77
77
  return false;
78
78
  }
79
79
  });
@@ -219,7 +219,7 @@ module.exports = function getModelsMapForPopulate(model, docs, options) {
219
219
 
220
220
  const originalSchema = schema;
221
221
  if (schema && schema.instance === 'Array') {
222
- schema = schema.caster;
222
+ schema = schema.embeddedSchemaType;
223
223
  }
224
224
  if (schema && schema.$isSchemaMap) {
225
225
  schema = schema.$__schemaType;
@@ -281,8 +281,8 @@ module.exports = function getModelsMapForPopulate(model, docs, options) {
281
281
 
282
282
  schemaForCurrentDoc = modelForCurrentDoc.schema._getSchema(options.path);
283
283
 
284
- if (schemaForCurrentDoc && schemaForCurrentDoc.caster) {
285
- schemaForCurrentDoc = schemaForCurrentDoc.caster;
284
+ if (schemaForCurrentDoc && schemaForCurrentDoc.embeddedSchemaType) {
285
+ schemaForCurrentDoc = schemaForCurrentDoc.embeddedSchemaType;
286
286
  }
287
287
  } else {
288
288
  schemaForCurrentDoc = schema;
@@ -418,7 +418,15 @@ function _virtualPopulate(model, docs, options, _virtualRes) {
418
418
  justOne = options.justOne;
419
419
  }
420
420
 
421
- modelNames = virtual._getModelNamesForPopulate(doc);
421
+ // Use the correct target doc/sub-doc for dynamic ref on nested schema. See gh-12363
422
+ if (_virtualRes.nestedSchemaPath && typeof virtual.options.ref === 'function') {
423
+ const subdocs = utils.getValue(_virtualRes.nestedSchemaPath, doc);
424
+ modelNames = Array.isArray(subdocs)
425
+ ? subdocs.flatMap(subdoc => virtual._getModelNamesForPopulate(subdoc))
426
+ : virtual._getModelNamesForPopulate(subdocs);
427
+ } else {
428
+ modelNames = virtual._getModelNamesForPopulate(doc);
429
+ }
422
430
  if (virtual.options.refPath) {
423
431
  justOne = !!virtual.options.justOne;
424
432
  data.isRefPath = true;
@@ -711,16 +719,16 @@ function _findRefPathForDiscriminators(doc, modelSchema, data, options, normaliz
711
719
  cur = cur + (cur.length === 0 ? '' : '.') + piece;
712
720
  const schematype = modelSchema.path(cur);
713
721
  if (schematype != null &&
714
- schematype.$isMongooseArray &&
715
- schematype.caster.discriminators != null &&
716
- Object.keys(schematype.caster.discriminators).length !== 0) {
722
+ schematype.$isMongooseDocumentArray &&
723
+ schematype.Constructor.discriminators != null &&
724
+ Object.keys(schematype.Constructor.discriminators).length !== 0) {
717
725
  const subdocs = utils.getValue(cur, doc);
718
726
  const remnant = options.path.substring(cur.length + 1);
719
- const discriminatorKey = schematype.caster.schema.options.discriminatorKey;
727
+ const discriminatorKey = schematype.Constructor.schema.options.discriminatorKey;
720
728
  modelNames = [];
721
729
  for (const subdoc of subdocs) {
722
730
  const discriminatorName = utils.getValue(discriminatorKey, subdoc);
723
- const discriminator = schematype.caster.discriminators[discriminatorName];
731
+ const discriminator = schematype.Constructor.discriminators[discriminatorName];
724
732
  const discriminatorSchema = discriminator && discriminator.schema;
725
733
  if (discriminatorSchema == null) {
726
734
  continue;
@@ -58,10 +58,10 @@ module.exports = function getSchemaTypes(model, schema, doc, path) {
58
58
  continue;
59
59
  }
60
60
 
61
- if (foundschema.caster) {
61
+ if (foundschema.embeddedSchemaType) {
62
62
  // array of Mixed?
63
- if (foundschema.caster instanceof Mixed) {
64
- return foundschema.caster;
63
+ if (foundschema.embeddedSchemaType instanceof Mixed) {
64
+ return foundschema.embeddedSchemaType;
65
65
  }
66
66
 
67
67
  let schemas = null;
@@ -142,11 +142,11 @@ module.exports = function getSchemaTypes(model, schema, doc, path) {
142
142
  }
143
143
  } else if (p !== parts.length &&
144
144
  foundschema.$isMongooseArray &&
145
- foundschema.casterConstructor.$isMongooseArray) {
145
+ foundschema.embeddedSchemaType.$isMongooseArray) {
146
146
  // Nested arrays. Drill down to the bottom of the nested array.
147
147
  let type = foundschema;
148
148
  while (type.$isMongooseArray && !type.$isMongooseDocumentArray) {
149
- type = type.casterConstructor;
149
+ type = type.embeddedSchemaType;
150
150
  }
151
151
 
152
152
  const ret = search(
@@ -146,7 +146,7 @@ function castNumberOperator(val) {
146
146
 
147
147
  try {
148
148
  return castNumber(val);
149
- } catch (err) {
149
+ } catch {
150
150
  throw new CastError('Number', val);
151
151
  }
152
152
  }
@@ -174,7 +174,7 @@ function castIn(val, schema, strictQuery) {
174
174
  }
175
175
 
176
176
  return [
177
- schematype.$isMongooseDocumentArray ? schematype.$embeddedSchemaType.cast(search) : schematype.caster.cast(search),
177
+ schematype.embeddedSchemaType.cast(search),
178
178
  path
179
179
  ];
180
180
  }
@@ -187,7 +187,7 @@ function castArithmetic(val) {
187
187
  }
188
188
  try {
189
189
  return castNumber(val);
190
- } catch (err) {
190
+ } catch {
191
191
  throw new CastError('Number', val);
192
192
  }
193
193
  }
@@ -198,7 +198,7 @@ function castArithmetic(val) {
198
198
  }
199
199
  try {
200
200
  return castNumber(v);
201
- } catch (err) {
201
+ } catch {
202
202
  throw new CastError('Number', v);
203
203
  }
204
204
  });
@@ -229,10 +229,8 @@ function castComparison(val, schema, strictQuery) {
229
229
  path = lhs[key].slice(1) + '.' + key;
230
230
  schematype = schema.path(lhs[key].slice(1));
231
231
  if (schematype != null) {
232
- if (schematype.$isMongooseDocumentArray) {
233
- schematype = schematype.$embeddedSchemaType;
234
- } else if (schematype.$isMongooseArray) {
235
- schematype = schematype.caster;
232
+ if (schematype.$isMongooseArray) {
233
+ schematype = schematype.embeddedSchemaType;
236
234
  }
237
235
  }
238
236
  }
@@ -250,13 +248,13 @@ function castComparison(val, schema, strictQuery) {
250
248
  if (is$literal) {
251
249
  try {
252
250
  val[1] = { $literal: caster(val[1].$literal) };
253
- } catch (err) {
251
+ } catch {
254
252
  throw new CastError(caster.name.replace(/^cast/, ''), val[1], path + '.$literal');
255
253
  }
256
254
  } else {
257
255
  try {
258
256
  val[1] = caster(val[1]);
259
- } catch (err) {
257
+ } catch {
260
258
  throw new CastError(caster.name.replace(/^cast/, ''), val[1], path);
261
259
  }
262
260
  }
@@ -22,7 +22,7 @@ module.exports = function castFilterPath(ctx, schematype, val) {
22
22
  const nested = val[$cond];
23
23
 
24
24
  if ($cond === '$not') {
25
- if (nested && schematype && !schematype.caster) {
25
+ if (nested && schematype && !schematype.embeddedSchemaType && !schematype.Constructor) {
26
26
  const _keys = Object.keys(nested);
27
27
  if (_keys.length && isOperator(_keys[0])) {
28
28
  for (const key of Object.keys(nested)) {
@@ -281,7 +281,7 @@ function walkUpdatePath(schema, obj, op, options, context, filter, prefix) {
281
281
  continue;
282
282
  }
283
283
 
284
- if (schematype && schematype.caster && op in castOps) {
284
+ if (schematype && (schematype.embeddedSchemaType || schematype.Constructor) && op in castOps) {
285
285
  // embedded doc schema
286
286
  if ('$each' in val) {
287
287
  hasKeys = true;
@@ -428,7 +428,7 @@ function walkUpdatePath(schema, obj, op, options, context, filter, prefix) {
428
428
  if (obj[key] == null) {
429
429
  throw new CastError('String', obj[key], `${prefix}${key}.$rename`);
430
430
  }
431
- const schematype = new SchemaString(`${prefix}${key}.$rename`);
431
+ const schematype = new SchemaString(`${prefix}${key}.$rename`, null, null, schema);
432
432
  obj[key] = schematype.castForQuery(null, obj[key], context);
433
433
  continue;
434
434
  }
@@ -449,9 +449,9 @@ function walkUpdatePath(schema, obj, op, options, context, filter, prefix) {
449
449
 
450
450
  if (Array.isArray(obj[key]) && (op === '$addToSet' || op === '$push') && key !== '$each') {
451
451
  if (schematype &&
452
- schematype.caster &&
453
- !schematype.caster.$isMongooseArray &&
454
- !schematype.caster[schemaMixedSymbol]) {
452
+ schematype.embeddedSchemaType &&
453
+ !schematype.embeddedSchemaType.$isMongooseArray &&
454
+ !schematype.embeddedSchemaType[schemaMixedSymbol]) {
455
455
  obj[key] = { $each: obj[key] };
456
456
  }
457
457
  }
@@ -546,17 +546,16 @@ function castUpdateVal(schema, val, op, $conditional, context, path) {
546
546
  if (op in numberOps) {
547
547
  try {
548
548
  return castNumber(val);
549
- } catch (err) {
549
+ } catch {
550
550
  throw new CastError('number', val, path);
551
551
  }
552
552
  }
553
553
  return val;
554
554
  }
555
555
 
556
- // console.log('CastUpdateVal', path, op, val, schema);
557
-
558
- const cond = schema.caster && op in castOps &&
559
- (utils.isObject(val) || Array.isArray(val));
556
+ const cond = schema.$isMongooseArray
557
+ && op in castOps
558
+ && (utils.isObject(val) || Array.isArray(val));
560
559
  if (cond && !overwriteOps[op]) {
561
560
  // Cast values for ops that add data to MongoDB.
562
561
  // Ensures embedded documents get ObjectIds etc.
@@ -564,7 +563,7 @@ function castUpdateVal(schema, val, op, $conditional, context, path) {
564
563
  let cur = schema;
565
564
  while (cur.$isMongooseArray) {
566
565
  ++schemaArrayDepth;
567
- cur = cur.caster;
566
+ cur = cur.embeddedSchemaType;
568
567
  }
569
568
  let arrayDepth = 0;
570
569
  let _val = val;
@@ -605,7 +604,7 @@ function castUpdateVal(schema, val, op, $conditional, context, path) {
605
604
  }
606
605
  try {
607
606
  return castNumber(val);
608
- } catch (error) {
607
+ } catch {
609
608
  throw new CastError('number', val, schema.path);
610
609
  }
611
610
  }
@@ -625,7 +624,10 @@ function castUpdateVal(schema, val, op, $conditional, context, path) {
625
624
  }
626
625
 
627
626
  if (overwriteOps[op]) {
628
- const skipQueryCastForUpdate = val != null && schema.$isMongooseArray && schema.$fullPath != null && !schema.$fullPath.match(/\d+$/);
627
+ const skipQueryCastForUpdate = val != null
628
+ && schema.$isMongooseArray
629
+ && schema.$fullPath != null
630
+ && !schema.$fullPath.match(/\d+$/);
629
631
  const applySetters = schema[schemaMixedSymbol] != null;
630
632
  if (skipQueryCastForUpdate || applySetters) {
631
633
  return schema.applySetters(val, context);
@@ -82,7 +82,7 @@ module.exports = function getEmbeddedDiscriminatorPath(schema, update, filter, p
82
82
  continue;
83
83
  }
84
84
 
85
- const discriminator = getDiscriminatorByValue(schematype.caster.discriminators, discriminatorKey);
85
+ const discriminator = getDiscriminatorByValue(schematype.Constructor.discriminators, discriminatorKey);
86
86
  const discriminatorSchema = discriminator && discriminator.schema;
87
87
  if (discriminatorSchema == null) {
88
88
  continue;
@@ -33,7 +33,7 @@ module.exports = function applyPlugins(schema, plugins, options, cacheKey) {
33
33
  applyPlugins(type.schema, plugins, options, cacheKey);
34
34
 
35
35
  // Recompile schema because plugins may have changed it, see gh-7572
36
- type.caster.prototype.$__setSchema(type.schema);
36
+ type.Constructor.prototype.$__setSchema(type.schema);
37
37
  }
38
38
  }
39
39
  }
@@ -67,7 +67,7 @@ module.exports = function getIndexes(schema) {
67
67
  }
68
68
  }
69
69
 
70
- const index = path._index || (path.caster && path.caster._index);
70
+ const index = path._index || (path.embeddedSchemaType && path.embeddedSchemaType._index);
71
71
 
72
72
  if (index !== false && index !== null && index !== undefined) {
73
73
  const field = {};
@@ -96,9 +96,6 @@ module.exports = function getIndexes(schema) {
96
96
  }
97
97
 
98
98
  delete options.type;
99
- if (!('background' in options)) {
100
- options.background = true;
101
- }
102
99
  if (schema.options.autoIndex != null) {
103
100
  options._autoIndex = schema.options.autoIndex;
104
101
  }
@@ -126,9 +123,6 @@ module.exports = function getIndexes(schema) {
126
123
  } else {
127
124
  schema._indexes.forEach(function(index) {
128
125
  const options = index[1];
129
- if (!('background' in options)) {
130
- options.background = true;
131
- }
132
126
  decorateDiscriminatorIndexOptions(schema, options);
133
127
  });
134
128
  indexes = indexes.concat(schema._indexes);
@@ -42,15 +42,13 @@ module.exports = function setupTimestamps(schema, timestamps) {
42
42
 
43
43
  schema.add(schemaAdditions);
44
44
 
45
- schema.pre('save', function timestampsPreSave(next) {
45
+ schema.pre('save', function timestampsPreSave() {
46
46
  const timestampOption = get(this, '$__.saveOptions.timestamps');
47
47
  if (timestampOption === false) {
48
- return next();
48
+ return;
49
49
  }
50
50
 
51
51
  setDocumentTimestamps(this, timestampOption, currentTime, createdAt, updatedAt);
52
-
53
- next();
54
52
  });
55
53
 
56
54
  schema.methods.initializeTimestamps = function() {
@@ -88,7 +86,7 @@ module.exports = function setupTimestamps(schema, timestamps) {
88
86
  schema.pre('updateOne', opts, _setTimestampsOnUpdate);
89
87
  schema.pre('updateMany', opts, _setTimestampsOnUpdate);
90
88
 
91
- function _setTimestampsOnUpdate(next) {
89
+ function _setTimestampsOnUpdate() {
92
90
  const now = currentTime != null ?
93
91
  currentTime() :
94
92
  this.model.base.now();
@@ -105,6 +103,5 @@ module.exports = function setupTimestamps(schema, timestamps) {
105
103
  replaceOps.has(this.op)
106
104
  );
107
105
  applyTimestampsToChildren(now, this.getUpdate(), this.model.schema);
108
- next();
109
106
  }
110
107
  };