mongoose 6.2.5 → 6.2.8

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.
@@ -17,6 +17,7 @@ const isObject = require('./helpers/isObject');
17
17
  * Document constructor.
18
18
  *
19
19
  * @param {Object} obj the values to set
20
+ * @param {Object} schema
20
21
  * @param {Object} [fields] optional object containing the fields which were selected in the query returning this document and any populated paths data
21
22
  * @param {Boolean} [skipId] bool, should we auto create an ObjectId _id
22
23
  * @inherits NodeJS EventEmitter https://nodejs.org/api/events.html#events_class_events_eventemitter
package/lib/connection.js CHANGED
@@ -788,10 +788,6 @@ Connection.prototype.openUri = function(uri, options, callback) {
788
788
  }
789
789
  _this.client = client;
790
790
 
791
- for (const db of this.otherDbs) {
792
- _setClient(db, client, {}, db.name);
793
- }
794
-
795
791
  client.setMaxListeners(0);
796
792
  client.connect((error) => {
797
793
  if (error) {
@@ -800,6 +796,10 @@ Connection.prototype.openUri = function(uri, options, callback) {
800
796
 
801
797
  _setClient(_this, client, options, dbName);
802
798
 
799
+ for (const db of this.otherDbs) {
800
+ _setClient(db, client, {}, db.name);
801
+ }
802
+
803
803
  resolve(_this);
804
804
  });
805
805
  });
@@ -26,7 +26,6 @@ const util = require('util');
26
26
  * Use [`Aggregate#cursor()`](/docs/api.html#aggregate_Aggregate-cursor) instead.
27
27
  *
28
28
  * @param {Aggregate} agg
29
- * @param {Object} options
30
29
  * @inherits Readable
31
30
  * @event `cursor`: Emitted when the cursor is created
32
31
  * @event `error`: Emitted when an error occurred
@@ -472,7 +472,8 @@ function _nextDoc(ctx, doc, pop, callback) {
472
472
  });
473
473
  }
474
474
 
