mongoose 7.3.0 → 7.3.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
@@ -703,8 +703,7 @@ Connection.prototype.onOpen = function() {
703
703
  * @param {Number} [options.heartbeatFrequencyMS] If `useUnifiedTopology = true`, the MongoDB driver sends a heartbeat every `heartbeatFrequencyMS` to check on the status of the connection. A heartbeat is subject to `serverSelectionTimeoutMS`, so the MongoDB driver will retry failed heartbeats for up to 30 seconds by default. Mongoose only emits a `'disconnected'` event after a heartbeat has failed, so you may want to decrease this setting to reduce the time between when your server goes down and when Mongoose emits `'disconnected'`. We recommend you do **not** set this setting below 1000, too many heartbeats can lead to performance degradation.
704
704
  * @param {Boolean} [options.autoIndex=true] Mongoose-specific option. Set to false to disable automatic index creation for all models associated with this connection.
705
705
  * @param {Class} [options.promiseLibrary] Sets the [underlying driver's promise library](https://mongodb.github.io/node-mongodb-native/4.9/interfaces/MongoClientOptions.html#promiseLibrary).
706
- * @param {Number} [options.connectTimeoutMS=30000] How long the MongoDB driver will wait before killing a socket due to inactivity _during initial connection_. Defaults to 30000. This option is passed transparently to [Node.js' `socket#setTimeout()` function](https://nodejs.org/api/net.html#net_socket_settimeout_timeout_callback).
707
- * @param {Number} [options.socketTimeoutMS=30000] How long the MongoDB driver will wait before killing a socket due to inactivity _after initial connection_. A socket may be inactive because of either no activity or a long-running operation. This is set to `30000` by default, you should set this to 2-3x your longest running operation if you expect some of your database operations to run longer than 20 seconds. This option is passed to [Node.js `socket#setTimeout()` function](https://nodejs.org/api/net.html#net_socket_settimeout_timeout_callback) after the MongoDB driver successfully completes.
706
+ * @param {Number} [options.socketTimeoutMS=0] How long the MongoDB driver will wait before killing a socket due to inactivity _after initial connection_. A socket may be inactive because of either no activity or a long-running operation. `socketTimeoutMS` defaults to 0, which means Node.js will not time out the socket due to inactivity. This option is passed to [Node.js `socket#setTimeout()` function](https://nodejs.org/api/net.html#net_socket_settimeout_timeout_callback) after the MongoDB driver successfully completes.
708
707
  * @param {Number} [options.family=0] Passed transparently to [Node.js' `dns.lookup()`](https://nodejs.org/api/dns.html#dns_dns_lookup_hostname_options_callback) function. May be either `0, `4`, or `6`. `4` means use IPv4 only, `6` means use IPv6 only, `0` means try both.
709
708
  * @param {Boolean} [options.autoCreate=false] Set to `true` to make Mongoose automatically call `createCollection()` on every model created on this connection.
710
709
  * @returns {Promise<Connection>}
@@ -84,25 +84,33 @@ function QueryCursor(query, options) {
84
84
  this.options._populateBatchSize = Math.min(this.options.batchSize, 5000);
85
85
  }
86
86
  Object.assign(this.options, query._optionsForExec());
87
- model.collection.find(query._conditions, this.options, (err, cursor) => {
88
- if (err != null) {
89
- this._markError(err);
90
- this.listeners('error').length > 0 && this.emit('error', this._error);
91
- return;
92
- }
93
-
94
- if (this._error) {
95
- cursor.close(function() {});
96
- this.listeners('error').length > 0 && this.emit('error', this._error);
97
- }
98
- this.cursor = cursor;
99
- this.emit('cursor', cursor);
100
- });
87
+ if (model.collection._shouldBufferCommands() && model.collection.buffer) {
88
+ model.collection.queue.push([
89
+ () => _getRawCursor(query, this)
90
+ ]);
91
+ } else {
92
+ _getRawCursor(query, this);
93
+ }
101
94
  });
102
95
  }
103
96
 
104
97
  util.inherits(QueryCursor, Readable);
105
98
 
99
+ /*!
100
+ * ignore
101
+ */
102
+
103
+ function _getRawCursor(query, queryCursor) {
104
+ try {
105
+ const cursor = query.model.collection.find(query._conditions, queryCursor.options);
106
+ queryCursor.cursor = cursor;
107
+ queryCursor.emit('cursor', cursor);
108
+ } catch (err) {
109
+ queryCursor._markError(err);
110
+ queryCursor.listeners('error').length > 0 && queryCursor.emit('error', queryCursor._error);
111
+ }
112
+ }
113
+
106
114
  /**
107
115
  * Necessary to satisfy the Readable API
108
116
  * @method _read
package/lib/index.js CHANGED
@@ -329,8 +329,7 @@ Mongoose.prototype.get = Mongoose.prototype.set;
329
329
  * @param {Class} [options.promiseLibrary] Sets the [underlying driver's promise library](https://mongodb.github.io/node-mongodb-native/4.9/interfaces/MongoClientOptions.html#promiseLibrary).
330
330
  * @param {Number} [options.maxPoolSize=5] The maximum number of sockets the MongoDB driver will keep open for this connection. Keep in mind that MongoDB only allows one operation per socket at a time, so you may want to increase this if you find you have a few slow queries that are blocking faster queries from proceeding. See [Slow Trains in MongoDB and Node.js](https://thecodebarbarian.com/slow-trains-in-mongodb-and-nodejs).
331
331
  * @param {Number} [options.minPoolSize=1] The minimum number of sockets the MongoDB driver will keep open for this connection. Keep in mind that MongoDB only allows one operation per socket at a time, so you may want to increase this if you find you have a few slow queries that are blocking faster queries from proceeding. See [Slow Trains in MongoDB and Node.js](https://thecodebarbarian.com/slow-trains-in-mongodb-and-nodejs).
332
- * @param {Number} [options.connectTimeoutMS=30000] How long the MongoDB driver will wait before killing a socket due to inactivity _during initial connection_. Defaults to 30000. This option is passed transparently to [Node.js' `socket#setTimeout()` function](https://nodejs.org/api/net.html#net_socket_settimeout_timeout_callback).
333
- * @param {Number} [options.socketTimeoutMS=30000] How long the MongoDB driver will wait before killing a socket due to inactivity _after initial connection_. A socket may be inactive because of either no activity or a long-running operation. This is set to `30000` by default, you should set this to 2-3x your longest running operation if you expect some of your database operations to run longer than 20 seconds. This option is passed to [Node.js `socket#setTimeout()` function](https://nodejs.org/api/net.html#net_socket_settimeout_timeout_callback) after the MongoDB driver successfully completes.
332
+ * @param {Number} [options.socketTimeoutMS=0] How long the MongoDB driver will wait before killing a socket due to inactivity _after initial connection_. Defaults to 0, which means Node.js will not time out the socket due to inactivity. A socket may be inactive because of either no activity or a long-running operation. This option is passed to [Node.js `socket#setTimeout()` function](https://nodejs.org/api/net.html#net_socket_settimeout_timeout_callback) after the MongoDB driver successfully completes.
334
333
  * @param {Number} [options.family=0] Passed transparently to [Node.js' `dns.lookup()`](https://nodejs.org/api/dns.html#dns_dns_lookup_hostname_options_callback) function. May be either `0`, `4`, or `6`. `4` means use IPv4 only, `6` means use IPv6 only, `0` means try both.
335
334
  * @return {Connection} the created Connection object. Connections are not thenable, so you can't do `await mongoose.createConnection()`. To await use `mongoose.createConnection(uri).asPromise()` instead.
336
335
  * @api public
@@ -385,8 +384,7 @@ Mongoose.prototype.createConnection = function(uri, options) {
385
384
  * @param {Number} [options.heartbeatFrequencyMS] If `useUnifiedTopology = true`, the MongoDB driver sends a heartbeat every `heartbeatFrequencyMS` to check on the status of the connection. A heartbeat is subject to `serverSelectionTimeoutMS`, so the MongoDB driver will retry failed heartbeats for up to 30 seconds by default. Mongoose only emits a `'disconnected'` event after a heartbeat has failed, so you may want to decrease this setting to reduce the time between when your server goes down and when Mongoose emits `'disconnected'`. We recommend you do **not** set this setting below 1000, too many heartbeats can lead to performance degradation.
386
385
  * @param {Boolean} [options.autoIndex=true] Mongoose-specific option. Set to false to disable automatic index creation for all models associated with this connection.
387
386
  * @param {Class} [options.promiseLibrary] Sets the [underlying driver's promise library](https://mongodb.github.io/node-mongodb-native/4.9/interfaces/MongoClientOptions.html#promiseLibrary).
388
- * @param {Number} [options.connectTimeoutMS=30000] How long the MongoDB driver will wait before killing a socket due to inactivity _during initial connection_. Defaults to 30000. This option is passed transparently to [Node.js' `socket#setTimeout()` function](https://nodejs.org/api/net.html#net_socket_settimeout_timeout_callback).
389
- * @param {Number} [options.socketTimeoutMS=30000] How long the MongoDB driver will wait before killing a socket due to inactivity _after initial connection_. A socket may be inactive because of either no activity or a long-running operation. This is set to `30000` by default, you should set this to 2-3x your longest running operation if you expect some of your database operations to run longer than 20 seconds. This option is passed to [Node.js `socket#setTimeout()` function](https://nodejs.org/api/net.html#net_socket_settimeout_timeout_callback) after the MongoDB driver successfully completes.
387
+ * @param {Number} [options.socketTimeoutMS=0] How long the MongoDB driver will wait before killing a socket due to inactivity _after initial connection_. A socket may be inactive because of either no activity or a long-running operation. `socketTimeoutMS` defaults to 0, which means Node.js will not time out the socket due to inactivity. This option is passed to [Node.js `socket#setTimeout()` function](https://nodejs.org/api/net.html#net_socket_settimeout_timeout_callback) after the MongoDB driver successfully completes.
390
388
  * @param {Number} [options.family=0] Passed transparently to [Node.js' `dns.lookup()`](https://nodejs.org/api/dns.html#dns_dns_lookup_hostname_options_callback) function. May be either `0`, `4`, or `6`. `4` means use IPv4 only, `6` means use IPv6 only, `0` means try both.
391
389
  * @param {Boolean} [options.autoCreate=false] Set to `true` to make Mongoose automatically call `createCollection()` on every model created on this connection.
392
390
  * @param {Function} [callback]
package/lib/model.js CHANGED
@@ -1046,16 +1046,18 @@ Model.prototype.$__deleteOne = function $__deleteOne(options, cb) {
1046
1046
  options.session = session;
1047
1047
  }
1048
1048
 
1049
- this[modelCollectionSymbol].deleteOne(where, options, err => {
1050
- if (!err) {
1049
+ this[modelCollectionSymbol].deleteOne(where, options).then(
1050
+ () => {
1051
1051
  this.$__.isDeleted = true;
1052
1052
  this.$emit('deleteOne', this);
1053
1053
  this.constructor.emit('deleteOne', this);
1054
1054
  return cb(null, this);
1055
+ },
1056
+ err => {
1057
+ this.$__.isDeleted = false;
1058
+ cb(err);
1055
1059
  }
1056
- this.$__.isDeleted = false;
1057
- cb(err);
1058
- });
1060
+ );
1059
1061
  };
1060
1062
 
1061
1063
  /**
@@ -3232,16 +3234,19 @@ Model.$__insertMany = function(arr, options, callback) {
3232
3234
  }
3233
3235
 
3234
3236
  // `insertedDocs` is a Mongoose-specific property
3237
+ const hasWriteErrors = error && error.writeErrors;
3235
3238
  const erroredIndexes = new Set((error && error.writeErrors || []).map(err => err.index));
3236
3239
 
3237
- for (let i = 0; i < error.writeErrors.length; ++i) {
3238
- const originalIndex = validDocIndexToOriginalIndex.get(error.writeErrors[i].index);
3239
- error.writeErrors[i] = {
3240
- ...error.writeErrors[i],
3241
- index: originalIndex
3242
- };
3243
- if (!ordered) {
3244
- results[originalIndex] = error.writeErrors[i];
3240
+ if (error.writeErrors != null) {
3241
+ for (let i = 0; i < error.writeErrors.length; ++i) {
3242
+ const originalIndex = validDocIndexToOriginalIndex.get(error.writeErrors[i].index);
3243
+ error.writeErrors[i] = {
3244
+ ...error.writeErrors[i],
3245
+ index: originalIndex
3246
+ };
3247
+ if (!ordered) {
3248
+ results[originalIndex] = error.writeErrors[i];
3249
+ }
3245
3250
  }
3246
3251
  }
3247
3252
 
@@ -3258,7 +3263,7 @@ Model.$__insertMany = function(arr, options, callback) {
3258
3263
  let firstErroredIndex = -1;
3259
3264
  error.insertedDocs = docAttributes.
3260
3265
  filter((doc, i) => {
3261
- const isErrored = erroredIndexes.has(i);
3266
+ const isErrored = !hasWriteErrors || erroredIndexes.has(i);
3262
3267
 
3263
3268
  if (ordered) {
3264
3269
  if (firstErroredIndex > -1) {
package/lib/query.js CHANGED
@@ -3281,6 +3281,12 @@ Query.prototype.findOneAndUpdate = function(filter, doc, options) {
3281
3281
  */
3282
3282
 
3283
3283
  Query.prototype._findOneAndUpdate = async function _findOneAndUpdate() {
3284
+ // For backwards compability with Mongoose 6 re: #13550
3285
+ if (this._mongooseOptions.overwrite) {
3286
+ this.op = 'findOneAndReplace';
3287
+ return this._findOneAndReplace();
3288
+ }
3289
+
3284
3290
  this._castConditions();
3285
3291
 
3286
3292
  _castArrayFilters(this);
@@ -3608,55 +3614,47 @@ Query.prototype._findOneAndReplace = async function _findOneAndReplace() {
3608
3614
  throw this.error();
3609
3615
  }
3610
3616
 
3617
+ if ('strict' in this.options) {
3618
+ this._mongooseOptions.strict = this.options.strict;
3619
+ delete this.options.strict;
3620
+ }
3621
+
3611
3622
  const filter = this._conditions;
3612
3623
  const options = this._optionsForExec();
3613
3624
  this._applyTranslateAliases(options);
3614
3625
  convertNewToReturnDocument(options);
3615
3626
 
3616
- const runValidators = _getOption(this, 'runValidators', false);
3617
- if (runValidators === false) {
3618
- try {
3619
- this._update = this._castUpdate(this._update, true);
3620
- } catch (err) {
3621
- const validationError = new ValidationError();
3622
- validationError.errors[err.path] = err;
3623
- throw validationError;
3624
- }
3625
-
3626
- let res = await this._collection.collection.findOneAndReplace(filter, this._update || {}, options);
3627
-
3628
- for (const fn of this._transforms) {
3629
- res = fn(res);
3630
- }
3631
-
3632
- const doc = res.value;
3633
- return new Promise((resolve, reject) => {
3634
- this._completeOne(doc, res, _wrapThunkCallback(this, (err, res) => {
3635
- if (err) {
3636
- return reject(err);
3637
- }
3638
- resolve(res);
3639
- }));
3640
- });
3627
+ const modelOpts = { skipId: true };
3628
+ if ('strict' in this._mongooseOptions) {
3629
+ modelOpts.strict = this._mongooseOptions.strict;
3641
3630
  }
3642
3631
 
3632
+ const runValidators = _getOption(this, 'runValidators', false);
3643
3633
 
3644
- let castedDoc = new this.model(this._update, null, true);
3645
- this._update = castedDoc;
3646
- await castedDoc.validate();
3647
-
3648
- if (castedDoc.toBSON) {
3649
- castedDoc = castedDoc.toBSON();
3634
+ try {
3635
+ const update = new this.model(this._update, null, modelOpts);
3636
+ if (runValidators) {
3637
+ await update.validate();
3638
+ } else if (update.$__.validationError) {
3639
+ throw update.$__.validationError;
3640
+ }
3641
+ this._update = update.toBSON();
3642
+ } catch (err) {
3643
+ if (err instanceof ValidationError) {
3644
+ throw err;
3645
+ }
3646
+ const validationError = new ValidationError();
3647
+ validationError.errors[err.path] = err;
3648
+ throw validationError;
3650
3649
  }
3651
3650
 
3652
- let res = await this._collection.collection.findOneAndReplace(filter, castedDoc, options);
3651
+ let res = await this._collection.collection.findOneAndReplace(filter, this._update, options);
3653
3652
 
3654
3653
  for (const fn of this._transforms) {
3655
3654
  res = fn(res);
3656
3655
  }
3657
3656
 
3658
3657
  const doc = res.value;
3659
-
3660
3658
  return new Promise((resolve, reject) => {
3661
3659
  this._completeOne(doc, res, _wrapThunkCallback(this, (err, res) => {
3662
3660
  if (err) {
@@ -4362,7 +4360,10 @@ Query.prototype.exec = async function exec(op) {
4362
4360
  }
4363
4361
 
4364
4362
  if (this.op == null) {
4365
- throw new Error('Query must have `op` before executing');
4363
+ throw new MongooseError('Query must have `op` before executing');
4364
+ }
4365
+ if (this.model == null) {
4366
+ throw new MongooseError('Query must have an associated model before executing');
4366
4367
  }
4367
4368
  this._validateOp();
4368
4369
 
@@ -4442,6 +4443,13 @@ function _executePostExecHooks(query) {
4442
4443
  */
4443
4444
 
4444
4445
  function _executePostHooks(query, res, error, op) {
4446
+ if (query._queryMiddleware == null) {
4447
+ if (error != null) {
4448
+ throw error;
4449
+ }
4450
+ return res;
4451
+ }
4452
+
4445
4453
  return new Promise((resolve, reject) => {
4446
4454
  const opts = error ? { error } : {};
4447
4455
 
@@ -4475,6 +4483,10 @@ function _executePreExecHooks(query) {
4475
4483
  */
4476
4484
 
4477
4485
  function _executePreHooks(query, op) {
4486
+ if (query._queryMiddleware == null) {
4487
+ return;
4488
+ }
4489
+
4478
4490
  return new Promise((resolve, reject) => {
4479
4491
  query._queryMiddleware.execPre(op || query.op, query, [], (error) => {
4480
4492
  if (error != null) {
package/lib/schematype.js CHANGED
@@ -810,8 +810,8 @@ SchemaType.prototype.get = function(fn) {
810
810
  * // adding many validators at a time
811
811
  *
812
812
  * const many = [
813
- * { validator: validator, msg: 'uh oh' }
814
- * , { validator: anotherValidator, msg: 'failed' }
813
+ * { validator: validator, message: 'uh oh' }
814
+ * , { validator: anotherValidator, message: 'failed' }
815
815
  * ]
816
816
  * new Schema({ name: { type: String, validate: many }});
817
817
  *
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "mongoose",
3
3
  "description": "Mongoose MongoDB ODM",
4
- "version": "7.3.0",
4
+ "version": "7.3.2",
5
5
  "author": "Guillermo Rauch <guillermo@learnboost.com>",
6
6
  "keywords": [
7
7
  "mongodb",
@@ -28,10 +28,10 @@
28
28
  "sift": "16.0.1"
29
29
  },
30
30
  "devDependencies": {
31
- "@babel/core": "7.22.1",
32
- "@babel/preset-env": "7.22.4",
33
- "@typescript-eslint/eslint-plugin": "5.59.8",
34
- "@typescript-eslint/parser": "5.59.8",
31
+ "@babel/core": "7.22.5",
32
+ "@babel/preset-env": "7.22.5",
33
+ "@typescript-eslint/eslint-plugin": "5.61.0",
34
+ "@typescript-eslint/parser": "5.61.0",
35
35
  "acquit": "1.3.0",
36
36
  "acquit-ignore": "0.2.1",
37
37
  "acquit-require": "0.1.1",
@@ -44,31 +44,32 @@
44
44
  "buffer": "^5.6.0",
45
45
  "cheerio": "1.0.0-rc.12",
46
46
  "crypto-browserify": "3.12.0",
47
- "dotenv": "16.1.3",
47
+ "dotenv": "16.3.1",
48
48
  "dox": "1.0.0",
49
- "eslint": "8.41.0",
49
+ "eslint": "8.44.0",
50
50
  "eslint-plugin-markdown": "^3.0.0",
51
51
  "eslint-plugin-mocha-no-only": "1.1.1",
52
52
  "express": "^4.18.1",
53
+ "fs-extra": "~11.1.1",
53
54
  "highlight.js": "11.8.0",
54
55
  "lodash.isequal": "4.5.0",
55
56
  "lodash.isequalwith": "4.4.0",
57
+ "markdownlint-cli2": "^0.8.1",
56
58
  "marked": "4.3.0",
57
- "mkdirp": "^2.1.3",
59
+ "mkdirp": "^3.0.1",
58
60
  "mocha": "10.2.0",
59
61
  "moment": "2.x",
60
- "mongodb-memory-server": "8.12.2",
62
+ "mongodb-memory-server": "8.13.0",
61
63
  "ncp": "^2.0.0",
62
64
  "nyc": "15.1.0",
63
65
  "pug": "3.0.2",
64
66
  "q": "1.5.1",
65
- "sinon": "15.1.0",
67
+ "sinon": "15.2.0",
66
68
  "stream-browserify": "3.0.0",
67
69
  "tsd": "0.28.1",
68
- "typescript": "5.1.3",
70
+ "typescript": "5.1.6",
69
71
  "uuid": "9.0.0",
70
- "webpack": "5.85.0",
71
- "fs-extra": "~11.1.1"
72
+ "webpack": "5.88.1"
72
73
  },
73
74
  "directories": {
74
75
  "lib": "./lib/mongoose"
@@ -98,9 +99,9 @@
98
99
  "docs:prepare:publish:6x": "npm run docs:checkout:6x && npm run docs:merge:6x && npm run docs:clean:stable && env DOCS_DEPLOY=true npm run docs:generate && npm run docs:move:6x:tmp && npm run docs:checkout:gh-pages && npm run docs:copy:tmp:6x",
99
100
  "docs:check-links": "blc http://127.0.0.1:8089 -ro",
100
101
  "lint": "eslint .",
101
- "lint-js": "eslint . --ext .js",
102
+ "lint-js": "eslint . --ext .js --ext .cjs",
102
103
  "lint-ts": "eslint . --ext .ts",
103
- "lint-md": "eslint . --ext .md",
104
+ "lint-md": "markdownlint-cli2 \"**/*.md\"",
104
105
  "build-browser": "(rm ./dist/* || true) && node ./scripts/build-browser.js",
105
106
  "prepublishOnly": "npm run build-browser",
106
107
  "release": "git pull && git push origin master --tags && npm publish",
package/types/index.d.ts CHANGED
@@ -197,7 +197,7 @@ declare module 'mongoose' {
197
197
 
198
198
  export type DiscriminatorSchema<DocType, M, TInstanceMethods, TQueryHelpers, TVirtuals, TStaticMethods, DisSchema> =
199
199
  DisSchema extends Schema<infer DisSchemaEDocType, infer DisSchemaM, infer DisSchemaInstanceMethods, infer DisSchemaQueryhelpers, infer DisSchemaVirtuals, infer DisSchemaStatics>
200
- ? Schema<Omit<DocType, keyof DisSchemaEDocType> & DisSchemaEDocType, DiscriminatorModel<DisSchemaM, M>, DisSchemaInstanceMethods | TInstanceMethods, DisSchemaQueryhelpers | TQueryHelpers, DisSchemaVirtuals | TVirtuals, DisSchemaStatics & TStaticMethods>
200
+ ? Schema<MergeType<DocType, DisSchemaEDocType>, DiscriminatorModel<DisSchemaM, M>, DisSchemaInstanceMethods | TInstanceMethods, DisSchemaQueryhelpers | TQueryHelpers, DisSchemaVirtuals | TVirtuals, DisSchemaStatics & TStaticMethods>
201
201
  : Schema<DocType, M, TInstanceMethods, TQueryHelpers, TVirtuals, TStaticMethods>;
202
202
 
203
203
  type QueryResultType<T> = T extends Query<infer ResultType, any> ? ResultType : never;
@@ -430,6 +430,8 @@ declare module 'mongoose' {
430
430
 
431
431
  /** Returns the virtual type with the given `name`. */
432
432
  virtualpath<T = THydratedDocumentType>(name: string): VirtualType<T> | null;
433
+
434
+ static ObjectId: typeof Schema.Types.ObjectId;
433
435
  }
434
436
 
435
437
  export type NumberSchemaDefinition = typeof Number | 'number' | 'Number' | typeof Schema.Types.Number;