mongoose 9.0.0 → 9.0.1

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 (38) 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 +54 -17
  6. package/lib/drivers/node-mongodb-native/collection.js +16 -1
  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 +8 -7
  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 +7 -7
  36. package/types/index.d.ts +1 -0
  37. package/types/models.d.ts +313 -85
  38. package/types/query.d.ts +91 -1
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
 
@@ -3309,7 +3309,7 @@ Model.bulkWrite = async function bulkWrite(ops, options) {
3309
3309
 
3310
3310
  const validations = options?._skipCastBulkWrite ? [] : ops.map(op => castBulkWrite(this, op, options));
3311
3311
  const asyncLocalStorage = this.db.base.transactionAsyncLocalStorage?.getStore();
3312
- if ((!options || !options.hasOwnProperty('session')) && asyncLocalStorage?.session != null) {
3312
+ if ((!options || !Object.hasOwn(options, 'session')) && asyncLocalStorage?.session != null) {
3313
3313
  options = { ...options, session: asyncLocalStorage.session };
3314
3314
  }
3315
3315
 
@@ -3517,6 +3517,7 @@ async function handleSuccessfulWrite(document) {
3517
3517
  }
3518
3518
 
3519
3519
  document.$__reset();
3520
+ document._applyVersionIncrement();
3520
3521
  return document.schema.s.hooks.execPost('save', document, [document]);
3521
3522
  }
3522
3523
 
@@ -4999,10 +5000,10 @@ Model._applyQueryMiddleware = function _applyQueryMiddleware() {
4999
5000
 
5000
5001
  function _getContexts(hook) {
5001
5002
  const ret = {};
5002
- if (hook.hasOwnProperty('query')) {
5003
+ if (Object.hasOwn(hook, 'query')) {
5003
5004
  ret.query = hook.query;
5004
5005
  }
5005
- if (hook.hasOwnProperty('document')) {
5006
+ if (Object.hasOwn(hook, 'document')) {
5006
5007
  ret.document = hook.document;
5007
5008
  }
5008
5009
  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;
@@ -30,7 +30,7 @@ Object.defineProperty(ObjectId.prototype, '_id', {
30
30
  * Convenience `valueOf()` to allow comparing ObjectIds using double equals re: gh-7299
31
31
  */
32
32
 
33
- if (!ObjectId.prototype.hasOwnProperty('valueOf')) {
33
+ if (!Object.hasOwn(ObjectId.prototype, 'valueOf')) {
34
34
  ObjectId.prototype.valueOf = function objectIdValueOf() {
35
35
  return this.toString();
36
36
  };
package/lib/utils.js CHANGED
@@ -190,6 +190,9 @@ exports.deepEqual = function deepEqual(a, b) {
190
190
  */
191
191
 
192
192
  exports.last = function(arr) {
193
+ if (arr == null) {
194
+ return void 0;
195
+ }
193
196
  if (arr.length > 0) {
194
197
  return arr[arr.length - 1];
195
198
  }
@@ -272,6 +275,10 @@ exports.clonePOJOsAndArrays = function clonePOJOsAndArrays(val) {
272
275
  exports.merge = function merge(to, from, options, path) {
273
276
  options = options || {};
274
277
 
278
+ if (from == null) {
279
+ return to;
280
+ }
281
+
275
282
  const keys = Object.keys(from);
276
283
  let i = 0;
277
284
  const len = keys.length;
@@ -690,6 +697,9 @@ exports.setValue = function(path, val, obj, map, _copying) {
690
697
 
691
698
  exports.object = {};
692
699
  exports.object.vals = function vals(o) {
700
+ if (o == null) {
701
+ return [];
702
+ }
693
703
  const keys = Object.keys(o);
694
704
  let i = keys.length;
695
705
  const ret = [];
@@ -701,18 +711,6 @@ exports.object.vals = function vals(o) {
701
711
  return ret;
702
712
  };
703
713
 
704
- const hop = Object.prototype.hasOwnProperty;
705
-
706
- /**
707
- * Safer helper for hasOwnProperty checks
708
- *
709
- * @param {Object} obj
710
- * @param {String} prop
711
- */
712
-
713
- exports.object.hasOwnProperty = function(obj, prop) {
714
- return hop.call(obj, prop);
715
- };
716
714
 
717
715
  /**
718
716
  * Determine if `val` is null or undefined
@@ -763,8 +761,6 @@ exports.array.flatten = function flatten(arr, filter, ret) {
763
761
  * ignore
764
762
  */
765
763
 
766
- const _hasOwnProperty = Object.prototype.hasOwnProperty;
767
-
768
764
  exports.hasUserDefinedProperty = function(obj, key) {
769
765
  if (obj == null) {
770
766
  return false;
@@ -779,7 +775,7 @@ exports.hasUserDefinedProperty = function(obj, key) {
779
775
  return false;
780
776
  }
781
777
 
782
- if (_hasOwnProperty.call(obj, key)) {
778
+ if (Object.hasOwn(obj, key)) {
783
779
  return true;
784
780
  }
785
781
  if (typeof obj === 'object' && key in obj) {
@@ -865,15 +861,7 @@ exports.buffer.areEqual = function(a, b) {
865
861
  if (!Buffer.isBuffer(b)) {
866
862
  return false;
867
863
  }
868
- if (a.length !== b.length) {
869
- return false;
870
- }
871
- for (let i = 0, len = a.length; i < len; ++i) {
872
- if (a[i] !== b[i]) {
873
- return false;
874
- }
875
- }
876
- return true;
864
+ return a.equals(b);
877
865
  };
878
866
 
879
867
  exports.getFunctionName = getFunctionName;
@@ -143,7 +143,7 @@ VirtualType.prototype.set = function(fn) {
143
143
  VirtualType.prototype.applyGetters = function(value, doc) {
144
144
  if (utils.hasUserDefinedProperty(this.options, ['ref', 'refPath']) &&
145
145
  doc.$$populatedVirtuals &&
146
- doc.$$populatedVirtuals.hasOwnProperty(this.path)) {
146
+ Object.hasOwn(doc.$$populatedVirtuals, this.path)) {
147
147
  value = doc.$$populatedVirtuals[this.path];
148
148
  }
149
149
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "mongoose",
3
3
  "description": "Mongoose MongoDB ODM",
4
- "version": "9.0.0",
4
+ "version": "9.0.1",
5
5
  "author": "Guillermo Rauch <guillermo@learnboost.com>",
6
6
  "keywords": [
7
7
  "mongodb",
@@ -28,7 +28,7 @@
28
28
  "sift": "17.1.3"
29
29
  },
30
30
  "devDependencies": {
31
- "@ark/attest": "0.53.0",
31
+ "@ark/attest": "0.55.0",
32
32
  "@mongodb-js/mongodb-downloader": "^1.0.0",
33
33
  "acquit": "1.4.0",
34
34
  "acquit-ignore": "0.2.1",
@@ -37,7 +37,7 @@
37
37
  "broken-link-checker": "^0.7.8",
38
38
  "cheerio": "1.1.2",
39
39
  "dox": "1.0.0",
40
- "eslint": "9.25.1",
40
+ "eslint": "9.39.1",
41
41
  "eslint-plugin-markdown": "^5.1.0",
42
42
  "eslint-plugin-mocha-no-only": "1.2.0",
43
43
  "express": "^4.19.2",
@@ -45,10 +45,10 @@
45
45
  "highlight.js": "11.11.1",
46
46
  "lodash.isequal": "4.5.0",
47
47
  "lodash.isequalwith": "4.4.0",
48
- "markdownlint-cli2": "^0.18.1",
48
+ "markdownlint-cli2": "^0.19.1",
49
49
  "marked": "15.x",
50
50
  "mkdirp": "^3.0.1",
51
- "mocha": "11.7.4",
51
+ "mocha": "11.7.5",
52
52
  "moment": "2.30.1",
53
53
  "mongodb-memory-server": "10.3.0",
54
54
  "mongodb-runner": "^6.0.0",
@@ -81,7 +81,7 @@
81
81
  "docs:prepare:publish:5x": "git checkout 5.x && git merge 5.x && npm run docs:clean:stable && npm run docs:generate && npm run docs:copy:tmp && git checkout gh-pages && npm run docs:copy:tmp:5x",
82
82
  "docs:prepare:publish:6x": "git checkout 6.x && git merge 6.x && npm run docs:clean:stable && env DOCS_DEPLOY=true npm run docs:generate && mv ./docs/6.x ./tmp && git checkout gh-pages && npm run docs:copy:tmp:6x",
83
83
  "docs:prepare:publish:7x": "env DOCS_DEPLOY=true npm run docs:generate && git checkout gh-pages && rimraf ./docs/7.x && mv ./tmp ./docs/7.x",
84
- "docs:prepare:publish:8x": "git checkout gh-pages && git merge 8.x && npm run docs:generate",
84
+ "docs:prepare:publish:8x": "env DOCS_DEPLOY=true npm run docs:generate && git checkout gh-pages && rimraf ./docs/8.x && mv ./tmp ./docs/8.x",
85
85
  "docs:check-links": "blc http://127.0.0.1:8089 -ro",
86
86
  "lint": "eslint .",
87
87
  "lint-js": "eslint . --ext .js --ext .cjs",
@@ -99,7 +99,7 @@
99
99
  "test-tsd": "node ./test/types/check-types-filename && tsd --full",
100
100
  "setup-test-encryption": "node scripts/setup-encryption-tests.js",
101
101
  "test-encryption": "mocha --exit ./test/encryption/*.test.js",
102
- "tdd": "mocha ./test/*.test.js --inspect --watch --recursive --watch-files ./**/*.{js,ts}",
102
+ "tdd": "mocha --watch --inspect --recursive ./test/*.test.js --watch-files lib/**/*.js test/**/*.js",
103
103
  "test-coverage": "nyc --reporter=html --reporter=text npm test",
104
104
  "ts-benchmark": "cd ./benchmarks/typescript/simple && npm install && npm run benchmark | node ../../../scripts/tsc-diagnostics-check",
105
105
  "attest-benchmark": "node ./benchmarks/typescript/infer.bench.mts"
package/types/index.d.ts CHANGED
@@ -623,6 +623,7 @@ declare module 'mongoose' {
623
623
 
624
624
  /** Adds static "class" methods to Models compiled from this schema. */
625
625
  static<K extends keyof TStaticMethods>(name: K, fn: TStaticMethods[K]): this;
626
+ static(obj: { [F in keyof TStaticMethods]: TStaticMethods[F] }): this;
626
627
  static(obj: { [F in keyof TStaticMethods]: TStaticMethods[F] } & { [name: string]: (this: TModelType, ...args: any[]) => any }): this;
627
628
  static(name: string, fn: (this: TModelType, ...args: any[]) => any): this;
628
629