mongoose 6.2.8 → 6.2.9

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/document.js CHANGED
@@ -156,9 +156,9 @@ function Document(obj, fields, skipId, options) {
156
156
  if (obj) {
157
157
  // Skip set hooks
158
158
  if (this.$__original_set) {
159
- this.$__original_set(obj, undefined, true);
159
+ this.$__original_set(obj, undefined, true, options);
160
160
  } else {
161
- this.$set(obj, undefined, true);
161
+ this.$set(obj, undefined, true, options);
162
162
  }
163
163
 
164
164
  if (obj instanceof Document) {
@@ -1836,6 +1836,7 @@ Document.prototype.$__path = function(path) {
1836
1836
  */
1837
1837
 
1838
1838
  Document.prototype.markModified = function(path, scope) {
1839
+ // console.log('MarkModified', path, new Error().stack);
1839
1840
  this.$__.activePaths.modify(path);
1840
1841
  if (scope != null && !this.$isSubdocument) {
1841
1842
  this.$__.pathsToScopes = this.$__pathsToScopes || {};
@@ -2422,6 +2423,7 @@ Document.prototype.validate = function(pathsToValidate, options, callback) {
2422
2423
 
2423
2424
  this.$__validate(pathsToValidate, options, (error) => {
2424
2425
  this.$op = null;
2426
+ this.$__.validating = null;
2425
2427
  cb(error);
2426
2428
  });
2427
2429
  }, this.constructor.events);
@@ -2504,12 +2506,32 @@ function _getPathsToValidate(doc) {
2504
2506
  }
2505
2507
  }
2506
2508
 
2509
+ for (const path of paths) {
2510
+ const _pathType = doc.$__schema.path(path);
2511
+ if (!_pathType) {
2512
+ continue;
2513
+ }
2514
+
2515
+ // Optimization: if primitive path with no validators, or array of primitives
2516
+ // with no validators, skip validating this path entirely.
2517
+ if (!_pathType.caster && _pathType.validators.length === 0) {
2518
+ paths.delete(path);
2519
+ } else if (_pathType.$isMongooseArray &&
2520
+ !_pathType.$isMongooseDocumentArray && // Skip document arrays...
2521
+ !_pathType.$embeddedSchemaType.$isMongooseArray && // and arrays of arrays
2522
+ _pathType.validators.length === 0 && // and arrays with top-level validators
2523
+ _pathType.$embeddedSchemaType.validators.length === 0) {
2524
+ paths.delete(path);
2525
+ }
2526
+ }
2527
+
2507
2528
  // from here on we're not removing items from paths
2508
2529
 
2509
2530
  // gh-661: if a whole array is modified, make sure to run validation on all
2510
2531
  // the children as well
2511
2532
  for (const path of paths) {
2512
2533
  const _pathType = doc.$__schema.path(path);
2534
+
2513
2535
  if (!_pathType ||
2514
2536
  !_pathType.$isMongooseArray ||
2515
2537
  // To avoid potential performance issues, skip doc arrays whose children
@@ -2616,7 +2638,8 @@ Document.prototype.$__validate = function(pathsToValidate, options, callback) {
2616
2638
  const _this = this;
2617
2639
  const _complete = () => {
2618
2640
  let validationError = this.$__.validationError;
2619
- this.$__.validationError = undefined;
2641
+ this.$__.validationError = null;
2642
+ this.$__.validating = null;
2620
2643
 
2621
2644
  if (shouldValidateModifiedOnly && validationError != null) {
2622
2645
  // Remove any validation errors that aren't from modified paths
package/lib/index.js CHANGED
@@ -24,7 +24,6 @@ const legacyPluralize = require('./helpers/pluralize');
24
24
  const utils = require('./utils');
25
25
  const pkg = require('../package.json');
26
26
  const cast = require('./cast');
27
- const clearValidating = require('./plugins/clearValidating');
28
27
  const removeSubdocs = require('./plugins/removeSubdocs');
29
28
  const saveSubdocs = require('./plugins/saveSubdocs');
30
29
  const trackTransaction = require('./plugins/trackTransaction');
@@ -107,8 +106,7 @@ function Mongoose(options) {
107
106
  [validateBeforeSave, { deduplicate: true }],
108
107
  [shardingPlugin, { deduplicate: true }],
109
108
  [removeSubdocs, { deduplicate: true }],
110
- [trackTransaction, { deduplicate: true }],
111
- [clearValidating, { deduplicate: true }]
109
+ [trackTransaction, { deduplicate: true }]
112
110
  ]
113
111
  });
114
112
  }
package/lib/model.js CHANGED
@@ -245,8 +245,7 @@ function _applyCustomWhere(doc, where) {
245
245
  */
246
246
 
247
247
  Model.prototype.$__handleSave = function(options, callback) {
248
- const _this = this;
249
- let saveOptions = {};
248
+ const saveOptions = {};
250
249
 
251
250
  applyWriteConcern(this.$__schema, options);
252
251
  if (typeof options.writeConcern !== 'undefined') {
@@ -274,14 +273,10 @@ Model.prototype.$__handleSave = function(options, callback) {
274
273
  if ('checkKeys' in options) {
275
274
  saveOptions.checkKeys = options.checkKeys;
276
275
  }
277
- const session = this.$session();
278
276
  if (!saveOptions.hasOwnProperty('session')) {
279
- saveOptions.session = session;
277
+ saveOptions.session = this.$session();
280
278
  }
281
279
 
282
- if (Object.keys(saveOptions).length === 0) {
283
- saveOptions = null;
284
- }
285
280
  if (this.$isNew) {
286
281
  // send entire doc
287
282
  const obj = this.toObject(saveToObjectOptions);
@@ -298,9 +293,9 @@ Model.prototype.$__handleSave = function(options, callback) {
298
293
  }
299
294
 
300
295
  this.$__version(true, obj);
301
- this[modelCollectionSymbol].insertOne(obj, saveOptions, function(err, ret) {
296
+ this[modelCollectionSymbol].insertOne(obj, saveOptions, (err, ret) => {
302
297
  if (err) {
303
- _setIsNew(_this, true);
298
+ _setIsNew(this, true);
304
299
 
305
300
  callback(err, null);
306
301
  return;
@@ -308,64 +303,67 @@ Model.prototype.$__handleSave = function(options, callback) {
308
303
 
309
304
  callback(null, ret);
310
305
  });
306
+
311
307
  this.$__reset();
312
308
  _setIsNew(this, false);
313
309
  // Make it possible to retry the insert
314
310
  this.$__.inserting = true;
315
- } else {
316
- // Make sure we don't treat it as a new object on error,
317
- // since it already exists
318
- this.$__.inserting = false;
319
-
320
- const delta = this.$__delta();
321
- if (delta) {
322
- if (delta instanceof MongooseError) {
323
- callback(delta);
324
- return;
325
- }
326
311
 
327
- const where = this.$__where(delta[0]);
328
- if (where instanceof MongooseError) {
329
- callback(where);
330
- return;
331
- }
312
+ return;
313
+ }
332
314
 
333
- _applyCustomWhere(this, where);
334
- this[modelCollectionSymbol].updateOne(where, delta[1], saveOptions, (err, ret) => {
335
- if (err) {
336
- this.$__undoReset();
315
+ // Make sure we don't treat it as a new object on error,
316
+ // since it already exists
317
+ this.$__.inserting = false;
337
318
 
338
- callback(err);
339
- return;
340
- }
341
- ret.$where = where;
342
- callback(null, ret);
343
- });
344
- } else {
345
- const optionsWithCustomValues = Object.assign({}, options, saveOptions);
346
- const where = this.$__where();
347
- if (this.$__schema.options.optimisticConcurrency) {
348
- const key = this.$__schema.options.versionKey;
349
- const val = this.$__getValue(key);
350
- if (val != null) {
351
- where[key] = val;
352
- }
353
- }
354
- this.constructor.exists(where, optionsWithCustomValues)
355
- .then(documentExists => {
356
- const matchedCount = !documentExists ? 0 : 1;
357
- callback(null, { $where: where, matchedCount });
358
- })
359
- .catch(callback);
319
+ const delta = this.$__delta();
320
+ if (delta) {
321
+ if (delta instanceof MongooseError) {
322
+ callback(delta);
360
323
  return;
361
324
  }
362
325
 
363
- // store the modified paths before the document is reset
364
- this.$__.modifiedPaths = this.modifiedPaths();
365
- this.$__reset();
326
+ const where = this.$__where(delta[0]);
327
+ if (where instanceof MongooseError) {
328
+ callback(where);
329
+ return;
330
+ }
366
331
 
367
- _setIsNew(this, false);
332
+ _applyCustomWhere(this, where);
333
+ this[modelCollectionSymbol].updateOne(where, delta[1], saveOptions, (err, ret) => {
334
+ if (err) {
335
+ this.$__undoReset();
336
+
337
+ callback(err);
338
+ return;
339
+ }
340
+ ret.$where = where;
341
+ callback(null, ret);
342
+ });
343
+ } else {
344
+ const optionsWithCustomValues = Object.assign({}, options, saveOptions);
345
+ const where = this.$__where();
346
+ if (this.$__schema.options.optimisticConcurrency) {
347
+ const key = this.$__schema.options.versionKey;
348
+ const val = this.$__getValue(key);
349
+ if (val != null) {
350
+ where[key] = val;
351
+ }
352
+ }
353
+ this.constructor.exists(where, optionsWithCustomValues)
354
+ .then(documentExists => {
355
+ const matchedCount = !documentExists ? 0 : 1;
356
+ callback(null, { $where: where, matchedCount });
357
+ })
358
+ .catch(callback);
359
+ return;
368
360
  }
361
+
362
+ // store the modified paths before the document is reset
363
+ this.$__.modifiedPaths = this.modifiedPaths();
364
+ this.$__reset();
365
+
366
+ _setIsNew(this, false);
369
367
  };
370
368
 
371
369
  /*!
@@ -374,8 +372,8 @@ Model.prototype.$__handleSave = function(options, callback) {
374
372
 
375
373
  Model.prototype.$__save = function(options, callback) {
376
374
  this.$__handleSave(options, (error, result) => {
377
- const hooks = this.$__schema.s.hooks;
378
375
  if (error) {
376
+ const hooks = this.$__schema.s.hooks;
379
377
  return hooks.execPost('save:error', this, [this], { error: error }, (error) => {
380
378
  callback(error, this);
381
379
  });
@@ -423,6 +421,7 @@ Model.prototype.$__save = function(options, callback) {
423
421
  this.$__undoReset();
424
422
  error = new DocumentNotFoundError(result.$where,
425
423
  this.constructor.modelName, numAffected, result);
424
+ const hooks = this.$__schema.s.hooks;
426
425
  return hooks.execPost('save:error', this, [this], { error: error }, (error) => {
427
426
  callback(error, this);
428
427
  });
@@ -516,9 +515,9 @@ Model.prototype.save = function(options, fn) {
516
515
  this.$__.saveOptions = options;
517
516
 
518
517
  this.$__save(options, error => {
519
- this.$__.saving = undefined;
520
- delete this.$__.saveOptions;
521
- delete this.$__.$versionError;
518
+ this.$__.saving = null;
519
+ this.$__.saveOptions = null;
520
+ this.$__.$versionError = null;
522
521
  this.$op = null;
523
522
 
524
523
  if (error) {
@@ -48,6 +48,13 @@ Object.defineProperty(SchemaDateOptions.prototype, 'max', opts);
48
48
  /**
49
49
  * If set, Mongoose creates a TTL index on this path.
50
50
  *
51
+ * mongo TTL index `expireAfterSeconds` value will take 'expires' value expressed in seconds.
52
+ *
53
+ * ####Example:
54
+ *
55
+ * const schema = new Schema({ "expireAt": { type: Date, expires: 11 } });
56
+ * // if 'expireAt' is set, then document expires at expireAt + 11 seconds
57
+ *
51
58
  * @api public
52
59
  * @property expires
53
60
  * @memberOf SchemaDateOptions
@@ -61,4 +68,4 @@ Object.defineProperty(SchemaDateOptions.prototype, 'expires', opts);
61
68
  * ignore
62
69
  */
63
70
 
64
- module.exports = SchemaDateOptions;
71
+ module.exports = SchemaDateOptions;
package/lib/query.js CHANGED
@@ -39,6 +39,31 @@ const utils = require('./utils');
39
39
  const validOps = require('./helpers/query/validOps');
40
40
  const wrapThunk = require('./helpers/query/wrapThunk');
41
41
 
42
+ const queryOptionMethods = new Set([
43
+ 'allowDiskUse',
44
+ 'batchSize',
45
+ 'collation',
46
+ 'comment',
47
+ 'explain',
48
+ 'hint',
49
+ 'j',
50
+ 'lean',
51
+ 'limit',
52
+ 'maxScan',
53
+ 'maxTimeMS',
54
+ 'maxscan',
55
+ 'projection',
56
+ 'read',
57
+ 'select',
58
+ 'skip',
59
+ 'slice',
60
+ 'sort',
61
+ 'tailable',
62
+ 'w',
63
+ 'writeConcern',
64
+ 'wtimeout'
65
+ ]);
66
+
42
67
  /**
43
68
  * Query constructor used for building queries. You do not need
44
69
  * to instantiate a `Query` directly. Instead use Model functions like
@@ -1630,7 +1655,19 @@ Query.prototype.setOptions = function(options, overwrite) {
1630
1655
  }
1631
1656
  }
1632
1657
 
1633
- return Query.base.setOptions.call(this, options);
1658
+ // set arbitrary options
1659
+ for (const key of Object.keys(options)) {
1660
+ if (queryOptionMethods.has(key)) {
1661
+ const args = Array.isArray(options[key]) ?
1662
+ options[key] :
1663
+ [options[key]];
1664
+ this[key].apply(this, args);
1665
+ } else {
1666
+ this.options[key] = options[key];
1667
+ }
1668
+ }
1669
+
1670
+ return this;
1634
1671
  };
1635
1672
 
1636
1673
  /**
@@ -5696,4 +5733,4 @@ Query.prototype.model;
5696
5733
  * Export
5697
5734
  */
5698
5735
 
5699
- module.exports = Query;
5736
+ module.exports = Query;
package/lib/schematype.js CHANGED
@@ -22,6 +22,8 @@ const populateModelSymbol = require('./helpers/symbols').populateModelSymbol;
22
22
  const CastError = MongooseError.CastError;
23
23
  const ValidatorError = MongooseError.ValidatorError;
24
24
 
25
+ const setOptionsForDefaults = { _skipMarkModified: true };
26
+
25
27
  /**
26
28
  * SchemaType constructor. Do **not** instantiate `SchemaType` directly.
27
29
  * Mongoose converts your schema paths into SchemaTypes automatically.
@@ -1124,7 +1126,7 @@ SchemaType.prototype.getDefault = function(scope, init) {
1124
1126
  ret = utils.clone(ret);
1125
1127
  }
1126
1128
 
1127
- const casted = this.applySetters(ret, scope, init);
1129
+ const casted = this.applySetters(ret, scope, init, undefined, setOptionsForDefaults);
1128
1130
  if (casted && !Array.isArray(casted) && casted.$isSingleNested) {
1129
1131
  casted.$__parent = scope;
1130
1132
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "mongoose",
3
3
  "description": "Mongoose MongoDB ODM",
4
- "version": "6.2.8",
4
+ "version": "6.2.9",
5
5
  "author": "Guillermo Rauch <guillermo@learnboost.com>",
6
6
  "keywords": [
7
7
  "mongodb",
@@ -20,7 +20,7 @@
20
20
  "license": "MIT",
21
21
  "dependencies": {
22
22
  "bson": "^4.2.2",
23
- "kareem": "2.3.4",
23
+ "kareem": "2.3.5",
24
24
  "mongodb": "4.3.1",
25
25
  "mpath": "0.8.4",
26
26
  "mquery": "4.0.2",
@@ -28,26 +28,26 @@
28
28
  "sift": "16.0.0"
29
29
  },
30
30
  "devDependencies": {
31
- "@babel/core": "7.17.5",
31
+ "@babel/core": "7.17.8",
32
32
  "@babel/preset-env": "7.16.11",
33
- "@typescript-eslint/eslint-plugin": "5.12.0",
34
- "@typescript-eslint/parser": "5.12.0",
33
+ "@typescript-eslint/eslint-plugin": "5.16.0",
34
+ "@typescript-eslint/parser": "5.16.0",
35
35
  "acquit": "1.x",
36
36
  "acquit-ignore": "0.2.x",
37
37
  "acquit-require": "0.1.x",
38
38
  "axios": "0.26.1",
39
- "babel-loader": "8.2.3",
39
+ "babel-loader": "8.2.4",
40
40
  "benchmark": "2.1.4",
41
41
  "bluebird": "3.7.2",
42
42
  "cheerio": "1.0.0-rc.10",
43
43
  "dox": "0.3.1",
44
- "eslint": "8.9.0",
44
+ "eslint": "8.11.0",
45
45
  "eslint-plugin-mocha-no-only": "1.1.1",
46
46
  "highlight.js": "9.18.3",
47
47
  "lodash.isequal": "4.5.0",
48
48
  "lodash.isequalwith": "4.4.0",
49
- "marked": "2.1.3",
50
- "mocha": "9.2.1",
49
+ "marked": "4.0.12",
50
+ "mocha": "9.2.2",
51
51
  "moment": "2.x",
52
52
  "mongodb-memory-server": "^8.3.0",
53
53
  "nyc": "^15.1.0",
@@ -55,7 +55,7 @@
55
55
  "q": "1.5.1",
56
56
  "serve-handler": "6.1.3",
57
57
  "tsd": "0.19.1",
58
- "typescript": "4.5.5",
58
+ "typescript": "4.6.3",
59
59
  "uuid": "8.3.2",
60
60
  "webpack": "4.44.1"
61
61
  },
package/tools/repl.js CHANGED
@@ -5,7 +5,7 @@ run().catch(error => {
5
5
  process.exit(-1);
6
6
  });
7
7
 
8
- async function run () {
8
+ async function run() {
9
9
  const ReplSet = require('mongodb-memory-server').MongoMemoryReplSet;
10
10
 
11
11
  // Create new instance
@@ -15,20 +15,20 @@ async function run () {
15
15
  },
16
16
  instanceOpts: [
17
17
  // Set the expiry job in MongoDB to run every second
18
- {
18
+ {
19
19
  port: 27017,
20
- args: ["--setParameter", "ttlMonitorSleepSecs=1"] },
20
+ args: ['--setParameter', 'ttlMonitorSleepSecs=1'] }
21
21
  ],
22
22
  dbName: 'mongoose_test',
23
23
  replSet: {
24
- name: "rs0",
24
+ name: 'rs0',
25
25
  count: 2,
26
- storageEngine: "wiredTiger",
27
- },
26
+ storageEngine: 'wiredTiger'
27
+ }
28
28
  });
29
29
 
30
30
  await replSet.start();
31
31
  await replSet.waitUntilRunning();
32
- console.log("MongoDB-ReplicaSet is now running.")
33
- console.log(replSet.getUri("mongoose_test"));
32
+ console.log('MongoDB-ReplicaSet is now running.');
33
+ console.log(replSet.getUri('mongoose_test'));
34
34
  }
package/tools/sharded.js CHANGED
@@ -6,7 +6,7 @@ run().catch(error => {
6
6
  });
7
7
 
8
8
 
9
- async function run () {
9
+ async function run() {
10
10
  const Sharded = require('mongodb-topology-manager').Sharded;
11
11
 
12
12
  // Create new instance
@@ -17,13 +17,13 @@ async function run () {
17
17
 
18
18
  await topology.addShard([{
19
19
  options: {
20
- bind_ip: 'localhost', port: 31000, dbpath: `/data/db/31000`, shardsvr: null
20
+ bind_ip: 'localhost', port: 31000, dbpath: '/data/db/31000', shardsvr: null
21
21
  }
22
22
  }], { replSet: 'rs1' });
23
23
 
24
24
  await topology.addConfigurationServers([{
25
25
  options: {
26
- bind_ip: 'localhost', port: 35000, dbpath: `/data/db/35000`
26
+ bind_ip: 'localhost', port: 35000, dbpath: '/data/db/35000'
27
27
  }
28
28
  }], { replSet: 'rs0' });
29
29