mongoose 8.19.0 → 8.19.2

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/connection.js CHANGED
@@ -28,6 +28,10 @@ const decorateBulkWriteResult = require('./helpers/model/decorateBulkWriteResult
28
28
  const arrayAtomicsSymbol = require('./helpers/symbols').arrayAtomicsSymbol;
29
29
  const sessionNewDocuments = require('./helpers/symbols').sessionNewDocuments;
30
30
 
31
+ // Snapshot the native Date constructor to ensure both Date.now() and new Date() (and other Date methods)
32
+ // bypass timer mocks such as those set up by useFakeTimers().
33
+ const Date = globalThis.Date;
34
+
31
35
  /**
32
36
  * A list of authentication mechanisms that don't require a password for authentication.
33
37
  * This is used by the authMechanismDoesNotRequirePassword method.
@@ -379,8 +379,13 @@ function walkUpdatePath(schema, obj, op, options, context, filter, prefix) {
379
379
  (utils.isObject(val) && Object.keys(val).length === 0);
380
380
  }
381
381
  } else {
382
- const checkPath = (key === '$each' || key === '$or' || key === '$and' || key === '$in') ?
383
- prefix : prefix + key;
382
+ const isModifier = (key === '$each' || key === '$or' || key === '$and' || key === '$in');
383
+ if (isModifier && !prefix) {
384
+ throw new MongooseError('Invalid update: Unexpected modifier "' + key + '" as a key in operator. '
385
+ + 'Did you mean something like { $addToSet: { fieldName: { $each: [...] } } }? '
386
+ + 'Modifiers such as "$each", "$or", "$and", "$in" must appear under a valid field path.');
387
+ }
388
+ const checkPath = isModifier ? prefix : prefix + key;
384
389
  schematype = schema._getSchema(checkPath);
385
390
 
386
391
  // You can use `$setOnInsert` with immutable keys
@@ -1,5 +1,4 @@
1
1
  'use strict';
2
- const modifiedPaths = require('./common').modifiedPaths;
3
2
  const get = require('./get');
4
3
 
5
4
  /**
@@ -29,21 +28,16 @@ module.exports = function(filter, schema, castedDoc, options) {
29
28
  const updatedKeys = {};
30
29
  const updatedValues = {};
31
30
  const numKeys = keys.length;
32
- const modified = {};
33
31
 
34
32
  let hasDollarUpdate = false;
35
33
 
36
34
  for (let i = 0; i < numKeys; ++i) {
37
- if (keys[i].startsWith('$')) {
38
- modifiedPaths(castedDoc[keys[i]], '', modified);
35
+ if (keys[i].charAt(0) === '$') {
39
36
  hasDollarUpdate = true;
37
+ break;
40
38
  }
41
39
  }
42
40
 
43
- if (!hasDollarUpdate) {
44
- modifiedPaths(castedDoc, '', modified);
45
- }
46
-
47
41
  const paths = Object.keys(filter);
48
42
  const numPaths = paths.length;
49
43
  for (let i = 0; i < numPaths; ++i) {
@@ -54,7 +48,7 @@ module.exports = function(filter, schema, castedDoc, options) {
54
48
  const numConditionKeys = conditionKeys.length;
55
49
  let hasDollarKey = false;
56
50
  for (let j = 0; j < numConditionKeys; ++j) {
57
- if (conditionKeys[j].startsWith('$')) {
51
+ if (conditionKeys[j].charAt(0) === '$') {
58
52
  hasDollarKey = true;
59
53
  break;
60
54
  }
@@ -64,7 +58,6 @@ module.exports = function(filter, schema, castedDoc, options) {
64
58
  }
65
59
  }
66
60
  updatedKeys[path] = true;
67
- modified[path] = true;
68
61
  }
69
62
 
70
63
  if (options && options.overwrite && !hasDollarUpdate) {
@@ -79,16 +72,17 @@ module.exports = function(filter, schema, castedDoc, options) {
79
72
  return;
80
73
  }
81
74
  const def = schemaType.getDefault(null, true);
82
- if (isModified(modified, path)) {
83
- return;
84
- }
85
75
  if (typeof def === 'undefined') {
86
76
  return;
87
77
  }
88
- if (schemaType.splitPath().includes('$*')) {
78
+ const pathPieces = schemaType.splitPath();
79
+ if (pathPieces.includes('$*')) {
89
80
  // Skip defaults underneath maps. We should never do `$setOnInsert` on a path with `$*`
90
81
  return;
91
82
  }
83
+ if (isModified(castedDoc, updatedKeys, path, pathPieces, hasDollarUpdate)) {
84
+ return;
85
+ }
92
86
 
93
87
  castedDoc = castedDoc || {};
94
88
  castedDoc.$setOnInsert = castedDoc.$setOnInsert || {};
@@ -101,31 +95,66 @@ module.exports = function(filter, schema, castedDoc, options) {
101
95
  return castedDoc;
102
96
  };
103
97
 
104
- function isModified(modified, path) {
105
- if (modified[path]) {
98
+ function isModified(castedDoc, updatedKeys, path, pathPieces, hasDollarUpdate) {
99
+ // Check if path is in filter (updatedKeys)
100
+ if (updatedKeys[path]) {
106
101
  return true;
107
102
  }
108
103
 
109
- // Is any parent path of `path` modified?
110
- const sp = path.split('.');
111
- let cur = sp[0];
112
- for (let i = 1; i < sp.length; ++i) {
113
- if (modified[cur]) {
104
+ // Check if any parent path is in filter
105
+ let cur = pathPieces[0];
106
+ for (let i = 1; i < pathPieces.length; ++i) {
107
+ if (updatedKeys[cur]) {
114
108
  return true;
115
109
  }
116
- cur += '.' + sp[i];
110
+ cur += '.' + pathPieces[i];
117
111
  }
118
112
 
119
- // Is any child of `path` modified?
120
- const modifiedKeys = Object.keys(modified);
121
- if (modifiedKeys.length) {
122
- const parentPath = path + '.';
123
-
124
- for (const modifiedPath of modifiedKeys) {
125
- if (modifiedPath.slice(0, path.length + 1) === parentPath) {
126
- return true;
113
+ // Check if path is modified in the update
114
+ if (hasDollarUpdate) {
115
+ // Check each update operator
116
+ for (const key in castedDoc) {
117
+ if (key.charAt(0) === '$') {
118
+ if (pathExistsInUpdate(castedDoc[key], path, pathPieces)) {
119
+ return true;
120
+ }
127
121
  }
128
122
  }
123
+ } else {
124
+ // No dollar operators, check the castedDoc directly
125
+ if (pathExistsInUpdate(castedDoc, path, pathPieces)) {
126
+ return true;
127
+ }
128
+ }
129
+
130
+ return false;
131
+ }
132
+
133
+ function pathExistsInUpdate(update, targetPath, pathPieces) {
134
+ if (update == null || typeof update !== 'object') {
135
+ return false;
136
+ }
137
+
138
+ // Check exact match
139
+ if (update.hasOwnProperty(targetPath)) {
140
+ return true;
141
+ }
142
+
143
+ // Check if any parent path exists
144
+ let cur = pathPieces[0];
145
+ for (let i = 1; i < pathPieces.length; ++i) {
146
+ if (update.hasOwnProperty(cur)) {
147
+ return true;
148
+ }
149
+ cur += '.' + pathPieces[i];
150
+ }
151
+
152
+ // Check if any child path exists (e.g., path is "a" and update has "a.b")
153
+ const prefix = targetPath + '.';
154
+ for (const key in update) {
155
+ if (key.startsWith(prefix)) {
156
+ return true;
157
+ }
129
158
  }
130
159
 
131
160
  return false;
@@ -7,6 +7,9 @@ const updatedPathsByArrayFilter = require('./updatedPathsByArrayFilter');
7
7
 
8
8
  module.exports = function castArrayFilters(query) {
9
9
  const arrayFilters = query.options.arrayFilters;
10
+ if (!Array.isArray(arrayFilters)) {
11
+ return;
12
+ }
10
13
  const update = query.getUpdate();
11
14
  const schema = query.schema;
12
15
  const updatedPathsByFilter = updatedPathsByArrayFilter(update);
@@ -29,10 +32,6 @@ module.exports = function castArrayFilters(query) {
29
32
  };
30
33
 
31
34
  function _castArrayFilters(arrayFilters, schema, strictQuery, updatedPathsByFilter, query) {
32
- if (!Array.isArray(arrayFilters)) {
33
- return;
34
- }
35
-
36
35
  // Map to store discriminator values for embedded documents in the array filters.
37
36
  // This is used to handle cases where array filters target specific embedded document types.
38
37
  const discriminatorValueMap = {};
@@ -1,7 +1,5 @@
1
1
  'use strict';
2
2
 
3
- const modifiedPaths = require('./modifiedPaths');
4
-
5
3
  /**
6
4
  * Decorate the update with a version key, if necessary
7
5
  * @api private
@@ -12,15 +10,26 @@ module.exports = function decorateUpdateWithVersionKey(update, options, versionK
12
10
  return;
13
11
  }
14
12
 
15
- const updatedPaths = modifiedPaths(update);
16
- if (!updatedPaths[versionKey]) {
17
- if (options.overwrite) {
13
+ if (options.overwrite) {
14
+ if (!hasKey(update, versionKey)) {
18
15
  update[versionKey] = 0;
19
- } else {
20
- if (!update.$setOnInsert) {
21
- update.$setOnInsert = {};
22
- }
23
- update.$setOnInsert[versionKey] = 0;
24
16
  }
17
+ } else if (
18
+ !hasKey(update, versionKey) &&
19
+ !hasKey(update?.$set, versionKey) &&
20
+ !hasKey(update?.$inc, versionKey) &&
21
+ !hasKey(update?.$setOnInsert, versionKey)
22
+ ) {
23
+ if (!update.$setOnInsert) {
24
+ update.$setOnInsert = {};
25
+ }
26
+ update.$setOnInsert[versionKey] = 0;
25
27
  }
26
28
  };
29
+
30
+ function hasKey(obj, key) {
31
+ if (obj == null || typeof obj !== 'object') {
32
+ return false;
33
+ }
34
+ return Object.prototype.hasOwnProperty.call(obj, key);
35
+ }
@@ -7,7 +7,6 @@
7
7
  const ValidationError = require('../error/validation');
8
8
  const cleanPositionalOperators = require('./schema/cleanPositionalOperators');
9
9
  const flatten = require('./common').flatten;
10
- const modifiedPaths = require('./common').modifiedPaths;
11
10
 
12
11
  /**
13
12
  * Applies validators and defaults to update and findOneAndUpdate operations,
@@ -29,7 +28,6 @@ module.exports = function(query, schema, castedDoc, options, callback) {
29
28
  const arrayAtomicUpdates = {};
30
29
  const numKeys = keys.length;
31
30
  let hasDollarUpdate = false;
32
- const modified = {};
33
31
  let currentUpdate;
34
32
  let key;
35
33
  let i;
@@ -51,7 +49,6 @@ module.exports = function(query, schema, castedDoc, options, callback) {
51
49
  }
52
50
  continue;
53
51
  }
54
- modifiedPaths(castedDoc[keys[i]], '', modified);
55
52
  const flat = flatten(castedDoc[keys[i]], null, null, schema);
56
53
  const paths = Object.keys(flat);
57
54
  const numPaths = paths.length;
@@ -76,7 +73,6 @@ module.exports = function(query, schema, castedDoc, options, callback) {
76
73
  }
77
74
 
78
75
  if (!hasDollarUpdate) {
79
- modifiedPaths(castedDoc, '', modified);
80
76
  updatedValues = flatten(castedDoc, null, null, schema);
81
77
  updatedKeys = Object.keys(updatedValues);
82
78
  }
package/lib/schema/map.js CHANGED
@@ -28,10 +28,14 @@ class SchemaMap extends SchemaType {
28
28
  return val;
29
29
  }
30
30
 
31
- const path = options?.path ?? this.path;
31
+ const path = this.path;
32
32
 
33
33
  if (init) {
34
- const map = new MongooseMap({}, path, doc, this.$__schemaType);
34
+ const map = new MongooseMap({}, path, doc, this.$__schemaType, options);
35
+
36
+ // Use the map's path for passing to nested casts.
37
+ // If map's parent is a subdocument, use the relative path so nested casts get relative paths.
38
+ const mapPath = map.$__pathRelativeToParent != null ? map.$__pathRelativeToParent : map.$__path;
35
39
 
36
40
  if (val instanceof global.Map) {
37
41
  for (const key of val.keys()) {
@@ -39,7 +43,7 @@ class SchemaMap extends SchemaType {
39
43
  if (_val == null) {
40
44
  _val = map.$__schemaType._castNullish(_val);
41
45
  } else {
42
- _val = map.$__schemaType.cast(_val, doc, true, null, { ...options, path: path + '.' + key });
46
+ _val = map.$__schemaType.cast(_val, doc, true, null, { ...options, path: mapPath + '.' + key });
43
47
  }
44
48
  map.$init(key, _val);
45
49
  }
@@ -49,7 +53,7 @@ class SchemaMap extends SchemaType {
49
53
  if (_val == null) {
50
54
  _val = map.$__schemaType._castNullish(_val);
51
55
  } else {
52
- _val = map.$__schemaType.cast(_val, doc, true, null, { ...options, path: path + '.' + key });
56
+ _val = map.$__schemaType.cast(_val, doc, true, null, { ...options, path: mapPath + '.' + key });
53
57
  }
54
58
  map.$init(key, _val);
55
59
  }
@@ -58,7 +62,7 @@ class SchemaMap extends SchemaType {
58
62
  return map;
59
63
  }
60
64
 
61
- return new MongooseMap(val, path, doc, this.$__schemaType);
65
+ return new MongooseMap(val, path, doc, this.$__schemaType, options);
62
66
  }
63
67
 
64
68
  clone() {
@@ -203,6 +203,13 @@ SchemaSubdocument.prototype.cast = function(val, doc, init, priorVal, options) {
203
203
  if (init) {
204
204
  subdoc = new Constructor(void 0, selected, doc, false, { defaults: false });
205
205
  delete subdoc.$__.defaults;
206
+ // Don't pass `path` to $init - it's only for the subdocument itself, not its fields.
207
+ // For change tracking, subdocuments use relative paths internally.
208
+ // Here, `options.path` contains the absolute path and is only used by the subdocument constructor, not by $init.
209
+ if (options.path != null) {
210
+ options = { ...options };
211
+ delete options.path;
212
+ }
206
213
  subdoc.$init(val, options);
207
214
  const exclude = isExclusive(selected);
208
215
  applyDefaults(subdoc, selected, exclude);
package/lib/schemaType.js CHANGED
@@ -1174,6 +1174,9 @@ SchemaType.prototype.ref = function(ref) {
1174
1174
 
1175
1175
  SchemaType.prototype.getDefault = function(scope, init, options) {
1176
1176
  let ret;
1177
+ if (this.defaultValue == null) {
1178
+ return this.defaultValue;
1179
+ }
1177
1180
  if (typeof this.defaultValue === 'function') {
1178
1181
  if (
1179
1182
  this.defaultValue === Date.now ||
@@ -611,7 +611,7 @@ const methods = {
611
611
 
612
612
  pull() {
613
613
  const values = [].map.call(arguments, (v, i) => this._cast(v, i, { defaults: false }), this);
614
- let cur = this[arrayParentSymbol].get(this[arrayPathSymbol]);
614
+ let cur = this;
615
615
  if (utils.isMongooseArray(cur)) {
616
616
  cur = cur.__array;
617
617
  }
package/lib/types/map.js CHANGED
@@ -18,13 +18,29 @@ const populateModelSymbol = require('../helpers/symbols').populateModelSymbol;
18
18
  */
19
19
 
20
20
  class MongooseMap extends Map {
21
- constructor(v, path, doc, schemaType) {
21
+ constructor(v, path, doc, schemaType, options) {
22
22
  if (getConstructorName(v) === 'Object') {
23
23
  v = Object.keys(v).reduce((arr, key) => arr.concat([[key, v[key]]]), []);
24
24
  }
25
25
  super(v);
26
26
  this.$__parent = doc != null && doc.$__ != null ? doc : null;
27
- this.$__path = path;
27
+
28
+ // Calculate the full path from the root document
29
+ // Priority: parent.$basePath (from subdoc) > options.path (from parent map/structure) > path (schema path)
30
+ // Subdocuments have the most up-to-date path info, so prefer that over options.path
31
+ if (this.$__parent?.$isSingleNested && this.$__parent.$basePath) {
32
+ this.$__path = this.$__parent.$basePath + '.' + path;
33
+ // Performance optimization: store path relative to parent subdocument
34
+ // to avoid string operations in set() hot path
35
+ this.$__pathRelativeToParent = path;
36
+ } else if (options?.path) {
37
+ this.$__path = options.path;
38
+ this.$__pathRelativeToParent = null;
39
+ } else {
40
+ this.$__path = path;
41
+ this.$__pathRelativeToParent = null;
42
+ }
43
+
28
44
  this.$__schemaType = schemaType == null ? new Mixed(path) : schemaType;
29
45
 
30
46
  this.$__runDeferred();
@@ -37,6 +53,14 @@ class MongooseMap extends Map {
37
53
 
38
54
  if (value != null && value.$isSingleNested) {
39
55
  value.$basePath = this.$__path + '.' + key;
56
+ // Store the path relative to parent subdoc for efficient markModified()
57
+ if (this.$__pathRelativeToParent != null) {
58
+ // Map's parent is a subdocument, store path relative to that subdoc
59
+ value.$pathRelativeToParent = this.$__pathRelativeToParent + '.' + key;
60
+ } else {
61
+ // Map's parent is root document, store the full path
62
+ value.$pathRelativeToParent = this.$__path + '.' + key;
63
+ }
40
64
  }
41
65
  }
42
66
 
@@ -136,9 +160,16 @@ class MongooseMap extends Map {
136
160
  }
137
161
  } else {
138
162
  try {
139
- const options = this.$__schemaType.$isMongooseDocumentArray || this.$__schemaType.$isSingleNested || this.$__schemaType.$isMongooseArray || this.$__schemaType.$isSchemaMap ?
140
- { path: fullPath.call(this) } :
141
- null;
163
+ let options = null;
164
+ if (this.$__schemaType.$isMongooseDocumentArray || this.$__schemaType.$isSingleNested || this.$__schemaType.$isMongooseArray || this.$__schemaType.$isSchemaMap) {
165
+ options = { path: fullPath.call(this) };
166
+ // For subdocuments, also pass the relative path to avoid string operations
167
+ if (this.$__schemaType.$isSingleNested) {
168
+ options.pathRelativeToParent = this.$__pathRelativeToParent != null ?
169
+ this.$__pathRelativeToParent + '.' + key :
170
+ this.$__path + '.' + key;
171
+ }
172
+ }
142
173
  value = this.$__schemaType.applySetters(
143
174
  value,
144
175
  this.$__parent,
@@ -157,13 +188,34 @@ class MongooseMap extends Map {
157
188
 
158
189
  super.set(key, value);
159
190
 
191
+ // Set relative path on subdocuments to avoid string operations in markModified()
192
+ // The path should be relative to the parent subdocument (if any), not just the key
193
+ if (value != null && value.$isSingleNested) {
194
+ if (this.$__pathRelativeToParent != null) {
195
+ // Map's parent is a subdocument, store path relative to that subdoc (e.g., 'items.i2')
196
+ value.$pathRelativeToParent = this.$__pathRelativeToParent + '.' + key;
197
+ } else {
198
+ // Map's parent is root document, store just the full path
199
+ value.$pathRelativeToParent = this.$__path + '.' + key;
200
+ }
201
+ }
202
+
160
203
  if (parent != null && parent.$__ != null && !deepEqual(value, priorVal)) {
161
- const path = fullPath.call(this);
162
- parent.markModified(path);
204
+ // Optimization: if parent is a subdocument, use precalculated relative path
205
+ // to avoid building a full path just to strip the parent's prefix
206
+ let pathToMark;
207
+ if (this.$__pathRelativeToParent != null) {
208
+ // Parent is a subdocument - use precalculated relative path (e.g., 'items.i1')
209
+ pathToMark = this.$__pathRelativeToParent + '.' + key;
210
+ } else {
211
+ // Parent is root document or map - use full path
212
+ pathToMark = fullPath.call(this);
213
+ }
214
+ parent.markModified(pathToMark);
163
215
  // If overwriting the full document array or subdoc, make sure to clean up any paths that were modified
164
216
  // before re: #15108
165
217
  if (this.$__schemaType.$isMongooseDocumentArray || this.$__schemaType.$isSingleNested) {
166
- cleanModifiedSubpaths(parent, path);
218
+ cleanModifiedSubpaths(parent, pathToMark);
167
219
  }
168
220
  }
169
221
 
@@ -31,7 +31,21 @@ function Subdocument(value, fields, parent, skipId, options) {
31
31
  if (options != null && options.path != null) {
32
32
  this.$basePath = options.path;
33
33
  }
34
- Document.call(this, value, fields, skipId, options);
34
+ if (options != null && options.pathRelativeToParent != null) {
35
+ this.$pathRelativeToParent = options.pathRelativeToParent;
36
+ }
37
+
38
+ // Don't pass `path` to Document constructor: path is used for storing the
39
+ // absolute path to this schematype relative to the top-level document, but
40
+ // subdocuments use relative paths (relative to the parent document) to track changes.
41
+ // This avoids the subdocument's fields receiving the subdocument's path as options.path.
42
+ let documentOptions = options;
43
+ if (options != null && options.path != null) {
44
+ documentOptions = Object.assign({}, options);
45
+ delete documentOptions.path;
46
+ }
47
+
48
+ Document.call(this, value, fields, skipId, documentOptions);
35
49
 
36
50
  delete this.$__.priorDoc;
37
51
  }
@@ -123,9 +137,18 @@ Subdocument.prototype.$__fullPath = function(path) {
123
137
  */
124
138
 
125
139
  Subdocument.prototype.$__pathRelativeToParent = function(p) {
140
+ // If this subdocument has a stored relative path (set by map when subdoc is created),
141
+ // use it directly to avoid string operations
142
+ if (this.$pathRelativeToParent != null) {
143
+ return p == null ? this.$pathRelativeToParent : this.$pathRelativeToParent + '.' + p;
144
+ }
145
+
126
146
  if (p == null) {
127
147
  return this.$basePath;
128
148
  }
149
+ if (!this.$basePath) {
150
+ return p;
151
+ }
129
152
  return [this.$basePath, p].join('.');
130
153
  };
131
154
 
@@ -165,9 +188,13 @@ Subdocument.prototype.$isValid = function(path) {
165
188
  Subdocument.prototype.markModified = function(path) {
166
189
  Document.prototype.markModified.call(this, path);
167
190
  const parent = this.$parent();
168
- const fullPath = this.$__pathRelativeToParent(path);
169
191
 
170
- if (parent == null || fullPath == null) {
192
+ if (parent == null) {
193
+ return;
194
+ }
195
+
196
+ const pathToMark = this.$__pathRelativeToParent(path);
197
+ if (pathToMark == null) {
171
198
  return;
172
199
  }
173
200
 
@@ -175,7 +202,8 @@ Subdocument.prototype.markModified = function(path) {
175
202
  if (parent.isDirectModified(myPath) || this.isNew) {
176
203
  return;
177
204
  }
178
- this.$__parent.markModified(fullPath, this);
205
+
206
+ this.$__parent.markModified(pathToMark, this);
179
207
  };
180
208
 
181
209
  /*!
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "mongoose",
3
3
  "description": "Mongoose MongoDB ODM",
4
- "version": "8.19.0",
4
+ "version": "8.19.2",
5
5
  "author": "Guillermo Rauch <guillermo@learnboost.com>",
6
6
  "keywords": [
7
7
  "mongodb",
@@ -30,7 +30,7 @@
30
30
  },
31
31
  "devDependencies": {
32
32
  "@ark/attest": "0.48.2",
33
- "@babel/core": "7.28.3",
33
+ "@babel/core": "7.28.4",
34
34
  "@babel/preset-env": "7.28.3",
35
35
  "@mongodb-js/mongodb-downloader": "^0.4.2",
36
36
  "@typescript-eslint/eslint-plugin": "^8.19.1",
@@ -57,9 +57,9 @@
57
57
  "markdownlint-cli2": "^0.18.1",
58
58
  "marked": "15.0.12",
59
59
  "mkdirp": "^3.0.1",
60
- "mocha": "11.7.2",
60
+ "mocha": "11.7.4",
61
61
  "moment": "2.30.1",
62
- "mongodb-memory-server": "10.2.0",
62
+ "mongodb-memory-server": "10.2.1",
63
63
  "mongodb-runner": "^5.8.2",
64
64
  "ncp": "^2.0.0",
65
65
  "nyc": "15.1.0",
@@ -68,9 +68,9 @@
68
68
  "sinon": "21.0.0",
69
69
  "stream-browserify": "3.0.0",
70
70
  "tsd": "0.33.0",
71
- "typescript": "5.9.2",
71
+ "typescript": "5.9.3",
72
72
  "uuid": "11.1.0",
73
- "webpack": "5.101.3"
73
+ "webpack": "5.102.0"
74
74
  },
75
75
  "directories": {
76
76
  "lib": "./lib/mongoose"
package/types/query.d.ts CHANGED
@@ -10,11 +10,9 @@ declare module 'mongoose' {
10
10
  * { age: { $gte: 30 } }
11
11
  * ```
12
12
  */
13
- type RootFilterQuery<T> = FilterQuery<T> | Query<any, any> | Types.ObjectId;
13
+ type RootFilterQuery<T> = IsItRecordAndNotAny<T> extends true ? FilterQuery<T> | Query<any, any> | Types.ObjectId : FilterQuery<Record<string, any>> | Query<any, any> | Types.ObjectId;
14
14
 
15
- type FilterQuery<T> = IsItRecordAndNotAny<T> extends true ?
16
- ({ [P in keyof T]?: Condition<T[P]>; } & RootQuerySelector<T> & { _id?: Condition<string>; }) :
17
- FilterQuery<Record<string, any>>;
15
+ type FilterQuery<T> = ({ [P in keyof T]?: Condition<T[P]>; } & RootQuerySelector<T> & { _id?: Condition<string>; });
18
16
 
19
17
  type MongooseBaseQueryOptionKeys =
20
18
  | 'context'
@@ -424,18 +422,10 @@ declare module 'mongoose' {
424
422
 
425
423
  /** Creates a `find` query: gets a list of documents that match `filter`. */
426
424
  find(
427
- filter: RootFilterQuery<RawDocType>,
425
+ filter?: RootFilterQuery<RawDocType>,
428
426
  projection?: ProjectionType<RawDocType> | null,
429
427
  options?: QueryOptions<RawDocType> | null
430
428
  ): QueryWithHelpers<Array<DocType>, DocType, THelpers, RawDocType, 'find', TDocOverrides>;
431
- find(
432
- filter: RootFilterQuery<RawDocType>,
433
- projection?: ProjectionType<RawDocType> | null
434
- ): QueryWithHelpers<Array<DocType>, DocType, THelpers, RawDocType, 'find', TDocOverrides>;
435
- find(
436
- filter: RootFilterQuery<RawDocType>
437
- ): QueryWithHelpers<Array<DocType>, DocType, THelpers, RawDocType, 'find', TDocOverrides>;
438
- find(): QueryWithHelpers<Array<DocType>, DocType, THelpers, RawDocType, 'find', TDocOverrides>;
439
429
 
440
430
  /** Declares the query a findOne operation. When executed, returns the first found document. */
441
431
  findOne(
@@ -443,13 +433,6 @@ declare module 'mongoose' {
443
433
  projection?: ProjectionType<RawDocType> | null,
444
434
  options?: QueryOptions<RawDocType> | null
445
435
  ): QueryWithHelpers<DocType | null, DocType, THelpers, RawDocType, 'findOne', TDocOverrides>;
446
- findOne(
447
- filter?: RootFilterQuery<RawDocType>,
448
- projection?: ProjectionType<RawDocType> | null
449
- ): QueryWithHelpers<DocType | null, DocType, THelpers, RawDocType, 'findOne', TDocOverrides>;
450
- findOne(
451
- filter?: RootFilterQuery<RawDocType>
452
- ): QueryWithHelpers<DocType | null, DocType, THelpers, RawDocType, 'findOne', TDocOverrides>;
453
436
 
454
437
  /** Creates a `findOneAndDelete` query: atomically finds the given document, deletes it, and returns the document as it was before deletion. */
455
438
  findOneAndDelete(
@@ -484,13 +467,6 @@ declare module 'mongoose' {
484
467
  projection?: ProjectionType<RawDocType> | null,
485
468
  options?: QueryOptions<RawDocType> | null
486
469
  ): QueryWithHelpers<DocType | null, DocType, THelpers, RawDocType, 'findOne', TDocOverrides>;
487
- findById(
488
- id: mongodb.ObjectId | any,
489
- projection?: ProjectionType<RawDocType> | null
490
- ): QueryWithHelpers<DocType | null, DocType, THelpers, RawDocType, 'findOne', TDocOverrides>;
491
- findById(
492
- id: mongodb.ObjectId | any
493
- ): QueryWithHelpers<DocType | null, DocType, THelpers, RawDocType, 'findOne', TDocOverrides>;
494
470
 
495
471
  /** Creates a `findByIdAndDelete` query, filtering by the given `_id`. */
496
472
  findByIdAndDelete(