mongoose 9.0.0 → 9.0.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.
Files changed (42) hide show
  1. package/lib/aggregate.js +1 -1
  2. package/lib/cast/double.js +1 -1
  3. package/lib/cast.js +1 -1
  4. package/lib/connection.js +10 -10
  5. package/lib/document.js +63 -19
  6. package/lib/drivers/node-mongodb-native/collection.js +38 -104
  7. package/lib/drivers/node-mongodb-native/connection.js +1 -1
  8. package/lib/helpers/common.js +1 -1
  9. package/lib/helpers/indexes/applySchemaCollation.js +1 -1
  10. package/lib/helpers/indexes/isDefaultIdIndex.js +1 -1
  11. package/lib/helpers/model/applyMethods.js +1 -1
  12. package/lib/helpers/model/castBulkWrite.js +13 -6
  13. package/lib/helpers/populate/getModelsMapForPopulate.js +3 -3
  14. package/lib/helpers/populate/modelNamesFromRefPath.js +1 -1
  15. package/lib/helpers/populate/removeDeselectedForeignField.js +1 -1
  16. package/lib/helpers/projection/applyProjection.js +2 -2
  17. package/lib/helpers/query/getEmbeddedDiscriminatorPath.js +1 -1
  18. package/lib/helpers/setDefaultsOnInsert.js +2 -2
  19. package/lib/helpers/timestamps/setupTimestamps.js +1 -1
  20. package/lib/helpers/update/applyTimestampsToUpdate.js +38 -25
  21. package/lib/helpers/update/decorateUpdateWithVersionKey.js +1 -1
  22. package/lib/model.js +17 -11
  23. package/lib/mongoose.js +3 -4
  24. package/lib/query.js +3 -3
  25. package/lib/schema/array.js +1 -1
  26. package/lib/schema/number.js +14 -2
  27. package/lib/schema/operators/text.js +1 -1
  28. package/lib/schema.js +21 -21
  29. package/lib/schemaType.js +8 -8
  30. package/lib/types/array/index.js +5 -5
  31. package/lib/types/documentArray/index.js +6 -6
  32. package/lib/types/objectid.js +1 -1
  33. package/lib/utils.js +12 -24
  34. package/lib/virtualType.js +1 -1
  35. package/package.json +8 -7
  36. package/types/index.d.ts +11 -3
  37. package/types/inferrawdoctype.d.ts +9 -3
  38. package/types/inferschematype.d.ts +20 -27
  39. package/types/models.d.ts +313 -85
  40. package/types/query.d.ts +91 -1
  41. package/types/utility.d.ts +1 -1
  42. package/types/virtuals.d.ts +3 -3
