mongoose 5.4.0 → 5.4.4

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/schema/map.js CHANGED
@@ -11,7 +11,7 @@ const SchemaType = require('../schematype');
11
11
  * ignore
12
12
  */
13
13
 
14
- class SchemaMap extends SchemaType {
14
+ class Map extends SchemaType {
15
15
  constructor(key, options) {
16
16
  super(key, options, 'Map');
17
17
  this.$isSchemaMap = true;
@@ -26,7 +26,7 @@ class SchemaMap extends SchemaType {
26
26
  const map = new MongooseMap({}, this.path, doc, this.$__schemaType);
27
27
 
28
28
  for (const key of Object.keys(val)) {
29
- map.$__set(key, this.$__schemaType.cast(val[key], doc, true));
29
+ map.$init(key, this.$__schemaType.cast(val[key], doc, true));
30
30
  }
31
31
 
32
32
  return map;
@@ -36,4 +36,4 @@ class SchemaMap extends SchemaType {
36
36
  }
37
37
  }
38
38
 
39
- module.exports = SchemaMap;
39
+ module.exports = Map;
@@ -48,19 +48,20 @@ SchemaString.prototype.constructor = SchemaString;
48
48
  SchemaString._cast = castString;
49
49
 
50
50
  /**
51
- * Get/set the function used to cast arbitrary values to objectids.
51
+ * Get/set the function used to cast arbitrary values to strings.
52
52
  *
53
53
  * ####Example:
54
54
  *
55
- * // Make Mongoose only try to cast strings
56
- * const original = mongoose.ObjectId.cast();
57
- * mongoose.ObjectId.cast(v => {
58
- * assert.ok(v == null || typeof v === 'string');
55
+ * // Throw an error if you pass in an object. Normally, Mongoose allows
56
+ * // objects with custom `toString()` functions.
57
+ * const original = mongoose.Schema.Types.String.cast();
58
+ * mongoose.Schema.Types.String.cast(v => {
59
+ * assert.ok(v == null || typeof v !== 'object');
59
60
  * return original(v);
60
61
  * });
61
62
  *
62
63
  * // Or disable casting entirely
63
- * mongoose.ObjectId.cast(false);
64
+ * mongoose.Schema.Types.String.cast(false);
64
65
  *
65
66
  * @param {Function} caster
66
67
  * @return {Function}
@@ -1,3 +1,5 @@
1
1
  'use strict';
2
2
 
3
- exports.schemaMixedSymbol = Symbol.for('mongoose:schema_mixed');
3
+ exports.schemaMixedSymbol = Symbol.for('mongoose:schema_mixed');
4
+
5
+ exports.builtInMiddleware = Symbol.for('mongoose:built-in-middleware');
package/lib/schema.js CHANGED
@@ -16,6 +16,7 @@ const handleTimestampOption = require('./helpers/schema/handleTimestampOption');
16
16
  const merge = require('./helpers/schema/merge');
17
17
  const mpath = require('mpath');
18
18
  const readPref = require('./driver').get().ReadPreference;
19
+ const symbols = require('./schema/symbols');
19
20
  const util = require('util');
20
21
  const utils = require('./utils');
21
22
  const validateRef = require('./helpers/populate/validateRef');
@@ -272,6 +273,7 @@ Schema.prototype.tree;
272
273
 
273
274
  Schema.prototype.clone = function() {
274
275
  const s = new Schema({}, this._userProvidedOptions);
276
+ s.base = this.base;
275
277
  s.obj = this.obj;
276
278
  s.options = utils.clone(this.options);
277
279
  s.callQueue = this.callQueue.map(function(f) { return f; });
@@ -463,6 +465,7 @@ reserved.schema =
463
465
  reserved.toObject =
464
466
  reserved.validate =
465
467
  reserved.remove =
468
+ reserved.populated =
466
469
  // hooks.js
467
470
  reserved._pres = reserved._posts = 1;
468
471
 
@@ -492,13 +495,13 @@ warnings.increment = '`increment` should not be used as a schema path name ' +
492
495
 
493
496
  Schema.prototype.path = function(path, obj) {
494
497
  if (obj === undefined) {
495
- if (this.paths[path]) {
498
+ if (this.paths.hasOwnProperty(path)) {
496
499
  return this.paths[path];
497
500
  }
498
- if (this.subpaths[path]) {
501
+ if (this.subpaths.hasOwnProperty(path)) {
499
502
  return this.subpaths[path];
500
503
  }
501
- if (this.singleNestedPaths[path]) {
504
+ if (this.singleNestedPaths.hasOwnProperty(path)) {
502
505
  return this.singleNestedPaths[path];
503
506
  }
504
507
 
@@ -576,11 +579,27 @@ Schema.prototype.path = function(path, obj) {
576
579
  schemaType.schema.singleNestedPaths[key];
577
580
  }
578
581
 
582
+ Object.defineProperty(schemaType.schema, 'base', {
583
+ configurable: true,
584
+ enumerable: false,
585
+ writable: false,
586
+ value: this.base
587
+ });
588
+
589
+ schemaType.caster.base = this.base;
579
590
  this.childSchemas.push({
580
591
  schema: schemaType.schema,
581
592
  model: schemaType.caster
582
593
  });
583
594
  } else if (schemaType.$isMongooseDocumentArray) {
595
+ Object.defineProperty(schemaType.schema, 'base', {
596
+ configurable: true,
597
+ enumerable: false,
598
+ writable: false,
599
+ value: this.base
600
+ });
601
+
602
+ schemaType.casterConstructor.base = this.base;
584
603
  this.childSchemas.push({
585
604
  schema: schemaType.schema,
586
605
  model: schemaType.casterConstructor
@@ -590,6 +609,20 @@ Schema.prototype.path = function(path, obj) {
590
609
  return this;
591
610
  };
592
611
 
612
+ /**
613
+ * The Mongoose instance this schema is associated with
614
+ *
615
+ * @property base
616
+ * @api private
617
+ */
618
+
619
+ Object.defineProperty(Schema.prototype, 'base', {
620
+ configurable: true,
621
+ enumerable: false,
622
+ writable: true,
623
+ value: null
624
+ });
625
+
593
626
  /**
594
627
  * Converts type arguments into Mongoose Types.
595
628
  *
@@ -682,8 +715,9 @@ Schema.prototype.interpretAsType = function(path, obj, options) {
682
715
  : type.schemaName || utils.getFunctionName(type);
683
716
 
684
717
  if (!(name in MongooseTypes)) {
685
- throw new TypeError('Undefined type `' + name + '` at array `' + path +
686
- '`');
718
+ throw new TypeError('Invalid schema configuration: ' +
719
+ `\`${name}\` is not a valid type within the array \`${path}\`.` +
720
+ 'See http://bit.ly/mongoose-schematypes for a list of valid schema types.');
687
721
  }
688
722
  }
689
723
 
@@ -696,12 +730,10 @@ Schema.prototype.interpretAsType = function(path, obj, options) {
696
730
 
697
731
  if (Buffer.isBuffer(type)) {
698
732
  name = 'Buffer';
733
+ } else if (typeof type === 'function' || typeof type === 'object') {
734
+ name = type.schemaName || utils.getFunctionName(type);
699
735
  } else {
700
- name = typeof type === 'string'
701
- ? type
702
- // If not string, `type` is a function. Outside of IE, function.name
703
- // gives you the function name. In IE, you need to compute it
704
- : type.schemaName || utils.getFunctionName(type);
736
+ name = type == null ? '' + type : type.toString();
705
737
  }
706
738
 
707
739
  if (name) {
@@ -713,10 +745,10 @@ Schema.prototype.interpretAsType = function(path, obj, options) {
713
745
  name = 'ObjectId';
714
746
  }
715
747
 
716
- if (undefined == MongooseTypes[name]) {
717
- throw new TypeError('Undefined type `' + name + '` at `' + path +
718
- '`\n Did you try nesting Schemas? ' +
719
- 'You can only nest using refs or arrays.');
748
+ if (MongooseTypes[name] == null) {
749
+ throw new TypeError(`Invalid schema configuration: \`${name}\` is not ` +
750
+ `a valid type at path \`${path}\`. See ` +
751
+ 'http://bit.ly/mongoose-schematypes for a list of valid schema types.');
720
752
  }
721
753
 
722
754
  return new MongooseTypes[name](path, obj);
@@ -862,7 +894,7 @@ Schema.prototype.setupTimestamp = function(timestamps) {
862
894
 
863
895
  function withTimestamp(s) {
864
896
  const ts = s.schema.options.timestamps;
865
- return ts == true || ts == null;
897
+ return !!ts;
866
898
  }
867
899
 
868
900
  if (!timestamps && !childHasTimestamp) {
@@ -886,6 +918,10 @@ Schema.prototype.setupTimestamp = function(timestamps) {
886
918
  this.add(schemaAdditions);
887
919
 
888
920
  this.pre('save', function(next) {
921
+ if (get(this, '$__.saveOptions.timestamps') === false) {
922
+ return next();
923
+ }
924
+
889
925
  const defaultTimestamp = (this.ownerDocument ? this.ownerDocument() : this).
890
926
  constructor.base.now();
891
927
  const auto_id = this._id && this._id.auto;
@@ -919,6 +955,8 @@ Schema.prototype.setupTimestamp = function(timestamps) {
919
955
  return this;
920
956
  };
921
957
 
958
+ _setTimestampsOnUpdate[symbols.builtInMiddleware] = true;
959
+
922
960
  this.pre('findOneAndUpdate', _setTimestampsOnUpdate);
923
961
  this.pre('replaceOne', _setTimestampsOnUpdate);
924
962
  this.pre('update', _setTimestampsOnUpdate);
@@ -941,7 +979,7 @@ Schema.prototype.setupTimestamp = function(timestamps) {
941
979
  function getPositionalPathType(self, path) {
942
980
  const subpaths = path.split(/\.(\d+)\.|\.(\d+)$/).filter(Boolean);
943
981
  if (subpaths.length < 2) {
944
- return self.paths[subpaths[0]];
982
+ return self.paths.hasOwnProperty(subpaths[0]) ? self.paths[subpath[0]] : null;
945
983
  }
946
984
 
947
985
  let val = self.path(subpaths[0]);
@@ -1462,7 +1500,7 @@ Schema.prototype.virtual = function(name, options) {
1462
1500
  */
1463
1501
 
1464
1502
  Schema.prototype.virtualpath = function(name) {
1465
- return this.virtuals[name];
1503
+ return this.virtuals.hasOwnProperty(name) ? this.virtuals[name] : null;
1466
1504
  };
1467
1505
 
1468
1506
  /**
package/lib/schematype.js CHANGED
@@ -70,6 +70,38 @@ function SchemaType(path, options, instance) {
70
70
  });
71
71
  }
72
72
 
73
+ /**
74
+ * Get/set the function used to cast arbitrary values to this type.
75
+ *
76
+ * ####Example:
77
+ *
78
+ * // Disallow `null` for numbers, and don't try to cast any values to
79
+ * // numbers, so even strings like '123' will cause a CastError.
80
+ * mongoose.Number.cast(function(v) {
81
+ * assert.ok(v === undefined || typeof v === 'number');
82
+ * return v;
83
+ * });
84
+ *
85
+ * @param {Function|false} caster Function that casts arbitrary values to this type, or throws an error if casting failed
86
+ * @return {Function}
87
+ * @static
88
+ * @receiver SchemaType
89
+ * @function cast
90
+ * @api public
91
+ */
92
+
93
+ SchemaType.cast = function cast(caster) {
94
+ if (arguments.length === 0) {
95
+ return this._cast;
96
+ }
97
+ if (caster === false) {
98
+ caster = v => v;
99
+ }
100
+ this._cast = caster;
101
+
102
+ return this._cast;
103
+ };
104
+
73
105
  /**
74
106
  * Attaches a getter for all instances of this schema type.
75
107
  *
@@ -80,8 +112,9 @@ function SchemaType(path, options, instance) {
80
112
  *
81
113
  * @param {Function} getter
82
114
  * @return {this}
83
- * @function get
84
115
  * @static
116
+ * @receiver SchemaType
117
+ * @function get
85
118
  * @api public
86
119
  */
87
120
 
@@ -1221,8 +1254,9 @@ SchemaType.prototype._castForQuery = function(val) {
1221
1254
  *
1222
1255
  * @param {Function} fn
1223
1256
  * @return {Function}
1224
- * @function checkRequired
1225
1257
  * @static
1258
+ * @receiver SchemaType
1259
+ * @function checkRequired
1226
1260
  * @api public
1227
1261
  */
1228
1262
 
@@ -44,7 +44,11 @@ function MongooseDocumentArray(values, path, doc) {
44
44
  // TODO: replace this with `new CoreMongooseArray().concat()` when we remove
45
45
  // support for node 4.x and 5.x, see https://i.imgur.com/UAAHk4S.png
46
46
  const arr = new CoreMongooseArray();
47
- if (Array.isArray(values)) values.forEach(v => arr.push(v));
47
+ if (Array.isArray(values)) {
48
+ values.forEach(v => {
49
+ arr.push(v);
50
+ });
51
+ }
48
52
  arr._path = path;
49
53
 
50
54
  const props = {
@@ -11,6 +11,7 @@
11
11
  'use strict';
12
12
 
13
13
  const ObjectId = require('../driver').get().ObjectId;
14
+ const objectIdSymbol = require('../helpers/symbols').objectIdSymbol;
14
15
 
15
16
  /*!
16
17
  * Getter for convenience with populate, see gh-6115
@@ -24,4 +25,6 @@ Object.defineProperty(ObjectId.prototype, '_id', {
24
25
  }
25
26
  });
26
27
 
28
+ ObjectId.prototype[objectIdSymbol] = true;
29
+
27
30
  module.exports = ObjectId;
package/lib/utils.js CHANGED
@@ -261,7 +261,7 @@ exports.promiseOrCallback = function promiseOrCallback(callback, fn, ee) {
261
261
  return new Promise((resolve, reject) => {
262
262
  fn(function(error, res) {
263
263
  if (error != null) {
264
- if (ee.listeners('error').length > 0 && !error[emittedSymbol]) {
264
+ if (ee != null && ee.listeners('error').length > 0 && !error[emittedSymbol]) {
265
265
  error[emittedSymbol] = true;
266
266
  ee.emit('error', error);
267
267
  }
@@ -382,9 +382,14 @@ exports.merge = function merge(to, from, options, path) {
382
382
  if (!exports.isObject(to[key])) {
383
383
  to[key] = {};
384
384
  }
385
- if (from[key] != null && from[key].instanceOfSchema) {
386
- to[key] = from[key].clone();
387
- continue;
385
+ if (from[key] != null) {
386
+ if (from[key].instanceOfSchema) {
387
+ to[key] = from[key].clone();
388
+ continue;
389
+ } else if (from[key] instanceof ObjectId) {
390
+ to[key] = new ObjectId(from[key]);
391
+ continue;
392
+ }
388
393
  }
389
394
  merge(to[key], from[key], options, path ? path + '.' + key : key);
390
395
  } else if (options.overwrite) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "mongoose",
3
3
  "description": "Mongoose MongoDB ODM",
4
- "version": "5.4.0",
4
+ "version": "5.4.4",
5
5
  "author": "Guillermo Rauch <guillermo@learnboost.com>",
6
6
  "keywords": [
7
7
  "mongodb",
@@ -22,7 +22,6 @@
22
22
  "async": "2.6.1",
23
23
  "bson": "~1.1.0",
24
24
  "kareem": "2.3.0",
25
- "lodash.get": "4.4.2",
26
25
  "mongodb": "3.1.10",
27
26
  "mongodb-core": "3.1.9",
28
27
  "mongoose-legacy-pluralize": "1.0.2",
@@ -35,7 +34,7 @@
35
34
  },
36
35
  "devDependencies": {
37
36
  "acorn": "5.7.3",
38
- "acquit": "1.0.0",
37
+ "acquit": "1.0.2",
39
38
  "acquit-ignore": "0.1.0",
40
39
  "acquit-require": "0.1.1",
41
40
  "babel-loader": "7.1.4",