mongoose 5.0.18 → 5.1.0

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/.travis.yml CHANGED
@@ -1,6 +1,7 @@
1
1
  language: node_js
2
2
  sudo: false
3
3
  node_js:
4
+ - "10"
4
5
  - "9"
5
6
  - "8"
6
7
  - "7"
@@ -8,11 +9,11 @@ node_js:
8
9
  - "5"
9
10
  - "4"
10
11
  before_script:
11
- - wget http://fastdl.mongodb.org/linux/mongodb-linux-x86_64-3.0.15.tgz
12
- - tar -zxvf mongodb-linux-x86_64-3.0.15.tgz
12
+ - wget http://fastdl.mongodb.org/linux/mongodb-linux-x86_64-3.6.4.tgz
13
+ - tar -zxvf mongodb-linux-x86_64-3.6.4.tgz
13
14
  - mkdir -p ./data/db/27017
14
15
  - mkdir -p ./data/db/27000
15
- - ./mongodb-linux-x86_64-3.0.15/bin/mongod --storageEngine mmapv1 --fork --nopreallocj --dbpath ./data/db/27017 --syslog --port 27017
16
+ - ./mongodb-linux-x86_64-3.6.4/bin/mongod --fork --nopreallocj --dbpath ./data/db/27017 --syslog --port 27017
16
17
  script:
17
18
  - npm test
18
19
  - npm run lint
package/History.md CHANGED
@@ -1,3 +1,19 @@
1
+ 5.1.0 / 2018-05-10
2
+ ==================
3
+ * feat(ObjectId): add `_id` getter so you can get a usable id whether or not the path is populated #6415 #6115
4
+ * feat(model): add Model.startSession() #6362
5
+ * feat(document): add doc.$session() and set session on doc after query #6362
6
+ * feat: add Map type that supports arbitrary keys #6287 #681
7
+ * feat: add `cloneSchemas` option to mongoose global to opt in to always cloning schemas before use #6274
8
+ * feat(model): add `findOneAndDelete()` and `findByIdAndDelete()` #6164
9
+ * feat(document): support `$ignore()` on single nested and array subdocs #6152
10
+ * feat(document): add warning about calling `save()` on subdocs #6152
11
+ * fix(model): make `save()` use `updateOne()` instead of `update()` #6031
12
+ * feat(error): add version number to VersionError #5966
13
+ * fix(query): allow `[]` as a value for `$in` when casting #5913
14
+ * fix(document): avoid running validators on single nested paths if only a child path is modified #5885
15
+ * feat(schema): print warning if method conflicts with mongoose internals #5860
16
+
1
17
  5.0.18 / 2018-05-09
2
18
  ===================
3
19
  * fix(update): stop clobbering $in when casting update #6441 #6339 [lineus](https://github.com/lineus)
