mongoose 8.8.0 → 8.8.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.
@@ -7,8 +7,7 @@
7
7
 
8
8
  function isBsonType(obj, typename) {
9
9
  return (
10
- typeof obj === 'object' &&
11
- obj !== null &&
10
+ obj != null &&
12
11
  obj._bsontype === typename
13
12
  );
14
13
  }
@@ -245,7 +245,7 @@ function walkUpdatePath(schema, obj, op, options, context, filter, pref) {
245
245
  }
246
246
 
247
247
  if (op !== '$setOnInsert' &&
248
- handleImmutable(schematype, strict, obj, key, prefix + key, context)) {
248
+ handleImmutable(schematype, strict, obj, key, prefix + key, options, context)) {
249
249
  continue;
250
250
  }
251
251
 
@@ -353,7 +353,7 @@ function walkUpdatePath(schema, obj, op, options, context, filter, pref) {
353
353
 
354
354
  // You can use `$setOnInsert` with immutable keys
355
355
  if (op !== '$setOnInsert' &&
356
- handleImmutable(schematype, strict, obj, key, prefix + key, context)) {
356
+ handleImmutable(schematype, strict, obj, key, prefix + key, options, context)) {
357
357
  continue;
358
358
  }
359
359
 
@@ -2,7 +2,20 @@
2
2
 
3
3
  const StrictModeError = require('../../error/strict');
4
4
 
5
- module.exports = function handleImmutable(schematype, strict, obj, key, fullPath, ctx) {
5
+ /**
6
+ * Handle immutable option for a given path when casting updates based on options
7
+ *
8
+ * @param {SchemaType} schematype the resolved schematype for this path
9
+ * @param {Boolean | 'throw' | null} strict whether strict mode is set for this query
10
+ * @param {Object} obj the object containing the value being checked so we can delete
11
+ * @param {String} key the key in `obj` which we are checking for immutability
12
+ * @param {String} fullPath the full path being checked
13
+ * @param {Object} options the query options
14
+ * @param {Query} ctx the query. Passed as `this` and first param to the `immutable` option, if `immutable` is a function
15
+ * @returns true if field was removed, false otherwise
16
+ */
17
+
18
+ module.exports = function handleImmutable(schematype, strict, obj, key, fullPath, options, ctx) {
6
19
  if (schematype == null || !schematype.options || !schematype.options.immutable) {
7
20
  return false;
8
21
  }
@@ -15,6 +28,9 @@ module.exports = function handleImmutable(schematype, strict, obj, key, fullPath
15
28
  return false;
16
29
  }
17
30
 
31
+ if (options && options.overwriteImmutable) {
32
+ return false;
33
+ }
18
34
  if (strict === false) {
19
35
  return false;
20
36
  }
@@ -1,7 +1,5 @@
1
1
  'use strict';
2
2
 
3
- const get = require('../get');
4
-
5
3
  module.exports = function applyReadConcern(schema, options) {
6
4
  if (options.readConcern !== undefined) {
7
5
  return;
@@ -15,7 +13,7 @@ module.exports = function applyReadConcern(schema, options) {
15
13
  return;
16
14
  }
17
15
 
18
- const level = get(schema, 'options.readConcern.level', null);
16
+ const level = schema.options?.readConcern?.level;
19
17
  if (level != null) {
20
18
  options.readConcern = { level };
21
19
  }
@@ -1,7 +1,5 @@
1
1
  'use strict';
2
2
 
3
- const get = require('../get');
4
-
5
3
  module.exports = function applyWriteConcern(schema, options) {
6
4
  if (options.writeConcern != null) {
7
5
  return;
@@ -12,7 +10,7 @@ module.exports = function applyWriteConcern(schema, options) {
12
10
  if (options && options.session && options.session.transaction) {
13
11
  return;
14
12
  }
15
- const writeConcern = get(schema, 'options.writeConcern', {});
13
+ const writeConcern = schema.options.writeConcern ?? {};
16
14
  if (Object.keys(writeConcern).length != 0) {
17
15
  options.writeConcern = {};
18
16
  if (!('w' in options) && writeConcern.w != null) {
package/lib/mongoose.js CHANGED
@@ -661,6 +661,8 @@ Mongoose.prototype._model = function(name, schema, collection, options) {
661
661
  utils.toCollectionName(name, _mongoose.pluralize());
662
662
  }
663
663
 
664
+ applyEmbeddedDiscriminators(schema);
665
+
664
666
  const connection = options.connection || _mongoose.connection;
665
667
  model = _mongoose.Model.compile(model || name, schema, collection, connection, _mongoose);
666
668
  // Errors handled internally, so safe to ignore error
@@ -678,8 +680,6 @@ Mongoose.prototype._model = function(name, schema, collection, options) {
678
680
  }
679
681
  }
680
682
 
681
- applyEmbeddedDiscriminators(schema);
682
-
683
683
  return model;
684
684
  };
685
685
 
package/lib/query.js CHANGED
@@ -22,7 +22,6 @@ const castUpdate = require('./helpers/query/castUpdate');
22
22
  const clone = require('./helpers/clone');
23
23
  const getDiscriminatorByValue = require('./helpers/discriminator/getDiscriminatorByValue');
24
24
  const helpers = require('./queryHelpers');
25
- const immediate = require('./helpers/immediate');
26
25
  const internalToObjectOptions = require('./options').internalToObjectOptions;
27
26
  const isExclusive = require('./helpers/projection/isExclusive');
28
27
  const isInclusive = require('./helpers/projection/isInclusive');
@@ -1626,6 +1625,7 @@ Query.prototype.getOptions = function() {
1626
1625
  * - [writeConcern](https://www.mongodb.com/docs/manual/reference/method/db.collection.update/)
1627
1626
  * - [timestamps](https://mongoosejs.com/docs/guide.html#timestamps): If `timestamps` is set in the schema, set this option to `false` to skip timestamps for that particular update. Has no effect if `timestamps` is not enabled in the schema options.
1628
1627
  * - overwriteDiscriminatorKey: allow setting the discriminator key in the update. Will use the correct discriminator schema if the update changes the discriminator key.
1628
+ * - overwriteImmutable: allow overwriting properties that are set to `immutable` in the schema. Defaults to false.
1629
1629
  *
1630
1630
  * The following options are only for `find()`, `findOne()`, `findById()`, `findOneAndUpdate()`, `findOneAndReplace()`, `findOneAndDelete()`, and `findByIdAndUpdate()`:
1631
1631
  *
@@ -1697,6 +1697,10 @@ Query.prototype.setOptions = function(options, overwrite) {
1697
1697
  this._mongooseOptions.overwriteDiscriminatorKey = options.overwriteDiscriminatorKey;
1698
1698
  delete options.overwriteDiscriminatorKey;
1699
1699
  }
1700
+ if ('overwriteImmutable' in options) {
1701
+ this._mongooseOptions.overwriteImmutable = options.overwriteImmutable;
1702
+ delete options.overwriteImmutable;
1703
+ }
1700
1704
  if ('sanitizeProjection' in options) {
1701
1705
  if (options.sanitizeProjection && !this._mongooseOptions.sanitizeProjection) {
1702
1706
  sanitizeProjection(this._fields);
@@ -2243,6 +2247,9 @@ Query.prototype.error = function error(err) {
2243
2247
  */
2244
2248
 
2245
2249
  Query.prototype._unsetCastError = function _unsetCastError() {
2250
+ if (this._error == null) {
2251
+ return;
2252
+ }
2246
2253
  if (this._error != null && !(this._error instanceof CastError)) {
2247
2254
  return;
2248
2255
  }
@@ -2286,9 +2293,9 @@ Query.prototype.mongooseOptions = function(v) {
2286
2293
 
2287
2294
  Query.prototype._castConditions = function() {
2288
2295
  let sanitizeFilterOpt = undefined;
2289
- if (this.model != null && utils.hasUserDefinedProperty(this.model.db.options, 'sanitizeFilter')) {
2296
+ if (this.model?.db.options?.sanitizeFilter != null) {
2290
2297
  sanitizeFilterOpt = this.model.db.options.sanitizeFilter;
2291
- } else if (this.model != null && utils.hasUserDefinedProperty(this.model.base.options, 'sanitizeFilter')) {
2298
+ } else if (this.model?.base.options?.sanitizeFilter != null) {
2292
2299
  sanitizeFilterOpt = this.model.base.options.sanitizeFilter;
2293
2300
  } else {
2294
2301
  sanitizeFilterOpt = this._mongooseOptions.sanitizeFilter;
@@ -2531,13 +2538,12 @@ Query.prototype.collation = function(value) {
2531
2538
  * @api private
2532
2539
  */
2533
2540
 
2534
- Query.prototype._completeOne = function(doc, res, callback) {
2541
+ Query.prototype._completeOne = function(doc, res, projection, callback) {
2535
2542
  if (!doc && !this.options.includeResultMetadata) {
2536
2543
  return callback(null, null);
2537
2544
  }
2538
2545
 
2539
2546
  const model = this.model;
2540
- const projection = clone(this._fields);
2541
2547
  const userProvidedFields = this._userProvidedFields || {};
2542
2548
  // `populate`, `lean`
2543
2549
  const mongooseOptions = this._mongooseOptions;
@@ -2638,7 +2644,7 @@ Query.prototype._findOne = async function _findOne() {
2638
2644
  // don't pass in the conditions because we already merged them in
2639
2645
  const doc = await this.mongooseCollection.findOne(this._conditions, options);
2640
2646
  return new Promise((resolve, reject) => {
2641
- this._completeOne(doc, null, (err, res) => {
2647
+ this._completeOne(doc, null, options.projection, (err, res) => {
2642
2648
  if (err) {
2643
2649
  return reject(err);
2644
2650
  }
@@ -3233,7 +3239,7 @@ function completeOne(model, doc, res, options, fields, userProvidedFields, pop,
3233
3239
 
3234
3240
  function _init(err, casted) {
3235
3241
  if (err) {
3236
- return immediate(() => callback(err));
3242
+ return callback(err);
3237
3243
  }
3238
3244
 
3239
3245
 
@@ -3246,12 +3252,12 @@ function completeOne(model, doc, res, options, fields, userProvidedFields, pop,
3246
3252
  } else {
3247
3253
  res.value = null;
3248
3254
  }
3249
- return immediate(() => callback(null, res));
3255
+ return callback(null, res);
3250
3256
  }
3251
3257
  if (options.session != null) {
3252
3258
  casted.$session(options.session);
3253
3259
  }
3254
- immediate(() => callback(null, casted));
3260
+ callback(null, casted);
3255
3261
  }
3256
3262
  }
3257
3263
 
@@ -3318,6 +3324,7 @@ function prepareDiscriminatorCriteria(query) {
3318
3324
  * @param {Boolean} [options.returnOriginal=null] An alias for the `new` option. `returnOriginal: false` is equivalent to `new: true`.
3319
3325
  * @param {Boolean} [options.translateAliases=null] If set to `true`, translates any schema-defined aliases in `filter`, `projection`, `update`, and `distinct`. Throws an error if there are any conflicts where both alias and raw property are defined on the same object.
3320
3326
  * @param {Boolean} [options.overwriteDiscriminatorKey=false] Mongoose removes discriminator key updates from `update` by default, set `overwriteDiscriminatorKey` to `true` to allow updating the discriminator key
3327
+ * @param {Boolean} [options.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.
3321
3328
  * @see Tutorial https://mongoosejs.com/docs/tutorials/findoneandupdate.html
3322
3329
  * @see findAndModify command https://www.mongodb.com/docs/manual/reference/command/findAndModify/
3323
3330
  * @see ModifyResult https://mongodb.github.io/node-mongodb-native/4.9/interfaces/ModifyResult.html
@@ -3459,7 +3466,7 @@ Query.prototype._findOneAndUpdate = async function _findOneAndUpdate() {
3459
3466
  const doc = !options.includeResultMetadata ? res : res.value;
3460
3467
 
3461
3468
  return new Promise((resolve, reject) => {
3462
- this._completeOne(doc, res, (err, res) => {
3469
+ this._completeOne(doc, res, options.projection, (err, res) => {
3463
3470
  if (err) {
3464
3471
  return reject(err);
3465
3472
  }
@@ -3555,7 +3562,7 @@ Query.prototype._findOneAndDelete = async function _findOneAndDelete() {
3555
3562
  const doc = !includeResultMetadata ? res : res.value;
3556
3563
 
3557
3564
  return new Promise((resolve, reject) => {
3558
- this._completeOne(doc, res, (err, res) => {
3565
+ this._completeOne(doc, res, options.projection, (err, res) => {
3559
3566
  if (err) {
3560
3567
  return reject(err);
3561
3568
  }
@@ -3709,7 +3716,7 @@ Query.prototype._findOneAndReplace = async function _findOneAndReplace() {
3709
3716
 
3710
3717
  const doc = !includeResultMetadata ? res : res.value;
3711
3718
  return new Promise((resolve, reject) => {
3712
- this._completeOne(doc, res, (err, res) => {
3719
+ this._completeOne(doc, res, options.projection, (err, res) => {
3713
3720
  if (err) {
3714
3721
  return reject(err);
3715
3722
  }
@@ -4016,6 +4023,7 @@ Query.prototype._replaceOne = async function _replaceOne() {
4016
4023
  * @param {Boolean} [options.timestamps=null] If set to `false` and [schema-level timestamps](https://mongoosejs.com/docs/guide.html#timestamps) are enabled, skip timestamps for this update. Does nothing if schema-level timestamps are not set.
4017
4024
  * @param {Boolean} [options.translateAliases=null] If set to `true`, translates any schema-defined aliases in `filter`, `projection`, `update`, and `distinct`. Throws an error if there are any conflicts where both alias and raw property are defined on the same object.
4018
4025
  * @param {Boolean} [options.overwriteDiscriminatorKey=false] Mongoose removes discriminator key updates from `update` by default, set `overwriteDiscriminatorKey` to `true` to allow updating the discriminator key
4026
+ * @param {Boolean} [options.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.
4019
4027
  * @param {Function} [callback] params are (error, writeOpResult)
4020
4028
  * @return {Query} this
4021
4029
  * @see Model.update https://mongoosejs.com/docs/api/model.html#Model.update()
@@ -4086,6 +4094,7 @@ Query.prototype.updateMany = function(conditions, doc, options, callback) {
4086
4094
  * @param {Boolean} [options.timestamps=null] If set to `false` and [schema-level timestamps](https://mongoosejs.com/docs/guide.html#timestamps) are enabled, skip timestamps for this update. Note that this allows you to overwrite timestamps. Does nothing if schema-level timestamps are not set.
4087
4095
  * @param {Boolean} [options.translateAliases=null] If set to `true`, translates any schema-defined aliases in `filter`, `projection`, `update`, and `distinct`. Throws an error if there are any conflicts where both alias and raw property are defined on the same object.
4088
4096
  * @param {Boolean} [options.overwriteDiscriminatorKey=false] Mongoose removes discriminator key updates from `update` by default, set `overwriteDiscriminatorKey` to `true` to allow updating the discriminator key
4097
+ * @param {Boolean} [options.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.
4089
4098
  * @param {Function} [callback] params are (error, writeOpResult)
4090
4099
  * @return {Query} this
4091
4100
  * @see Model.update https://mongoosejs.com/docs/api/model.html#Model.update()
@@ -4707,7 +4716,8 @@ Query.prototype._castUpdate = function _castUpdate(obj) {
4707
4716
  strict: this._mongooseOptions.strict,
4708
4717
  upsert: upsert,
4709
4718
  arrayFilters: this.options.arrayFilters,
4710
- overwriteDiscriminatorKey: this._mongooseOptions.overwriteDiscriminatorKey
4719
+ overwriteDiscriminatorKey: this._mongooseOptions.overwriteDiscriminatorKey,
4720
+ overwriteImmutable: this._mongooseOptions.overwriteImmutable
4711
4721
  }, this, this._conditions);
4712
4722
  };
4713
4723
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "mongoose",
3
3
  "description": "Mongoose MongoDB ODM",
4
- "version": "8.8.0",
4
+ "version": "8.8.1",
5
5
  "author": "Guillermo Rauch <guillermo@learnboost.com>",
6
6
  "keywords": [
7
7
  "mongodb",
@@ -28,8 +28,8 @@
28
28
  "sift": "17.1.3"
29
29
  },
30
30
  "devDependencies": {
31
- "@babel/core": "7.24.7",
32
- "@babel/preset-env": "7.25.4",
31
+ "@babel/core": "7.26.0",
32
+ "@babel/preset-env": "7.26.0",
33
33
  "@typescript-eslint/eslint-plugin": "^8.4.0",
34
34
  "@typescript-eslint/parser": "^8.4.0",
35
35
  "acquit": "1.3.0",
@@ -41,7 +41,7 @@
41
41
  "broken-link-checker": "^0.7.8",
42
42
  "buffer": "^5.6.0",
43
43
  "cheerio": "1.0.0",
44
- "crypto-browserify": "3.12.0",
44
+ "crypto-browserify": "3.12.1",
45
45
  "dotenv": "16.4.5",
46
46
  "dox": "1.0.0",
47
47
  "eslint": "8.57.0",
@@ -53,11 +53,11 @@
53
53
  "lodash.isequal": "4.5.0",
54
54
  "lodash.isequalwith": "4.4.0",
55
55
  "markdownlint-cli2": "^0.14.0",
56
- "marked": "14.1.2",
56
+ "marked": "14.1.3",
57
57
  "mkdirp": "^3.0.1",
58
- "mocha": "10.7.3",
58
+ "mocha": "10.8.2",
59
59
  "moment": "2.30.1",
60
- "mongodb-memory-server": "10.0.1",
60
+ "mongodb-memory-server": "10.1.2",
61
61
  "ncp": "^2.0.0",
62
62
  "nyc": "15.1.0",
63
63
  "pug": "3.0.3",
@@ -65,9 +65,9 @@
65
65
  "sinon": "19.0.2",
66
66
  "stream-browserify": "3.0.0",
67
67
  "tsd": "0.31.2",
68
- "typescript": "5.6.2",
69
- "uuid": "10.0.0",
70
- "webpack": "5.95.0"
68
+ "typescript": "5.6.3",
69
+ "uuid": "11.0.2",
70
+ "webpack": "5.96.1"
71
71
  },
72
72
  "directories": {
73
73
  "lib": "./lib/mongoose"
package/types/query.d.ts CHANGED
@@ -20,6 +20,7 @@ declare module 'mongoose' {
20
20
  | 'context'
21
21
  | 'multipleCastError'
22
22
  | 'overwriteDiscriminatorKey'
23
+ | 'overwriteImmutable'
23
24
  | 'populate'
24
25
  | 'runValidators'
25
26
  | 'sanitizeProjection'
@@ -154,6 +155,11 @@ declare module 'mongoose' {
154
155
  new?: boolean;
155
156
 
156
157
  overwriteDiscriminatorKey?: boolean;
158
+ /**
159
+ * Mongoose removes updated immutable properties from `update` by default (excluding $setOnInsert).
160
+ * Set `overwriteImmutable` to `true` to allow updating immutable properties using other update operators.
161
+ */
162
+ overwriteImmutable?: boolean;
157
163
  projection?: ProjectionType<DocType>;
158
164
  /**
159
165
  * if true, returns the full ModifyResult rather than just the document