mongoose 8.5.5 → 8.6.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.
@@ -33,15 +33,18 @@ class ChangeStream extends EventEmitter {
33
33
  );
34
34
  }
35
35
 
36
- // This wrapper is necessary because of buffering.
37
- changeStreamThunk((err, driverChangeStream) => {
38
- if (err != null) {
39
- this.emit('error', err);
40
- return;
41
- }
36
+ this.$driverChangeStreamPromise = new Promise((resolve, reject) => {
37
+ // This wrapper is necessary because of buffering.
38
+ changeStreamThunk((err, driverChangeStream) => {
39
+ if (err != null) {
40
+ this.emit('error', err);
41
+ return reject(err);
42
+ }
42
43
 
43
- this.driverChangeStream = driverChangeStream;
44
- this.emit('ready');
44
+ this.driverChangeStream = driverChangeStream;
45
+ this.emit('ready');
46
+ resolve();
47
+ });
45
48
  });
46
49
  }
47
50
 
@@ -53,20 +56,23 @@ class ChangeStream extends EventEmitter {
53
56
  this.bindedEvents = true;
54
57
 
55
58
  if (this.driverChangeStream == null) {
56
- this.once('ready', () => {
57
- this.driverChangeStream.on('close', () => {
58
- this.closed = true;
59
- });
59
+ this.$driverChangeStreamPromise.then(
60
+ () => {
61
+ this.driverChangeStream.on('close', () => {
62
+ this.closed = true;
63
+ });
60
64
 
61
- driverChangeStreamEvents.forEach(ev => {
62
- this.driverChangeStream.on(ev, data => {
63
- if (data != null && data.fullDocument != null && this.options && this.options.hydrate) {
64
- data.fullDocument = this.options.model.hydrate(data.fullDocument);
65
- }
66
- this.emit(ev, data);
65
+ driverChangeStreamEvents.forEach(ev => {
66
+ this.driverChangeStream.on(ev, data => {
67
+ if (data != null && data.fullDocument != null && this.options && this.options.hydrate) {
68
+ data.fullDocument = this.options.model.hydrate(data.fullDocument);
69
+ }
70
+ this.emit(ev, data);
71
+ });
67
72
  });
68
- });
69
- });
73
+ },
74
+ () => {} // No need to register events if opening change stream failed
75
+ );
70
76
 
71
77
  return;
72
78
  }
@@ -142,8 +148,12 @@ class ChangeStream extends EventEmitter {
142
148
  this.closed = true;
143
149
  if (this.driverChangeStream) {
144
150
  return this.driverChangeStream.close();
151
+ } else {
152
+ return this.$driverChangeStreamPromise.then(
153
+ () => this.driverChangeStream.close(),
154
+ () => {} // No need to close if opening the change stream failed
155
+ );
145
156
  }
146
- return Promise.resolve();
147
157
  }
148
158
  }
149
159
 
@@ -10,6 +10,7 @@ const eachAsync = require('../helpers/cursor/eachAsync');
10
10
  const helpers = require('../queryHelpers');
11
11
  const kareem = require('kareem');
12
12
  const immediate = require('../helpers/immediate');
13
+ const { once } = require('node:events');
13
14
  const util = require('util');
14
15
 
15
16
  /**
@@ -42,6 +43,7 @@ function QueryCursor(query) {
42
43
  this.cursor = null;
43
44
  this.skipped = false;
44
45
  this.query = query;
46
+ this._closed = false;
45
47
  const model = query.model;
46
48
  this._mongooseOptions = {};
47
49
  this._transforms = [];
@@ -135,6 +137,25 @@ QueryCursor.prototype._read = function() {
135
137
  });
136
138
  };
137
139
 
140
+ /**
141
+ * Returns the underlying cursor from the MongoDB Node driver that this cursor uses.
142
+ *
143
+ * @method getDriverCursor
144
+ * @memberOf QueryCursor
145
+ * @returns {Cursor} MongoDB Node driver cursor instance
146
+ * @instance
147
+ * @api public
148
+ */
149
+
150
+ QueryCursor.prototype.getDriverCursor = async function getDriverCursor() {
151
+ if (this.cursor) {
152
+ return this.cursor;
153
+ }
154
+
155
+ await once(this, 'cursor');
156
+ return this.cursor;
157
+ };
158
+
138
159
  /**
139
160
  * Registers a transform function which subsequently maps documents retrieved
140
161
  * via the streams interface or `.next()`
@@ -209,6 +230,7 @@ QueryCursor.prototype.close = async function close() {
209
230
  }
210
231
  try {
211
232
  await this.cursor.close();
233
+ this._closed = true;
212
234
  this.emit('close');
213
235
  } catch (error) {
214
236
  this.listeners('error').length > 0 && this.emit('error', error);
@@ -246,6 +268,9 @@ QueryCursor.prototype.next = async function next() {
246
268
  if (typeof arguments[0] === 'function') {
247
269
  throw new MongooseError('QueryCursor.prototype.next() no longer accepts a callback');
248
270
  }
271
+ if (this._closed) {
272
+ throw new MongooseError('Cannot call `next()` on a closed cursor');
273
+ }
249
274
  return new Promise((resolve, reject) => {
250
275
  _next(this, function(error, doc) {
251
276
  if (error) {
package/lib/model.js CHANGED
@@ -2115,17 +2115,21 @@ Model.countDocuments = function countDocuments(conditions, options) {
2115
2115
  *
2116
2116
  * @param {String} field
2117
2117
  * @param {Object} [conditions] optional
2118
+ * @param {Object} [options] optional
2118
2119
  * @return {Query}
2119
2120
  * @api public
2120
2121
  */
2121
2122
 
2122
- Model.distinct = function distinct(field, conditions) {
2123
+ Model.distinct = function distinct(field, conditions, options) {
2123
2124
  _checkContext(this, 'distinct');
2124
- if (typeof arguments[0] === 'function' || typeof arguments[1] === 'function') {
2125
+ if (typeof arguments[0] === 'function' || typeof arguments[1] === 'function' || typeof arguments[2] === 'function') {
2125
2126
  throw new MongooseError('Model.distinct() no longer accepts a callback');
2126
2127
  }
2127
2128
 
2128
2129
  const mq = new this.Query({}, {}, this, this.$__collection);
2130
+ if (options != null) {
2131
+ mq.setOptions(options);
2132
+ }
2129
2133
 
2130
2134
  return mq.distinct(field, conditions);
2131
2135
  };
package/lib/query.js CHANGED
@@ -2777,7 +2777,7 @@ Query.prototype.estimatedDocumentCount = function(options) {
2777
2777
  this.op = 'estimatedDocumentCount';
2778
2778
  this._validateOp();
2779
2779
 
2780
- if (typeof options === 'object' && options != null) {
2780
+ if (options != null) {
2781
2781
  this.setOptions(options);
2782
2782
  }
2783
2783
 
@@ -2836,7 +2836,7 @@ Query.prototype.countDocuments = function(conditions, options) {
2836
2836
  this.merge(conditions);
2837
2837
  }
2838
2838
 
2839
- if (typeof options === 'object' && options != null) {
2839
+ if (options != null) {
2840
2840
  this.setOptions(options);
2841
2841
  }
2842
2842
 
@@ -2874,21 +2874,24 @@ Query.prototype.__distinct = async function __distinct() {
2874
2874
  *
2875
2875
  * #### Example:
2876
2876
  *
2877
+ * distinct(field, conditions, options)
2877
2878
  * distinct(field, conditions)
2878
2879
  * distinct(field)
2879
2880
  * distinct()
2880
2881
  *
2881
2882
  * @param {String} [field]
2882
2883
  * @param {Object|Query} [filter]
2884
+ * @param {Object} [options]
2883
2885
  * @return {Query} this
2884
2886
  * @see distinct https://www.mongodb.com/docs/manual/reference/method/db.collection.distinct/
2885
2887
  * @api public
2886
2888
  */
2887
2889
 
2888
- Query.prototype.distinct = function(field, conditions) {
2890
+ Query.prototype.distinct = function(field, conditions, options) {
2889
2891
  if (typeof field === 'function' ||
2890
2892
  typeof conditions === 'function' ||
2891
- typeof arguments[2] === 'function') {
2893
+ typeof options === 'function' ||
2894
+ typeof arguments[3] === 'function') {
2892
2895
  throw new MongooseError('Query.prototype.distinct() no longer accepts a callback');
2893
2896
  }
2894
2897
 
@@ -2907,6 +2910,10 @@ Query.prototype.distinct = function(field, conditions) {
2907
2910
  this._distinct = field;
2908
2911
  }
2909
2912
 
2913
+ if (options != null) {
2914
+ this.setOptions(options);
2915
+ }
2916
+
2910
2917
  return this;
2911
2918
  };
2912
2919
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "mongoose",
3
3
  "description": "Mongoose MongoDB ODM",
4
- "version": "8.5.5",
4
+ "version": "8.6.0",
5
5
  "author": "Guillermo Rauch <guillermo@learnboost.com>",
6
6
  "keywords": [
7
7
  "mongodb",
@@ -21,7 +21,7 @@
21
21
  "dependencies": {
22
22
  "bson": "^6.7.0",
23
23
  "kareem": "2.6.3",
24
- "mongodb": "6.7.0",
24
+ "mongodb": "6.8.0",
25
25
  "mpath": "0.9.0",
26
26
  "mquery": "5.0.0",
27
27
  "ms": "2.1.3",
@@ -67,7 +67,7 @@
67
67
  "tsd": "0.31.1",
68
68
  "typescript": "5.5.4",
69
69
  "uuid": "10.0.0",
70
- "webpack": "5.93.0"
70
+ "webpack": "5.94.0"
71
71
  },
72
72
  "directories": {
73
73
  "lib": "./lib/mongoose"
@@ -22,7 +22,7 @@ declare module 'mongoose' {
22
22
  constructor(doc?: any);
23
23
 
24
24
  /** This documents _id. */
25
- _id?: T;
25
+ _id: T;
26
26
 
27
27
  /** This documents __v. */
28
28
  __v?: any;
@@ -259,11 +259,14 @@ declare module 'mongoose' {
259
259
  set(value: string | Record<string, any>): this;
260
260
 
261
261
  /** The return value of this method is used in calls to JSON.stringify(doc). */
262
+ toJSON(options?: ToObjectOptions & { flattenMaps?: true }): FlattenMaps<Require_id<DocType>>;
263
+ toJSON(options: ToObjectOptions & { flattenMaps: false }): Require_id<DocType>;
262
264
  toJSON<T = Require_id<DocType>>(options?: ToObjectOptions & { flattenMaps?: true }): FlattenMaps<T>;
263
265
  toJSON<T = Require_id<DocType>>(options: ToObjectOptions & { flattenMaps: false }): T;
264
266
 
265
267
  /** Converts this document into a plain-old JavaScript object ([POJO](https://masteringjs.io/tutorials/fundamentals/pojo)). */
266
- toObject<T = Require_id<DocType>>(options?: ToObjectOptions): Require_id<T>;
268
+ toObject(options?: ToObjectOptions): Require_id<DocType>;
269
+ toObject<T>(options?: ToObjectOptions): Require_id<T>;
267
270
 
268
271
  /** Clears the modified state on the specified path. */
269
272
  unmarkModified<T extends keyof DocType>(path: T): void;
@@ -1,4 +1,5 @@
1
1
  import {
2
+ IsPathRequired,
2
3
  IsSchemaTypeFromBuiltinClass,
3
4
  RequiredPaths,
4
5
  OptionalPaths,
@@ -14,7 +15,9 @@ declare module 'mongoose' {
14
15
  [
15
16
  K in keyof (RequiredPaths<DocDefinition, TSchemaOptions['typeKey']> &
16
17
  OptionalPaths<DocDefinition, TSchemaOptions['typeKey']>)
17
- ]: ObtainRawDocumentPathType<DocDefinition[K], TSchemaOptions['typeKey']>;
18
+ ]: IsPathRequired<DocDefinition[K], TSchemaOptions['typeKey']> extends true
19
+ ? ObtainRawDocumentPathType<DocDefinition[K], TSchemaOptions['typeKey']>
20
+ : ObtainRawDocumentPathType<DocDefinition[K], TSchemaOptions['typeKey']> | null;
18
21
  }, TSchemaOptions>;
19
22
 
20
23
  /**
package/types/models.d.ts CHANGED
@@ -188,7 +188,7 @@ declare module 'mongoose' {
188
188
 
189
189
  export interface ReplaceOneModel<TSchema = AnyObject> {
190
190
  /** The filter to limit the replaced document. */
191
- filter: FilterQuery<TSchema>;
191
+ filter: RootFilterQuery<TSchema>;
192
192
  /** The document with which to replace the matched document. */
193
193
  replacement: mongodb.WithoutId<TSchema>;
194
194
  /** Specifies a collation. */
@@ -203,7 +203,7 @@ declare module 'mongoose' {
203
203
 
204
204
  export interface UpdateOneModel<TSchema = AnyObject> {
205
205
  /** The filter to limit the updated documents. */
206
- filter: FilterQuery<TSchema>;
206
+ filter: RootFilterQuery<TSchema>;
207
207
  /** A document or pipeline containing update operators. */
208
208
  update: UpdateQuery<TSchema>;
209
209
  /** A set of filters specifying to which array elements an update should apply. */
@@ -220,7 +220,7 @@ declare module 'mongoose' {
220
220
 
221
221
  export interface UpdateManyModel<TSchema = AnyObject> {
222
222
  /** The filter to limit the updated documents. */
223
- filter: FilterQuery<TSchema>;
223
+ filter: RootFilterQuery<TSchema>;
224
224
  /** A document or pipeline containing update operators. */
225
225
  update: UpdateQuery<TSchema>;
226
226
  /** A set of filters specifying to which array elements an update should apply. */
@@ -237,7 +237,7 @@ declare module 'mongoose' {
237
237
 
238
238
  export interface DeleteOneModel<TSchema = AnyObject> {
239
239
  /** The filter to limit the deleted documents. */
240
- filter: FilterQuery<TSchema>;
240
+ filter: RootFilterQuery<TSchema>;
241
241
  /** Specifies a collation. */
242
242
  collation?: mongodb.CollationOptions;
243
243
  /** The index to use. If specified, then the query system will only consider plans using the hinted index. */
@@ -246,7 +246,7 @@ declare module 'mongoose' {
246
246
 
247
247
  export interface DeleteManyModel<TSchema = AnyObject> {
248
248
  /** The filter to limit the deleted documents. */
249
- filter: FilterQuery<TSchema>;
249
+ filter: RootFilterQuery<TSchema>;
250
250
  /** Specifies a collation. */
251
251
  collation?: mongodb.CollationOptions;
252
252
  /** The index to use. If specified, then the query system will only consider plans using the hinted index. */
@@ -318,7 +318,7 @@ declare module 'mongoose' {
318
318
 
319
319
  /** Creates a `countDocuments` query: counts the number of documents that match `filter`. */
320
320
  countDocuments(
321
- filter?: FilterQuery<TRawDocType>,
321
+ filter?: RootFilterQuery<TRawDocType>,
322
322
  options?: (mongodb.CountOptions & MongooseBaseQueryOptions<TRawDocType>) | null
323
323
  ): QueryWithHelpers<
324
324
  number,
@@ -357,7 +357,7 @@ declare module 'mongoose' {
357
357
  * regardless of the `single` option.
358
358
  */
359
359
  deleteMany(
360
- filter?: FilterQuery<TRawDocType>,
360
+ filter?: RootFilterQuery<TRawDocType>,
361
361
  options?: (mongodb.DeleteOptions & MongooseBaseQueryOptions<TRawDocType>) | null
362
362
  ): QueryWithHelpers<
363
363
  mongodb.DeleteResult,
@@ -368,7 +368,7 @@ declare module 'mongoose' {
368
368
  TInstanceMethods
369
369
  >;
370
370
  deleteMany(
371
- filter: FilterQuery<TRawDocType>
371
+ filter: RootFilterQuery<TRawDocType>
372
372
  ): QueryWithHelpers<
373
373
  mongodb.DeleteResult,
374
374
  THydratedDocumentType,
@@ -384,7 +384,7 @@ declare module 'mongoose' {
384
384
  * `single` option.
385
385
  */
386
386
  deleteOne(
387
- filter?: FilterQuery<TRawDocType>,
387
+ filter?: RootFilterQuery<TRawDocType>,
388
388
  options?: (mongodb.DeleteOptions & MongooseBaseQueryOptions<TRawDocType>) | null
389
389
  ): QueryWithHelpers<
390
390
  mongodb.DeleteResult,
@@ -395,7 +395,7 @@ declare module 'mongoose' {
395
395
  TInstanceMethods
396
396
  >;
397
397
  deleteOne(
398
- filter: FilterQuery<TRawDocType>
398
+ filter: RootFilterQuery<TRawDocType>
399
399
  ): QueryWithHelpers<
400
400
  mongodb.DeleteResult,
401
401
  THydratedDocumentType,
@@ -446,7 +446,7 @@ declare module 'mongoose' {
446
446
 
447
447
  /** Finds one document. */
448
448
  findOne<ResultDoc = THydratedDocumentType>(
449
- filter: FilterQuery<TRawDocType>,
449
+ filter: RootFilterQuery<TRawDocType>,
450
450
  projection: ProjectionType<TRawDocType> | null | undefined,
451
451
  options: QueryOptions<TRawDocType> & { lean: true }
452
452
  ): QueryWithHelpers<
@@ -458,16 +458,16 @@ declare module 'mongoose' {
458
458
  TInstanceMethods
459
459
  >;
460
460
  findOne<ResultDoc = THydratedDocumentType>(
461
- filter?: FilterQuery<TRawDocType>,
461
+ filter?: RootFilterQuery<TRawDocType>,
462
462
  projection?: ProjectionType<TRawDocType> | null,
463
463
  options?: QueryOptions<TRawDocType> | null
464
464
  ): QueryWithHelpers<ResultDoc | null, ResultDoc, TQueryHelpers, TRawDocType, 'findOne', TInstanceMethods>;
465
465
  findOne<ResultDoc = THydratedDocumentType>(
466
- filter?: FilterQuery<TRawDocType>,
466
+ filter?: RootFilterQuery<TRawDocType>,
467
467
  projection?: ProjectionType<TRawDocType> | null
468
468
  ): QueryWithHelpers<ResultDoc | null, ResultDoc, TQueryHelpers, TRawDocType, 'findOne', TInstanceMethods>;
469
469
  findOne<ResultDoc = THydratedDocumentType>(
470
- filter?: FilterQuery<TRawDocType>
470
+ filter?: RootFilterQuery<TRawDocType>
471
471
  ): QueryWithHelpers<ResultDoc | null, ResultDoc, TQueryHelpers, TRawDocType, 'findOne', TInstanceMethods>;
472
472
 
473
473
  /**
@@ -621,7 +621,8 @@ declare module 'mongoose' {
621
621
  /** Creates a `distinct` query: returns the distinct values of the given `field` that match `filter`. */
622
622
  distinct<DocKey extends string, ResultType = unknown>(
623
623
  field: DocKey,
624
- filter?: FilterQuery<TRawDocType>
624
+ filter?: RootFilterQuery<TRawDocType>,
625
+ options?: QueryOptions<TRawDocType>
625
626
  ): QueryWithHelpers<
626
627
  Array<
627
628
  DocKey extends keyof WithLevel1NestedPaths<TRawDocType>
@@ -650,7 +651,7 @@ declare module 'mongoose' {
650
651
  * the given `filter`, and `null` otherwise.
651
652
  */
652
653
  exists(
653
- filter: FilterQuery<TRawDocType>
654
+ filter: RootFilterQuery<TRawDocType>
654
655
  ): QueryWithHelpers<
655
656
  { _id: InferId<TRawDocType> } | null,
656
657
  THydratedDocumentType,
@@ -662,7 +663,7 @@ declare module 'mongoose' {
662
663
 
663
664
  /** Creates a `find` query: gets a list of documents that match `filter`. */
664
665
  find<ResultDoc = THydratedDocumentType>(
665
- filter: FilterQuery<TRawDocType>,
666
+ filter: RootFilterQuery<TRawDocType>,
666
667
  projection: ProjectionType<TRawDocType> | null | undefined,
667
668
  options: QueryOptions<TRawDocType> & { lean: true }
668
669
  ): QueryWithHelpers<
@@ -674,16 +675,16 @@ declare module 'mongoose' {
674
675
  TInstanceMethods
675
676
  >;
676
677
  find<ResultDoc = THydratedDocumentType>(
677
- filter: FilterQuery<TRawDocType>,
678
+ filter: RootFilterQuery<TRawDocType>,
678
679
  projection?: ProjectionType<TRawDocType> | null | undefined,
679
680
  options?: QueryOptions<TRawDocType> | null | undefined
680
681
  ): QueryWithHelpers<Array<ResultDoc>, ResultDoc, TQueryHelpers, TRawDocType, 'find', TInstanceMethods>;
681
682
  find<ResultDoc = THydratedDocumentType>(
682
- filter: FilterQuery<TRawDocType>,
683
+ filter: RootFilterQuery<TRawDocType>,
683
684
  projection?: ProjectionType<TRawDocType> | null | undefined
684
685
  ): QueryWithHelpers<Array<ResultDoc>, ResultDoc, TQueryHelpers, TRawDocType, 'find', TInstanceMethods>;
685
686
  find<ResultDoc = THydratedDocumentType>(
686
- filter: FilterQuery<TRawDocType>
687
+ filter: RootFilterQuery<TRawDocType>
687
688
  ): QueryWithHelpers<Array<ResultDoc>, ResultDoc, TQueryHelpers, TRawDocType, 'find', TInstanceMethods>;
688
689
  find<ResultDoc = THydratedDocumentType>(
689
690
  ): QueryWithHelpers<Array<ResultDoc>, ResultDoc, TQueryHelpers, TRawDocType, 'find', TInstanceMethods>;
@@ -711,7 +712,7 @@ declare module 'mongoose' {
711
712
 
712
713
  /** Creates a `findOneAndUpdate` query, filtering by the given `_id`. */
713
714
  findByIdAndUpdate<ResultDoc = THydratedDocumentType>(
714
- filter: FilterQuery<TRawDocType>,
715
+ filter: RootFilterQuery<TRawDocType>,
715
716
  update: UpdateQuery<TRawDocType>,
716
717
  options: QueryOptions<TRawDocType> & { includeResultMetadata: true, lean: true }
717
718
  ): QueryWithHelpers<
@@ -756,7 +757,7 @@ declare module 'mongoose' {
756
757
 
757
758
  /** Creates a `findOneAndDelete` query: atomically finds the given document, deletes it, and returns the document as it was before deletion. */
758
759
  findOneAndDelete<ResultDoc = THydratedDocumentType>(
759
- filter: FilterQuery<TRawDocType>,
760
+ filter: RootFilterQuery<TRawDocType>,
760
761
  options: QueryOptions<TRawDocType> & { lean: true }
761
762
  ): QueryWithHelpers<
762
763
  GetLeanResultType<TRawDocType, TRawDocType, 'findOneAndDelete'> | null,
@@ -767,17 +768,17 @@ declare module 'mongoose' {
767
768
  TInstanceMethods
768
769
  >;
769
770
  findOneAndDelete<ResultDoc = THydratedDocumentType>(
770
- filter: FilterQuery<TRawDocType>,
771
+ filter: RootFilterQuery<TRawDocType>,
771
772
  options: QueryOptions<TRawDocType> & { includeResultMetadata: true }
772
773
  ): QueryWithHelpers<ModifyResult<ResultDoc>, ResultDoc, TQueryHelpers, TRawDocType, 'findOneAndDelete', TInstanceMethods>;
773
774
  findOneAndDelete<ResultDoc = THydratedDocumentType>(
774
- filter?: FilterQuery<TRawDocType> | null,
775
+ filter?: RootFilterQuery<TRawDocType> | null,
775
776
  options?: QueryOptions<TRawDocType> | null
776
777
  ): QueryWithHelpers<ResultDoc | null, ResultDoc, TQueryHelpers, TRawDocType, 'findOneAndDelete', TInstanceMethods>;
777
778
 
778
779
  /** Creates a `findOneAndReplace` query: atomically finds the given document and replaces it with `replacement`. */
779
780
  findOneAndReplace<ResultDoc = THydratedDocumentType>(
780
- filter: FilterQuery<TRawDocType>,
781
+ filter: RootFilterQuery<TRawDocType>,
781
782
  replacement: TRawDocType | AnyObject,
782
783
  options: QueryOptions<TRawDocType> & { lean: true }
783
784
  ): QueryWithHelpers<
@@ -789,24 +790,24 @@ declare module 'mongoose' {
789
790
  TInstanceMethods
790
791
  >;
791
792
  findOneAndReplace<ResultDoc = THydratedDocumentType>(
792
- filter: FilterQuery<TRawDocType>,
793
+ filter: RootFilterQuery<TRawDocType>,
793
794
  replacement: TRawDocType | AnyObject,
794
795
  options: QueryOptions<TRawDocType> & { includeResultMetadata: true }
795
796
  ): QueryWithHelpers<ModifyResult<ResultDoc>, ResultDoc, TQueryHelpers, TRawDocType, 'findOneAndReplace', TInstanceMethods>;
796
797
  findOneAndReplace<ResultDoc = THydratedDocumentType>(
797
- filter: FilterQuery<TRawDocType>,
798
+ filter: RootFilterQuery<TRawDocType>,
798
799
  replacement: TRawDocType | AnyObject,
799
800
  options: QueryOptions<TRawDocType> & { upsert: true } & ReturnsNewDoc
800
801
  ): QueryWithHelpers<ResultDoc, ResultDoc, TQueryHelpers, TRawDocType, 'findOneAndReplace', TInstanceMethods>;
801
802
  findOneAndReplace<ResultDoc = THydratedDocumentType>(
802
- filter?: FilterQuery<TRawDocType>,
803
+ filter?: RootFilterQuery<TRawDocType>,
803
804
  replacement?: TRawDocType | AnyObject,
804
805
  options?: QueryOptions<TRawDocType> | null
805
806
  ): QueryWithHelpers<ResultDoc | null, ResultDoc, TQueryHelpers, TRawDocType, 'findOneAndReplace', TInstanceMethods>;
806
807
 
807
808
  /** Creates a `findOneAndUpdate` query: atomically find the first document that matches `filter` and apply `update`. */
808
809
  findOneAndUpdate<ResultDoc = THydratedDocumentType>(
809
- filter: FilterQuery<TRawDocType>,
810
+ filter: RootFilterQuery<TRawDocType>,
810
811
  update: UpdateQuery<TRawDocType>,
811
812
  options: QueryOptions<TRawDocType> & { includeResultMetadata: true, lean: true }
812
813
  ): QueryWithHelpers<
@@ -818,7 +819,7 @@ declare module 'mongoose' {
818
819
  TInstanceMethods
819
820
  >;
820
821
  findOneAndUpdate<ResultDoc = THydratedDocumentType>(
821
- filter: FilterQuery<TRawDocType>,
822
+ filter: RootFilterQuery<TRawDocType>,
822
823
  update: UpdateQuery<TRawDocType>,
823
824
  options: QueryOptions<TRawDocType> & { lean: true }
824
825
  ): QueryWithHelpers<
@@ -830,24 +831,24 @@ declare module 'mongoose' {
830
831
  TInstanceMethods
831
832
  >;
832
833
  findOneAndUpdate<ResultDoc = THydratedDocumentType>(
833
- filter: FilterQuery<TRawDocType>,
834
+ filter: RootFilterQuery<TRawDocType>,
834
835
  update: UpdateQuery<TRawDocType>,
835
836
  options: QueryOptions<TRawDocType> & { includeResultMetadata: true }
836
837
  ): QueryWithHelpers<ModifyResult<ResultDoc>, ResultDoc, TQueryHelpers, TRawDocType, 'findOneAndUpdate', TInstanceMethods>;
837
838
  findOneAndUpdate<ResultDoc = THydratedDocumentType>(
838
- filter: FilterQuery<TRawDocType>,
839
+ filter: RootFilterQuery<TRawDocType>,
839
840
  update: UpdateQuery<TRawDocType>,
840
841
  options: QueryOptions<TRawDocType> & { upsert: true } & ReturnsNewDoc
841
842
  ): QueryWithHelpers<ResultDoc, ResultDoc, TQueryHelpers, TRawDocType, 'findOneAndUpdate', TInstanceMethods>;
842
843
  findOneAndUpdate<ResultDoc = THydratedDocumentType>(
843
- filter?: FilterQuery<TRawDocType>,
844
+ filter?: RootFilterQuery<TRawDocType>,
844
845
  update?: UpdateQuery<TRawDocType>,
845
846
  options?: QueryOptions<TRawDocType> | null
846
847
  ): QueryWithHelpers<ResultDoc | null, ResultDoc, TQueryHelpers, TRawDocType, 'findOneAndUpdate', TInstanceMethods>;
847
848
 
848
849
  /** Creates a `replaceOne` query: finds the first document that matches `filter` and replaces it with `replacement`. */
849
850
  replaceOne<ResultDoc = THydratedDocumentType>(
850
- filter?: FilterQuery<TRawDocType>,
851
+ filter?: RootFilterQuery<TRawDocType>,
851
852
  replacement?: TRawDocType | AnyObject,
852
853
  options?: (mongodb.ReplaceOptions & MongooseQueryOptions<TRawDocType>) | null
853
854
  ): QueryWithHelpers<UpdateWriteOpResult, ResultDoc, TQueryHelpers, TRawDocType, 'replaceOne', TInstanceMethods>;
@@ -860,14 +861,14 @@ declare module 'mongoose' {
860
861
 
861
862
  /** Creates a `updateMany` query: updates all documents that match `filter` with `update`. */
862
863
  updateMany<ResultDoc = THydratedDocumentType>(
863
- filter?: FilterQuery<TRawDocType>,
864
+ filter?: RootFilterQuery<TRawDocType>,
864
865
  update?: UpdateQuery<TRawDocType> | UpdateWithAggregationPipeline,
865
866
  options?: (mongodb.UpdateOptions & MongooseUpdateQueryOptions<TRawDocType>) | null
866
867
  ): QueryWithHelpers<UpdateWriteOpResult, ResultDoc, TQueryHelpers, TRawDocType, 'updateMany', TInstanceMethods>;
867
868
 
868
869
  /** Creates a `updateOne` query: updates the first document that matches `filter` with `update`. */
869
870
  updateOne<ResultDoc = THydratedDocumentType>(
870
- filter?: FilterQuery<TRawDocType>,
871
+ filter?: RootFilterQuery<TRawDocType>,
871
872
  update?: UpdateQuery<TRawDocType> | UpdateWithAggregationPipeline,
872
873
  options?: (mongodb.UpdateOptions & MongooseUpdateQueryOptions<TRawDocType>) | null
873
874
  ): QueryWithHelpers<UpdateWriteOpResult, ResultDoc, TQueryHelpers, TRawDocType, 'updateOne', TInstanceMethods>;
package/types/query.d.ts CHANGED
@@ -10,9 +10,11 @@ declare module 'mongoose' {
10
10
  * { age: { $gte: 30 } }
11
11
  * ```
12
12
  */
13
- type FilterQuery<T> = {
13
+ type RootFilterQuery<T> = FilterQuery<T> | Query<any, any> | Types.ObjectId;
14
+
15
+ type FilterQuery<T> ={
14
16
  [P in keyof T]?: Condition<T[P]>;
15
- } & RootQuerySelector<T>;
17
+ } & RootQuerySelector<T> & { _id?: Condition<string>; };
16
18
 
17
19
  type MongooseBaseQueryOptionKeys =
18
20
  | 'context'
@@ -115,8 +117,9 @@ declare module 'mongoose' {
115
117
  /** @see https://www.mongodb.com/docs/manual/reference/operator/query/comment/#op._S_comment */
116
118
  $comment?: string;
117
119
  // we could not find a proper TypeScript generic to support nested queries e.g. 'user.friends.name'
118
- // this will mark all unrecognized properties as any (including nested queries)
119
- [key: string]: any;
120
+ // this will mark all unrecognized properties as any (including nested queries) only if
121
+ // they include a "." (to avoid generically allowing any unexpected keys)
122
+ [nestedSelector: `${string}.${string}`]: any;
120
123
  };
121
124
 
122
125
  interface QueryTimestampsConfig {
@@ -224,7 +227,7 @@ declare module 'mongoose' {
224
227
  : MergeType<ResultType, Paths>
225
228
  : MergeType<ResultType, Paths>;
226
229
 
227
- class Query<ResultType, DocType, THelpers = {}, RawDocType = DocType, QueryOp = 'find', TInstanceMethods = Record<string, never>> implements SessionOperation {
230
+ class Query<ResultType, DocType, THelpers = {}, RawDocType = unknown, QueryOp = 'find', TInstanceMethods = Record<string, never>> implements SessionOperation {
228
231
  _mongooseOptions: MongooseQueryOptions<DocType>;
229
232
 
230
233
  /**
@@ -303,7 +306,7 @@ declare module 'mongoose' {
303
306
 
304
307
  /** Specifies this query as a `countDocuments` query. */
305
308
  countDocuments(
306
- criteria?: FilterQuery<RawDocType>,
309
+ criteria?: RootFilterQuery<RawDocType>,
307
310
  options?: QueryOptions<DocType>
308
311
  ): QueryWithHelpers<number, DocType, THelpers, RawDocType, 'countDocuments', TInstanceMethods>;
309
312
 
@@ -319,10 +322,10 @@ declare module 'mongoose' {
319
322
  * collection, regardless of the value of `single`.
320
323
  */
321
324
  deleteMany(
322
- filter?: FilterQuery<RawDocType>,
325
+ filter?: RootFilterQuery<RawDocType>,
323
326
  options?: QueryOptions<DocType>
324
327
  ): QueryWithHelpers<any, DocType, THelpers, RawDocType, 'deleteMany', TInstanceMethods>;
325
- deleteMany(filter: FilterQuery<RawDocType>): QueryWithHelpers<
328
+ deleteMany(filter: RootFilterQuery<RawDocType>): QueryWithHelpers<
326
329
  any,
327
330
  DocType,
328
331
  THelpers,
@@ -338,10 +341,10 @@ declare module 'mongoose' {
338
341
  * option.
339
342
  */
340
343
  deleteOne(
341
- filter?: FilterQuery<RawDocType>,
344
+ filter?: RootFilterQuery<RawDocType>,
342
345
  options?: QueryOptions<DocType>
343
346
  ): QueryWithHelpers<any, DocType, THelpers, RawDocType, 'deleteOne', TInstanceMethods>;
344
- deleteOne(filter: FilterQuery<RawDocType>): QueryWithHelpers<
347
+ deleteOne(filter: RootFilterQuery<RawDocType>): QueryWithHelpers<
345
348
  any,
346
349
  DocType,
347
350
  THelpers,
@@ -354,7 +357,8 @@ declare module 'mongoose' {
354
357
  /** Creates a `distinct` query: returns the distinct values of the given `field` that match `filter`. */
355
358
  distinct<DocKey extends string, ResultType = unknown>(
356
359
  field: DocKey,
357
- filter?: FilterQuery<RawDocType>
360
+ filter?: RootFilterQuery<RawDocType>,
361
+ options?: QueryOptions<DocType>
358
362
  ): QueryWithHelpers<
359
363
  Array<
360
364
  DocKey extends keyof WithLevel1NestedPaths<DocType>
@@ -406,52 +410,52 @@ declare module 'mongoose' {
406
410
 
407
411
  /** Creates a `find` query: gets a list of documents that match `filter`. */
408
412
  find(
409
- filter: FilterQuery<RawDocType>,
413
+ filter: RootFilterQuery<RawDocType>,
410
414
  projection?: ProjectionType<RawDocType> | null,
411
415
  options?: QueryOptions<DocType> | null
412
416
  ): QueryWithHelpers<Array<DocType>, DocType, THelpers, RawDocType, 'find', TInstanceMethods>;
413
417
  find(
414
- filter: FilterQuery<RawDocType>,
418
+ filter: RootFilterQuery<RawDocType>,
415
419
  projection?: ProjectionType<RawDocType> | null
416
420
  ): QueryWithHelpers<Array<DocType>, DocType, THelpers, RawDocType, 'find', TInstanceMethods>;
417
421
  find(
418
- filter: FilterQuery<RawDocType>
422
+ filter: RootFilterQuery<RawDocType>
419
423
  ): QueryWithHelpers<Array<DocType>, DocType, THelpers, RawDocType, 'find', TInstanceMethods>;
420
424
  find(): QueryWithHelpers<Array<DocType>, DocType, THelpers, RawDocType, 'find', TInstanceMethods>;
421
425
 
422
426
  /** Declares the query a findOne operation. When executed, returns the first found document. */
423
427
  findOne(
424
- filter?: FilterQuery<RawDocType>,
428
+ filter?: RootFilterQuery<RawDocType>,
425
429
  projection?: ProjectionType<RawDocType> | null,
426
430
  options?: QueryOptions<DocType> | null
427
431
  ): QueryWithHelpers<DocType | null, DocType, THelpers, RawDocType, 'findOne', TInstanceMethods>;
428
432
  findOne(
429
- filter?: FilterQuery<RawDocType>,
433
+ filter?: RootFilterQuery<RawDocType>,
430
434
  projection?: ProjectionType<RawDocType> | null
431
435
  ): QueryWithHelpers<DocType | null, DocType, THelpers, RawDocType, 'findOne', TInstanceMethods>;
432
436
  findOne(
433
- filter?: FilterQuery<RawDocType>
437
+ filter?: RootFilterQuery<RawDocType>
434
438
  ): QueryWithHelpers<DocType | null, DocType, THelpers, RawDocType, 'findOne', TInstanceMethods>;
435
439
 
436
440
  /** Creates a `findOneAndDelete` query: atomically finds the given document, deletes it, and returns the document as it was before deletion. */
437
441
  findOneAndDelete(
438
- filter?: FilterQuery<RawDocType>,
442
+ filter?: RootFilterQuery<RawDocType>,
439
443
  options?: QueryOptions<DocType> | null
440
444
  ): QueryWithHelpers<DocType | null, DocType, THelpers, RawDocType, 'findOneAndDelete'>;
441
445
 
442
446
  /** Creates a `findOneAndUpdate` query: atomically find the first document that matches `filter` and apply `update`. */
443
447
  findOneAndUpdate(
444
- filter: FilterQuery<RawDocType>,
448
+ filter: RootFilterQuery<RawDocType>,
445
449
  update: UpdateQuery<RawDocType>,
446
450
  options: QueryOptions<DocType> & { includeResultMetadata: true }
447
451
  ): QueryWithHelpers<ModifyResult<DocType>, DocType, THelpers, RawDocType, 'findOneAndUpdate', TInstanceMethods>;
448
452
  findOneAndUpdate(
449
- filter: FilterQuery<RawDocType>,
453
+ filter: RootFilterQuery<RawDocType>,
450
454
  update: UpdateQuery<RawDocType>,
451
455
  options: QueryOptions<DocType> & { upsert: true } & ReturnsNewDoc
452
456
  ): QueryWithHelpers<DocType, DocType, THelpers, RawDocType, 'findOneAndUpdate', TInstanceMethods>;
453
457
  findOneAndUpdate(
454
- filter?: FilterQuery<RawDocType>,
458
+ filter?: RootFilterQuery<RawDocType>,
455
459
  update?: UpdateQuery<RawDocType>,
456
460
  options?: QueryOptions<DocType> | null
457
461
  ): QueryWithHelpers<DocType | null, DocType, THelpers, RawDocType, 'findOneAndUpdate', TInstanceMethods>;
@@ -548,9 +552,19 @@ declare module 'mongoose' {
548
552
  j(val: boolean | null): this;
549
553
 
550
554
  /** Sets the lean option. */
551
- lean<
552
- LeanResultType = GetLeanResultType<RawDocType, ResultType, QueryOp>
553
- >(
555
+ lean(
556
+ val?: boolean | any
557
+ ): QueryWithHelpers<
558
+ ResultType extends null
559
+ ? GetLeanResultType<RawDocType, ResultType, QueryOp> | null
560
+ : GetLeanResultType<RawDocType, ResultType, QueryOp>,
561
+ DocType,
562
+ THelpers,
563
+ RawDocType,
564
+ QueryOp,
565
+ TInstanceMethods
566
+ >;
567
+ lean<LeanResultType>(
554
568
  val?: boolean | any
555
569
  ): QueryWithHelpers<
556
570
  ResultType extends null
@@ -592,7 +606,7 @@ declare module 'mongoose' {
592
606
  maxTimeMS(ms: number): this;
593
607
 
594
608
  /** Merges another Query or conditions object into this one. */
595
- merge(source: Query<any, any> | FilterQuery<RawDocType>): this;
609
+ merge(source: RootFilterQuery<RawDocType>): this;
596
610
 
597
611
  /** Specifies a `$mod` condition, filters documents for documents whose `path` property is a number that is equal to `remainder` modulo `divisor`. */
598
612
  mod<K = string>(path: K, val: number): this;
@@ -711,7 +725,7 @@ declare module 'mongoose' {
711
725
  * not accept any [atomic](https://www.mongodb.com/docs/manual/tutorial/model-data-for-atomic-operations/#pattern) operators (`$set`, etc.)
712
726
  */
713
727
  replaceOne(
714
- filter?: FilterQuery<RawDocType>,
728
+ filter?: RootFilterQuery<RawDocType>,
715
729
  replacement?: DocType | AnyObject,
716
730
  options?: QueryOptions<DocType> | null
717
731
  ): QueryWithHelpers<any, DocType, THelpers, RawDocType, 'replaceOne', TInstanceMethods>;
@@ -819,7 +833,7 @@ declare module 'mongoose' {
819
833
  * the `multi` option.
820
834
  */
821
835
  updateMany(
822
- filter?: FilterQuery<RawDocType>,
836
+ filter?: RootFilterQuery<RawDocType>,
823
837
  update?: UpdateQuery<RawDocType> | UpdateWithAggregationPipeline,
824
838
  options?: QueryOptions<DocType> | null
825
839
  ): QueryWithHelpers<UpdateWriteOpResult, DocType, THelpers, RawDocType, 'updateMany', TInstanceMethods>;
@@ -829,7 +843,7 @@ declare module 'mongoose' {
829
843
  * `update()`, except it does not support the `multi` or `overwrite` options.
830
844
  */
831
845
  updateOne(
832
- filter?: FilterQuery<RawDocType>,
846
+ filter?: RootFilterQuery<RawDocType>,
833
847
  update?: UpdateQuery<RawDocType> | UpdateWithAggregationPipeline,
834
848
  options?: QueryOptions<DocType> | null
835
849
  ): QueryWithHelpers<UpdateWriteOpResult, DocType, THelpers, RawDocType, 'updateOne', TInstanceMethods>;