package/lib/document.js CHANGED
@@ -326,7 +326,10 @@ function $__applyDefaults(doc, fields, skipId, exclude, hasIncludedChildren, isB
326
326
  Document.prototype.$__buildDoc = function(obj, fields, skipId, exclude, hasIncludedChildren) {
327
327
  const doc = {};
328
328
 
329
- const paths = Object.keys(this.schema.paths);
329
+ const paths = Object.keys(this.schema.paths).
330
+ // Don't build up any paths that are underneath a map, we don't know
331
+ // what the keys will be
332
+ filter(p => !p.includes('$*'));
330
333
  const plen = paths.length;
331
334
  let ii = 0;
332
335
 
@@ -541,6 +544,26 @@ Document.prototype.update = function update() {
541
544
  return this.constructor.update.apply(this.constructor, args);
542
545
  };
543
546
 
547
+ /**
548
+ * Getter/setter around the session associated with this document. Used to
549
+ * automatically set `session` if you `save()` a doc that you got from a
550
+ * query with an associated session.
551
+ *
552
+ * @param {ClientSession} [session] overwrite the current session
553
+ * @return {ClientSession}
554
+ * @method $session
555
+ * @api public
556
+ * @memberOf Document
557
+ */
558
+
559
+ Document.prototype.$session = function $session(session) {
560
+ if (arguments.length === 0) {
561
+ return this.$__.session;
562
+ }
563
+ this.$__.session = session;
564
+ return session;
565
+ };
566
+
544
567
  /**
545
568
  * Alias for `set()`, used internally to avoid conflicts
546
569
  *
@@ -978,7 +1001,11 @@ Document.prototype.$__set = function(pathToMark, path, constructing, parts, sche
978
1001
  cur += (cur ? '.' + parts[i] : parts[i]);
979
1002
 
980
1003
  if (last) {
981
- obj[parts[i]] = val;
1004
+ if (obj instanceof Map) {
1005
+ obj.set(parts[i], val);
1006
+ } else {
1007
+ obj[parts[i]] = val;
1008
+ }
982
1009
  } else {
983
1010
  if (obj[parts[i]] && utils.getFunctionName(obj[parts[i]].constructor) === 'Object') {
984
1011
  obj = obj[parts[i]];
@@ -1055,9 +1082,13 @@ Document.prototype.get = function(path, type, options) {
1055
1082
  }
1056
1083
 
1057
1084
  for (var i = 0, l = pieces.length; i < l; i++) {
1058
- obj = obj === null || obj === void 0
1059
- ? undefined
1060
- : obj[pieces[i]];
1085
+ if (obj == null) {
1086
+ obj = void 0;
1087
+ } else if (obj instanceof Map) {
1088
+ obj = obj.get(pieces[i]);
1089
+ } else {
1090
+ obj = obj[pieces[i]];
1091
+ }
1061
1092
  }
1062
1093
 
1063
1094
  if (adhoc) {
@@ -1485,6 +1516,7 @@ Document.prototype.validate = function(options, callback) {
1485
1516
  function _getPathsToValidate(doc) {
1486
1517
  var i;
1487
1518
  var len;
1519
+ var skipSchemaValidators = {};
1488
1520
 
1489
1521
  // only validate required fields when necessary
1490
1522
  var paths = Object.keys(doc.$__.activePaths.states.require).filter(function(path) {
@@ -1517,6 +1549,7 @@ function _getPathsToValidate(doc) {
1517
1549
  return p != null && p.indexOf(subdoc.$basePath + '.') !== 0;
1518
1550
  });
1519
1551
  paths.push(subdoc.$basePath);
1552
+ skipSchemaValidators[subdoc.$basePath] = true;
1520
1553
  }
1521
1554
  }
1522
1555
  }
@@ -1563,7 +1596,24 @@ function _getPathsToValidate(doc) {
1563
1596
  }
1564
1597
  }
1565
1598
 
1566
- return paths;
1599
+ len = paths.length;
1600
+ for (i = 0; i < len; ++i) {
1601
+ const path = paths[i];
1602
+ const _pathType = doc.schema.path(path);
1603
+ if (!_pathType || !_pathType.$isSchemaMap) {
1604
+ continue;
1605
+ }
1606
+
1607
+ const val = doc.getValue(path);
1608
+ if (val == null) {
1609
+ continue;
1610
+ }
1611
+ for (let key of val.keys()) {
1612
+ paths.push(path + '.' + key);
1613
+ }
1614
+ }
1615
+
1616
+ return [paths, skipSchemaValidators];
1567
1617
  }
1568
1618
 
1569
1619
  /*!
@@ -1590,7 +1640,9 @@ Document.prototype.$__validate = function(callback) {
1590
1640
  };
1591
1641
 
1592
1642
  // only validate required fields when necessary
1593
- const paths = _getPathsToValidate(this);
1643
+ const pathDetails = _getPathsToValidate(this);
1644
+ const paths = pathDetails[0];
1645
+ const skipSchemaValidators = pathDetails[1];
1594
1646
 
1595
1647
  if (paths.length === 0) {
1596
1648
  return process.nextTick(function() {
@@ -1627,6 +1679,7 @@ Document.prototype.$__validate = function(callback) {
1627
1679
 
1628
1680
  process.nextTick(function() {
1629
1681
  const p = _this.schema.path(path);
1682
+
1630
1683
  if (!p) {
1631
1684
  return --total || complete();
1632
1685
  }
@@ -1647,7 +1700,7 @@ Document.prototype.$__validate = function(callback) {
1647
1700
  _this.invalidate(path, err, undefined, true);
1648
1701
  }
1649
1702
  --total || complete();
1650
- }, scope);
1703
+ }, scope, { skipSchemaValidators: skipSchemaValidators[path] });
1651
1704
  });
1652
1705
  };
1653
1706
 
@@ -1679,14 +1732,16 @@ Document.prototype.$__validate = function(callback) {
1679
1732
  */
1680
1733
 
1681
1734
  Document.prototype.validateSync = function(pathsToValidate) {
1682
- var _this = this;
1735
+ const _this = this;
1683
1736
 
1684
1737
  if (typeof pathsToValidate === 'string') {
1685
1738
  pathsToValidate = pathsToValidate.split(' ');
1686
1739
  }
1687
1740
 
1688
1741
  // only validate required fields when necessary
1689
- var paths = _getPathsToValidate(this);
1742
+ const pathDetails = _getPathsToValidate(this);
1743
+ let paths = pathDetails[0];
1744
+ const skipSchemaValidators = pathDetails[1];
1690
1745
 
1691
1746
  if (pathsToValidate && pathsToValidate.length) {
1692
1747
  var tmp = [];
@@ -1716,7 +1771,9 @@ Document.prototype.validateSync = function(pathsToValidate) {
1716
1771
  }
1717
1772
 
1718
1773
  var val = _this.getValue(path);
1719
- var err = p.doValidateSync(val, _this);
1774
+ var err = p.doValidateSync(val, _this, {
1775
+ skipSchemaValidators: skipSchemaValidators[path]
1776
+ });
1720
1777
  if (err) {
1721
1778
  _this.invalidate(path, err, undefined, true);
1722
1779
  }
@@ -2691,7 +2748,6 @@ Document.prototype.execPopulate = function() {
2691
2748
 
2692
2749
  Document.prototype.populated = function(path, val, options) {
2693
2750
  // val and options are internal
2694
-
2695
2751
  if (val === null || val === void 0) {
2696
2752
  if (!this.$__.populated) {
2697
2753
  return undefined;
@@ -7,6 +7,18 @@
7
7
 
8
8
  var ObjectId = require('bson').ObjectID;
9
9
 
10
+ /*!
11
+ * Getter for convenience with populate, see gh-6115
12
+ */
13
+
14
+ Object.defineProperty(ObjectId.prototype, '_id', {
15
+ enumerable: false,
16
+ configurable: true,
17
+ get: function() {
18
+ return this;
19
+ }
20
+ });
21
+
10
22
  /*!
11
23
  * ignore
12
24
  */
@@ -1,10 +1,13 @@
1
+ 'use strict';
2
+
1
3
  /*!
2
4
  * Module dependencies.
3
5
  */
4
6
 
5
- var MongooseCollection = require('../../collection');
6
- var Collection = require('mongodb').Collection;
7
- var utils = require('../../utils');
7
+ const MongooseCollection = require('../../collection');
8
+ const Collection = require('mongodb').Collection;
9
+ const get = require('lodash.get');
10
+ const utils = require('../../utils');
8
11
 
9
12
  /**
10
13
  * A [node-mongodb-native](https://github.com/mongodb/node-mongodb-native) collection implementation.
@@ -248,6 +251,10 @@ function format(obj, sub) {
248
251
  formatObjectId(x, key);
249
252
  } else if (x[key].constructor.name === 'Date') {
250
253
  formatDate(x, key);
254
+ } else if (x[key].constructor.name === 'ClientSession') {
255
+ representation = 'ClientSession("' +
256
+ get(x[key], 'id.id.buffer', '').toString('hex') + '")';
257
+ x[key] = {inspect: function() { return representation; }};
251
258
  } else if (Array.isArray(x[key])) {
252
259
  x[key] = x[key].map(map);
253
260
  }
@@ -13,10 +13,11 @@ var MongooseError = require('./');
13
13
  * @api private
14
14
  */
15
15
 
16
- function VersionError(doc) {
16
+ function VersionError(doc, currentVersion) {
17
17
  MongooseError.call(this, 'No matching document found for id "' + doc._id +
18
- '"');
18
+ '" version ' + currentVersion);
19
19
  this.name = 'VersionError';
20
+ this.version = currentVersion;
20
21
  }
21
22
 
22
23
  /*!
package/lib/index.js CHANGED
@@ -80,6 +80,7 @@ Mongoose.prototype.STATES = STATES;
80
80
  * - 'debug': prints the operations mongoose sends to MongoDB to the console
81
81
  * - 'bufferCommands': enable/disable mongoose's buffering mechanism for all connections and models
82
82
  * - 'useFindAndModify': true by default. Set to `false` to make `findOneAndUpdate()` and `findOneAndRemove()` use native `findOneAndUpdate()` rather than `findAndModify()`.
83
+ * - 'cloneSchemas': false by default. Set to `true` to `clone()` all schemas before compiling into a model.
83
84
  *
84
85
  * @param {String} key
85
86
  * @param {String|Function|Boolean} value
@@ -291,7 +292,7 @@ Mongoose.prototype.pluralize = function(fn) {
291
292
  */
292
293
 
293
294
  Mongoose.prototype.model = function(name, schema, collection, skipInit) {
294
- var model;
295
+ let model;
295
296
  if (typeof name === 'function') {
296
297
  model = name;
297
298
  name = model.name;
@@ -319,7 +320,7 @@ Mongoose.prototype.model = function(name, schema, collection, skipInit) {
319
320
  }
320
321
 
321
322
  // handle internal options from connection.model()
322
- var options;
323
+ let options;
323
324
  if (skipInit && utils.isObject(skipInit)) {
324
325
  options = skipInit;
325
326
  skipInit = true;
@@ -337,16 +338,20 @@ Mongoose.prototype.model = function(name, schema, collection, skipInit) {
337
338
  }
338
339
  }
339
340
 
341
+ const originalSchema = schema;
340
342
  if (schema) {
343
+ if (this.get('cloneSchemas')) {
344
+ schema = schema.clone();
345
+ }
341
346
  this._applyPlugins(schema);
342
347
  }
343
348
 
344
- var sub;
349
+ let sub;
345
350
 
346
351
  // connection.model() may be passing a different schema for
347
352
  // an existing model name. in this case don't read from cache.
348
353
  if (this.models[name] && options.cache !== false) {
349
- if (schema && schema.instanceOfSchema && schema !== this.models[name].schema) {
354
+ if (originalSchema && originalSchema.instanceOfSchema && originalSchema !== this.models[name].schema) {
350
355
  throw new mongoose.Error.OverwriteModelError(name);
351
356
  }
352
357
 
@@ -380,7 +385,7 @@ Mongoose.prototype.model = function(name, schema, collection, skipInit) {
380
385
  utils.toCollectionName(name, this.pluralize());
381
386
  }
382
387
 
383
- var connection = options.connection || this.connection;
388
+ const connection = options.connection || this.connection;
384
389
  model = this.Model.compile(model || name, schema, collection, connection, this);
385
390
 
386
391
  if (!skipInit) {
package/lib/internal.js CHANGED
@@ -25,6 +25,7 @@ function InternalCache() {
25
25
  this.scope = undefined;
26
26
  this.activePaths = new ActiveRoster;
27
27
  this.pathsToScopes = {};
28
+ this.session = null;
28
29
 
29
30
  // embedded docs
30
31
  this.ownerDocument = undefined;