mongoose 7.2.1 → 7.2.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
@@ -1128,9 +1128,10 @@ Connection.prototype.onClose = function(force) {
1128
1128
  };
1129
1129
 
1130
1130
  /**
1131
- * Retrieves a collection, creating it if not cached.
1132
- *
1133
- * Not typically needed by applications. Just talk to your collection through your model.
1131
+ * Retrieves a raw collection instance, creating it if not cached.
1132
+ * This method returns a thin wrapper around a [MongoDB Node.js driver collection]([MongoDB Node.js driver collection](https://mongodb.github.io/node-mongodb-native/Next/classes/Collection.html)).
1133
+ * Using a Collection bypasses Mongoose middleware, validation, and casting,
1134
+ * letting you use [MongoDB Node.js driver](https://mongodb.github.io/node-mongodb-native/) functionality directly.
1134
1135
  *
1135
1136
  * @param {String} name of the collection
1136
1137
  * @param {Object} [options] optional collection options
@@ -1582,7 +1583,7 @@ Connection.prototype.syncIndexes = async function syncIndexes(options = {}) {
1582
1583
  };
1583
1584
 
1584
1585
  /**
1585
- * Switches to a different database using the same connection pool.
1586
+ * Switches to a different database using the same [connection pool](https://mongoosejs.com/docs/api/connectionshtml#connection_pools).
1586
1587
  *
1587
1588
  * Returns a new connection object, with the new db.
1588
1589
  *
@@ -42,7 +42,6 @@ function QueryCursor(query, options) {
42
42
  this.cursor = null;
43
43
  this.skipped = false;
44
44
  this.query = query;
45
- const _this = this;
46
45
  const model = query.model;
47
46
  this._mongooseOptions = {};
48
47
  this._transforms = [];
@@ -59,16 +58,16 @@ function QueryCursor(query, options) {
59
58
  util.inspect(resultValue) +
60
59
  '".'
61
60
  );
62
- _this._markError(err);
63
- _this.listeners('error').length > 0 && _this.emit('error', err);
61
+ this._markError(err);
62
+ this.listeners('error').length > 0 && this.emit('error', err);
64
63
  return;
65
64
  }
66
65
  this.skipped = true;
67
- _this.emit('cursor', null);
66
+ this.emit('cursor', null);
68
67
  return;
69
68
  }
70
- _this._markError(err);
71
- _this.listeners('error').length > 0 && _this.emit('error', err);
69
+ this._markError(err);
70
+ this.listeners('error').length > 0 && this.emit('error', err);
72
71
  return;
73
72
  }
74
73
  this._transforms = this._transforms.concat(query._transforms.slice());
@@ -87,17 +86,17 @@ function QueryCursor(query, options) {
87
86
  Object.assign(this.options, query._optionsForExec());
88
87
  model.collection.find(query._conditions, this.options, (err, cursor) => {
89
88
  if (err != null) {
90
- _this._markError(err);
91
- _this.listeners('error').length > 0 && _this.emit('error', _this._error);
89
+ this._markError(err);
90
+ this.listeners('error').length > 0 && this.emit('error', this._error);
92
91
  return;
93
92
  }
94
93
 
95
- if (_this._error) {
94
+ if (this._error) {
96
95
  cursor.close(function() {});
97
- _this.listeners('error').length > 0 && _this.emit('error', _this._error);
96
+ this.listeners('error').length > 0 && this.emit('error', this._error);
98
97
  }
99
- _this.cursor = cursor;
100
- _this.emit('cursor', cursor);
98
+ this.cursor = cursor;
99
+ this.emit('cursor', cursor);
101
100
  });
102
101
  });
103
102
  }
@@ -113,21 +112,20 @@ util.inherits(QueryCursor, Readable);
113
112
  */
114
113
 