475
- ctx.query._completeOne(doc, null, (err, doc) => {
475
+ const { model, _fields, _userProvidedFields, options } = ctx.query;
476
+ helpers.createModelAndInit(model, doc, _fields, _userProvidedFields, options, pop, (err, doc) => {
476
477
  if (err != null) {
477
478
  return callback(err);
478
479
  }
package/lib/document.js CHANGED
@@ -801,7 +801,7 @@ function init(self, obj, doc, opts, prefix) {
801
801
  init(self, obj[i], doc[i], opts, path + '.');
802
802
  } else if (!schemaType) {
803
803
  doc[i] = obj[i];
804
- if (!strict) {
804
+ if (!strict && !prefix) {
805
805
  self[i] = obj[i];
806
806
  }
807
807
  } else {
@@ -2472,7 +2472,6 @@ function _getPathsToValidate(doc) {
2472
2472
  return true;
2473
2473
  }));
2474
2474
 
2475
-
2476
2475
  Object.keys(doc.$__.activePaths.states.init).forEach(addToPaths);
2477
2476
  Object.keys(doc.$__.activePaths.states.modify).forEach(addToPaths);
2478
2477
  Object.keys(doc.$__.activePaths.states.default).forEach(addToPaths);
@@ -2484,18 +2483,23 @@ function _getPathsToValidate(doc) {
2484
2483
  if (subdoc.$basePath) {
2485
2484
  // Remove child paths for now, because we'll be validating the whole
2486
2485
  // subdoc
2486
+ if (!subdoc.$__.fullPath) {
2487
+ subdoc.ownerDocument();
2488
+ }
2489
+ const fullPathToSubdoc = subdoc.$__.fullPath;
2490
+
2487
2491
  for (const p of paths) {
2488
- if (p === null || p.startsWith(subdoc.$basePath + '.')) {
2492
+ if (p === null || p.startsWith(fullPathToSubdoc + '.')) {
2489
2493
  paths.delete(p);
2490
2494
  }
2491
2495
  }
2492
2496
 
2493
- if (doc.$isModified(subdoc.$basePath, modifiedPaths) &&
2494
- !doc.isDirectModified(subdoc.$basePath) &&
2495
- !doc.$isDefault(subdoc.$basePath)) {
2496
- paths.add(subdoc.$basePath);
2497
+ if (doc.$isModified(fullPathToSubdoc, modifiedPaths) &&
2498
+ !doc.isDirectModified(fullPathToSubdoc) &&
2499
+ !doc.$isDefault(fullPathToSubdoc)) {
2500
+ paths.add(fullPathToSubdoc);
2497
2501
 
2498
- skipSchemaValidators[subdoc.$basePath] = true;
2502
+ skipSchemaValidators[fullPathToSubdoc] = true;
2499
2503
  }
2500
2504
  }
2501
2505
  }
@@ -2517,6 +2521,16 @@ function _getPathsToValidate(doc) {
2517
2521
  continue;
2518
2522
  }
2519
2523
 
2524
+ // gh-11380: optimization. If the array isn't a document array and there's no validators
2525
+ // on the array type, there's no need to run validation on the individual array elements.
2526
+ if (_pathType &&
2527
+ _pathType.$isMongooseArray &&
2528
+ !_pathType.$isMongooseDocumentArray && // Skip document arrays...
2529
+ !_pathType.$embeddedSchemaType.$isMongooseArray && // and arrays of arrays
2530
+ _pathType.$embeddedSchemaType.validators.length === 0) {
2531
+ continue;
2532
+ }
2533
+
2520
2534
  const val = doc.$__getValue(path);
2521
2535
  _pushNestedArrayPaths(val, paths, path);
2522
2536
  }
@@ -2648,6 +2662,7 @@ Document.prototype.$__validate = function(pathsToValidate, options, callback) {
2648
2662
  } else if (pathsToSkip) {
2649
2663
  paths = _handlePathsToSkip(paths, pathsToSkip);
2650
2664
  }
2665
+
2651
2666
  if (paths.length === 0) {
2652
2667
  return immediate(function() {
2653
2668
  const error = _complete();
@@ -2,14 +2,32 @@
2
2
 
3
3
  const utils = require('../../utils');
4
4
 
5
+ const keysToSkip = new Set(['__index', '__parentArray', '_doc']);
6
+
5
7
  /**
6
8
  * Using spread operator on a Mongoose document gives you a
7
9
  * POJO that has a tendency to cause infinite recursion. So
8
10
  * we use this function on `set()` to prevent that.
9
11
  */
10
12
 
11
- module.exports = function handleSpreadDoc(v) {
13
+ module.exports = function handleSpreadDoc(v, includeExtraKeys) {
12
14
  if (utils.isPOJO(v) && v.$__ != null && v._doc != null) {
15
+ if (includeExtraKeys) {
16
+ const extraKeys = {};
17
+ for (const key of Object.keys(v)) {
18
+ if (typeof key === 'symbol') {
19
+ continue;
20
+ }
21
+ if (key[0] === '$') {
22
+ continue;
23
+ }
24
+ if (keysToSkip.has(key)) {
25
+ continue;
26
+ }
27
+ extraKeys[key] = v[key];
28
+ }
29
+ return { ...v._doc, ...extraKeys };
30
+ }
13
31
  return v._doc;
14
32
  }
15
33
 
@@ -41,7 +41,6 @@ module.exports = function castFilterPath(query, schematype, val) {
41
41
  }
42
42
  continue;
43
43
  }
44
- // cast(schematype.caster ? schematype.caster.schema : schema, nested, options, context);
45
44
  } else {
46
45
  val[$cond] = schematype.castForQueryWrapper({
47
46
  $conditional: $cond,
package/lib/model.js CHANGED
@@ -1375,6 +1375,16 @@ Model.createCollection = function createCollection(options, callback) {
1375
1375
  this.schema.options.timeseries;
1376
1376
  if (timeseries != null) {
1377
1377
  options = Object.assign({ timeseries }, options);
1378
+ if (options.expireAfterSeconds != null) {
1379
+ // do nothing
1380
+ } else if (options.expires != null) {
1381
+ utils.expires(options);
1382
+ } else if (this.schema.options.expireAfterSeconds != null) {
1383
+ options.expireAfterSeconds = this.schema.options.expireAfterSeconds;
1384
+ } else if (this.schema.options.expires != null) {
1385
+ options.expires = this.schema.options.expires;
1386
+ utils.expires(options);
1387
+ }
1378
1388
  }
1379
1389
 
1380
1390
  callback = this.$handleCallbackError(callback);
@@ -1875,7 +1885,7 @@ Model.discriminators;
1875
1885
  * ####Note:
1876
1886
  * Only translate arguments of object type anything else is returned raw
1877
1887
  *
1878
- * @param {Object} raw fields/conditions that may contain aliased keys
1888
+ * @param {Object} fields fields/conditions that may contain aliased keys
1879
1889
  * @return {Object} the translated 'pure' fields/conditions
1880
1890
  */
1881
1891
  Model.translateAliases = function translateAliases(fields) {
@@ -2836,11 +2846,11 @@ Model.findByIdAndDelete = function(id, options, callback) {
2836
2846
  *
2837
2847
  * ####Examples:
2838
2848
  *
2839
- * A.findOneAndReplace(conditions, options, callback) // executes
2840
- * A.findOneAndReplace(conditions, options) // return Query
2841
- * A.findOneAndReplace(conditions, callback) // executes
2842
- * A.findOneAndReplace(conditions) // returns Query
2843
- * A.findOneAndReplace() // returns Query
2849
+ * A.findOneAndReplace(filter, replacement, options, callback) // executes
2850
+ * A.findOneAndReplace(filter, replacement, options) // return Query
2851
+ * A.findOneAndReplace(filter, replacement, callback) // executes
2852
+ * A.findOneAndReplace(filter, replacement) // returns Query
2853
+ * A.findOneAndReplace() // returns Query
2844
2854
  *
2845
2855
  * @param {Object} filter Replace the first document that matches this filter
2846
2856
  * @param {Object} [replacement] Replace with this document
@@ -2861,8 +2871,10 @@ Model.findOneAndReplace = function(filter, replacement, options, callback) {
2861
2871
 
2862
2872
  if (arguments.length === 1 && typeof filter === 'function') {
2863
2873
  const msg = 'Model.findOneAndReplace(): First argument must not be a function.\n\n'
2864
- + ' ' + this.modelName + '.findOneAndReplace(conditions, callback)\n'
2865
- + ' ' + this.modelName + '.findOneAndReplace(conditions)\n'
2874
+ + ' ' + this.modelName + '.findOneAndReplace(filter, replacement, options, callback)\n'
2875
+ + ' ' + this.modelName + '.findOneAndReplace(filter, replacement, callback)\n'
2876
+ + ' ' + this.modelName + '.findOneAndReplace(filter, replacement)\n'
2877
+ + ' ' + this.modelName + '.findOneAndReplace(filter, callback)\n'
2866
2878
  + ' ' + this.modelName + '.findOneAndReplace()\n';
2867
2879
  throw new TypeError(msg);
2868
2880
  }
package/lib/query.js CHANGED
@@ -3168,23 +3168,14 @@ Query.prototype._deleteMany = wrapThunk(function(callback) {
3168
3168
  */
3169
3169
 
3170
3170
  function completeOne(model, doc, res, options, fields, userProvidedFields, pop, callback) {
3171
- const opts = pop ?
3172
- { populated: pop }
3173
- : undefined;
3174
-
3175
3171
  if (options.rawResult && doc == null) {
3176
3172
  _init(null);
3177
3173
  return null;
3178
3174
  }
3179
3175
 
3180
- const casted = helpers.createModel(model, doc, fields, userProvidedFields, options);
3181
- try {
3182
- casted.$init(doc, opts, _init);
3183
- } catch (error) {
3184
- _init(error);
3185
- }
3176
+ helpers.createModelAndInit(model, doc, fields, userProvidedFields, options, pop, _init);
3186
3177
 
3187
- function _init(err) {
3178
+ function _init(err, casted) {
3188
3179
  if (err) {
3189
3180
  return immediate(() => callback(err));
3190
3181
  }
@@ -123,6 +123,23 @@ exports.createModel = function createModel(model, doc, fields, userProvidedField
123
123
  return new model(undefined, fields, _opts);
124
124
  };
125
125
 
126
+ /*!
127
+ * ignore
128
+ */
129
+
130
+ exports.createModelAndInit = function createModelAndInit(model, doc, fields, userProvidedFields, options, populatedIds, callback) {
131
+ const initOpts = populatedIds ?
132
+ { populated: populatedIds } :
133
+ undefined;
134
+
135
+ const casted = exports.createModel(model, doc, fields, userProvidedFields, options);
136
+ try {
137
+ casted.$init(doc, initOpts, callback);
138
+ } catch (error) {
139
+ callback(error, casted);
140
+ }
141
+ };
142
+
126
143
  /*!
127
144
  * ignore
128
145
  */
@@ -26,7 +26,7 @@ module.exports = SubdocumentPath;
26
26
  * Single nested subdocument SchemaType constructor.
27
27
  *
28
28
  * @param {Schema} schema
29
- * @param {String} key
29
+ * @param {String} path
30
30
  * @param {Object} options
31
31
  * @inherits SchemaType
32
32
  * @api public
@@ -243,6 +243,9 @@ SubdocumentPath.prototype.doValidate = function(value, fn, scope, options) {
243
243
  }
244
244
 
245
245
  if (options && options.skipSchemaValidators) {
246
+ if (!value) {
247
+ return fn(null);
248
+ }
246
249
  return value.validate(fn);
247
250
  }
248
251
 
@@ -32,6 +32,7 @@ const emptyOpts = Object.freeze({});
32
32
  * @param {String} key
33
33
  * @param {SchemaType} cast
34
34
  * @param {Object} options
35
+ * @param {Object} schemaOptions
35
36
  * @inherits SchemaType
36
37
  * @api public
37
38
  */
@@ -12,6 +12,7 @@ const SchemaDocumentArrayOptions =
12
12
  const SchemaType = require('../schematype');
13
13
  const discriminator = require('../helpers/model/discriminator');
14
14
  const handleIdOption = require('../helpers/schema/handleIdOption');
15
+ const handleSpreadDoc = require('../helpers/document/handleSpreadDoc');
15
16
  const util = require('util');
16
17
  const utils = require('../utils');
17
18
  const getConstructor = require('../helpers/discriminator/getConstructor');
@@ -29,6 +30,7 @@ let Subdocument;
29
30
  * @param {String} key
30
31
  * @param {Schema} schema
31
32
  * @param {Object} options
33
+ * @param {Object} schemaOptions
32
34
  * @inherits SchemaArray
33
35
  * @api public
34
36
  */
@@ -427,13 +429,18 @@ DocumentArrayPath.prototype.cast = function(value, doc, init, prev, options) {
427
429
  const Constructor = getConstructor(this.casterConstructor, rawArray[i]);
428
430
 
429
431
  // Check if the document has a different schema (re gh-3701)
430
- if (rawArray[i].$__ && !(rawArray[i] instanceof Constructor)) {
431
- rawArray[i] = rawArray[i].toObject({
432
- transform: false,
433
- // Special case: if different model, but same schema, apply virtuals
434
- // re: gh-7898
435
- virtuals: rawArray[i].schema === Constructor.schema
436
- });
432
+ if (rawArray[i].$__ != null && !(rawArray[i] instanceof Constructor)) {
433
+ const spreadDoc = handleSpreadDoc(rawArray[i], true);
434
+ if (rawArray[i] !== spreadDoc) {
435
+ rawArray[i] = spreadDoc;
436
+ } else {
437
+ rawArray[i] = rawArray[i].toObject({
438
+ transform: false,
439
+ // Special case: if different model, but same schema, apply virtuals
440
+ // re: gh-7898
441
+ virtuals: rawArray[i].schema === Constructor.schema
442
+ });
443
+ }
437
444
  }
438
445
 
439
446
  if (rawArray[i] instanceof Subdocument) {
package/lib/schema.js CHANGED
@@ -329,6 +329,10 @@ Schema.prototype.clone = function() {
329
329
  return s;
330
330
  };
331
331
 
332
+ /*!
333
+ * ignore
334
+ */
335
+
332
336
  Schema.prototype._clone = function _clone(Constructor) {
333
337
  Constructor = Constructor || (this.base == null ? Schema : this.base.Schema);
334
338
 
@@ -961,8 +965,11 @@ Schema.prototype.interpretAsType = function(path, obj, options) {
961
965
  if (cast && cast.instanceOfSchema) {
962
966
  if (!(cast instanceof Schema)) {
963
967
  throw new TypeError('Schema for array path `' + path +
964
- '` is from a different copy of the Mongoose module. Please make sure you\'re using the same version ' +
965
- 'of Mongoose everywhere with `npm list mongoose`.');
968
+ '` is from a different copy of the Mongoose module. ' +
969
+ 'Please make sure you\'re using the same version ' +
970
+ 'of Mongoose everywhere with `npm list mongoose`. If you are still ' +
971
+ 'getting this error, please add `new Schema()` around the path: ' +
972
+ `${path}: new Schema(...)`);
966
973
  }
967
974
  return new MongooseTypes.DocumentArray(path, cast, obj);
968
975
  }
@@ -971,8 +978,11 @@ Schema.prototype.interpretAsType = function(path, obj, options) {
971
978
  cast[options.typeKey].instanceOfSchema) {
972
979
  if (!(cast[options.typeKey] instanceof Schema)) {
973
980
  throw new TypeError('Schema for array path `' + path +
974
- '` is from a different copy of the Mongoose module. Please make sure you\'re using the same version ' +
975
- 'of Mongoose everywhere with `npm list mongoose`.');
981
+ '` is from a different copy of the Mongoose module. ' +
982
+ 'Please make sure you\'re using the same version ' +
983
+ 'of Mongoose everywhere with `npm list mongoose`. If you are still ' +
984
+ 'getting this error, please add `new Schema()` around the path: ' +
985
+ `${path}: new Schema(...)`);
976
986
  }
977
987
  return new MongooseTypes.DocumentArray(path, cast[options.typeKey], obj, cast);
978
988
  }
@@ -445,6 +445,7 @@ const methods = {
445
445
  * Return whether or not the `obj` is included in the array.
446
446
  *
447
447
  * @param {Object} obj the item to check
448
+ * @param {Number} fromIndex
448
449
  * @return {Boolean}
449
450
  * @api public
450
451
  * @method includes
@@ -460,6 +461,7 @@ const methods = {
460
461
  * Return the index of `obj` or `-1` if not found.
461
462
  *
462
463
  * @param {Object} obj the item to look for
464
+ * @param {Number} fromIndex
463
465
  * @return {Number}
464
466
  * @api public
465
467
  * @method indexOf
@@ -24,6 +24,7 @@ const utils = require('./utils');
24
24
  * @param {Number} [options.skip=null] add a default `skip` to the `populate()` query
25
25
  * @param {Number} [options.perDocumentLimit=null] For legacy reasons, `limit` with `populate()` may give incorrect results because it only executes a single query for every document being populated. If you set `perDocumentLimit`, Mongoose will ensure correct `limit` per document by executing a separate query for each document to `populate()`. For example, `.find().populate({ path: 'test', perDocumentLimit: 2 })` will execute 2 additional queries if `.find()` returns 2 documents.
26
26
  * @param {Object} [options.options=null] Additional options like `limit` and `lean`.
27
+ * @param {string} name
27
28
  * @api public
28
29
  */
29
30
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "mongoose",
3
3
  "description": "Mongoose MongoDB ODM",
4
- "version": "6.2.5",
4
+ "version": "6.2.8",
5
5
  "author": "Guillermo Rauch <guillermo@learnboost.com>",
6
6
  "keywords": [
7
7
  "mongodb",
@@ -35,6 +35,7 @@
35
35
  "acquit": "1.x",
36
36
  "acquit-ignore": "0.2.x",
37
37
  "acquit-require": "0.1.x",
38
+ "axios": "0.26.1",
38
39
  "babel-loader": "8.2.3",
39
40
  "benchmark": "2.1.4",
40
41
  "bluebird": "3.7.2",
@@ -116,4 +117,4 @@
116
117
  "target": "ES2017"
117
118
  }
118
119
  }
119
- }
120
+ }
File without changes