mongoose 6.1.7 → 6.2.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/lib/query.js CHANGED
@@ -34,7 +34,6 @@ const sanitizeFilter = require('./helpers/query/sanitizeFilter');
34
34
  const sanitizeProjection = require('./helpers/query/sanitizeProjection');
35
35
  const selectPopulatedFields = require('./helpers/query/selectPopulatedFields');
36
36
  const setDefaultsOnInsert = require('./helpers/setDefaultsOnInsert');
37
- const slice = require('sliced');
38
37
  const updateValidators = require('./helpers/updateValidators');
39
38
  const util = require('util');
40
39
  const utils = require('./utils');
@@ -379,14 +378,14 @@ Query.prototype.slice = function() {
379
378
  if ('number' === typeof arguments[0]) {
380
379
  this._ensurePath('slice');
381
380
  path = this._path;
382
- val = slice(arguments);
381
+ val = [arguments[0], arguments[1]];
383
382
  } else {
384
383
  path = arguments[0];
385
384
  val = arguments[1];
386
385
  }
387
386
  } else if (arguments.length === 3) {
388
387
  path = arguments[0];
389
- val = slice(arguments, 1);
388
+ val = [arguments[1], arguments[2]];
390
389
  }
391
390
 
392
391
  const p = {};
@@ -680,10 +679,10 @@ Query.prototype.mod = function() {
680
679
  path = this._path;
681
680
  } else if (arguments.length === 2 && !Array.isArray(arguments[1])) {
682
681
  this._ensurePath('mod');
683
- val = slice(arguments);
682
+ val = [arguments[0], arguments[1]];
684
683
  path = this._path;
685
684
  } else if (arguments.length === 3) {
686
- val = slice(arguments, 1);
685
+ val = [arguments[1], arguments[2]];
687
686
  path = arguments[0];
688
687
  } else {
689
688
  val = arguments[1];
@@ -5058,18 +5057,19 @@ Query.prototype.cast = function(model, obj) {
5058
5057
  model = getDiscriminatorByValue(model.discriminators, obj[discriminatorKey]) || model;
5059
5058
  }
5060
5059
 
5060
+ const opts = { upsert: this.options && this.options.upsert };
5061
+ if (this.options) {
5062
+ if ('strict' in this.options) {
5063
+ opts.strict = this.options.strict;
5064
+ opts.strictQuery = opts.strict;
5065
+ }
5066
+ if ('strictQuery' in this.options) {
5067
+ opts.strictQuery = this.options.strictQuery;
5068
+ }
5069
+ }
5070
+
5061
5071
  try {
5062
- return cast(model.schema, obj, {
5063
- upsert: this.options && this.options.upsert,
5064
- strict: (this.options && 'strict' in this.options) ?
5065
- this.options.strict :
5066
- get(model, 'schema.options.strict', null),
5067
- strictQuery: (this.options && 'strictQuery' in this.options) ?
5068
- this.options.strictQuery :
5069
- (this.options && 'strict' in this.options) ?
5070
- this.options.strict :
5071
- get(model, 'schema.options.strictQuery', null)
5072
- }, this);
5072
+ return cast(model.schema, obj, opts, this);
5073
5073
  } catch (err) {
5074
5074
  // CastError, assign model
5075
5075
  if (typeof err.setModel === 'function') {
@@ -168,7 +168,7 @@ SubdocumentPath.prototype.cast = function(val, doc, init, priorVal, options) {
168
168
  const path = this.path;
169
169
  const selected = Object.keys(parentSelected).reduce((obj, key) => {
170
170
  if (key.startsWith(path + '.')) {
171
- obj[key.substr(path.length + 1)] = parentSelected[key];
171
+ obj[key.substring(path.length + 1)] = parentSelected[key];
172
172
  }
173
173
  return obj;
174
174
  }, {});
@@ -344,7 +344,7 @@ SchemaArray.prototype.cast = function(value, doc, init, prev, options) {
344
344
  // Special case: if this index is on the parent of what looks like
345
345
  // GeoJSON, skip setting the default to empty array re: #1668, #3233
346
346
  const arrayGeojsonPath = this.path.endsWith('.coordinates') ?
347
- this.path.substr(0, this.path.lastIndexOf('.')) : null;
347
+ this.path.substring(0, this.path.lastIndexOf('.')) : null;
348
348
  if (arrayGeojsonPath != null) {
349
349
  for (i = 0, l = indexes.length; i < l; ++i) {
350
350
  const pathIndex = indexes[i][0][arrayGeojsonPath];
@@ -546,7 +546,7 @@ function scopePaths(array, fields, init) {
546
546
  continue;
547
547
  }
548
548
  if (sub.startsWith('$.')) {
549
- sub = sub.substr(2);
549
+ sub = sub.substring(2);
550
550
  }
551
551
  hasKeys || (hasKeys = true);
552
552
  selected[sub] = fields[key];
package/lib/schema.js CHANGED
@@ -31,6 +31,8 @@ const documentHooks = require('./helpers/model/applyHooks').middlewareFunctions;
31
31
  const hookNames = queryHooks.concat(documentHooks).
32
32
  reduce((s, hook) => s.add(hook), new Set());
33
33
 
34
+ const isPOJO = utils.isPOJO;
35
+
34
36
  let id = 0;
35
37
 
36
38
  /**
@@ -73,6 +75,7 @@ let id = 0;
73
75
  * - [selectPopulatedPaths](/docs/guide.html#selectPopulatedPaths): boolean - defaults to `true`
74
76
  * - [skipVersioning](/docs/guide.html#skipVersioning): object - paths to exclude from versioning
75
77
  * - [timestamps](/docs/guide.html#timestamps): object or boolean - defaults to `false`. If true, Mongoose adds `createdAt` and `updatedAt` properties to your schema and manages those properties for you.
78
+ * - [pluginTags](/docs/guide.html#pluginTags): array of strings - defaults to `undefined`. If set and plugin called with `tags` option, will only apply that plugin to schemas with a matching tag.
76
79
  *
77
80
  * ####Options for Nested Schemas:
78
81
  * - `excludeIndexes`: bool - defaults to `false`. If `true`, skip building indexes on this schema's paths.
@@ -502,64 +505,66 @@ Schema.prototype.add = function add(obj, prefix) {
502
505
  }
503
506
 
504
507
  const keys = Object.keys(obj);
508
+ const typeKey = this.options.typeKey;
505
509
 
506
510
  for (const key of keys) {
507
511
  const fullPath = prefix + key;
512
+ const val = obj[key];
508
513
 
509
- if (obj[key] == null) {
514
+ if (val == null) {
510
515
  throw new TypeError('Invalid value for schema path `' + fullPath +
511
- '`, got value "' + obj[key] + '"');
516
+ '`, got value "' + val + '"');
512
517
  }
513
518
  // Retain `_id: false` but don't set it as a path, re: gh-8274.
514
- if (key === '_id' && obj[key] === false) {
519
+ if (key === '_id' && val === false) {
515
520
  continue;
516
521
  }
517
- if (obj[key] instanceof VirtualType || get(obj[key], 'constructor.name', null) === 'VirtualType') {
518
- this.virtual(obj[key]);
522
+ if (val instanceof VirtualType || get(val, 'constructor.name', null) === 'VirtualType') {
523
+ this.virtual(val);
519
524
  continue;
520
525
  }
521
526
 
522
- if (Array.isArray(obj[key]) && obj[key].length === 1 && obj[key][0] == null) {
527
+ if (Array.isArray(val) && val.length === 1 && val[0] == null) {
523
528
  throw new TypeError('Invalid value for schema Array path `' + fullPath +
524
- '`, got value "' + obj[key][0] + '"');
529
+ '`, got value "' + val[0] + '"');
525
530
  }
526
531
 
527
- if (!(utils.isPOJO(obj[key]) || obj[key] instanceof SchemaTypeOptions)) {
532
+ if (!(isPOJO(val) || val instanceof SchemaTypeOptions)) {
528
533
  // Special-case: Non-options definitely a path so leaf at this node
529
534
  // Examples: Schema instances, SchemaType instances
530
535
  if (prefix) {
531
- this.nested[prefix.substr(0, prefix.length - 1)] = true;
536
+ this.nested[prefix.substring(0, prefix.length - 1)] = true;
532
537
  }
533
- this.path(prefix + key, obj[key]);
534
- } else if (Object.keys(obj[key]).length < 1) {
538
+ this.path(prefix + key, val);
539
+ } else if (Object.keys(val).length < 1) {
535
540
  // Special-case: {} always interpreted as Mixed path so leaf at this node
536
541
  if (prefix) {
537
- this.nested[prefix.substr(0, prefix.length - 1)] = true;
542
+ this.nested[prefix.substring(0, prefix.length - 1)] = true;
538
543
  }
539
- this.path(fullPath, obj[key]); // mixed type
540
- } else if (!obj[key][this.options.typeKey] || (this.options.typeKey === 'type' && !(obj[key].type instanceof Function) && obj[key].type.type)) {
544
+ this.path(fullPath, val); // mixed type
545
+ } else if (!val[typeKey] || (typeKey === 'type' && isPOJO(val.type) && val.type.type)) {
541
546
  // Special-case: POJO with no bona-fide type key - interpret as tree of deep paths so recurse
542
547
  // nested object `{ last: { name: String } }`. Avoid functions with `.type` re: #10807 because
543
548
  // NestJS sometimes adds `Date.type`.
544
549
  this.nested[fullPath] = true;
545
- this.add(obj[key], fullPath + '.');
550
+ this.add(val, fullPath + '.');
546
551
  } else {
547
552
  // There IS a bona-fide type key that may also be a POJO
548
- const _typeDef = obj[key][this.options.typeKey];
549
- if (utils.isPOJO(_typeDef) && Object.keys(_typeDef).length > 0) {
553
+ const _typeDef = val[typeKey];
554
+ if (isPOJO(_typeDef) && Object.keys(_typeDef).length > 0) {
550
555
  // If a POJO is the value of a type key, make it a subdocument
551
556
  if (prefix) {
552
- this.nested[prefix.substr(0, prefix.length - 1)] = true;
557
+ this.nested[prefix.substring(0, prefix.length - 1)] = true;
553
558
  }
554
559
  const _schema = new Schema(_typeDef);
555
- const schemaWrappedPath = Object.assign({}, obj[key], { type: _schema });
560
+ const schemaWrappedPath = Object.assign({}, val, { type: _schema });
556
561
  this.path(prefix + key, schemaWrappedPath);
557
562
  } else {
558
563
  // Either the type is non-POJO or we interpret it as Mixed anyway
559
564
  if (prefix) {
560
- this.nested[prefix.substr(0, prefix.length - 1)] = true;
565
+ this.nested[prefix.substring(0, prefix.length - 1)] = true;
561
566
  }
562
- this.path(prefix + key, obj[key]);
567
+ this.path(prefix + key, val);
563
568
  }
564
569
  }
565
570
  }
package/lib/schematype.js CHANGED
@@ -128,6 +128,51 @@ function SchemaType(path, options, instance) {
128
128
 
129
129
  SchemaType.prototype.OptionsConstructor = SchemaTypeOptions;
130
130
 
131
+ /**
132
+ * The path to this SchemaType in a Schema.
133
+ *
134
+ * ####Example:
135
+ * const schema = new Schema({ name: String });
136
+ * schema.path('name').path; // 'name'
137
+ *
138
+ * @property path
139
+ * @api public
140
+ * @memberOf SchemaType
141
+ */
142
+
143
+ SchemaType.prototype.path;
144
+
145
+ /**
146
+ * The validators that Mongoose should run to validate properties at this SchemaType's path.
147
+ *
148
+ * ####Example:
149
+ * const schema = new Schema({ name: { type: String, required: true } });
150
+ * schema.path('name').validators.length; // 1, the `required` validator
151
+ *
152
+ * @property validators
153
+ * @api public
154
+ * @memberOf SchemaType
155
+ */
156
+
157
+ SchemaType.prototype.validators;
158
+
159
+ /**
160
+ * True if this SchemaType has a required validator. False otherwise.
161
+ *
162
+ * ####Example:
163
+ * const schema = new Schema({ name: { type: String, required: true } });
164
+ * schema.path('name').isRequired; // true
165
+ *
166
+ * schema.path('name').required(false);
167
+ * schema.path('name').isRequired; // false
168
+ *
169
+ * @property isRequired
170
+ * @api public
171
+ * @memberOf SchemaType
172
+ */
173
+
174
+ SchemaType.prototype.validators;
175
+
131
176
  /*!
132
177
  * ignore
133
178
  */
@@ -326,7 +371,7 @@ SchemaType.prototype.default = function(val) {
326
371
  this.defaultValue = val;
327
372
  return this.defaultValue;
328
373
  } else if (arguments.length > 1) {
329
- this.defaultValue = utils.args(arguments);
374
+ this.defaultValue = [...arguments];
330
375
  }
331
376
  return this.defaultValue;
332
377
  };
@@ -5,7 +5,7 @@
5
5
 
6
6
  'use strict';
7
7
 
8
- const utils = require('./utils');
8
+ const utils = require('./utils'); // eslint-disable-line no-unused-vars
9
9
 
10
10
  /*!
11
11
  * StateMachine represents a minimal `interface` for the
@@ -32,7 +32,7 @@ const StateMachine = module.exports = exports = function StateMachine() {
32
32
  */
33
33
 
34
34
  StateMachine.ctor = function() {
35
- const states = utils.args(arguments);
35
+ const states = [...arguments];
36
36
 
37
37
  const ctor = function() {
38
38
  StateMachine.apply(this, arguments);
@@ -122,9 +122,8 @@ StateMachine.prototype.some = function some() {
122
122
 
123
123
  StateMachine.prototype._iter = function _iter(iterMethod) {
124
124
  return function() {
125
- const numArgs = arguments.length;
126
- let states = utils.args(arguments, 0, numArgs - 1);
127
- const callback = arguments[numArgs - 1];
125
+ let states = [...arguments];
126
+ const callback = states.pop();
128
127
 
129
128
  if (!states.length) states = this.stateNames;
130
129
 
package/lib/utils.js CHANGED
@@ -6,7 +6,6 @@
6
6
 
7
7
  const ms = require('ms');
8
8
  const mpath = require('mpath');
9
- const sliced = require('sliced');
10
9
  const Decimal = require('./types/decimal128');
11
10
  const ObjectId = require('./types/objectid');
12
11
  const PopulateOptions = require('./options/PopulateOptions');
@@ -81,7 +80,11 @@ exports.deepEqual = function deepEqual(a, b) {
81
80
  return a.source === b.source &&
82
81
  a.ignoreCase === b.ignoreCase &&
83
82
  a.multiline === b.multiline &&
84
- a.global === b.global;
83
+ a.global === b.global &&
84
+ a.dotAll === b.dotAll &&
85
+ a.unicode === b.unicode &&
86
+ a.sticky === b.sticky &&
87
+ a.hasIndices === b.hasIndices;
85
88
  }
86
89
 
87
90
  if (a == null || b == null) {
@@ -236,16 +239,6 @@ exports.options = function(defaults, options) {
236
239
  return options;
237
240
  };
238
241
 
239
- /*!
240
- * Generates a random string
241
- *
242
- * @api private
243
- */
244
-
245
- exports.random = function() {
246
- return Math.random().toString().substr(3);
247
- };
248
-
249
242
  /*!
250
243
  * Merges `from` into `to` without overwriting existing properties.
251
244
  *
@@ -441,13 +434,6 @@ exports.hasKey = function hasKey(obj, key) {
441
434
  return false;
442
435
  };
443
436
 
444
- /*!
445
- * A faster Array.prototype.slice.call(arguments) alternative
446
- * @api private
447
- */
448
-
449
- exports.args = sliced;
450
-
451
437
  /*!
452
438
  * process.nextTick helper.
453
439
  *
@@ -502,13 +488,9 @@ exports.expires = function expires(object) {
502
488
  return;
503
489
  }
504
490
 
505
- let when;
506
- if (typeof object.expires !== 'string') {
507
- when = object.expires;
508
- } else {
509
- when = Math.round(ms(object.expires) / 1000);
510
- }
511
- object.expireAfterSeconds = when;
491
+ object.expireAfterSeconds = (typeof object.expires !== 'string')
492
+ ? object.expires
493
+ : Math.round(ms(object.expires) / 1000);
512
494
  delete object.expires;
513
495
  };
514
496
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "mongoose",
3
3
  "description": "Mongoose MongoDB ODM",
4
- "version": "6.1.7",
4
+ "version": "6.2.0",
5
5
  "author": "Guillermo Rauch <guillermo@learnboost.com>",
6
6
  "keywords": [
7
7
  "mongodb",
@@ -19,16 +19,14 @@
19
19
  ],
20
20
  "license": "MIT",
21
21
  "dependencies": {
22
- "@types/node": "< 17.0.6",
23
22
  "bson": "^4.2.2",
24
23
  "kareem": "2.3.3",
25
- "mongodb": "4.2.2",
24
+ "mongodb": "4.3.1",
26
25
  "mpath": "0.8.4",
27
- "mquery": "4.0.0",
26
+ "mquery": "4.0.2",
28
27
  "ms": "2.1.2",
29
28
  "regexp-clone": "1.0.0",
30
- "sift": "13.5.2",
31
- "sliced": "1.0.1"
29
+ "sift": "13.5.2"
32
30
  },
33
31
  "devDependencies": {
34
32
  "@babel/core": "7.10.5",
@@ -41,27 +39,26 @@
41
39
  "babel-loader": "8.1.0",
42
40
  "benchmark": "2.1.4",
43
41
  "bluebird": "3.7.2",
44
- "chalk": "4.1.2",
45
42
  "cheerio": "1.0.0-rc.5",
46
43
  "dox": "0.3.1",
47
44
  "eslint": "8.5.0",
48
45
  "eslint-plugin-mocha-no-only": "1.1.0",
49
46
  "highlight.js": "9.18.3",
47
+ "js-yaml": "4.1.0",
50
48
  "lodash.isequal": "4.5.0",
51
49
  "lodash.isequalwith": "4.4.0",
52
50
  "marked": "2.1.3",
53
51
  "mkdirp": "0.5.5",
54
- "mocha": "9.1.3",
52
+ "mocha": "9.2.0",
55
53
  "moment": "2.x",
56
- "object-sizeof": "1.3.0",
54
+ "mongodb-memory-server": "^8.2.0",
55
+ "nyc": "^15.1.0",
57
56
  "pug": "3.0.2",
58
57
  "q": "1.5.1",
59
58
  "rimraf": "2.6.3",
60
- "semver": "5.5.0",
61
59
  "serve-handler": "6.1.3",
62
60
  "typescript": "4.5.3",
63
- "uuid": "2.0.3",
64
- "uuid-parse": "1.0.0",
61
+ "uuid": "8.3.2",
65
62
  "webpack": "4.44.1"
66
63
  },
67
64
  "directories": {
@@ -73,9 +70,10 @@
73
70
  "prepublishOnly": "npm run build-browser",
74
71
  "release": "git pull && git push origin master --tags && npm publish",
75
72
  "release-legacy": "git pull origin 5.x && git push origin 5.x --tags && npm publish --tag legacy",
73
+ "mongo": "node ./tools/repl.js",
76
74
  "test": "mocha --exit ./test/*.test.js ./test/typescript/main.test.js",
77
75
  "tdd": "mocha ./test/*.test.js ./test/typescript/main.test.js --inspect --watch --recursive --watch-files ./**/*.js",
78
- "test-cov": "nyc --reporter=html --reporter=text npm test"
76
+ "test-coverage": "nyc --reporter=html --reporter=text npm test"
79
77
  },
80
78
  "main": "./index.js",
81
79
  "types": "./index.d.ts",
@@ -147,8 +145,8 @@
147
145
  "no-whitespace-before-property": "error",
148
146
  "no-buffer-constructor": "warn",
149
147
  "no-console": "off",
150
- "no-multi-spaces": "error",
151
148
  "no-constant-condition": "off",
149
+ "no-multi-spaces": "error",
152
150
  "func-call-spacing": "error",
153
151
  "no-trailing-spaces": "error",
154
152
  "no-undef": "error",
@@ -242,6 +240,11 @@
242
240
  ]
243
241
  }
244
242
  },
243
+ "config": {
244
+ "mongodbMemoryServer": {
245
+ "disablePostinstall": true
246
+ }
247
+ },
245
248
  "funding": {
246
249
  "type": "opencollective",
247
250
  "url": "https://opencollective.com/mongoose"
package/tools/repl.js CHANGED
@@ -6,31 +6,29 @@ run().catch(error => {
6
6
  });
7
7
 
8
8
  async function run () {
9
- const ReplSet = require('mongodb-topology-manager').ReplSet;
9
+ const ReplSet = require('mongodb-memory-server').MongoMemoryReplSet;
10
10
 
11
11
  // Create new instance
12
- const topology = new ReplSet('mongod', [{
13
- // mongod process options
14
- options: {
15
- bind_ip: 'localhost', port: 31000, dbpath: `/data/db/31000`
16
- }
17
- }, {
18
- // mongod process options
19
- options: {
20
- bind_ip: 'localhost', port: 31001, dbpath: `/data/db/31001`
21
- }
22
- }, {
23
- // Type of node
24
- arbiterOnly: true,
25
- // mongod process options
26
- options: {
27
- bind_ip: 'localhost', port: 31002, dbpath: `/data/db/31002`
28
- }
29
- }], {
30
- replSet: 'rs'
12
+ const replSet = new ReplSet({
13
+ binary: {
14
+ version: process.argv[3]
15
+ },
16
+ instanceOpts: [
17
+ // Set the expiry job in MongoDB to run every second
18
+ {
19
+ port: 27017,
20
+ args: ["--setParameter", "ttlMonitorSleepSecs=1"] },
21
+ ],
22
+ dbName: 'mongoose_test',
23
+ replSet: {
24
+ name: "rs0",
25
+ count: 2,
26
+ storageEngine: "wiredTiger",
27
+ },
31
28
  });
32
29
 
33
- await topology.start();
34
-
35
- console.log('done');
30
+ await replSet.start();
31
+ await replSet.waitUntilRunning();
32
+ console.log("MongoDB-ReplicaSet is now running.")
33
+ console.log(replSet.getUri("mongoose_test"));
36
34
  }