mongoose 6.6.1 → 6.6.3

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/.eslintrc.json CHANGED
@@ -25,6 +25,7 @@
25
25
  "rules": {
26
26
  "@typescript-eslint/triple-slash-reference": "off",
27
27
  "@typescript-eslint/no-non-null-assertion": "off",
28
+ "@typescript-eslint/no-empty-function": "off",
28
29
  "spaced-comment": [
29
30
  "error",
30
31
  "always",
package/lib/aggregate.js CHANGED
@@ -126,7 +126,7 @@ Aggregate.prototype.model = function(model) {
126
126
  /**
127
127
  * Appends new operators to this aggregate pipeline
128
128
  *
129
- * #### Examples:
129
+ * #### Example:
130
130
  *
131
131
  * aggregate.append({ $project: { field: 1 }}, { $limit: 2 });
132
132
  *
@@ -157,7 +157,7 @@ Aggregate.prototype.append = function() {
157
157
  * Appends a new $addFields operator to this aggregate pipeline.
158
158
  * Requires MongoDB v3.4+ to work
159
159
  *
160
- * #### Examples:
160
+ * #### Example:
161
161
  *
162
162
  * // adding new fields based on existing fields
163
163
  * aggregate.addFields({
@@ -188,7 +188,7 @@ Aggregate.prototype.addFields = function(arg) {
188
188
  *
189
189
  * Mongoose query [selection syntax](#query_Query-select) is also supported.
190
190
  *
191
- * #### Examples:
191
+ * #### Example:
192
192
  *
193
193
  * // include a, include b, exclude _id
194
194
  * aggregate.project("a b -_id");
@@ -243,7 +243,7 @@ Aggregate.prototype.project = function(arg) {
243
243
  /**
244
244
  * Appends a new custom $group operator to this aggregate pipeline.
245
245
  *
246
- * #### Examples:
246
+ * #### Example:
247
247
  *
248
248
  * aggregate.group({ _id: "$department" });
249
249
  *
@@ -259,7 +259,7 @@ Aggregate.prototype.project = function(arg) {
259
259
  /**
260
260
  * Appends a new custom $match operator to this aggregate pipeline.
261
261
  *
262
- * #### Examples:
262
+ * #### Example:
263
263
  *
264
264
  * aggregate.match({ department: { $in: [ "sales", "engineering" ] } });
265
265
  *
@@ -275,7 +275,7 @@ Aggregate.prototype.project = function(arg) {
275
275
  /**
276
276
  * Appends a new $skip operator to this aggregate pipeline.
277
277
  *
278
- * #### Examples:
278
+ * #### Example:
279
279
  *
280
280
  * aggregate.skip(10);
281
281
  *
@@ -291,7 +291,7 @@ Aggregate.prototype.project = function(arg) {
291
291
  /**
292
292
  * Appends a new $limit operator to this aggregate pipeline.
293
293
  *
294
- * #### Examples:
294
+ * #### Example:
295
295
  *
296
296
  * aggregate.limit(10);
297
297
  *
@@ -308,7 +308,7 @@ Aggregate.prototype.project = function(arg) {
308
308
  /**
309
309
  * Appends a new $densify operator to this aggregate pipeline.
310
310
  *
311
- * #### Examples:
311
+ * #### Example:
312
312
  *
313
313
  * aggregate.densify({
314
314
  * field: 'timestamp',
@@ -335,7 +335,7 @@ Aggregate.prototype.project = function(arg) {
335
335
  *
336
336
  * **MUST** be used as the first operator in the pipeline.
337
337
  *
338
- * #### Examples:
338
+ * #### Example:
339
339
  *
340
340
  * aggregate.near({
341
341
  * near: [40.724, -73.997],
@@ -380,7 +380,7 @@ Aggregate.prototype.near = function(arg) {
380
380
  * Note that the `$unwind` operator requires the path name to start with '$'.
381
381
  * Mongoose will prepend '$' if the specified field doesn't start '$'.
382
382
  *
383
- * #### Examples:
383
+ * #### Example:
384
384
  *
385
385
  * aggregate.unwind("tags");
386
386
  * aggregate.unwind("a", "b", "c");
@@ -419,7 +419,7 @@ Aggregate.prototype.unwind = function() {
419
419
  * If you are passing in a string Mongoose will prepend '$' if the specified field doesn't start '$'.
420
420
  * If you are passing in an object the strings in your expression will not be altered.
421
421
  *
422
- * #### Examples:
422
+ * #### Example:
423
423
  *
424
424
  * aggregate.replaceRoot("user");
425
425
  *
@@ -450,7 +450,7 @@ Aggregate.prototype.replaceRoot = function(newRoot) {
450
450
  /**
451
451
  * Appends a new $count operator to this aggregate pipeline.
452
452
  *
453
- * #### Examples:
453
+ * #### Example:
454
454
  *
455
455
  * aggregate.count("userCount");
456
456
  *
@@ -471,7 +471,7 @@ Aggregate.prototype.count = function(fieldName) {
471
471
  * Note that the `$sortByCount` operator requires the new root to start with '$'.
472
472
  * Mongoose will prepend '$' if the specified field name doesn't start with '$'.
473
473
  *
474
- * #### Examples:
474
+ * #### Example:
475
475
  *
476
476
  * aggregate.sortByCount('users');
477
477
  * aggregate.sortByCount({ $mergeObjects: [ "$employee", "$business" ] })
@@ -498,7 +498,7 @@ Aggregate.prototype.sortByCount = function(arg) {
498
498
  /**
499
499
  * Appends new custom $lookup operator to this aggregate pipeline.
500
500
  *
501
- * #### Examples:
501
+ * #### Example:
502
502
  *
503
503
  * aggregate.lookup({ from: 'users', localField: 'userId', foreignField: '_id', as: 'users' });
504
504
  *
@@ -517,7 +517,7 @@ Aggregate.prototype.lookup = function(options) {
517
517
  *
518
518
  * Note that graphLookup can only consume at most 100MB of memory, and does not allow disk use even if `{ allowDiskUse: true }` is specified.
519
519
  *
520
- * #### Examples:
520
+ * #### Example:
521
521
  *
522
522
  * // Suppose we have a collection of courses, where a document might look like `{ _id: 0, name: 'Calculus', prerequisite: 'Trigonometry'}` and `{ _id: 0, name: 'Trigonometry', prerequisite: 'Algebra' }`
523
523
  * aggregate.graphLookup({ from: 'courses', startWith: '$prerequisite', connectFromField: 'prerequisite', connectToField: 'name', as: 'prerequisites', maxDepth: 3 }) // this will recursively search the 'courses' collection up to 3 prerequisites
@@ -551,7 +551,7 @@ Aggregate.prototype.graphLookup = function(options) {
551
551
  /**
552
552
  * Appends new custom $sample operator to this aggregate pipeline.
553
553
  *
554
- * #### Examples:
554
+ * #### Example:
555
555
  *
556
556
  * aggregate.sample(3); // Add a pipeline that picks 3 random documents
557
557
  *
@@ -572,7 +572,7 @@ Aggregate.prototype.sample = function(size) {
572
572
  *
573
573
  * If a string is passed, it must be a space delimited list of path names. The sort order of each path is ascending unless the path name is prefixed with `-` which will be treated as descending.
574
574
  *
575
- * #### Examples:
575
+ * #### Example:
576
576
  *
577
577
  * // these are equivalent
578
578
  * aggregate.sort({ field: 'asc', test: -1 });
@@ -620,7 +620,7 @@ Aggregate.prototype.sort = function(arg) {
620
620
  /**
621
621
  * Appends new $unionWith operator to this aggregate pipeline.
622
622
  *
623
- * #### Examples:
623
+ * #### Example:
624
624
  *
625
625
  * aggregate.unionWith({ coll: 'users', pipeline: [ { $match: { _id: 1 } } ] });
626
626
  *
package/lib/document.js CHANGED
@@ -851,11 +851,12 @@ Document.prototype.update = function update() {
851
851
 
852
852
  Document.prototype.updateOne = function updateOne(doc, options, callback) {
853
853
  const query = this.constructor.updateOne({ _id: this._id }, doc, options);
854
- query.pre(cb => {
855
- this.constructor._middleware.execPre('updateOne', this, [this], cb);
854
+ const self = this;
855
+ query.pre(function queryPreUpdateOne(cb) {
856
+ self.constructor._middleware.execPre('updateOne', self, [self], cb);
856
857
  });
857
- query.post(cb => {
858
- this.constructor._middleware.execPost('updateOne', this, [this], {}, cb);
858
+ query.post(function queryPostUpdateOne(cb) {
859
+ self.constructor._middleware.execPost('updateOne', self, [self], {}, cb);
859
860
  });
860
861
 
861
862
  if (this.$session() != null) {
@@ -1735,7 +1736,7 @@ Document.prototype.$inc = function $inc(path, val) {
1735
1736
  this.invalidate(path, new MongooseError.CastError('number', val, path, err));
1736
1737
  }
1737
1738
 
1738
- const currentValue = this.$__getValue(path);
1739
+ const currentValue = this.$__getValue(path) || 0;
1739
1740
 
1740
1741
  this.$__setValue(path, currentValue + val);
1741
1742
 
@@ -0,0 +1,63 @@
1
+ 'use strict';
2
+ const schemaMerge = require('../schema/merge');
3
+ const specialProperties = require('../../helpers/specialProperties');
4
+ const isBsonType = require('../../helpers/isBsonType');
5
+ const ObjectId = require('../../types/objectid');
6
+ const isObject = require('../../helpers/isObject');
7
+ /**
8
+ * Merges `from` into `to` without overwriting existing properties.
9
+ *
10
+ * @param {Object} to
11
+ * @param {Object} from
12
+ * @param {String} [path]
13
+ * @api private
14
+ */
15
+
16
+ module.exports = function mergeDiscriminatorSchema(to, from, path) {
17
+ const keys = Object.keys(from);
18
+ let i = 0;
19
+ const len = keys.length;
20
+ let key;
21
+
22
+ path = path || '';
23
+
24
+ while (i < len) {
25
+ key = keys[i++];
26
+ if (key === 'discriminators' || key === 'base' || key === '_applyDiscriminators') {
27
+ continue;
28
+ }
29
+ if (path === 'tree' && from != null && from.instanceOfSchema) {
30
+ continue;
31
+ }
32
+ if (specialProperties.has(key)) {
33
+ continue;
34
+ }
35
+ if (to[key] == null) {
36
+ to[key] = from[key];
37
+ } else if (isObject(from[key])) {
38
+ if (!isObject(to[key])) {
39
+ to[key] = {};
40
+ }
41
+ if (from[key] != null) {
42
+ // Skip merging schemas if we're creating a discriminator schema and
43
+ // base schema has a given path as a single nested but discriminator schema
44
+ // has the path as a document array, or vice versa (gh-9534)
45
+ if ((from[key].$isSingleNested && to[key].$isMongooseDocumentArray) ||
46
+ (from[key].$isMongooseDocumentArray && to[key].$isSingleNested)) {
47
+ continue;
48
+ } else if (from[key].instanceOfSchema) {
49
+ if (to[key].instanceOfSchema) {
50
+ schemaMerge(to[key], from[key].clone(), true);
51
+ } else {
52
+ to[key] = from[key].clone();
53
+ }
54
+ continue;
55
+ } else if (isBsonType(from[key], 'ObjectID')) {
56
+ to[key] = new ObjectId(from[key]);
57
+ continue;
58
+ }
59
+ }
60
+ mergeDiscriminatorSchema(to[key], from[key], path ? path + '.' + key : key);
61
+ }
62
+ }
63
+ };
@@ -12,6 +12,8 @@ const utils = require('../../utils');
12
12
  */
13
13
 
14
14
  module.exports = function applyMethods(model, schema) {
15
+ const Model = require('../../model');
16
+
15
17
  function apply(method, schema) {
16
18
  Object.defineProperty(model.prototype, method, {
17
19
  get: function() {
@@ -34,7 +36,8 @@ module.exports = function applyMethods(model, schema) {
34
36
  // Avoid making custom methods if user sets a method to itself, e.g.
35
37
  // `schema.method(save, Document.prototype.save)`. Can happen when
36
38
  // calling `loadClass()` with a class that `extends Document`. See gh-12254
37
- if (typeof fn === 'function' && model.prototype[method] === fn) {
39
+ if (typeof fn === 'function' &&
40
+ Model.prototype[method] === fn) {
38
41
  delete schema.methods[method];
39
42
  continue;
40
43
  }
@@ -4,6 +4,7 @@ const Mixed = require('../../schema/mixed');
4
4
  const defineKey = require('../document/compile').defineKey;
5
5
  const get = require('../get');
6
6
  const utils = require('../../utils');
7
+ const mergeDiscriminatorSchema = require('../../helpers/discriminator/mergeDiscriminatorSchema');
7
8
 
8
9
  const CUSTOMIZABLE_DISCRIMINATOR_OPTIONS = {
9
10
  toJSON: true,
@@ -108,8 +109,7 @@ module.exports = function discriminator(model, name, schema, tiedValue, applyPlu
108
109
  }
109
110
  }
110
111
 
111
- utils.merge(schema, baseSchema, {
112
- isDiscriminatorSchemaMerge: true,
112
+ mergeDiscriminatorSchema(schema, baseSchema, {
113
113
  omit: { discriminators: true, base: true, _applyDiscriminators: true },
114
114
  omitNested: conflictingPaths.reduce((cur, path) => {
115
115
  cur['tree.' + path] = true;
@@ -27,19 +27,19 @@ module.exports = function setupTimestamps(schema, timestamps) {
27
27
 
28
28
  schema.$timestamps = { createdAt: createdAt, updatedAt: updatedAt };
29
29
 
30
- if (updatedAt && !schema.paths[updatedAt]) {
31
- schemaAdditions[updatedAt] = Date;
32
- }
33
-
34
30
  if (createdAt && !schema.paths[createdAt]) {
35
31
  const baseImmutableCreatedAt = schema.base.get('timestamps.createdAt.immutable');
36
32
  const immutable = baseImmutableCreatedAt != null ? baseImmutableCreatedAt : true;
37
33
  schemaAdditions[createdAt] = { [schema.options.typeKey || 'type']: Date, immutable };
38
34
  }
39
35
 
36
+ if (updatedAt && !schema.paths[updatedAt]) {
37
+ schemaAdditions[updatedAt] = Date;
38
+ }
39
+
40
40
  schema.add(schemaAdditions);
41
41
 
42
- schema.pre('save', function(next) {
42
+ schema.pre('save', function timestampsPreSave(next) {
43
43
  const timestampOption = get(this, '$__.saveOptions.timestamps');
44
44
  if (timestampOption === false) {
45
45
  return next();
package/lib/model.js CHANGED
@@ -2172,7 +2172,7 @@ Model.deleteMany = function deleteMany(conditions, options, callback) {
2172
2172
  * See our [query casting tutorial](/docs/tutorials/query_casting.html) for
2173
2173
  * more information on how Mongoose casts `filter`.
2174
2174
  *
2175
- * #### Examples:
2175
+ * #### Example:
2176
2176
  *
2177
2177
  * // find all documents
2178
2178
  * await MyModel.find({});
@@ -2537,7 +2537,7 @@ Model.$where = function $where() {
2537
2537
  *
2538
2538
  * Finds a matching document, updates it according to the `update` arg, passing any `options`, and returns the found document (if any) to the callback. The query executes if `callback` is passed else a Query object is returned.
2539
2539
  *
2540
- * #### Examples:
2540
+ * #### Example:
2541
2541
  *
2542
2542
  * A.findOneAndUpdate(conditions, update, options, callback) // executes
2543
2543
  * A.findOneAndUpdate(conditions, update, options) // returns Query
@@ -2558,6 +2558,7 @@ Model.$where = function $where() {
2558
2558
  * Model.findOneAndUpdate(query, { $set: { name: 'jason bourne' }}, options, callback)
2559
2559
  *
2560
2560
  * This helps prevent accidentally overwriting your document with `{ name: 'jason bourne' }`.
2561
+ * To prevent this behaviour, see the `overwrite` option
2561
2562
  *
2562
2563
  * #### Note:
2563
2564
  *
@@ -2670,7 +2671,7 @@ function _decorateUpdateWithVersionKey(update, options, versionKey) {
2670
2671
  *
2671
2672
  * - `findOneAndUpdate()`
2672
2673
  *
2673
- * #### Examples:
2674
+ * #### Example:
2674
2675
  *
2675
2676
  * A.findByIdAndUpdate(id, update, options, callback) // executes
2676
2677
  * A.findByIdAndUpdate(id, update, options) // returns Query
@@ -2690,6 +2691,7 @@ function _decorateUpdateWithVersionKey(update, options, versionKey) {
2690
2691
  * Model.findByIdAndUpdate(id, { $set: { name: 'jason bourne' }}, options, callback)
2691
2692
  *
2692
2693
  * This helps prevent accidentally overwriting your document with `{ name: 'jason bourne' }`.
2694
+ * To prevent this behaviour, see the `overwrite` option
2693
2695
  *
2694
2696
  * #### Note:
2695
2697
  *
@@ -2767,7 +2769,7 @@ Model.findByIdAndUpdate = function(id, update, options, callback) {
2767
2769
  * this distinction is purely pedantic. You should use `findOneAndDelete()`
2768
2770
  * unless you have a good reason not to.
2769
2771
  *
2770
- * #### Examples:
2772
+ * #### Example:
2771
2773
  *
2772
2774
  * A.findOneAndDelete(conditions, options, callback) // executes
2773
2775
  * A.findOneAndDelete(conditions, options) // return Query
@@ -2873,7 +2875,7 @@ Model.findByIdAndDelete = function(id, options, callback) {
2873
2875
  *
2874
2876
  * - `findOneAndReplace()`
2875
2877
  *
2876
- * #### Examples:
2878
+ * #### Example:
2877
2879
  *
2878
2880
  * A.findOneAndReplace(filter, replacement, options, callback) // executes
2879
2881
  * A.findOneAndReplace(filter, replacement, options) // return Query
@@ -2947,7 +2949,7 @@ Model.findOneAndReplace = function(filter, replacement, options, callback) {
2947
2949
  *
2948
2950
  * - `findOneAndRemove()`
2949
2951
  *
2950
- * #### Examples:
2952
+ * #### Example:
2951
2953
  *
2952
2954
  * A.findOneAndRemove(conditions, options, callback) // executes
2953
2955
  * A.findOneAndRemove(conditions, options) // return Query
@@ -3020,7 +3022,7 @@ Model.findOneAndRemove = function(conditions, options, callback) {
3020
3022
  *
3021
3023
  * - `findOneAndRemove()`
3022
3024
  *
3023
- * #### Examples:
3025
+ * #### Example:
3024
3026
  *
3025
3027
  * A.findByIdAndRemove(id, options, callback) // executes
3026
3028
  * A.findByIdAndRemove(id, options) // return Query
@@ -3967,7 +3969,7 @@ Model.hydrate = function(obj, projection, options) {
3967
3969
  *
3968
3970
  * This method is deprecated. See [Deprecation Warnings](../deprecations.html#update) for details.
3969
3971
  *
3970
- * #### Examples:
3972
+ * #### Example:
3971
3973
  *
3972
3974
  * MyModel.update({ age: { $gt: 18 } }, { oldEnough: true }, fn);
3973
3975
  *
@@ -4524,7 +4526,7 @@ Model.validate = function validate(obj, pathsToValidate, context, callback) {
4524
4526
  * - justOne: optional boolean, if true Mongoose will always set `path` to an array. Inferred from schema by default.
4525
4527
  * - strictPopulate: optional boolean, set to `false` to allow populating paths that aren't in the schema.
4526
4528
  *
4527
- * #### Examples:
4529
+ * #### Example:
4528
4530
  *
4529
4531
  * const Dog = mongoose.model('Dog', new Schema({ name: String, breed: String }));
4530
4532
  * const Person = mongoose.model('Person', new Schema({
@@ -4,11 +4,11 @@
4
4
  * ignore
5
5
  */
6
6
 
7
- module.exports = function(schema) {
7
+ module.exports = function clearValidating(schema) {
8
8
  // `this.$__.validating` tracks whether there are multiple validations running
9
9
  // in parallel. We need to clear `this.$__.validating` before post hooks for gh-8597
10
10
  const unshift = true;
11
- schema.s.hooks.post('validate', false, function() {
11
+ schema.s.hooks.post('validate', false, function clearValidatingPostValidate() {
12
12
  if (this.$isSubdocument) {
13
13
  return;
14
14
  }
@@ -16,7 +16,7 @@ module.exports = function(schema) {
16
16
  this.$__.validating = null;
17
17
  }, unshift);
18
18
 
19
- schema.s.hooks.post('validate', false, function(error, res, next) {
19
+ schema.s.hooks.post('validate', false, function clearValidatingPostValidateError(error, res, next) {
20
20
  if (this.$isSubdocument) {
21
21
  next();
22
22
  return;
@@ -6,9 +6,9 @@ const each = require('../helpers/each');
6
6
  * ignore
7
7
  */
8
8
 
9
- module.exports = function(schema) {
9
+ module.exports = function removeSubdocs(schema) {
10
10
  const unshift = true;
11
- schema.s.hooks.pre('remove', false, function(next) {
11
+ schema.s.hooks.pre('remove', false, function removeSubDocsPreRemove(next) {
12
12
  if (this.$isSubdocument) {
13
13
  next();
14
14
  return;
@@ -6,9 +6,9 @@ const each = require('../helpers/each');
6
6
  * ignore
7
7
  */
8
8
 
9
- module.exports = function(schema) {
9
+ module.exports = function saveSubdocs(schema) {
10
10
  const unshift = true;
11
- schema.s.hooks.pre('save', false, function(next) {
11
+ schema.s.hooks.pre('save', false, function saveSubdocsPreSave(next) {
12
12
  if (this.$isSubdocument) {
13
13
  next();
14
14
  return;
@@ -36,7 +36,7 @@ module.exports = function(schema) {
36
36
  });
37
37
  }, null, unshift);
38
38
 
39
- schema.s.hooks.post('save', function(doc, next) {
39
+ schema.s.hooks.post('save', function saveSubdocsPostSave(doc, next) {
40
40
  if (this.$isSubdocument) {
41
41
  next();
42
42
  return;
@@ -8,19 +8,19 @@ const utils = require('../utils');
8
8
  */
9
9
 
10
10
  module.exports = function shardingPlugin(schema) {
11
- schema.post('init', function() {
11
+ schema.post('init', function shardingPluginPostInit() {
12
12
  storeShard.call(this);
13
13
  return this;
14
14
  });
15
- schema.pre('save', function(next) {
15
+ schema.pre('save', function shardingPluginPreSave(next) {
16
16
  applyWhere.call(this);
17
17
  next();
18
18
  });
19
- schema.pre('remove', function(next) {
19
+ schema.pre('remove', function shardingPluginPreRemove(next) {
20
20
  applyWhere.call(this);
21
21
  next();
22
22
  });
23
- schema.post('save', function() {
23
+ schema.post('save', function shardingPluginPostSave() {
24
24
  storeShard.call(this);
25
25
  });
26
26
  };
@@ -5,7 +5,7 @@ const sessionNewDocuments = require('../helpers/symbols').sessionNewDocuments;
5
5
  const utils = require('../utils');
6
6
 
7
7
  module.exports = function trackTransaction(schema) {
8
- schema.pre('save', function() {
8
+ schema.pre('save', function trackTransactionPreSave() {
9
9
  const session = this.$session();
10
10
  if (session == null) {
11
11
  return;
@@ -4,7 +4,7 @@
4
4
  * ignore
5
5
  */
6
6
 
7
- module.exports = function(schema) {
7
+ module.exports = function validateBeforeSave(schema) {
8
8
  const unshift = true;
9
9
  schema.pre('save', false, function validateBeforeSave(next, options) {
10
10
  const _this = this;
package/lib/query.js CHANGED
@@ -2402,6 +2402,10 @@ Query.prototype.merge = function(source) {
2402
2402
 
2403
2403
  utils.merge(this._mongooseOptions, source._mongooseOptions);
2404
2404
 
2405
+ return this;
2406
+ } else if (this.model != null && source instanceof this.model.base.Types.ObjectId) {
2407
+ utils.merge(this._conditions, { _id: source }, opts);
2408
+
2405
2409
  return this;
2406
2410
  }
2407
2411
 
@@ -2951,11 +2955,14 @@ Query.prototype.distinct = function(field, conditions, callback) {
2951
2955
  * // equivalent
2952
2956
  * query.sort('field -test');
2953
2957
  *
2958
+ * // also possible is to use a array with array key-value pairs
2959
+ * query.sort([['field', 'asc']]);
2960
+ *
2954
2961
  * #### Note:
2955
2962
  *
2956
2963
  * Cannot be used with `distinct()`
2957
2964
  *
2958
- * @param {Object|String} arg
2965
+ * @param {Object|String|Array<Array<(string | number)>>} arg
2959
2966
  * @return {Query} this
2960
2967
  * @see cursor.sort https://docs.mongodb.org/manual/reference/method/cursor.sort/
2961
2968
  * @api public
@@ -3340,7 +3347,7 @@ function prepareDiscriminatorCriteria(query) {
3340
3347
  * // doc: the document before updates are applied if `new: false`, or after updates if `new = true`
3341
3348
  * }
3342
3349
  *
3343
- * #### Examples:
3350
+ * #### Example:
3344
3351
  *
3345
3352
  * query.findOneAndUpdate(conditions, update, options, callback) // executes
3346
3353
  * query.findOneAndUpdate(conditions, update, options) // returns Query
@@ -3486,7 +3493,7 @@ Query.prototype._findOneAndUpdate = wrapThunk(function(callback) {
3486
3493
  * // doc: the document before updates are applied if `new: false`, or after updates if `new = true`
3487
3494
  * }
3488
3495
  *
3489
- * #### Examples:
3496
+ * #### Example:
3490
3497
  *
3491
3498
  * A.where().findOneAndRemove(conditions, options, callback) // executes
3492
3499
  * A.where().findOneAndRemove(conditions, options) // return Query
@@ -3574,7 +3581,7 @@ Query.prototype.findOneAndRemove = function(conditions, options, callback) {
3574
3581
  * // doc: the document before updates are applied if `new: false`, or after updates if `new = true`
3575
3582
  * }
3576
3583
  *
3577
- * #### Examples:
3584
+ * #### Example:
3578
3585
  *
3579
3586
  * A.where().findOneAndDelete(conditions, options, callback) // executes
3580
3587
  * A.where().findOneAndDelete(conditions, options) // return Query
@@ -3696,7 +3703,7 @@ Query.prototype._findOneAndDelete = wrapThunk(function(callback) {
3696
3703
  * // doc: the document before updates are applied if `new: false`, or after updates if `new = true`
3697
3704
  * }
3698
3705
  *
3699
- * #### Examples:
3706
+ * #### Example:
3700
3707
  *
3701
3708
  * A.where().findOneAndReplace(filter, replacement, options, callback); // executes
3702
3709
  * A.where().findOneAndReplace(filter, replacement, options); // return Query
@@ -4863,7 +4870,7 @@ function _orFailError(err, query) {
4863
4870
  /**
4864
4871
  * Executes the query
4865
4872
  *
4866
- * #### Examples:
4873
+ * #### Example:
4867
4874
  *
4868
4875
  * const promise = query.exec();
4869
4876
  * const promise = query.exec('update');
@@ -232,6 +232,9 @@ exports.applyPaths = function applyPaths(fields, schema) {
232
232
  schema.eachPath(function(path, type) {
233
233
  if (prefix) path = prefix + '.' + path;
234
234
  if (type.$isSchemaMap || path.endsWith('.$*')) {
235
+ if (type.options && type.options.select === false) {
236
+ excluded.push(path);
237
+ }
235
238
  return;
236
239
  }
237
240
  let addedPath = analyzePath(path, type);
package/lib/schema.js CHANGED
@@ -2013,7 +2013,7 @@ Schema.prototype.virtual = function(name, options) {
2013
2013
  throw new Error('Reference virtuals require `foreignField` option');
2014
2014
  }
2015
2015
 
2016
- this.pre('init', function(obj) {
2016
+ this.pre('init', function virtualPreInit(obj) {
2017
2017
  if (mpath.has(name, obj)) {
2018
2018
  const _v = mpath.get(name, obj);
2019
2019
  if (!this.$$populatedVirtuals) {
package/lib/schematype.js CHANGED
@@ -793,7 +793,7 @@ SchemaType.prototype.get = function(fn) {
793
793
  *
794
794
  * The error message argument is optional. If not passed, the [default generic error message template](#error_messages_MongooseError-messages) will be used.
795
795
  *
796
- * #### Examples:
796
+ * #### Example:
797
797
  *
798
798
  * // make sure every value is equal to "something"
799
799
  * function validator (val) {
@@ -557,7 +557,7 @@ const methods = {
557
557
  * the provided value to an embedded document and comparing using
558
558
  * [the `Document.equals()` function.](/docs/api.html#document_Document-equals)
559
559
  *
560
- * #### Examples:
560
+ * #### Example:
561
561
  *
562
562
  * doc.array.pull(ObjectId)
563
563
  * doc.array.pull({ _id: 'someId' })
Binary file
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "mongoose",
3
3
  "description": "Mongoose MongoDB ODM",
4
- "version": "6.6.1",
4
+ "version": "6.6.3",
5
5
  "author": "Guillermo Rauch <guillermo@learnboost.com>",
6
6
  "keywords": [
7
7
  "mongodb",
@@ -53,7 +53,7 @@
53
53
  "mkdirp": "^1.0.4",
54
54
  "mocha": "10.0.0",
55
55
  "moment": "2.x",
56
- "mongodb-memory-server": "8.9.1",
56
+ "mongodb-memory-server": "8.9.3",
57
57
  "ncp": "^2.0.0",
58
58
  "nyc": "15.1.0",
59
59
  "pug": "3.0.2",
package/types/index.d.ts CHANGED
@@ -58,6 +58,12 @@ declare module 'mongoose' {
58
58
  */
59
59
  export function deleteModel(name: string | RegExp): Mongoose;
60
60
 
61
+ /**
62
+ * Sanitizes query filters against query selector injection attacks by wrapping
63
+ * any nested objects that have a property whose name starts with `$` in a `$eq`.
64
+ */
65
+ export function sanitizeFilter<T>(filter: FilterQuery<T>): FilterQuery<T>;
66
+
61
67
  /** Gets mongoose options */
62
68
  export function get<K extends keyof MongooseOptions>(key: K): MongooseOptions[K];
63
69
 
@@ -118,6 +124,12 @@ declare module 'mongoose' {
118
124
 
119
125
  export type HydratedDocument<DocType, TMethodsAndOverrides = {}, TVirtuals = {}> = DocType extends Document ? Require_id<DocType> : (Document<unknown, any, DocType> & Require_id<DocType> & TVirtuals & TMethodsAndOverrides);
120
126
 
127
+ export type HydratedDocumentFromSchema<TSchema extends Schema> = HydratedDocument<
128
+ InferSchemaType<TSchema>,
129
+ ObtainSchemaGeneric<TSchema, 'TQueryHelpers'>,
130
+ ObtainSchemaGeneric<TSchema, 'TInstanceMethods'>
131
+ >;
132
+
121
133
  export interface TagSet {
122
134
  [k: string]: string;
123
135
  }
@@ -150,19 +162,20 @@ declare module 'mongoose' {
150
162
  : M
151
163
  : M;
152
164
 
153
- export type DiscriminatorSchema<DocType, M, TInstanceMethods, TQueryHelpers, TVirtuals, T> = T extends Schema<infer T1, infer T2, infer T3, infer T4, infer T5>
154
- ? Schema<Omit<DocType, keyof T1> & T1, DiscriminatorModel<T2, M>, T3 | TInstanceMethods, T4 | TQueryHelpers, T5 | TVirtuals>
155
- : Schema<DocType, M, TInstanceMethods, TQueryHelpers, TVirtuals>;
165
+ export type DiscriminatorSchema<DocType, M, TInstanceMethods, TQueryHelpers, TVirtuals, TStaticMethods, DisSchema> =
166
+ DisSchema extends Schema<infer DisSchemaEDocType, infer DisSchemaM, infer DisSchemaInstanceMethods, infer DisSchemaQueryhelpers, infer DisSchemaVirtuals, infer DisSchemaStatics>
167
+ ? Schema<Omit<DocType, keyof DisSchemaEDocType> & DisSchemaEDocType, DiscriminatorModel<DisSchemaM, M>, DisSchemaInstanceMethods | TInstanceMethods, DisSchemaQueryhelpers | TQueryHelpers, DisSchemaVirtuals | TVirtuals, DisSchemaStatics & TStaticMethods>
168
+ : Schema<DocType, M, TInstanceMethods, TQueryHelpers, TVirtuals, TStaticMethods>;
156
169
 
157
170
  type QueryResultType<T> = T extends Query<infer ResultType, any> ? ResultType : never;
158
171
 
159
172
  type PluginFunction<
160
173
  DocType,
161
- M = Model<DocType, any, any, any>,
162
- TInstanceMethods = {},
163
- TQueryHelpers = {},
164
- TVirtuals = {},
165
- TStaticMethods = {}> = (schema: Schema<DocType, M, TInstanceMethods, TQueryHelpers, TVirtuals, TStaticMethods>, opts?: any) => void;
174
+ M,
175
+ TInstanceMethods,
176
+ TQueryHelpers,
177
+ TVirtuals,
178
+ TStaticMethods> = (schema: Schema<DocType, M, TInstanceMethods, TQueryHelpers, TVirtuals, TStaticMethods>, opts?: any) => void;
166
179
 
167
180
  export class Schema<
168
181
  EnforcedDocType = any,
@@ -195,7 +208,7 @@ declare module 'mongoose' {
195
208
  /** Returns a copy of this schema */
196
209
  clone<T = this>(): T;
197
210
 
198
- discriminator<T = Schema>(name: string, schema: T): DiscriminatorSchema<DocType, M, TInstanceMethods, TQueryHelpers, TVirtuals, T>;
211
+ discriminator<DisSchema = Schema>(name: string, schema: DisSchema): DiscriminatorSchema<DocType, M, TInstanceMethods, TQueryHelpers, TVirtuals, TStaticMethods, DisSchema>;
199
212
 
200
213
  /** Returns a new schema that has the picked `paths` from this schema. */
201
214
  pick<T = this>(paths: string[], options?: SchemaOptions): T;
@@ -251,7 +264,7 @@ declare module 'mongoose' {
251
264
  pathType(path: string): string;
252
265
 
253
266
  /** Registers a plugin for this schema. */
254
- plugin<PFunc extends PluginFunction<DocType, M, TInstanceMethods, TQueryHelpers, TVirtuals, TStaticMethods>, POptions extends Parameters<PFunc>[1] = Parameters<PFunc>[1]>(fn: PFunc, opts?: POptions): this;
267
+ plugin<PFunc extends PluginFunction<DocType, M, any, any, any, any>, POptions extends Parameters<PFunc>[1] = Parameters<PFunc>[1]>(fn: PFunc, opts?: POptions): this;
255
268
 
256
269
  /** Defines a post hook for the model. */
257
270
  post<T = HydratedDocument<DocType, TInstanceMethods>>(method: MongooseDocumentMiddleware | MongooseDocumentMiddleware[] | RegExp, fn: PostMiddlewareFunction<T, T>): this;
@@ -156,7 +156,7 @@ type ResolvePathType<PathValueType, Options extends SchemaTypeOptions<PathValueT
156
156
  PathValueType extends Schema ? InferSchemaType<PathValueType> :
157
157
  PathValueType extends (infer Item)[] ? IfEquals<Item, never, any[], Item extends Schema ? Types.DocumentArray<ResolvePathType<Item>> : ResolvePathType<Item>[]> :
158
158
  PathValueType extends StringSchemaDefinition ? PathEnumOrString<Options['enum']> :
159
- PathValueType extends NumberSchemaDefinition ? number :
159
+ PathValueType extends NumberSchemaDefinition ? Options['enum'] extends ReadonlyArray<any> ? Options['enum'][number] : number :
160
160
  PathValueType extends DateSchemaDefinition ? Date :
161
161
  PathValueType extends typeof Buffer | 'buffer' | 'Buffer' | typeof Schema.Types.Buffer ? Buffer :
162
162
  PathValueType extends BooleanSchemaDefinition ? boolean :
package/types/query.d.ts CHANGED
@@ -601,7 +601,7 @@ declare module 'mongoose' {
601
601
  snapshot(val?: boolean): this;
602
602
 
603
603
  /** Sets the sort order. If an object is passed, values allowed are `asc`, `desc`, `ascending`, `descending`, `1`, and `-1`. */
604
- sort(arg?: string | { [key: string]: SortOrder | { $meta: 'textScore' } } | undefined | null): this;
604
+ sort(arg?: string | { [key: string]: SortOrder | { $meta: 'textScore' } } | [string, SortOrder][] | undefined | null): this;
605
605
 
606
606
  /** Sets the tailable option (for use with capped collections). */
607
607
  tailable(bool?: boolean, opts?: {
@@ -100,7 +100,7 @@ declare module 'mongoose' {
100
100
  * If [truthy](https://masteringjs.io/tutorials/fundamentals/truthy), Mongoose will
101
101
  * build an index on this path when the model is compiled.
102
102
  */
103
- index?: boolean | number | IndexOptions | '2d' | '2dsphere' | 'hashed' | 'text';
103
+ index?: boolean | IndexDirection;
104
104
 
105
105
  /**
106
106
  * If [truthy](https://masteringjs.io/tutorials/fundamentals/truthy), Mongoose