115
114
  QueryCursor.prototype._read = function() {
116
- const _this = this;
117
- _next(this, function(error, doc) {
115
+ _next(this, (error, doc) => {
118
116
  if (error) {
119
- return _this.emit('error', error);
117
+ return this.emit('error', error);
120
118
  }
121
119
  if (!doc) {
122
- _this.push(null);
123
- _this.cursor.close(function(error) {
120
+ this.push(null);
121
+ this.cursor.close(function(error) {
124
122
  if (error) {
125
- return _this.emit('error', error);
123
+ return this.emit('error', error);
126
124
  }
127
125
  });
128
126
  return;
129
127
  }
130
- _this.push(doc);
128
+ this.push(doc);
131
129
  });
132
130
  };
133
131
 
@@ -223,9 +221,8 @@ QueryCursor.prototype.close = async function close() {
223
221
  */
224
222
 
225
223
  QueryCursor.prototype.rewind = function() {
226
- const _this = this;
227
- _waitForCursor(this, function() {
228
- _this.cursor.rewind();
224
+ _waitForCursor(this, () => {
225
+ this.cursor.rewind();
229
226
  });
230
227
  return this;
231
228
  };
@@ -281,14 +278,13 @@ QueryCursor.prototype.next = async function next() {
281
278
  */
282
279
 
283
280
  QueryCursor.prototype.eachAsync = function(fn, opts, callback) {
284
- const _this = this;
285
281
  if (typeof opts === 'function') {
286
282
  callback = opts;
287
283
  opts = {};
288
284
  }
289
285
  opts = opts || {};
290
286
 
291
- return eachAsync(function(cb) { return _next(_this, cb); }, fn, opts, callback);
287
+ return eachAsync((cb) => _next(this, cb), fn, opts, callback);
292
288
  };
293
289
 
294
290
  /**
@@ -312,9 +308,8 @@ QueryCursor.prototype.options;
312
308
  */
313
309
 
314
310
  QueryCursor.prototype.addCursorFlag = function(flag, value) {
315
- const _this = this;
316
- _waitForCursor(this, function() {
317
- _this.cursor.addCursorFlag(flag, value);
311
+ _waitForCursor(this, () => {
312
+ this.cursor.addCursorFlag(flag, value);
318
313
  });
319
314
  return this;
320
315
  };
@@ -521,13 +516,12 @@ function _populateBatch() {
521
516
  if (!this.ctx._batchDocs.length) {
522
517
  return this.callback(null, null);
523
518
  }
524
- const _this = this;
525
519
  this.ctx.query.model.populate(this.ctx._batchDocs, this.ctx._pop).then(
526
520
  () => {
527
- _nextDoc(_this.ctx, _this.ctx._batchDocs.shift(), _this.ctx._pop, _this.callback);
521
+ _nextDoc(this.ctx, this.ctx._batchDocs.shift(), this.ctx._pop, this.callback);
528
522
  },
529
523
  err => {
530
- _this.callback(err);
524
+ this.callback(err);
531
525
  }
532
526
  );
533
527
  }
@@ -360,7 +360,7 @@ function walkUpdatePath(schema, obj, op, options, context, filter, pref) {
360
360
  try {
361
361
  if (prefix.length === 0 || key.indexOf('.') === -1) {
362
362
  obj[key] = castUpdateVal(schematype, val, op, key, context, prefix + key);
363
- } else {
363
+ } else if (isStrict !== false || schematype != null) {
364
364
  // Setting a nested dotted path that's in the schema. We don't allow paths with '.' in
365
365
  // a schema, so replace the dotted path with a nested object to avoid ending up with
366
366
  // dotted properties in the updated object. See (gh-10200)
@@ -9,7 +9,9 @@ module.exports = function merge(s1, s2, skipConflictingPaths) {
9
9
  }
10
10
  pathsToAdd[key] = s2.tree[key];
11
11
  }
12
- s1.add(pathsToAdd);
12
+ s1.options._isMerging = true;
13
+ s1.add(pathsToAdd, null);
14
+ delete s1.options._isMerging;
13
15
 
14
16
  s1.callQueue = s1.callQueue.concat(s2.callQueue);
15
17
  s1.method(s2.methods);
@@ -17,8 +19,7 @@ module.exports = function merge(s1, s2, skipConflictingPaths) {
17
19
 
18
20
  for (const [option, value] of Object.entries(s2._userProvidedOptions)) {
19
21
  if (!(option in s1._userProvidedOptions)) {
20
- s1._userProvidedOptions[option] = value;
21
- s1.options[option] = value;
22
+ s1.set(option, value);
22
23
  }
23
24
  }
24
25
 
package/lib/model.js CHANGED
@@ -145,7 +145,9 @@ Model.prototype.$isMongooseModelPrototype = true;
145
145
  Model.prototype.db;
146
146
 
147
147
  /**
148
- * Collection the model uses.
148
+ * The collection instance this model uses.
149
+ * A Mongoose collection is a thin wrapper around a [MongoDB Node.js driver collection]([MongoDB Node.js driver collection](https://mongodb.github.io/node-mongodb-native/Next/classes/Collection.html)).
150
+ * Using `Model.collection` means you bypass Mongoose middleware, validation, and casting.
149
151
  *
150
152
  * This property is read-only. Modifying this property is a no-op.
151
153
  *
package/lib/schema.js CHANGED
@@ -1285,12 +1285,16 @@ Schema.prototype.interpretAsType = function(path, obj, options) {
1285
1285
  // new Schema({ path: [new Schema({ ... })] })
1286
1286
  if (cast && cast.instanceOfSchema) {
1287
1287
  if (!(cast instanceof Schema)) {
1288
- throw new TypeError('Schema for array path `' + path +
1289
- '` is from a different copy of the Mongoose module. ' +
1290
- 'Please make sure you\'re using the same version ' +
1291
- 'of Mongoose everywhere with `npm list mongoose`. If you are still ' +
1292
- 'getting this error, please add `new Schema()` around the path: ' +
1293
- `${path}: new Schema(...)`);
1288
+ if (this.options._isMerging) {
1289
+ cast = new Schema(cast);
1290
+ } else {
1291
+ throw new TypeError('Schema for array path `' + path +
1292
+ '` is from a different copy of the Mongoose module. ' +
1293
+ 'Please make sure you\'re using the same version ' +
1294
+ 'of Mongoose everywhere with `npm list mongoose`. If you are still ' +
1295
+ 'getting this error, please add `new Schema()` around the path: ' +
1296
+ `${path}: new Schema(...)`);
1297
+ }
1294
1298
  }
1295
1299
  return new MongooseTypes.DocumentArray(path, cast, obj);
1296
1300
  }
@@ -1298,12 +1302,16 @@ Schema.prototype.interpretAsType = function(path, obj, options) {
1298
1302
  cast[options.typeKey] &&
1299
1303
  cast[options.typeKey].instanceOfSchema) {
1300
1304
  if (!(cast[options.typeKey] instanceof Schema)) {
1301
- throw new TypeError('Schema for array path `' + path +
1302
- '` is from a different copy of the Mongoose module. ' +
1303
- 'Please make sure you\'re using the same version ' +
1304
- 'of Mongoose everywhere with `npm list mongoose`. If you are still ' +
1305
- 'getting this error, please add `new Schema()` around the path: ' +
1306
- `${path}: new Schema(...)`);
1305
+ if (this.options._isMerging) {
1306
+ cast[options.typeKey] = new Schema(cast[options.typeKey]);
1307
+ } else {
1308
+ throw new TypeError('Schema for array path `' + path +
1309
+ '` is from a different copy of the Mongoose module. ' +
1310
+ 'Please make sure you\'re using the same version ' +
1311
+ 'of Mongoose everywhere with `npm list mongoose`. If you are still ' +
1312
+ 'getting this error, please add `new Schema()` around the path: ' +
1313
+ `${path}: new Schema(...)`);
1314
+ }
1307
1315
  }
1308
1316
  return new MongooseTypes.DocumentArray(path, cast[options.typeKey], obj, cast);
1309
1317
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "mongoose",
3
3
  "description": "Mongoose MongoDB ODM",
4
- "version": "7.2.1",
4
+ "version": "7.2.2",
5
5
  "author": "Guillermo Rauch <guillermo@learnboost.com>",
6
6
  "keywords": [
7
7
  "mongodb",
@@ -64,7 +64,7 @@
64
64
  "q": "1.5.1",
65
65
  "sinon": "15.0.4",
66
66
  "stream-browserify": "3.0.0",
67
- "tsd": "0.25.0",
67
+ "tsd": "0.28.1",
68
68
  "typescript": "5.0.4",
69
69
  "uuid": "9.0.0",
70
70
  "webpack": "5.81.0",
package/types/index.d.ts CHANGED
@@ -161,7 +161,7 @@ declare module 'mongoose' {
161
161
  [k: string]: string;
162
162
  }
163
163
 
164
- export interface ToObjectOptions {
164
+ export interface ToObjectOptions<THydratedDocumentType = HydratedDocument<unknown>> {
165
165
  /** apply all getters (path and virtual getters) */
166
166
  getters?: boolean;
167
167
  /** apply virtual getters (can override getters option) */
@@ -171,7 +171,11 @@ declare module 'mongoose' {
171
171
  /** remove empty objects (defaults to true) */
172
172
  minimize?: boolean;
173
173
  /** if set, mongoose will call this function to allow you to transform the returned object */
174
- transform?: boolean | ((doc: any, ret: any, options: any) => any);
174
+ transform?: boolean | ((
175
+ doc: THydratedDocumentType,
176
+ ret: Record<string, any>,
177
+ options: ToObjectOptions<THydratedDocumentType>
178
+ ) => any);
175
179
  /** if true, replace any conventionally populated paths with the original id in the output. Has no affect on virtual populated paths. */
176
180
  depopulate?: boolean;
177
181
  /** if false, exclude the version key (`__v` by default) from the output */
@@ -133,14 +133,14 @@ declare module 'mongoose' {
133
133
  */
134
134
  strictQuery?: boolean | 'throw';
135
135
  /** Exactly the same as the toObject option but only applies when the document's toJSON method is called. */
136
- toJSON?: ToObjectOptions;
136
+ toJSON?: ToObjectOptions<THydratedDocumentType>;
137
137
  /**
138
138
  * Documents have a toObject method which converts the mongoose document into a plain JavaScript object.
139
139
  * This method accepts a few options. Instead of applying these options on a per-document basis, we may
140
140
  * declare the options at the schema level and have them applied to all of the schema's documents by
141
141
  * default.
142
142
  */
143
- toObject?: ToObjectOptions;
143
+ toObject?: ToObjectOptions<THydratedDocumentType>;
144
144
  /**
145
145
  * By default, if you have an object with key 'type' in your schema, mongoose will interpret it as a
146
146
  * type declaration. However, for applications like geoJSON, the 'type' property is important. If you want to
package/types/types.d.ts CHANGED
@@ -42,8 +42,8 @@ declare module 'mongoose' {
42
42
  shift(): T;
43
43
 
44
44
  /** Returns a native js Array. */
45
- toObject(options?: ToObjectOptions): any;
46
- toObject<T>(options?: ToObjectOptions): T;
45
+ toObject(options?: ToObjectOptions<T>): any;
46
+ toObject<T>(options?: ToObjectOptions<T>): T;
47
47
 
48
48
  /** Wraps [`Array#unshift`](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/unshift) with proper change tracking. */
49
49
  unshift(...args: any[]): number;