mongoose 8.20.3 → 8.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/document.js CHANGED
@@ -842,7 +842,7 @@ function init(self, obj, doc, opts, prefix) {
842
842
  * - same as in [Model.updateOne](https://mongoosejs.com/docs/api/model.html#Model.updateOne)
843
843
  *
844
844
  * @see Model.updateOne https://mongoosejs.com/docs/api/model.html#Model.updateOne
845
- * @param {Object} doc
845
+ * @param {Object} update
846
846
  * @param {Object} [options] optional see [`Query.prototype.setOptions()`](https://mongoosejs.com/docs/api/query.html#Query.prototype.setOptions())
847
847
  * @param {Object} [options.lean] if truthy, mongoose will return the document as a plain JavaScript object rather than a mongoose document. See [`Query.lean()`](https://mongoosejs.com/docs/api/query.html#Query.prototype.lean()) and the [Mongoose lean tutorial](https://mongoosejs.com/docs/tutorials/lean.html).
848
848
  * @param {Boolean|String} [options.strict] overwrites the schema's [strict mode option](https://mongoosejs.com/docs/guide.html#strict)
@@ -853,22 +853,24 @@ function init(self, obj, doc, opts, prefix) {
853
853
  * @instance
854
854
  */
855
855
 
856
- Document.prototype.updateOne = function updateOne(doc, options, callback) {
857
- const query = this.constructor.updateOne({ _id: this._doc._id }, doc, options);
856
+ Document.prototype.updateOne = function updateOne(update, options, callback) {
857
+ const query = this.constructor.updateOne();
858
858
  const self = this;
859
859
  query.pre(function queryPreUpdateOne(cb) {
860
- self.constructor._middleware.execPre('updateOne', self, [self], cb);
860
+ self.constructor._middleware.execPre('updateOne', self, [self, update, options], (err, res) => {
861
+ this.updateOne({ _id: self._doc._id }, update, options);
862
+ if (self.$session() != null) {
863
+ if (!('session' in query.options)) {
864
+ query.options.session = self.$session();
865
+ }
866
+ }
867
+ return cb(err, res);
868
+ });
861
869
  });
862
870
  query.post(function queryPostUpdateOne(cb) {
863
871
  self.constructor._middleware.execPost('updateOne', self, [self], {}, cb);
864
872
  });
865
873
 
866
- if (this.$session() != null) {
867
- if (!('session' in query.options)) {
868
- query.options.session = this.$session();
869
- }
870
- }
871
-
872
874
  if (callback != null) {
873
875
  return query.exec(callback);
874
876
  }
@@ -3545,7 +3547,9 @@ Document.prototype.$__reset = function reset() {
3545
3547
  this.$__dirty().forEach(function(dirt) {
3546
3548
  const type = dirt.value;
3547
3549
 
3548
- if (type && type[arrayAtomicsSymbol]) {
3550
+ if (type && typeof type.clearAtomics === 'function') {
3551
+ type.clearAtomics();
3552
+ } else if (type && type[arrayAtomicsSymbol]) {
3549
3553
  type[arrayAtomicsBackupSymbol] = type[arrayAtomicsSymbol];
3550
3554
  type[arrayAtomicsSymbol] = {};
3551
3555
  }
@@ -5028,8 +5032,8 @@ Document.prototype.$__delta = function $__delta() {
5028
5032
  operand(this, where, delta, data, 1, '$unset');
5029
5033
  } else if (value === null) {
5030
5034
  operand(this, where, delta, data, null);
5031
- } else if (utils.isMongooseArray(value) && value.$path() && value[arrayAtomicsSymbol]) {
5032
- // arrays and other custom types (support plugins etc)
5035
+ } else if (typeof value.getAtomics === 'function') {
5036
+ // arrays and other custom container types
5033
5037
  handleAtomics(this, where, delta, data, value);
5034
5038
  } else if (value[MongooseBuffer.pathSymbol] && Buffer.isBuffer(value)) {
5035
5039
  // MongooseBuffer
@@ -5174,7 +5178,7 @@ function operand(self, where, delta, data, val, op) {
5174
5178
  if (/\.\d+\.|\.\d+$/.test(data.path)) {
5175
5179
  self.$__.version = VERSION_ALL;
5176
5180
  } else {
5177
- self.$__.version = VERSION_INC;
5181
+ self.$__.version |= VERSION_INC;
5178
5182
  }
5179
5183
  } else if (/^\$p/.test(op)) {
5180
5184
  // potentially changing array positions
@@ -5185,7 +5189,7 @@ function operand(self, where, delta, data, val, op) {
5185
5189
  } else if (/\.\d+\.|\.\d+$/.test(data.path)) {
5186
5190
  // now handling $set, $unset
5187
5191
  // subpath of array
5188
- self.$__.version = VERSION_WHERE;
5192
+ self.$__.version |= VERSION_WHERE;
5189
5193
  }
5190
5194
  }
5191
5195
 
@@ -5206,6 +5210,15 @@ function handleAtomics(self, where, delta, data, value) {
5206
5210
  return;
5207
5211
  }
5208
5212
 
5213
+ if (typeof value.getAtomics === 'function') {
5214
+ value.getAtomics().forEach(function(atomic) {
5215
+ const op = atomic[0];
5216
+ const val = atomic[1];
5217
+ operand(self, where, delta, data, val, op);
5218
+ });
5219
+ return;
5220
+ }
5221
+
5209
5222
  if (typeof value.$__getAtomics === 'function') {
5210
5223
  value.$__getAtomics().forEach(function(atomic) {
5211
5224
  const op = atomic[0];
package/lib/model.js CHANGED
@@ -789,7 +789,7 @@ Model.prototype.deleteOne = function deleteOne(options) {
789
789
  if (where instanceof Error) {
790
790
  throw where;
791
791
  }
792
- const query = self.constructor.deleteOne(where, options);
792
+ const query = self.constructor.deleteOne();
793
793
 
794
794
  if (this.$session() != null) {
795
795
  if (!('session' in query.options)) {
@@ -799,7 +799,8 @@ Model.prototype.deleteOne = function deleteOne(options) {
799
799
 
800
800
  query.pre(async function queryPreDeleteOne() {
801
801
  await new Promise((resolve, reject) => {
802
- self.constructor._middleware.execPre('deleteOne', self, [self], err => {
802
+ self.constructor._middleware.execPre('deleteOne', self, [self, options], err => {
803
+ query.deleteOne(where, options);
803
804
  if (err) reject(err);
804
805
  else resolve();
805
806
  });
@@ -812,7 +813,7 @@ Model.prototype.deleteOne = function deleteOne(options) {
812
813
  });
813
814
  query.pre(function callSubdocPreHooks(cb) {
814
815
  each(self.$getAllSubdocs(), (subdoc, cb) => {
815
- subdoc.constructor._middleware.execPre('deleteOne', subdoc, [subdoc], cb);
816
+ subdoc.constructor._middleware.execPre('deleteOne', subdoc, [subdoc, options], cb);
816
817
  }, cb);
817
818
  });
818
819
  query.pre(function skipIfAlreadyDeleted(cb) {
@@ -829,6 +830,12 @@ Model.prototype.deleteOne = function deleteOne(options) {
829
830
  query.post(function queryPostDeleteOne(cb) {
830
831
  self.constructor._middleware.execPost('deleteOne', self, [self], {}, cb);
831
832
  });
833
+ query.transform(function setIsDeleted(result) {
834
+ if (result?.deletedCount > 0) {
835
+ self.$isDeleted(true);
836
+ }
837
+ return result;
838
+ });
832
839
 
833
840
  return query;
834
841
  };
@@ -330,7 +330,25 @@ SchemaNumber.prototype.enum = function(values, message) {
330
330
  }
331
331
 
332
332
  if (utils.isPOJO(values)) {
333
- values = Object.values(values);
333
+ // TypeScript numeric enums produce objects with reverse
334
+ // mappings, e.g. { 0: 'Zero', 1: 'One', Zero: 0, One: 1 }.
335
+ // Object.values on that will yield ['Zero','One',0,1].
336
+ // For Number schema enums we only want the numeric values,
337
+ // otherwise casting the name strings to Number will throw.
338
+ const keys = Object.keys(values).sort();
339
+ const objVals = Object.values(values).sort();
340
+ // If keys and values are equal and half of values are numbers,
341
+ // this is likely a TS enum with reverse mapping, so use only the numbers.
342
+ if (
343
+ keys.length === objVals.length &&
344
+ keys.every((k, i) => k === String(objVals[i])) &&
345
+ objVals.filter(v => typeof v === 'number').length === Math.floor(objVals.length / 2)
346
+ ) {
347
+ values = objVals.filter(v => typeof v === 'number');
348
+ } else {
349
+ // Avoid sorting the values to preserve user-specified order
350
+ values = Object.values(values);
351
+ }
334
352
  }
335
353
  message = message || MongooseError.messages.Number.enum;
336
354
  }
@@ -10,6 +10,7 @@ const mpath = require('mpath');
10
10
  const utils = require('../../../utils');
11
11
  const isBsonType = require('../../../helpers/isBsonType');
12
12
 
13
+ const arrayAtomicsBackupSymbol = require('../../../helpers/symbols').arrayAtomicsBackupSymbol;
13
14
  const arrayAtomicsSymbol = require('../../../helpers/symbols').arrayAtomicsSymbol;
14
15
  const arrayParentSymbol = require('../../../helpers/symbols').arrayParentSymbol;
15
16
  const arrayPathSymbol = require('../../../helpers/symbols').arrayPathSymbol;
@@ -75,6 +76,36 @@ const methods = {
75
76
  return ret;
76
77
  },
77
78
 
79
+ /**
80
+ * Public API for getting atomics. Alias for $__getAtomics() that can be
81
+ * implemented by custom container types.
82
+ *
83
+ * @return {Array}
84
+ * @method getAtomics
85
+ * @memberOf MongooseArray
86
+ * @instance
87
+ * @api public
88
+ */
89
+
90
+ getAtomics() {
91
+ return this.$__getAtomics();
92
+ },
93
+
94
+ /**
95
+ * Clears all pending atomic operations. Called by Mongoose after save().
96
+ *
97
+ * @return {void}
98
+ * @method clearAtomics
99
+ * @memberOf MongooseArray
100
+ * @instance
101
+ * @api public
102
+ */
103
+
104
+ clearAtomics() {
105
+ this[arrayAtomicsBackupSymbol] = this[arrayAtomicsSymbol];
106
+ this[arrayAtomicsSymbol] = {};
107
+ },
108
+
78
109
  /*!
79
110
  * ignore
80
111
  */
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "mongoose",
3
3
  "description": "Mongoose MongoDB ODM",
4
- "version": "8.20.3",
4
+ "version": "8.21.0",
5
5
  "author": "Guillermo Rauch <guillermo@learnboost.com>",
6
6
  "keywords": [
7
7
  "mongodb",
package/types/index.d.ts CHANGED
@@ -468,9 +468,14 @@ declare module 'mongoose' {
468
468
  pre<T = never>(method: MongooseDistinctDocumentMiddleware | MongooseDistinctDocumentMiddleware[] | RegExp, options: SchemaPreOptions & { document: false, query: boolean }, fn: PreMiddlewareFunction<T>): this;
469
469
  // this = Union of Document and Query, could be called with any of them
470
470
  pre<T = THydratedDocumentType | Query<any, any>>(
471
- method: MongooseQueryAndDocumentMiddleware | MongooseQueryAndDocumentMiddleware[] | RegExp,
471
+ method: 'updateOne' | RegExp,
472
472
  options: SchemaPreOptions & { document: true, query: true },
473
- fn: PreMiddlewareFunction<T>
473
+ fn: PreUpdateOneMiddlewareFunction<T>
474
+ ): this;
475
+ pre<T = THydratedDocumentType | Query<any, any>>(
476
+ method: 'deleteOne' | RegExp,
477
+ options: SchemaPreOptions & { document: true, query: true },
478
+ fn: PreDeleteOneMiddlewareFunction<T>
474
479
  ): this;
475
480
  // this = Document
476
481
  pre<T = THydratedDocumentType>(method: 'save', fn: PreSaveMiddlewareFunction<T>): this;
@@ -478,9 +483,14 @@ declare module 'mongoose' {
478
483
  pre<T = THydratedDocumentType>(method: MongooseDistinctDocumentMiddleware|MongooseDistinctDocumentMiddleware[], fn: PreMiddlewareFunction<T>): this;
479
484
  pre<T = THydratedDocumentType>(method: MongooseDistinctDocumentMiddleware|MongooseDistinctDocumentMiddleware[], options: SchemaPreOptions, fn: PreMiddlewareFunction<T>): this;
480
485
  pre<T = THydratedDocumentType>(
481
- method: MongooseQueryAndDocumentMiddleware | MongooseQueryAndDocumentMiddleware[] | RegExp,
486
+ method: 'updateOne' | RegExp,
487
+ options: SchemaPreOptions & { document: true },
488
+ fn: PreUpdateOneMiddlewareFunction<T>
489
+ ): this;
490
+ pre<T = THydratedDocumentType>(
491
+ method: 'deleteOne' | RegExp,
482
492
  options: SchemaPreOptions & { document: true },
483
- fn: PreMiddlewareFunction<T>
493
+ fn: PreDeleteOneMiddlewareFunction<T>
484
494
  ): this;
485
495
  pre<T = THydratedDocumentType>(method: MongooseQueryOrDocumentMiddleware | MongooseQueryOrDocumentMiddleware[] | RegExp, options: SchemaPreOptions & { document: true, query: false }, fn: PreMiddlewareFunction<T>): this;
486
496
  // this = Query
@@ -39,6 +39,19 @@ declare module 'mongoose' {
39
39
  next: CallbackWithoutResultAndOptionalError,
40
40
  opts?: Record<string, any>
41
41
  ) => void | Promise<void> | Kareem.SkipWrappedFunction;
42
+ type PreDeleteOneMiddlewareFunction<ThisType = any> = (
43
+ this: ThisType,
44
+ next: CallbackWithoutResultAndOptionalError,
45
+ doc: ThisType,
46
+ opts?: Record<string, any>
47
+ ) => void | Promise<void> | Kareem.SkipWrappedFunction;
48
+ type PreUpdateOneMiddlewareFunction<ThisType = any> = (
49
+ this: ThisType,
50
+ next: CallbackWithoutResultAndOptionalError,
51
+ doc: ThisType,
52
+ update?: Record<string, any>,
53
+ opts?: Record<string, any>
54
+ ) => void | Promise<void> | Kareem.SkipWrappedFunction;
42
55
  type PreSaveMiddlewareFunction<ThisType = any> = (
43
56
  this: ThisType,
44
57
  next: CallbackWithoutResultAndOptionalError,