@@ -56,7 +56,7 @@ module.exports = function modelNamesFromRefPath(refPath, doc, populatedPath, mod
56
56
  const refValue = mpath.get(refPath, doc, lookupLocalFields);
57
57
 
58
58
  let modelNames;
59
- if (modelSchema != null && modelSchema.virtuals.hasOwnProperty(refPath)) {
59
+ if (modelSchema != null && Object.hasOwn(modelSchema.virtuals, refPath)) {
60
60
  modelNames = [modelSchema.virtuals[refPath].applyGetters(void 0, doc)];
61
61
  } else {
62
62
  modelNames = Array.isArray(refValue) ? refValue : [refValue];
@@ -16,7 +16,7 @@ module.exports = function removeDeselectedForeignField(foreignFields, options, d
16
16
  return;
17
17
  }
18
18
  for (const foreignField of foreignFields) {
19
- if (!projection.hasOwnProperty('-' + foreignField)) {
19
+ if (!Object.hasOwn(projection, '-' + foreignField)) {
20
20
  continue;
21
21
  }
22
22
 
@@ -43,7 +43,7 @@ function applyExclusiveProjection(doc, projection, hasIncludedChildren, projecti
43
43
 
44
44
  for (const key of Object.keys(ret)) {
45
45
  const fullPath = prefix ? prefix + '.' + key : key;
46
- if (projection.hasOwnProperty(fullPath) || projectionLimb.hasOwnProperty(key)) {
46
+ if (Object.hasOwn(projection, fullPath) || Object.hasOwn(projectionLimb, key)) {
47
47
  if (isPOJO(projection[fullPath]) || isPOJO(projectionLimb[key])) {
48
48
  ret[key] = applyExclusiveProjection(ret[key], projection, hasIncludedChildren, projectionLimb[key], fullPath);
49
49
  } else {
@@ -68,7 +68,7 @@ function applyInclusiveProjection(doc, projection, hasIncludedChildren, projecti
68
68
 
69
69
  for (const key of Object.keys(ret)) {
70
70
  const fullPath = prefix ? prefix + '.' + key : key;
71
- if (projection.hasOwnProperty(fullPath) || projectionLimb.hasOwnProperty(key)) {
71
+ if (Object.hasOwn(projection, fullPath) || Object.hasOwn(projectionLimb, key)) {
72
72
  if (isPOJO(projection[fullPath]) || isPOJO(projectionLimb[key])) {
73
73
  ret[key] = applyInclusiveProjection(ret[key], projection, hasIncludedChildren, projectionLimb[key], fullPath);
74
74
  }
@@ -71,7 +71,7 @@ module.exports = function getEmbeddedDiscriminatorPath(schema, update, filter, p
71
71
  const schemaKey = updatedPathsByFilter[filterKey] + '.' + key;
72
72
  const arrayFilterKey = filterKey + '.' + key;
73
73
  if (schemaKey === discriminatorFilterPath) {
74
- const filter = arrayFilters.find(filter => filter.hasOwnProperty(arrayFilterKey));
74
+ const filter = arrayFilters.find(filter => Object.hasOwn(filter, arrayFilterKey));
75
75
  if (filter != null) {
76
76
  discriminatorKey = filter[arrayFilterKey];
77
77
  }
@@ -136,14 +136,14 @@ function pathExistsInUpdate(update, targetPath, pathPieces) {
136
136
  }
137
137
 
138
138
  // Check exact match
139
- if (update.hasOwnProperty(targetPath)) {
139
+ if (Object.hasOwn(update, targetPath)) {
140
140
  return true;
141
141
  }
142
142
 
143
143
  // Check if any parent path exists
144
144
  let cur = pathPieces[0];
145
145
  for (let i = 1; i < pathPieces.length; ++i) {
146
- if (update.hasOwnProperty(cur)) {
146
+ if (Object.hasOwn(update, cur)) {
147
147
  return true;
148
148
  }
149
149
  cur += '.' + pathPieces[i];
@@ -23,7 +23,7 @@ module.exports = function setupTimestamps(schema, timestamps) {
23
23
  }
24
24
  const createdAt = handleTimestampOption(timestamps, 'createdAt');
25
25
  const updatedAt = handleTimestampOption(timestamps, 'updatedAt');
26
- const currentTime = timestamps != null && timestamps.hasOwnProperty('currentTime') ?
26
+ const currentTime = timestamps != null && Object.hasOwn(timestamps, 'currentTime') ?
27
27
  timestamps.currentTime :
28
28
  null;
29
29
  const schemaAdditions = {};
@@ -74,39 +74,52 @@ function applyTimestampsToUpdate(now, createdAt, updatedAt, currentUpdate, optio
74
74
  updates.$set[updatedAt] = now;
75
75
  }
76
76
 
77
- if (updates.hasOwnProperty(updatedAt)) {
77
+ if (Object.hasOwn(updates, updatedAt)) {
78
78
  delete updates[updatedAt];
79
79
  }
80
80
  }
81
81
 
82
82
  if (!skipCreatedAt && createdAt) {
83
- if (currentUpdate[createdAt]) {
84
- delete currentUpdate[createdAt];
85
- }
86
- if (currentUpdate.$set && currentUpdate.$set[createdAt]) {
87
- delete currentUpdate.$set[createdAt];
88
- }
89
- let timestampSet = false;
90
- if (createdAt.indexOf('.') !== -1) {
91
- const pieces = createdAt.split('.');
92
- for (let i = 1; i < pieces.length; ++i) {
93
- const remnant = pieces.slice(-i).join('.');
94
- const start = pieces.slice(0, -i).join('.');
95
- if (currentUpdate[start] != null) {
96
- currentUpdate[start][remnant] = now;
97
- timestampSet = true;
98
- break;
99
- } else if (currentUpdate.$set && currentUpdate.$set[start]) {
100
- currentUpdate.$set[start][remnant] = now;
101
- timestampSet = true;
102
- break;
83
+ const overwriteImmutable = get(options, 'overwriteImmutable', false);
84
+ const hasUserCreatedAt = currentUpdate[createdAt] != null || currentUpdate?.$set[createdAt] != null;
85
+
86
+ // If overwriteImmutable is true and user provided createdAt, keep their value
87
+ if (overwriteImmutable && hasUserCreatedAt) {
88
+ // Move createdAt from top-level to $set if needed
89
+ if (currentUpdate[createdAt] != null) {
90
+ updates.$set[createdAt] = currentUpdate[createdAt];
91
+ delete currentUpdate[createdAt];
92
+ }
93
+ // User's value is already in $set, nothing more to do
94
+ } else {
95
+ if (currentUpdate[createdAt]) {
96
+ delete currentUpdate[createdAt];
97
+ }
98
+ if (currentUpdate.$set && currentUpdate.$set[createdAt]) {
99
+ delete currentUpdate.$set[createdAt];
100
+ }
101
+ let timestampSet = false;
102
+ if (createdAt.indexOf('.') !== -1) {
103
+ const pieces = createdAt.split('.');
104
+ for (let i = 1; i < pieces.length; ++i) {
105
+ const remnant = pieces.slice(-i).join('.');
106
+ const start = pieces.slice(0, -i).join('.');
107
+ if (currentUpdate[start] != null) {
108
+ currentUpdate[start][remnant] = now;
109
+ timestampSet = true;
110
+ break;
111
+ } else if (currentUpdate.$set && currentUpdate.$set[start]) {
112
+ currentUpdate.$set[start][remnant] = now;
113
+ timestampSet = true;
114
+ break;
115
+ }
103
116
  }
104
117
  }
105
- }
106
118
 
107
- if (!timestampSet) {
108
- updates.$setOnInsert = updates.$setOnInsert || {};
109
- updates.$setOnInsert[createdAt] = now;
119
+ if (!timestampSet) {
120
+ updates.$setOnInsert = updates.$setOnInsert || {};
121
+ updates.$setOnInsert[createdAt] = now;
122
+ }
110
123
  }
111
124
  }
112
125
 
@@ -31,5 +31,5 @@ function hasKey(obj, key) {
31
31
  if (obj == null || typeof obj !== 'object') {
32
32
  return false;
33
33
  }
34
- return Object.prototype.hasOwnProperty.call(obj, key);
34
+ return Object.hasOwn(obj, key);
35
35
  }
package/lib/model.js CHANGED
@@ -352,7 +352,7 @@ function _createSaveOptions(doc, options) {
352
352
  const asyncLocalStorage = doc[modelDbSymbol].base.transactionAsyncLocalStorage?.getStore();
353
353
  if (session != null) {
354
354
  saveOptions.session = session;
355
- } else if (!options.hasOwnProperty('session') && asyncLocalStorage?.session != null) {
355
+ } else if (!Object.hasOwn(options, 'session') && asyncLocalStorage?.session != null) {
356
356
  // Only set session from asyncLocalStorage if `session` option wasn't originally passed in options
357
357
  saveOptions.session = asyncLocalStorage.session;
358
358
  }
@@ -586,7 +586,7 @@ Model.prototype.save = async function save(options) {
586
586
  }
587
587
 
588
588
  options = new SaveOptions(options);
589
- if (options.hasOwnProperty('session')) {
589
+ if (Object.hasOwn(options, 'session')) {
590
590
  this.$session(options.session);
591
591
  }
592
592
  if (this.$__.timestamps != null) {
@@ -748,7 +748,7 @@ Model.prototype.deleteOne = function deleteOne(options) {
748
748
  options = {};
749
749
  }
750
750
 
751
- if (options.hasOwnProperty('session')) {
751
+ if (Object.hasOwn(options, 'session')) {
752
752
  this.$session(options.session);
753
753
  }
754
754
 
@@ -2944,7 +2944,7 @@ Model.insertMany = async function insertMany(arr, options) {
2944
2944
  const lean = !!options.lean;
2945
2945
 
2946
2946
  const asyncLocalStorage = this.db.base.transactionAsyncLocalStorage?.getStore();
2947
- if ((!options || !options.hasOwnProperty('session')) && asyncLocalStorage?.session != null) {
2947
+ if ((!options || !Object.hasOwn(options, 'session')) && asyncLocalStorage?.session != null) {
2948
2948
  options = { ...options, session: asyncLocalStorage.session };
2949
2949
  }
2950
2950
 
@@ -3248,12 +3248,14 @@ function _setIsNew(doc, val) {
3248
3248
  * @param {Object} [ops.updateOne.update] An object containing [update operators](https://www.mongodb.com/docs/manual/reference/operator/update/)
3249
3249
  * @param {Boolean} [ops.updateOne.upsert=false] If true, insert a doc if none match
3250
3250
  * @param {Boolean} [ops.updateOne.timestamps=true] If false, do not apply [timestamps](https://mongoosejs.com/docs/guide.html#timestamps) to the operation
3251
+ * @param {Boolean} [ops.updateOne.overwriteImmutable=false] Mongoose removes updated immutable properties from `update` by default (excluding $setOnInsert). Set `overwriteImmutable` to `true` to allow updating immutable properties using other update operators.
3251
3252
  * @param {Object} [ops.updateOne.collation] The [MongoDB collation](https://thecodebarbarian.com/a-nodejs-perspective-on-mongodb-34-collations) to use
3252
3253
  * @param {Array} [ops.updateOne.arrayFilters] The [array filters](https://thecodebarbarian.com/a-nodejs-perspective-on-mongodb-36-array-filters.html) used in `update`
3253
3254
  * @param {Object} [ops.updateMany.filter] Update all the documents that match this filter
3254
3255
  * @param {Object} [ops.updateMany.update] An object containing [update operators](https://www.mongodb.com/docs/manual/reference/operator/update/)
3255
3256
  * @param {Boolean} [ops.updateMany.upsert=false] If true, insert a doc if no documents match `filter`
3256
3257
  * @param {Boolean} [ops.updateMany.timestamps=true] If false, do not apply [timestamps](https://mongoosejs.com/docs/guide.html#timestamps) to the operation
3258
+ * @param {Boolean} [ops.updateMany.overwriteImmutable=false] Mongoose removes updated immutable properties from `update` by default (excluding $setOnInsert). Set `overwriteImmutable` to `true` to allow updating immutable properties using other update operators.
3257
3259
  * @param {Object} [ops.updateMany.collation] The [MongoDB collation](https://thecodebarbarian.com/a-nodejs-perspective-on-mongodb-34-collations) to use
3258
3260
  * @param {Array} [ops.updateMany.arrayFilters] The [array filters](https://thecodebarbarian.com/a-nodejs-perspective-on-mongodb-36-array-filters.html) used in `update`
3259
3261
  * @param {Object} [ops.deleteOne.filter] Delete the first document that matches this filter
@@ -3286,12 +3288,15 @@ Model.bulkWrite = async function bulkWrite(ops, options) {
3286
3288
  }
3287
3289
  options = options || {};
3288
3290
 
3289
- [ops, options] = await this.hooks.execPre('bulkWrite', this, [ops, options]).catch(err => {
3291
+ try {
3292
+ [ops, options] = await this.hooks.execPre('bulkWrite', this, [ops, options]);
3293
+ } catch (err) {
3290
3294
  if (err instanceof Kareem.skipWrappedFunction) {
3291
- return [err];
3295
+ ops = err;
3296
+ } else {
3297
+ await this.hooks.execPost('bulkWrite', this, [null], { error: err });
3292
3298
  }
3293
- throw err;
3294
- });
3299
+ }
3295
3300
 
3296
3301
  if (ops instanceof Kareem.skipWrappedFunction) {
3297
3302
  return ops.args[0];
@@ -3309,7 +3314,7 @@ Model.bulkWrite = async function bulkWrite(ops, options) {
3309
3314
 
3310
3315
  const validations = options?._skipCastBulkWrite ? [] : ops.map(op => castBulkWrite(this, op, options));
3311
3316
  const asyncLocalStorage = this.db.base.transactionAsyncLocalStorage?.getStore();
3312
- if ((!options || !options.hasOwnProperty('session')) && asyncLocalStorage?.session != null) {
3317
+ if ((!options || !Object.hasOwn(options, 'session')) && asyncLocalStorage?.session != null) {
3313
3318
  options = { ...options, session: asyncLocalStorage.session };
3314
3319
  }
3315
3320
 
@@ -3517,6 +3522,7 @@ async function handleSuccessfulWrite(document) {
3517
3522
  }
3518
3523
 
3519
3524
  document.$__reset();
3525
+ document._applyVersionIncrement();
3520
3526
  return document.schema.s.hooks.execPost('save', document, [document]);
3521
3527
  }
3522
3528
 
@@ -4999,10 +5005,10 @@ Model._applyQueryMiddleware = function _applyQueryMiddleware() {
4999
5005
 
5000
5006
  function _getContexts(hook) {
5001
5007
  const ret = {};
5002
- if (hook.hasOwnProperty('query')) {
5008
+ if (Object.hasOwn(hook, 'query')) {
5003
5009
  ret.query = hook.query;
5004
5010
  }
5005
- if (hook.hasOwnProperty('document')) {
5011
+ if (Object.hasOwn(hook, 'document')) {
5006
5012
  ret.document = hook.document;
5007
5013
  }
5008
5014
  return ret;
package/lib/mongoose.js CHANGED
@@ -601,12 +601,11 @@ Mongoose.prototype.model = function model(name, schema, collection, options) {
601
601
 
602
602
  // connection.model() may be passing a different schema for
603
603
  // an existing model name. in this case don't read from cache.
604
- const overwriteModels = _mongoose.options.hasOwnProperty('overwriteModels') ?
604
+ const overwriteModels = Object.hasOwn(_mongoose.options, 'overwriteModels') ?
605
605
  _mongoose.options.overwriteModels :
606
606
  options.overwriteModels;
607
- if (_mongoose.models.hasOwnProperty(name) && options.cache !== false && overwriteModels !== true) {
608
- if (originalSchema &&
609
- originalSchema.instanceOfSchema &&
607
+ if (Object.hasOwn(_mongoose.models, name) && options.cache !== false && overwriteModels !== true) {
608
+ if (originalSchema?.instanceOfSchema &&
610
609
  originalSchema !== _mongoose.models[name].schema) {
611
610
  throw new _mongoose.Error.OverwriteModelError(name);
612
611
  }
package/lib/query.js CHANGED
@@ -2100,7 +2100,7 @@ Query.prototype._optionsForExec = function(model) {
2100
2100
  applyWriteConcern(model.schema, options);
2101
2101
 
2102
2102
  const asyncLocalStorage = this.model?.db?.base.transactionAsyncLocalStorage?.getStore();
2103
- if (!this.options.hasOwnProperty('session') && asyncLocalStorage?.session != null) {
2103
+ if (!Object.hasOwn(this.options, 'session') && asyncLocalStorage?.session != null) {
2104
2104
  options.session = asyncLocalStorage.session;
2105
2105
  }
2106
2106
 
@@ -4595,7 +4595,7 @@ Query.prototype.exec = async function exec(op) {
4595
4595
  throw new MongooseError('Query has invalid `op`: "' + this.op + '"');
4596
4596
  }
4597
4597
 
4598
- if (this.options && this.options.sort && typeof this.options.sort === 'object' && this.options.sort.hasOwnProperty('')) {
4598
+ if (this.options && this.options.sort && typeof this.options.sort === 'object' && Object.hasOwn(this.options.sort, '')) {
4599
4599
  throw new Error('Invalid field "" passed to sort()');
4600
4600
  }
4601
4601
 
@@ -4995,7 +4995,7 @@ Query.prototype.cast = function(model, obj) {
4995
4995
  model = model || this.model;
4996
4996
  const discriminatorKey = model.schema.options.discriminatorKey;
4997
4997
  if (obj != null &&
4998
- obj.hasOwnProperty(discriminatorKey)) {
4998
+ Object.hasOwn(obj, discriminatorKey)) {
4999
4999
  model = getDiscriminatorByValue(model.discriminators, obj[discriminatorKey]) || model;
5000
5000
  }
5001
5001
 
@@ -80,7 +80,7 @@ function SchemaArray(key, cast, options, schemaOptions, parentSchema) {
80
80
  : utils.getFunctionName(cast);
81
81
 
82
82
  const Types = require('./index.js');
83
- const schemaTypeDefinition = Types.hasOwnProperty(name) ? Types[name] : cast;
83
+ const schemaTypeDefinition = Object.hasOwn(Types, name) ? Types[name] : cast;
84
84
 
85
85
  if (typeof schemaTypeDefinition === 'function') {
86
86
  if (schemaTypeDefinition === SchemaArray) {
@@ -26,6 +26,7 @@ const CastError = SchemaType.CastError;
26
26
  */
27
27
 
28
28
  function SchemaNumber(key, options, _schemaOptions, parentSchema) {
29
+ this.enumValues = [];
29
30
  SchemaType.call(this, key, options, 'Number', parentSchema);
30
31
  }
31
32
 
@@ -316,8 +317,12 @@ SchemaNumber.prototype.enum = function(values, message) {
316
317
  this.validators = this.validators.filter(function(v) {
317
318
  return v.validator !== this.enumValidator;
318
319
  }, this);
320
+ this.enumValidator = false;
319
321
  }
320
322
 
323
+ if (values === void 0 || values === false) {
324
+ return this;
325
+ }
321
326
 
322
327
  if (!Array.isArray(values)) {
323
328
  const isObjectSyntax = utils.isPOJO(values) && values.values != null;
@@ -337,12 +342,19 @@ SchemaNumber.prototype.enum = function(values, message) {
337
342
 
338
343
  message = message == null ? MongooseError.messages.Number.enum : message;
339
344
 
340
- this.enumValidator = v => v == null || values.indexOf(v) !== -1;
345
+ for (const value of values) {
346
+ if (value !== undefined) {
347
+ this.enumValues.push(this.cast(value));
348
+ }
349
+ }
350
+
351
+ const vals = this.enumValues;
352
+ this.enumValidator = v => v == null || vals.indexOf(v) !== -1;
341
353
  this.validators.push({
342
354
  validator: this.enumValidator,
343
355
  message: message,
344
356
  type: 'enum',
345
- enumValues: values
357
+ enumValues: vals
346
358
  });
347
359
 
348
360
  return this;
@@ -28,7 +28,7 @@ module.exports = function castTextSearch(val, path) {
28
28
  }
29
29
  if (val.$caseSensitive != null) {
30
30
  val.$caseSensitive = castBoolean(val.$caseSensitive,
31
- path + '.$castSensitive');
31
+ path + '.$caseSensitive');
32
32
  }
33
33
  if (val.$diacriticSensitive != null) {
34
34
  val.$diacriticSensitive = castBoolean(val.$diacriticSensitive,
package/lib/schema.js CHANGED
@@ -1485,17 +1485,17 @@ Schema.prototype._gatherChildSchemas = function _gatherChildSchemas() {
1485
1485
  */
1486
1486
 
1487
1487
  function _getPath(schema, path, cleanPath) {
1488
- if (schema.paths.hasOwnProperty(path)) {
1488
+ if (Object.hasOwn(schema.paths, path)) {
1489
1489
  return schema.paths[path];
1490
1490
  }
1491
- if (schema.subpaths.hasOwnProperty(cleanPath)) {
1491
+ if (Object.hasOwn(schema.subpaths, cleanPath)) {
1492
1492
  const subpath = schema.subpaths[cleanPath];
1493
1493
  if (subpath === 'nested') {
1494
1494
  return undefined;
1495
1495
  }
1496
1496
  return subpath;
1497
1497
  }
1498
- if (schema.singleNestedPaths.hasOwnProperty(cleanPath) && typeof schema.singleNestedPaths[cleanPath] === 'object') {
1498
+ if (Object.hasOwn(schema.singleNestedPaths, cleanPath) && typeof schema.singleNestedPaths[cleanPath] === 'object') {
1499
1499
  const singleNestedPath = schema.singleNestedPaths[cleanPath];
1500
1500
  if (singleNestedPath === 'nested') {
1501
1501
  return undefined;
@@ -1683,20 +1683,20 @@ Schema.prototype.interpretAsType = function(path, obj, options) {
1683
1683
  childSchemaOptions.typeKey = options.typeKey;
1684
1684
  }
1685
1685
  // propagate 'strict' option to child schema
1686
- if (options.hasOwnProperty('strict')) {
1686
+ if (Object.hasOwn(options, 'strict')) {
1687
1687
  childSchemaOptions.strict = options.strict;
1688
1688
  }
1689
- if (options.hasOwnProperty('strictQuery')) {
1689
+ if (Object.hasOwn(options, 'strictQuery')) {
1690
1690
  childSchemaOptions.strictQuery = options.strictQuery;
1691
1691
  }
1692
- if (options.hasOwnProperty('toObject')) {
1692
+ if (Object.hasOwn(options, 'toObject')) {
1693
1693
  childSchemaOptions.toObject = utils.omit(options.toObject, ['transform']);
1694
1694
  }
1695
- if (options.hasOwnProperty('toJSON')) {
1695
+ if (Object.hasOwn(options, 'toJSON')) {
1696
1696
  childSchemaOptions.toJSON = utils.omit(options.toJSON, ['transform']);
1697
1697
  }
1698
1698
 
1699
- if (this._userProvidedOptions.hasOwnProperty('_id')) {
1699
+ if (Object.hasOwn(this._userProvidedOptions, '_id')) {
1700
1700
  childSchemaOptions._id = this._userProvidedOptions._id;
1701
1701
  } else if (Schema.Types.DocumentArray.defaultOptions._id != null) {
1702
1702
  childSchemaOptions._id = Schema.Types.DocumentArray.defaultOptions._id;
@@ -1733,7 +1733,7 @@ Schema.prototype.interpretAsType = function(path, obj, options) {
1733
1733
  `Could not determine the embedded type for array \`${path}\`. ` +
1734
1734
  'See https://mongoosejs.com/docs/guide.html#definition for more info on supported schema syntaxes.');
1735
1735
  }
1736
- if (!MongooseTypes.hasOwnProperty(name)) {
1736
+ if (!Object.hasOwn(MongooseTypes, name)) {
1737
1737
  throw new TypeError('Invalid schema configuration: ' +
1738
1738
  `\`${name}\` is not a valid type within the array \`${path}\`.` +
1739
1739
  'See https://bit.ly/mongoose-schematypes for a list of valid schema types.');
@@ -1894,24 +1894,24 @@ Schema.prototype.indexedPaths = function indexedPaths() {
1894
1894
  */
1895
1895
 
1896
1896
  Schema.prototype.pathType = function(path) {
1897
- if (this.paths.hasOwnProperty(path)) {
1897
+ if (Object.hasOwn(this.paths, path)) {
1898
1898
  return 'real';
1899
1899
  }
1900
- if (this.virtuals.hasOwnProperty(path)) {
1900
+ if (Object.hasOwn(this.virtuals, path)) {
1901
1901
  return 'virtual';
1902
1902
  }
1903
- if (this.nested.hasOwnProperty(path)) {
1903
+ if (Object.hasOwn(this.nested, path)) {
1904
1904
  return 'nested';
1905
1905
  }
1906
1906
 
1907
1907
  // Convert to '.$' to check subpaths re: gh-6405
1908
1908
  const cleanPath = _pathToPositionalSyntax(path);
1909
1909
 
1910
- if (this.subpaths.hasOwnProperty(cleanPath) || this.subpaths.hasOwnProperty(path)) {
1910
+ if (Object.hasOwn(this.subpaths, cleanPath) || Object.hasOwn(this.subpaths, path)) {
1911
1911
  return 'real';
1912
1912
  }
1913
1913
 
1914
- const singleNestedPath = this.singleNestedPaths.hasOwnProperty(cleanPath) || this.singleNestedPaths.hasOwnProperty(path);
1914
+ const singleNestedPath = Object.hasOwn(this.singleNestedPaths, cleanPath) || Object.hasOwn(this.singleNestedPaths, path);
1915
1915
  if (singleNestedPath) {
1916
1916
  return singleNestedPath === 'nested' ? 'nested' : 'real';
1917
1917
  }
@@ -1941,7 +1941,7 @@ Schema.prototype.hasMixedParent = function(path) {
1941
1941
  path = '';
1942
1942
  for (let i = 0; i < subpaths.length; ++i) {
1943
1943
  path = i > 0 ? path + '.' + subpaths[i] : subpaths[i];
1944
- if (this.paths.hasOwnProperty(path) &&
1944
+ if (Object.hasOwn(this.paths, path) &&
1945
1945
  this.paths[path] instanceof MongooseTypes.Mixed) {
1946
1946
  return this.paths[path];
1947
1947
  }
@@ -1970,7 +1970,7 @@ Schema.prototype.setupTimestamp = function(timestamps) {
1970
1970
  function getPositionalPathType(self, path, cleanPath) {
1971
1971
  const subpaths = path.split(/\.(\d+)\.|\.(\d+)$/).filter(Boolean);
1972
1972
  if (subpaths.length < 2) {
1973
- return self.paths.hasOwnProperty(subpaths[0]) ?
1973
+ return Object.hasOwn(self.paths, subpaths[0]) ?
1974
1974
  self.paths[subpaths[0]] :
1975
1975
  'adhocOrUndefined';
1976
1976
  }
@@ -2675,7 +2675,7 @@ Schema.prototype.virtual = function(name, options) {
2675
2675
  */
2676
2676
 
2677
2677
  Schema.prototype.virtualpath = function(name) {
2678
- return this.virtuals.hasOwnProperty(name) ? this.virtuals[name] : null;
2678
+ return Object.hasOwn(this.virtuals, name) ? this.virtuals[name] : null;
2679
2679
  };
2680
2680
 
2681
2681
  /**
@@ -2823,8 +2823,8 @@ Schema.prototype.loadClass = function(model, virtualsOnly) {
2823
2823
  // Stop copying when hit certain base classes
2824
2824
  if (model === Object.prototype ||
2825
2825
  model === Function.prototype ||
2826
- model.prototype.hasOwnProperty('$isMongooseModelPrototype') ||
2827
- model.prototype.hasOwnProperty('$isMongooseDocumentPrototype')) {
2826
+ Object.hasOwn(model.prototype, '$isMongooseModelPrototype') ||
2827
+ Object.hasOwn(model.prototype, '$isMongooseDocumentPrototype')) {
2828
2828
  return this;
2829
2829
  }
2830
2830
 
@@ -2837,7 +2837,7 @@ Schema.prototype.loadClass = function(model, virtualsOnly) {
2837
2837
  return;
2838
2838
  }
2839
2839
  const prop = Object.getOwnPropertyDescriptor(model, name);
2840
- if (prop.hasOwnProperty('value')) {
2840
+ if (Object.hasOwn(prop, 'value')) {
2841
2841
  this.static(name, prop.value);
2842
2842
  }
2843
2843
  }, this);
@@ -3063,7 +3063,7 @@ Schema.prototype._transformDuplicateKeyError = function _transformDuplicateKeyEr
3063
3063
  return error;
3064
3064
  }
3065
3065
  const firstKey = keys[0];
3066
- if (!this._duplicateKeyErrorMessagesByPath.hasOwnProperty(firstKey)) {
3066
+ if (!Object.hasOwn(this._duplicateKeyErrorMessagesByPath, firstKey)) {
3067
3067
  return error;
3068
3068
  }
3069
3069
  return new MongooseError(this._duplicateKeyErrorMessagesByPath[firstKey], { cause: error });
package/lib/schemaType.js CHANGED
@@ -46,10 +46,10 @@ function SchemaType(path, options, instance, parentSchema) {
46
46
  this.instance = instance;
47
47
  this.schemaName = this.constructor.schemaName;
48
48
  this.validators = [];
49
- this.getters = this.constructor.hasOwnProperty('getters') ?
49
+ this.getters = Object.hasOwn(this.constructor, 'getters') ?
50
50
  this.constructor.getters.slice() :
51
51
  [];
52
- this.setters = this.constructor.hasOwnProperty('setters') ?
52
+ this.setters = Object.hasOwn(this.constructor, 'setters') ?
53
53
  this.constructor.setters.slice() :
54
54
  [];
55
55
 
@@ -62,7 +62,7 @@ function SchemaType(path, options, instance, parentSchema) {
62
62
  for (const option of defaultOptionsKeys) {
63
63
  if (option === 'validate') {
64
64
  this.validate(defaultOptions.validate);
65
- } else if (defaultOptions.hasOwnProperty(option) && !Object.prototype.hasOwnProperty.call(options, option)) {
65
+ } else if (Object.hasOwn(defaultOptions, option) && !Object.hasOwn(options, option)) {
66
66
  options[option] = defaultOptions[option];
67
67
  }
68
68
  }
@@ -339,7 +339,7 @@ SchemaType.prototype.cast = function cast() {
339
339
  */
340
340
 
341
341
  SchemaType.set = function set(option, value) {
342
- if (!this.hasOwnProperty('defaultOptions')) {
342
+ if (!Object.hasOwn(this, 'defaultOptions')) {
343
343
  this.defaultOptions = Object.assign({}, this.defaultOptions);
344
344
  }
345
345
  this.defaultOptions[option] = value;
@@ -362,7 +362,7 @@ SchemaType.set = function set(option, value) {
362
362
  */
363
363
 
364
364
  SchemaType.get = function(getter) {
365
- this.getters = this.hasOwnProperty('getters') ? this.getters : [];
365
+ this.getters = Object.hasOwn(this, 'getters') ? this.getters : [];
366
366
  this.getters.push(getter);
367
367
  };
368
368
 
@@ -496,7 +496,7 @@ SchemaType.prototype.unique = function unique(value, message) {
496
496
  'false and `unique` set to true');
497
497
  }
498
498
 
499
- if (!this.options.hasOwnProperty('index') && value === false) {
499
+ if (!Object.hasOwn(this.options, 'index') && value === false) {
500
500
  return this;
501
501
  }
502
502
 
@@ -535,7 +535,7 @@ SchemaType.prototype.text = function(bool) {
535
535
  'false and `text` set to true');
536
536
  }
537
537
 
538
- if (!this.options.hasOwnProperty('index') && bool === false) {
538
+ if (!Object.hasOwn(this.options, 'index') && bool === false) {
539
539
  return this;
540
540
  }
541
541
 
@@ -572,7 +572,7 @@ SchemaType.prototype.sparse = function(bool) {
572
572
  'false and `sparse` set to true');
573
573
  }
574
574
 
575
- if (!this.options.hasOwnProperty('index') && bool === false) {
575
+ if (!Object.hasOwn(this.options, 'index') && bool === false) {
576
576
  return this;
577
577
  }
578
578
 
@@ -79,13 +79,13 @@ function MongooseArray(values, path, doc, schematype) {
79
79
 
80
80
  const proxy = new Proxy(__array, {
81
81
  get: function(target, prop) {
82
- if (internals.hasOwnProperty(prop)) {
82
+ if (Object.hasOwn(internals, prop)) {
83
83
  return internals[prop];
84
84
  }
85
- if (mongooseArrayMethods.hasOwnProperty(prop)) {
85
+ if (Object.hasOwn(mongooseArrayMethods, prop)) {
86
86
  return mongooseArrayMethods[prop];
87
87
  }
88
- if (schematype && schematype.virtuals && schematype.virtuals.hasOwnProperty(prop)) {
88
+ if (schematype && schematype.virtuals && Object.hasOwn(schematype.virtuals, prop)) {
89
89
  return schematype.virtuals[prop].applyGetters(undefined, target);
90
90
  }
91
91
  if (typeof prop === 'string' && numberRE.test(prop) && schematype?.embeddedSchemaType != null) {
@@ -97,9 +97,9 @@ function MongooseArray(values, path, doc, schematype) {
97
97
  set: function(target, prop, value) {
98
98
  if (typeof prop === 'string' && numberRE.test(prop)) {
99
99
  mongooseArrayMethods.set.call(proxy, prop, value, false);
100
- } else if (internals.hasOwnProperty(prop)) {
100
+ } else if (Object.hasOwn(internals, prop)) {
101
101
  internals[prop] = value;
102
- } else if (schematype && schematype.virtuals && schematype.virtuals.hasOwnProperty(prop)) {
102
+ } else if (schematype?.virtuals && Object.hasOwn(schematype.virtuals, prop)) {
103
103
  schematype.virtuals[prop].applySetters(value, target);
104
104
  } else {
105
105
  __array[prop] = value;
@@ -73,16 +73,16 @@ function MongooseDocumentArray(values, path, doc, schematype) {
73
73
  prop === 'isMongooseDocumentArrayProxy') {
74
74
  return true;
75
75
  }
76
- if (internals.hasOwnProperty(prop)) {
76
+ if (Object.hasOwn(internals, prop)) {
77
77
  return internals[prop];
78
78
  }
79
- if (DocumentArrayMethods.hasOwnProperty(prop)) {
79
+ if (Object.hasOwn(DocumentArrayMethods, prop)) {
80
80
  return DocumentArrayMethods[prop];
81
81
  }
82
- if (schematype && schematype.virtuals && schematype.virtuals.hasOwnProperty(prop)) {
82
+ if (schematype && schematype.virtuals && Object.hasOwn(schematype.virtuals, prop)) {
83
83
  return schematype.virtuals[prop].applyGetters(undefined, target);
84
84
  }
85
- if (ArrayMethods.hasOwnProperty(prop)) {
85
+ if (Object.hasOwn(ArrayMethods, prop)) {
86
86
  return ArrayMethods[prop];
87
87
  }
88
88
 
@@ -91,9 +91,9 @@ function MongooseDocumentArray(values, path, doc, schematype) {
91
91
  set: function(target, prop, value) {
92
92
  if (typeof prop === 'string' && numberRE.test(prop)) {
93
93
  DocumentArrayMethods.set.call(proxy, prop, value, false);
94
- } else if (internals.hasOwnProperty(prop)) {
94
+ } else if (Object.hasOwn(internals, prop)) {
95
95
  internals[prop] = value;
96
- } else if (schematype && schematype.virtuals && schematype.virtuals.hasOwnProperty(prop)) {
96
+ } else if (schematype?.virtuals && Object.hasOwn(schematype.virtuals, prop)) {
97
97
  schematype.virtuals[prop].applySetters(value, target);
98
98
  } else {
99
99
  __array[prop] = value;