mongoose 8.2.4 → 8.3.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
@@ -2756,47 +2756,7 @@ function _getPathsToValidate(doc, pathsToValidate, pathsToSkip) {
2756
2756
 
2757
2757
  // gh-661: if a whole array is modified, make sure to run validation on all
2758
2758
  // the children as well
2759
- for (const path of paths) {
2760
- const _pathType = doc.$__schema.path(path);
2761
- if (!_pathType) {
2762
- continue;
2763
- }
2764
-
2765
- if (!_pathType.$isMongooseArray ||
2766
- // To avoid potential performance issues, skip doc arrays whose children
2767
- // are not required. `getPositionalPathType()` may be slow, so avoid
2768
- // it unless we have a case of #6364
2769
- (!Array.isArray(_pathType) &&
2770
- _pathType.$isMongooseDocumentArray &&
2771
- !(_pathType && _pathType.schemaOptions && _pathType.schemaOptions.required))) {
2772
- continue;
2773
- }
2774
-
2775
- // gh-11380: optimization. If the array isn't a document array and there's no validators
2776
- // on the array type, there's no need to run validation on the individual array elements.
2777
- if (_pathType.$isMongooseArray &&
2778
- !_pathType.$isMongooseDocumentArray && // Skip document arrays...
2779
- !_pathType.$embeddedSchemaType.$isMongooseArray && // and arrays of arrays
2780
- _pathType.$embeddedSchemaType.validators.length === 0) {
2781
- continue;
2782
- }
2783
-
2784
- const val = doc.$__getValue(path);
2785
- _pushNestedArrayPaths(val, paths, path);
2786
- }
2787
-
2788
- function _pushNestedArrayPaths(val, paths, path) {
2789
- if (val != null) {
2790
- const numElements = val.length;
2791
- for (let j = 0; j < numElements; ++j) {
2792
- if (Array.isArray(val[j])) {
2793
- _pushNestedArrayPaths(val[j], paths, path + '.' + j);
2794
- } else {
2795
- paths.add(path + '.' + j);
2796
- }
2797
- }
2798
- }
2799
- }
2759
+ _addArrayPathsToValidate(doc, paths);
2800
2760
 
2801
2761
  const flattenOptions = { skipArrays: true };
2802
2762
  for (const pathToCheck of paths) {
@@ -2841,12 +2801,58 @@ function _getPathsToValidate(doc, pathsToValidate, pathsToSkip) {
2841
2801
  return [paths, doValidateOptions];
2842
2802
  }
2843
2803
 
2804
+ function _addArrayPathsToValidate(doc, paths) {
2805
+ for (const path of paths) {
2806
+ const _pathType = doc.$__schema.path(path);
2807
+ if (!_pathType) {
2808
+ continue;
2809
+ }
2810
+
2811
+ if (!_pathType.$isMongooseArray ||
2812
+ // To avoid potential performance issues, skip doc arrays whose children
2813
+ // are not required. `getPositionalPathType()` may be slow, so avoid
2814
+ // it unless we have a case of #6364
2815
+ (!Array.isArray(_pathType) &&
2816
+ _pathType.$isMongooseDocumentArray &&
2817
+ !(_pathType && _pathType.schemaOptions && _pathType.schemaOptions.required))) {
2818
+ continue;
2819
+ }
2820
+
2821
+ // gh-11380: optimization. If the array isn't a document array and there's no validators
2822
+ // on the array type, there's no need to run validation on the individual array elements.
2823
+ if (_pathType.$isMongooseArray &&
2824
+ !_pathType.$isMongooseDocumentArray && // Skip document arrays...
2825
+ !_pathType.$embeddedSchemaType.$isMongooseArray && // and arrays of arrays
2826
+ _pathType.$embeddedSchemaType.validators.length === 0) {
2827
+ continue;
2828
+ }
2829
+
2830
+ const val = doc.$__getValue(path);
2831
+ _pushNestedArrayPaths(val, paths, path);
2832
+ }
2833
+ }
2834
+
2835
+ function _pushNestedArrayPaths(val, paths, path) {
2836
+ if (val != null) {
2837
+ const numElements = val.length;
2838
+ for (let j = 0; j < numElements; ++j) {
2839
+ if (Array.isArray(val[j])) {
2840
+ _pushNestedArrayPaths(val[j], paths, path + '.' + j);
2841
+ } else {
2842
+ paths.add(path + '.' + j);
2843
+ }
2844
+ }
2845
+ }
2846
+ }
2847
+
2844
2848
  /*!
2845
2849
  * ignore
2846
2850
  */
2847
2851
 
2848
2852
  Document.prototype.$__validate = function(pathsToValidate, options, callback) {
2849
- if (typeof pathsToValidate === 'function') {
2853
+ if (this.$__.saveOptions && this.$__.saveOptions.pathsToSave && !pathsToValidate) {
2854
+ pathsToValidate = [...this.$__.saveOptions.pathsToSave];
2855
+ } else if (typeof pathsToValidate === 'function') {
2850
2856
  callback = pathsToValidate;
2851
2857
  options = null;
2852
2858
  pathsToValidate = null;
@@ -2868,6 +2874,19 @@ Document.prototype.$__validate = function(pathsToValidate, options, callback) {
2868
2874
  shouldValidateModifiedOnly = this.$__schema.options.validateModifiedOnly;
2869
2875
  }
2870
2876
 
2877
+ const validateAllPaths = options && options.validateAllPaths;
2878
+ if (validateAllPaths) {
2879
+ if (pathsToSkip) {
2880
+ throw new TypeError('Cannot set both `validateAllPaths` and `pathsToSkip`');
2881
+ }
2882
+ if (pathsToValidate) {
2883
+ throw new TypeError('Cannot set both `validateAllPaths` and `pathsToValidate`');
2884
+ }
2885
+ if (hasValidateModifiedOnlyOption && shouldValidateModifiedOnly) {
2886
+ throw new TypeError('Cannot set both `validateAllPaths` and `validateModifiedOnly`');
2887
+ }
2888
+ }
2889
+
2871
2890
  const _this = this;
2872
2891
  const _complete = () => {
2873
2892
  let validationError = this.$__.validationError;
@@ -2905,11 +2924,33 @@ Document.prototype.$__validate = function(pathsToValidate, options, callback) {
2905
2924
  };
2906
2925
 
2907
2926
  // only validate required fields when necessary
2908
- const pathDetails = _getPathsToValidate(this, pathsToValidate, pathsToSkip);
2909
- const paths = shouldValidateModifiedOnly ?
2910
- pathDetails[0].filter((path) => this.$isModified(path)) :
2911
- pathDetails[0];
2912
- const doValidateOptionsByPath = pathDetails[1];
2927
+ let paths;
2928
+ let doValidateOptionsByPath;
2929
+ if (validateAllPaths) {
2930
+ paths = new Set(Object.keys(this.$__schema.paths));
2931
+ // gh-661: if a whole array is modified, make sure to run validation on all
2932
+ // the children as well
2933
+ for (const path of paths) {
2934
+ const schemaType = this.$__schema.path(path);
2935
+ if (!schemaType || !schemaType.$isMongooseArray) {
2936
+ continue;
2937
+ }
2938
+ const val = this.$__getValue(path);
2939
+ if (!val) {
2940
+ continue;
2941
+ }
2942
+ _pushNestedArrayPaths(val, paths, path);
2943
+ }
2944
+ paths = [...paths];
2945
+ doValidateOptionsByPath = {};
2946
+ } else {
2947
+ const pathDetails = _getPathsToValidate(this, pathsToValidate, pathsToSkip);
2948
+ paths = shouldValidateModifiedOnly ?
2949
+ pathDetails[0].filter((path) => this.$isModified(path)) :
2950
+ pathDetails[0];
2951
+ doValidateOptionsByPath = pathDetails[1];
2952
+ }
2953
+
2913
2954
  if (typeof pathsToValidate === 'string') {
2914
2955
  pathsToValidate = pathsToValidate.split(' ');
2915
2956
  }
@@ -2929,8 +2970,19 @@ Document.prototype.$__validate = function(pathsToValidate, options, callback) {
2929
2970
  const validated = {};
2930
2971
  let total = 0;
2931
2972
 
2932
- for (const path of paths) {
2933
- validatePath(path);
2973
+ let pathsToSave = this.$__.saveOptions?.pathsToSave;
2974
+ if (Array.isArray(pathsToSave)) {
2975
+ pathsToSave = new Set(pathsToSave);
2976
+ for (const path of paths) {
2977
+ if (!pathsToSave.has(path)) {
2978
+ continue;
2979
+ }
2980
+ validatePath(path);
2981
+ }
2982
+ } else {
2983
+ for (const path of paths) {
2984
+ validatePath(path);
2985
+ }
2934
2986
  }
2935
2987
 
2936
2988
  function validatePath(path) {
@@ -2979,7 +3031,8 @@ Document.prototype.$__validate = function(pathsToValidate, options, callback) {
2979
3031
  const doValidateOptions = {
2980
3032
  ...doValidateOptionsByPath[path],
2981
3033
  path: path,
2982
- validateModifiedOnly: shouldValidateModifiedOnly
3034
+ validateModifiedOnly: shouldValidateModifiedOnly,
3035
+ validateAllPaths
2983
3036
  };
2984
3037
 
2985
3038
  schemaType.doValidate(val, function(err) {
@@ -3097,6 +3150,16 @@ Document.prototype.validateSync = function(pathsToValidate, options) {
3097
3150
 
3098
3151
  let pathsToSkip = options && options.pathsToSkip;
3099
3152
 
3153
+ const validateAllPaths = options && options.validateAllPaths;
3154
+ if (validateAllPaths) {
3155
+ if (pathsToSkip) {
3156
+ throw new TypeError('Cannot set both `validateAllPaths` and `pathsToSkip`');
3157
+ }
3158
+ if (pathsToValidate) {
3159
+ throw new TypeError('Cannot set both `validateAllPaths` and `pathsToValidate`');
3160
+ }
3161
+ }
3162
+
3100
3163
  if (typeof pathsToValidate === 'string') {
3101
3164
  const isOnePathOnly = pathsToValidate.indexOf(' ') === -1;
3102
3165
  pathsToValidate = isOnePathOnly ? [pathsToValidate] : pathsToValidate.split(' ');
@@ -3105,11 +3168,32 @@ Document.prototype.validateSync = function(pathsToValidate, options) {
3105
3168
  }
3106
3169
 
3107
3170
  // only validate required fields when necessary
3108
- const pathDetails = _getPathsToValidate(this, pathsToValidate, pathsToSkip);
3109
- const paths = shouldValidateModifiedOnly ?
3110
- pathDetails[0].filter((path) => this.$isModified(path)) :
3111
- pathDetails[0];
3112
- const skipSchemaValidators = pathDetails[1];
3171
+ let paths;
3172
+ let skipSchemaValidators;
3173
+ if (validateAllPaths) {
3174
+ paths = new Set(Object.keys(this.$__schema.paths));
3175
+ // gh-661: if a whole array is modified, make sure to run validation on all
3176
+ // the children as well
3177
+ for (const path of paths) {
3178
+ const schemaType = this.$__schema.path(path);
3179
+ if (!schemaType || !schemaType.$isMongooseArray) {
3180
+ continue;
3181
+ }
3182
+ const val = this.$__getValue(path);
3183
+ if (!val) {
3184
+ continue;
3185
+ }
3186
+ _pushNestedArrayPaths(val, paths, path);
3187
+ }
3188
+ paths = [...paths];
3189
+ skipSchemaValidators = {};
3190
+ } else {
3191
+ const pathDetails = _getPathsToValidate(this, pathsToValidate, pathsToSkip);
3192
+ paths = shouldValidateModifiedOnly ?
3193
+ pathDetails[0].filter((path) => this.$isModified(path)) :
3194
+ pathDetails[0];
3195
+ skipSchemaValidators = pathDetails[1];
3196
+ }
3113
3197
 
3114
3198
  const validating = {};
3115
3199
 
@@ -3134,7 +3218,8 @@ Document.prototype.validateSync = function(pathsToValidate, options) {
3134
3218
  const err = p.doValidateSync(val, _this, {
3135
3219
  skipSchemaValidators: skipSchemaValidators[path],
3136
3220
  path: path,
3137
- validateModifiedOnly: shouldValidateModifiedOnly
3221
+ validateModifiedOnly: shouldValidateModifiedOnly,
3222
+ validateAllPaths
3138
3223
  });
3139
3224
  if (err) {
3140
3225
  const isSubdoc = p.$isSingleNested ||
package/lib/model.js CHANGED
@@ -298,7 +298,6 @@ Model.prototype.$__handleSave = function(options, callback) {
298
298
  if (!saveOptions.hasOwnProperty('session') && session != null) {
299
299
  saveOptions.session = session;
300
300
  }
301
-
302
301
  if (this.$isNew) {
303
302
  // send entire doc
304
303
  const obj = this.toObject(saveToObjectOptions);
@@ -335,6 +334,18 @@ Model.prototype.$__handleSave = function(options, callback) {
335
334
  // since it already exists
336
335
  this.$__.inserting = false;
337
336
  const delta = this.$__delta();
337
+
338
+ if (options.pathsToSave) {
339
+ for (const key in delta[1]['$set']) {
340
+ if (options.pathsToSave.includes(key)) {
341
+ continue;
342
+ } else if (options.pathsToSave.some(pathToSave => key.slice(0, pathToSave.length) === pathToSave && key.charAt(pathToSave.length) === '.')) {
343
+ continue;
344
+ } else {
345
+ delete delta[1]['$set'][key];
346
+ }
347
+ }
348
+ }
338
349
  if (delta) {
339
350
  if (delta instanceof MongooseError) {
340
351
  callback(delta);
@@ -521,6 +532,7 @@ function generateVersionError(doc, modifiedPaths) {
521
532
  * @param {Number} [options.wtimeout] sets a [timeout for the write concern](https://www.mongodb.com/docs/manual/reference/write-concern/#wtimeout). Overrides the [schema-level `writeConcern` option](https://mongoosejs.com/docs/guide.html#writeConcern).
522
533
  * @param {Boolean} [options.checkKeys=true] the MongoDB driver prevents you from saving keys that start with '$' or contain '.' by default. Set this option to `false` to skip that check. See [restrictions on field names](https://docs.mongodb.com/manual/reference/limits/#mongodb-limit-Restrictions-on-Field-Names)
523
534
  * @param {Boolean} [options.timestamps=true] if `false` and [timestamps](https://mongoosejs.com/docs/guide.html#timestamps) are enabled, skip timestamps for this `save()`.
535
+ * @param {Array} [options.pathsToSave] An array of paths that tell mongoose to only validate and save the paths in `pathsToSave`.
524
536
  * @throws {DocumentNotFoundError} if this [save updates an existing document](https://mongoosejs.com/docs/api/document.html#Document.prototype.isNew) but the document doesn't exist in the database. For example, you will get this error if the document is [deleted between when you retrieved the document and when you saved it](documents.html#updating).
525
537
  * @return {Promise}
526
538
  * @api public
@@ -747,7 +759,6 @@ function handleAtomics(self, where, delta, data, value) {
747
759
 
748
760
  Model.prototype.$__delta = function() {
749
761
  const dirty = this.$__dirty();
750
-
751
762
  const optimisticConcurrency = this.$__schema.options.optimisticConcurrency;
752
763
  if (optimisticConcurrency) {
753
764
  if (Array.isArray(optimisticConcurrency)) {
package/lib/query.js CHANGED
@@ -2861,19 +2861,27 @@ Query.prototype.distinct = function(field, conditions) {
2861
2861
  * Cannot be used with `distinct()`
2862
2862
  *
2863
2863
  * @param {Object|String|Array<Array<(string | number)>>} arg
2864
+ * @param {Object} [options]
2865
+ * @param {Boolean} [options.override=false] If true, replace existing sort options with `arg`
2864
2866
  * @return {Query} this
2865
2867
  * @see cursor.sort https://www.mongodb.com/docs/manual/reference/method/cursor.sort/
2866
2868
  * @api public
2867
2869
  */
2868
2870
 
2869
- Query.prototype.sort = function(arg) {
2870
- if (arguments.length > 1) {
2871
- throw new Error('sort() only takes 1 Argument');
2871
+ Query.prototype.sort = function(arg, options) {
2872
+ if (arguments.length > 2) {
2873
+ throw new Error('sort() takes at most 2 arguments');
2874
+ }
2875
+ if (options != null && typeof options !== 'object') {
2876
+ throw new Error('sort() options argument must be an object or nullish');
2872
2877
  }
2873
2878
 
2874
2879
  if (this.options.sort == null) {
2875
2880
  this.options.sort = {};
2876
2881
  }
2882
+ if (options && options.override) {
2883
+ this.options.sort = {};
2884
+ }
2877
2885
  const sort = this.options.sort;
2878
2886
  if (typeof arg === 'string') {
2879
2887
  const properties = arg.indexOf(' ') === -1 ? [arg] : arg.split(' ');
@@ -279,7 +279,7 @@ SchemaDocumentArray.prototype.doValidate = function(array, fn, scope, options) {
279
279
  continue;
280
280
  }
281
281
 
282
- doc.$__validate(callback);
282
+ doc.$__validate(null, options, callback);
283
283
  }
284
284
  }
285
285
  };
@@ -330,7 +330,7 @@ SchemaDocumentArray.prototype.doValidateSync = function(array, scope, options) {
330
330
  continue;
331
331
  }
332
332
 
333
- const subdocValidateError = doc.validateSync();
333
+ const subdocValidateError = doc.validateSync(options);
334
334
 
335
335
  if (subdocValidateError && resultError == null) {
336
336
  resultError = subdocValidateError;
package/lib/schema.js CHANGED
@@ -1300,6 +1300,7 @@ Schema.prototype.interpretAsType = function(path, obj, options) {
1300
1300
  return clone;
1301
1301
  }
1302
1302
 
1303
+
1303
1304
  // If this schema has an associated Mongoose object, use the Mongoose object's
1304
1305
  // copy of SchemaTypes re: gh-7158 gh-6933
1305
1306
  const MongooseTypes = this.base != null ? this.base.Schema.Types : Schema.Types;
@@ -1365,9 +1366,13 @@ Schema.prototype.interpretAsType = function(path, obj, options) {
1365
1366
  }
1366
1367
  return new MongooseTypes.DocumentArray(path, cast[options.typeKey], obj, cast);
1367
1368
  }
1368
-
1369
- if (Array.isArray(cast)) {
1370
- return new MongooseTypes.Array(path, this.interpretAsType(path, cast, options), obj);
1369
+ if (typeof cast !== 'undefined') {
1370
+ if (Array.isArray(cast) || cast.type === Array || cast.type == 'Array') {
1371
+ if (cast && cast.type == 'Array') {
1372
+ cast.type = Array;
1373
+ }
1374
+ return new MongooseTypes.Array(path, this.interpretAsType(path, cast, options), obj);
1375
+ }
1371
1376
  }
1372
1377
 
1373
1378
  // Handle both `new Schema({ arr: [{ subpath: String }] })` and `new Schema({ arr: [{ type: { subpath: string } }] })`
@@ -1418,7 +1423,6 @@ Schema.prototype.interpretAsType = function(path, obj, options) {
1418
1423
  type = cast[options.typeKey] && (options.typeKey !== 'type' || !cast.type.type)
1419
1424
  ? cast[options.typeKey]
1420
1425
  : cast;
1421
-
1422
1426
  if (Array.isArray(type)) {
1423
1427
  return new MongooseTypes.Array(path, this.interpretAsType(path, type, options), obj);
1424
1428
  }
package/lib/schemaType.js CHANGED
@@ -803,6 +803,21 @@ SchemaType.prototype.get = function(fn) {
803
803
  return this;
804
804
  };
805
805
 
806
+ /**
807
+ * Adds multiple validators for this document path.
808
+ * Calls `validate()` for every element in validators.
809
+ *
810
+ * @param {Array<RegExp|Function|Object>} validators
811
+ * @returns this
812
+ */
813
+
814
+ SchemaType.prototype.validateAll = function(validators) {
815
+ for (let i = 0; i < validators.length; i++) {
816
+ this.validate(validators[i]);
817
+ }
818
+ return this;
819
+ };
820
+
806
821
  /**
807
822
  * Adds validator(s) for this document path.
808
823
  *
@@ -1285,6 +1300,9 @@ SchemaType.prototype.select = function select(val) {
1285
1300
  SchemaType.prototype.doValidate = function(value, fn, scope, options) {
1286
1301
  let err = false;
1287
1302
  const path = this.path;
1303
+ if (typeof fn !== 'function') {
1304
+ throw new TypeError(`Must pass callback function to doValidate(), got ${typeof fn}`);
1305
+ }
1288
1306
 
1289
1307
  // Avoid non-object `validators`
1290
1308
  const validators = this.validators.
@@ -1419,7 +1437,6 @@ SchemaType.prototype.doValidateSync = function(value, scope, options) {
1419
1437
  let i = 0;
1420
1438
  const len = validators.length;
1421
1439
  for (i = 0; i < len; ++i) {
1422
-
1423
1440
  const v = validators[i];
1424
1441
 
1425
1442
  if (v === null || typeof v !== 'object') {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "mongoose",
3
3
  "description": "Mongoose MongoDB ODM",
4
- "version": "8.2.4",
4
+ "version": "8.3.0",
5
5
  "author": "Guillermo Rauch <guillermo@learnboost.com>",
6
6
  "keywords": [
7
7
  "mongodb",
@@ -19,17 +19,17 @@
19
19
  ],
20
20
  "license": "MIT",
21
21
  "dependencies": {
22
- "bson": "^6.2.0",
23
- "kareem": "2.5.1",
24
- "mongodb": "6.3.0",
22
+ "bson": "^6.5.0",
23
+ "kareem": "2.6.0",
24
+ "mongodb": "6.5.0",
25
25
  "mpath": "0.9.0",
26
26
  "mquery": "5.0.0",
27
27
  "ms": "2.1.3",
28
28
  "sift": "16.0.1"
29
29
  },
30
30
  "devDependencies": {
31
- "@babel/core": "7.24.0",
32
- "@babel/preset-env": "7.24.0",
31
+ "@babel/core": "7.24.3",
32
+ "@babel/preset-env": "7.24.3",
33
33
  "@typescript-eslint/eslint-plugin": "^6.2.1",
34
34
  "@typescript-eslint/parser": "^6.2.1",
35
35
  "acquit": "1.3.0",
@@ -46,7 +46,7 @@
46
46
  "dotenv": "16.4.5",
47
47
  "dox": "1.0.0",
48
48
  "eslint": "8.57.0",
49
- "eslint-plugin-markdown": "^3.0.1",
49
+ "eslint-plugin-markdown": "^4.0.1",
50
50
  "eslint-plugin-mocha-no-only": "1.1.1",
51
51
  "express": "^4.18.1",
52
52
  "fs-extra": "~11.2.0",
@@ -56,7 +56,7 @@
56
56
  "markdownlint-cli2": "^0.12.1",
57
57
  "marked": "4.3.0",
58
58
  "mkdirp": "^3.0.1",
59
- "mocha": "10.3.0",
59
+ "mocha": "10.4.0",
60
60
  "moment": "2.x",
61
61
  "mongodb-memory-server": "8.15.1",
62
62
  "ncp": "^2.0.0",
@@ -65,10 +65,10 @@
65
65
  "q": "1.5.1",
66
66
  "sinon": "17.0.1",
67
67
  "stream-browserify": "3.0.0",
68
- "tsd": "0.30.7",
69
- "typescript": "5.3.3",
68
+ "tsd": "0.31.0",
69
+ "typescript": "5.4.3",
70
70
  "uuid": "9.0.1",
71
- "webpack": "5.90.3"
71
+ "webpack": "5.91.0"
72
72
  },
73
73
  "directories": {
74
74
  "lib": "./lib/mongoose"
package/types/index.d.ts CHANGED
@@ -27,6 +27,7 @@
27
27
  declare class NativeDate extends global.Date { }
28
28
 
29
29
  declare module 'mongoose' {
30
+ import Kareem = require('kareem');
30
31
  import events = require('events');
31
32
  import mongodb = require('mongodb');
32
33
  import mongoose = require('mongoose');
@@ -397,7 +398,6 @@ declare module 'mongoose' {
397
398
  ): this;
398
399
  // this = Document
399
400
  pre<T = THydratedDocumentType>(method: 'save', fn: PreSaveMiddlewareFunction<T>): this;
400
- pre<T = THydratedDocumentType>(method: 'save', options: SchemaPreOptions, fn: PreSaveMiddlewareFunction<T>): this;
401
401
  pre<T = THydratedDocumentType>(method: MongooseDistinctDocumentMiddleware|MongooseDistinctDocumentMiddleware[], fn: PreMiddlewareFunction<T>): this;
402
402
  pre<T = THydratedDocumentType>(method: MongooseDistinctDocumentMiddleware|MongooseDistinctDocumentMiddleware[], options: SchemaPreOptions, fn: PreMiddlewareFunction<T>): this;
403
403
  pre<T = THydratedDocumentType>(
@@ -415,7 +415,6 @@ declare module 'mongoose' {
415
415
  pre<T = THydratedDocumentType|Query<any, any>>(method: MongooseQueryOrDocumentMiddleware | MongooseQueryOrDocumentMiddleware[] | RegExp, fn: PreMiddlewareFunction<T>): this;
416
416
  // method aggregate
417
417
  pre<T extends Aggregate<any>>(method: 'aggregate' | RegExp, fn: PreMiddlewareFunction<T>): this;
418
- pre<T extends Aggregate<any>>(method: 'aggregate' | RegExp, options: SchemaPreOptions, fn: PreMiddlewareFunction<T>): this;
419
418
  /* method insertMany */
420
419
  pre<T = TModelType>(
421
420
  method: 'insertMany' | RegExp,
@@ -426,16 +425,6 @@ declare module 'mongoose' {
426
425
  options?: InsertManyOptions & { lean?: boolean }
427
426
  ) => void | Promise<void>
428
427
  ): this;
429
- pre<T = TModelType>(
430
- method: 'insertMany' | RegExp,
431
- options: SchemaPreOptions,
432
- fn: (
433
- this: T,
434
- next: (err?: CallbackError) => void,
435
- docs: any | Array<any>,
436
- options?: InsertManyOptions & { lean?: boolean }
437
- ) => void | Promise<void>
438
- ): this;
439
428
  /* method bulkWrite */
440
429
  pre<T = TModelType>(
441
430
  method: 'bulkWrite' | RegExp,
@@ -446,16 +435,6 @@ declare module 'mongoose' {
446
435
  options?: mongodb.BulkWriteOptions & MongooseBulkWriteOptions
447
436
  ) => void | Promise<void>
448
437
  ): this;
449
- pre<T = TModelType>(
450
- method: 'bulkWrite' | RegExp,
451
- options: SchemaPreOptions,
452
- fn: (
453
- this: T,
454
- next: (err?: CallbackError) => void,
455
- ops: Array<mongodb.AnyBulkWriteOperation<any> & MongooseBulkWritePerWriteOptions>,
456
- options?: mongodb.BulkWriteOptions & MongooseBulkWriteOptions
457
- ) => void | Promise<void>
458
- ): this;
459
438
  /* method createCollection */
460
439
  pre<T = TModelType>(
461
440
  method: 'createCollection' | RegExp,
@@ -465,15 +444,6 @@ declare module 'mongoose' {
465
444
  options?: mongodb.CreateCollectionOptions & Pick<SchemaOptions, 'expires'>
466
445
  ) => void | Promise<void>
467
446
  ): this;
468
- pre<T = TModelType>(
469
- method: 'createCollection' | RegExp,
470
- options: SchemaPreOptions,
471
- fn: (
472
- this: T,
473
- next: (err?: CallbackError) => void,
474
- options?: mongodb.CreateCollectionOptions & Pick<SchemaOptions, 'expires'>
475
- ) => void | Promise<void>
476
- ): this;
477
447
 
478
448
  /** Object of currently defined query helpers on this schema. */
479
449
  query: TQueryHelpers;
@@ -722,5 +692,9 @@ declare module 'mongoose' {
722
692
  /* for ts-mongoose */
723
693
  export class mquery { }
724
694
 
695
+ export function overwriteMiddlewareResult(val: any): Kareem.OverwriteMiddlewareResult;
696
+
697
+ export function skipMiddlewareFunction(val: any): Kareem.SkipWrappedFunction;
698
+
725
699
  export default mongoose;
726
700
  }
@@ -1,4 +1,5 @@
1
1
  declare module 'mongoose' {
2
+ import Kareem = require('kareem');
2
3
 
3
4
  type MongooseQueryAndDocumentMiddleware = 'updateOne' | 'deleteOne';
4
5
 
@@ -37,13 +38,13 @@ declare module 'mongoose' {
37
38
  this: ThisType,
38
39
  next: CallbackWithoutResultAndOptionalError,
39
40
  opts?: Record<string, any>
40
- ) => void | Promise<void>;
41
+ ) => void | Promise<void> | Kareem.SkipWrappedFunction;
41
42
  type PreSaveMiddlewareFunction<ThisType = any> = (
42
43
  this: ThisType,
43
44
  next: CallbackWithoutResultAndOptionalError,
44
45
  opts: SaveOptions
45
- ) => void | Promise<void>;
46
- type PostMiddlewareFunction<ThisType = any, ResType = any> = (this: ThisType, res: ResType, next: CallbackWithoutResultAndOptionalError) => void | Promise<void>;
46
+ ) => void | Promise<void> | Kareem.SkipWrappedFunction;
47
+ type PostMiddlewareFunction<ThisType = any, ResType = any> = (this: ThisType, res: ResType, next: CallbackWithoutResultAndOptionalError) => void | Promise<void> | Kareem.OverwriteMiddlewareResult;
47
48
  type ErrorHandlingMiddlewareFunction<ThisType = any, ResType = any> = (this: ThisType, err: NativeError, res: ResType, next: CallbackWithoutResultAndOptionalError) => void;
48
- type ErrorHandlingMiddlewareWithOption<ThisType = any, ResType = any> = (this: ThisType, err: NativeError, res: ResType | null, next: CallbackWithoutResultAndOptionalError) => void | Promise<void>;
49
+ type ErrorHandlingMiddlewareWithOption<ThisType = any, ResType = any> = (this: ThisType, err: NativeError, res: ResType | null, next: CallbackWithoutResultAndOptionalError) => void | Promise<void> | Kareem.OverwriteMiddlewareResult;
49
50
  }
package/types/query.d.ts CHANGED
@@ -741,7 +741,10 @@ declare module 'mongoose' {
741
741
  slice(val: number | Array<number>): this;
742
742
 
743
743
  /** Sets the sort order. If an object is passed, values allowed are `asc`, `desc`, `ascending`, `descending`, `1`, and `-1`. */
744
- sort(arg?: string | { [key: string]: SortOrder | { $meta: any } } | [string, SortOrder][] | undefined | null): this;
744
+ sort(
745
+ arg?: string | { [key: string]: SortOrder | { $meta: any } } | [string, SortOrder][] | undefined | null,
746
+ options?: { override?: boolean }
747
+ ): this;
745
748
 
746
749
  /** Sets the tailable option (for use with capped collections). */
747
750
  tailable(bool?: boolean, opts?: {
@@ -192,10 +192,14 @@ declare module 'mongoose' {
192
192
  [other: string]: any;
193
193
  }
194
194
 
195
- interface Validator {
196
- message?: string; type?: string; validator?: Function
195
+ interface Validator<DocType = any> {
196
+ message?: string;
197
+ type?: string;
198
+ validator?: ValidatorFunction<DocType>;
197
199
  }
198
200
 
201
+ type ValidatorFunction<DocType = any> = (this: DocType, value: any, validatorProperties?: Validator) => any;
202
+
199
203
  class SchemaType<T = any, DocType = any> {
200
204
  /** SchemaType constructor */
201
205
  constructor(path: string, options?: AnyObject, instance?: string);
@@ -281,7 +285,10 @@ declare module 'mongoose' {
281
285
  validators: Validator[];
282
286
 
283
287
  /** Adds validator(s) for this document path. */
284
- validate(obj: RegExp | ((this: DocType, value: any, validatorProperties?: Validator) => any), errorMsg?: string, type?: string): this;
288
+ validate(obj: RegExp | ValidatorFunction<DocType> | Validator<DocType>, errorMsg?: string, type?: string): this;
289
+
290
+ /** Adds multiple validators for this document path. */
291
+ validateAll(validators: Array<RegExp | ValidatorFunction<DocType> | Validator<DocType>>): this;
285
292
 
286
293
  /** Default options for this SchemaType */
287
294
  defaultOptions?: Record<string, any>;