mongoose 7.2.0 → 7.2.1

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.
@@ -8,6 +8,7 @@ const MongooseError = require('../error/mongooseError');
8
8
  const Readable = require('stream').Readable;
9
9
  const eachAsync = require('../helpers/cursor/eachAsync');
10
10
  const helpers = require('../queryhelpers');
11
+ const kareem = require('kareem');
11
12
  const immediate = require('../helpers/immediate');
12
13
  const util = require('util');
13
14
 
@@ -39,6 +40,7 @@ function QueryCursor(query, options) {
39
40
  Readable.call(this, { autoDestroy: true, objectMode: true });
40
41
 
41
42
  this.cursor = null;
43
+ this.skipped = false;
42
44
  this.query = query;
43
45
  const _this = this;
44
46
  const model = query.model;
@@ -46,9 +48,25 @@ function QueryCursor(query, options) {
46
48
  this._transforms = [];
47
49
  this.model = model;
48
50
  this.options = options || {};
49
-
50
51
  model.hooks.execPre('find', query, (err) => {
51
52
  if (err != null) {
53
+ if (err instanceof kareem.skipWrappedFunction) {
54
+ const resultValue = err.args[0];
55
+ if (resultValue != null && (!Array.isArray(resultValue) || resultValue.length)) {
56
+ const err = new MongooseError(
57
+ 'Cannot `skipMiddlewareFunction()` with a value when using ' +
58
+ '`.find().cursor()`, value must be nullish or empty array, got "' +
59
+ util.inspect(resultValue) +
60
+ '".'
61
+ );
62
+ _this._markError(err);
63
+ _this.listeners('error').length > 0 && _this.emit('error', err);
64
+ return;
65
+ }
66
+ this.skipped = true;
67
+ _this.emit('cursor', null);
68
+ return;
69
+ }
52
70
  _this._markError(err);
53
71
  _this.listeners('error').length > 0 && _this.emit('error', err);
54
72
  return;
@@ -66,6 +84,7 @@ function QueryCursor(query, options) {
66
84
  // Max out the number of documents we'll populate in parallel at 5000.
67
85
  this.options._populateBatchSize = Math.min(this.options.batchSize, 5000);
68
86
  }
87
+ Object.assign(this.options, query._optionsForExec());
69
88
  model.collection.find(query._conditions, this.options, (err, cursor) => {
70
89
  if (err != null) {
71
90
  _this._markError(err);
@@ -393,6 +412,9 @@ function _next(ctx, cb) {
393
412
  callback(ctx._error);
394
413
  });
395
414
  }
415
+ if (ctx.skipped) {
416
+ return immediate(() => callback(null, null));
417
+ }
396
418
 
397
419
  if (ctx.cursor) {
398
420
  if (ctx.query._mongooseOptions.populate && !ctx._pop) {
@@ -448,6 +470,9 @@ function _next(ctx, cb) {
448
470
  ctx.once('cursor', function(cursor) {
449
471
  ctx.removeListener('error', cb);
450
472
  if (cursor == null) {
473
+ if (ctx.skipped) {
474
+ return cb(null, null);
475
+ }
451
476
  return;
452
477
  }
453
478
  _next(ctx, cb);
@@ -1,10 +1,12 @@
1
1
  'use strict';
2
2
 
3
+ const MongooseError = require('../../error/mongooseError');
3
4
  const getDiscriminatorByValue = require('../../helpers/discriminator/getDiscriminatorByValue');
4
5
  const applyTimestampsToChildren = require('../update/applyTimestampsToChildren');
5
6
  const applyTimestampsToUpdate = require('../update/applyTimestampsToUpdate');
6
7
  const cast = require('../../cast');
7
8
  const castUpdate = require('../query/castUpdate');
9
+ const { inspect } = require('util');
8
10
  const setDefaultsOnInsert = require('../setDefaultsOnInsert');
9
11
 
10
12
  /**
@@ -212,7 +214,8 @@ module.exports = function castBulkWrite(originalModel, op, options) {
212
214
  };
213
215
  } else {
214
216
  return (callback) => {
215
- callback(new Error('Invalid op passed to `bulkWrite()`'), null);
217
+ const error = new MongooseError(`Invalid op passed to \`bulkWrite()\`: ${inspect(op)}`);
218
+ callback(error, null);
216
219
  };
217
220
  }
218
221
  };
@@ -44,11 +44,12 @@ function applyTimestampsToUpdate(now, createdAt, updatedAt, currentUpdate, optio
44
44
 
45
45
  if (Array.isArray(updates)) {
46
46
  // Update with aggregation pipeline
47
+ if (updatedAt == null) {
48
+ return updates;
49
+ }
47
50
  updates.push({ $set: { [updatedAt]: now } });
48
-
49
51
  return updates;
50
52
  }
51
-
52
53
  updates.$set = updates.$set || {};
53
54
  if (!skipUpdatedAt && updatedAt &&
54
55
  (!currentUpdate.$currentDate || !currentUpdate.$currentDate[updatedAt])) {
package/lib/query.js CHANGED
@@ -3289,19 +3289,15 @@ Query.prototype._findOneAndUpdate = async function _findOneAndUpdate() {
3289
3289
  throw this.error();
3290
3290
  }
3291
3291
 
3292
- this._applyPaths();
3293
- this._fields = this._castFields(this._fields);
3294
3292
  applyGlobalMaxTimeMS(this.options, this.model);
3295
3293
  applyGlobalDiskUse(this.options, this.model);
3296
3294
 
3297
- const opts = this._optionsForExec(this.model);
3298
- this._applyTranslateAliases(opts);
3299
-
3300
- if ('strict' in opts) {
3301
- this._mongooseOptions.strict = opts.strict;
3295
+ if ('strict' in this.options) {
3296
+ this._mongooseOptions.strict = this.options.strict;
3302
3297
  }
3303
- const options = { projection: this._fields, ...opts };
3298
+ const options = this._optionsForExec(this.model);
3304
3299
  convertNewToReturnDocument(options);
3300
+ this._applyTranslateAliases(options);
3305
3301
 
3306
3302
  this._update = this._castUpdate(this._update, false);
3307
3303
 
@@ -3312,7 +3308,7 @@ Query.prototype._findOneAndUpdate = async function _findOneAndUpdate() {
3312
3308
  this._update, _opts);
3313
3309
 
3314
3310
  if (!this._update || Object.keys(this._update).length === 0) {
3315
- if (opts.upsert) {
3311
+ if (options.upsert) {
3316
3312
  // still need to do the upsert to empty doc
3317
3313
  const doc = clone(this._update);
3318
3314
  delete doc._id;
@@ -3488,18 +3484,8 @@ Query.prototype._findOneAndDelete = async function _findOneAndDelete() {
3488
3484
  }
3489
3485
 
3490
3486
  const filter = this._conditions;
3491
- const options = this._optionsForExec();
3487
+ const options = this._optionsForExec(this.model);
3492
3488
  this._applyTranslateAliases(options);
3493
- let fields = null;
3494
-
3495
- this._applyPaths();
3496
- if (this._fields != null) {
3497
- options.projection = this._castFields(clone(this._fields));
3498
- fields = options.projection;
3499
- if (fields instanceof Error) {
3500
- throw fields;
3501
- }
3502
- }
3503
3489
 
3504
3490
  let res = await this._collection.collection.findOneAndDelete(filter, options);
3505
3491
  for (const fn of this._transforms) {
@@ -5021,6 +5007,7 @@ Query.prototype.cursor = function cursor(opts) {
5021
5007
  }
5022
5008
 
5023
5009
  const options = this._optionsForExec();
5010
+
5024
5011
  try {
5025
5012
  this.cast(this.model);
5026
5013
  } catch (err) {
@@ -359,7 +359,11 @@ SchemaArray.prototype.cast = function(value, doc, init, prev, options) {
359
359
  options = options || emptyOpts;
360
360
 
361
361
  let rawValue = utils.isMongooseArray(value) ? value.__array : value;
362
- value = MongooseArray(rawValue, options.path || this._arrayPath || this.path, doc, this);
362
+ let path = options.path || this.path;
363
+ if (options.arrayPathIndex != null) {
364
+ path += '.' + options.arrayPathIndex;
365
+ }
366
+ value = MongooseArray(rawValue, path, doc, this);
363
367
  rawValue = value.__array;
364
368
 
365
369
  if (init && doc != null && doc.$__ != null && doc.$populated(this.path)) {
package/lib/schematype.js CHANGED
@@ -822,10 +822,12 @@ SchemaType.prototype.get = function(fn) {
822
822
  *
823
823
  * #### Error message templates:
824
824
  *
825
- * From the examples above, you may have noticed that error messages support
826
- * basic templating. There are a few other template keywords besides `{PATH}`
827
- * and `{VALUE}` too. To find out more, details are available
828
- * [here](./error.html#Error.prototype.name).
825
+ * Below is a list of supported template keywords:
826
+ *
827
+ * - PATH: The schema path where the error is being triggered.
828
+ * - VALUE: The value assigned to the PATH that is triggering the error.
829
+ * - KIND: The validation property that triggered the error i.e. required.
830
+ * - REASON: The error object that caused this error if there was one.
829
831
  *
830
832
  * If Mongoose's built-in error message templating isn't enough, Mongoose
831
833
  * supports setting the `message` property to a function.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "mongoose",
3
3
  "description": "Mongoose MongoDB ODM",
4
- "version": "7.2.0",
4
+ "version": "7.2.1",
5
5
  "author": "Guillermo Rauch <guillermo@learnboost.com>",
6
6
  "keywords": [
7
7
  "mongodb",