mongoose 7.6.7 → 7.6.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.
@@ -60,12 +60,6 @@ class ChangeStream extends EventEmitter {
60
60
 
61
61
  driverChangeStreamEvents.forEach(ev => {
62
62
  this.driverChangeStream.on(ev, data => {
63
- // Sometimes Node driver still polls after close, so
64
- // avoid any uncaught exceptions due to closed change streams
65
- // See tests for gh-7022
66
- if (ev === 'error' && this.closed) {
67
- return;
68
- }
69
63
  if (data != null && data.fullDocument != null && this.options && this.options.hydrate) {
70
64
  data.fullDocument = this.options.model.hydrate(data.fullDocument);
71
65
  }
@@ -83,12 +77,6 @@ class ChangeStream extends EventEmitter {
83
77
 
84
78
  driverChangeStreamEvents.forEach(ev => {
85
79
  this.driverChangeStream.on(ev, data => {
86
- // Sometimes Node driver still polls after close, so
87
- // avoid any uncaught exceptions due to closed change streams
88
- // See tests for gh-7022
89
- if (ev === 'error' && this.closed) {
90
- return;
91
- }
92
80
  if (data != null && data.fullDocument != null && this.options && this.options.hydrate) {
93
81
  data.fullDocument = this.options.model.hydrate(data.fullDocument);
94
82
  }
package/lib/document.js CHANGED
@@ -1121,6 +1121,8 @@ Document.prototype.$set = function $set(path, val, type, options) {
1121
1121
  } else {
1122
1122
  throw new StrictModeError(key);
1123
1123
  }
1124
+ } else if (pathtype === 'nested' && valForKey == null) {
1125
+ this.$set(pathName, valForKey, constructing, options);
1124
1126
  }
1125
1127
  } else if (valForKey !== void 0) {
1126
1128
  this.$set(pathName, valForKey, constructing, options);
@@ -2228,12 +2230,15 @@ Document.prototype[documentModifiedPaths] = Document.prototype.modifiedPaths;
2228
2230
  * doc.isDirectModified('documents') // false
2229
2231
  *
2230
2232
  * @param {String} [path] optional
2233
+ * @param {Object} [options]
2234
+ * @param {Boolean} [options.ignoreAtomics=false] If true, doesn't return true if path is underneath an array that was modified with atomic operations like `push()`
2231
2235
  * @return {Boolean}
2232
2236
  * @api public
2233
2237
  */
2234
2238
 
2235
- Document.prototype.isModified = function(paths, modifiedPaths) {
2239
+ Document.prototype.isModified = function(paths, options, modifiedPaths) {
2236
2240
  if (paths) {
2241
+ const ignoreAtomics = options && options.ignoreAtomics;
2237
2242
  const directModifiedPathsObj = this.$__.activePaths.states.modify;
2238
2243
  if (directModifiedPathsObj == null) {
2239
2244
  return false;
@@ -2254,7 +2259,16 @@ Document.prototype.isModified = function(paths, modifiedPaths) {
2254
2259
  return !!~modified.indexOf(path);
2255
2260
  });
2256
2261
 
2257
- const directModifiedPaths = Object.keys(directModifiedPathsObj);
2262
+ let directModifiedPaths = Object.keys(directModifiedPathsObj);
2263
+ if (ignoreAtomics) {
2264
+ directModifiedPaths = directModifiedPaths.filter(path => {
2265
+ const value = this.$__getValue(path);
2266
+ if (value != null && value[arrayAtomicsSymbol] != null && value[arrayAtomicsSymbol].$set === undefined) {
2267
+ return false;
2268
+ }
2269
+ return true;
2270
+ });
2271
+ }
2258
2272
  return isModifiedChild || paths.some(function(path) {
2259
2273
  return directModifiedPaths.some(function(mod) {
2260
2274
  return mod === path || path.startsWith(mod + '.');
@@ -2676,7 +2690,7 @@ function _getPathsToValidate(doc, pathsToValidate, pathsToSkip) {
2676
2690
  paths.delete(fullPathToSubdoc + '.' + modifiedPath);
2677
2691
  }
2678
2692
 
2679
- if (doc.$isModified(fullPathToSubdoc, modifiedPaths) &&
2693
+ if (doc.$isModified(fullPathToSubdoc, null, modifiedPaths) &&
2680
2694
  !doc.isDirectModified(fullPathToSubdoc) &&
2681
2695
  !doc.$isDefault(fullPathToSubdoc)) {
2682
2696
  paths.add(fullPathToSubdoc);
@@ -16,8 +16,15 @@ function applyEmbeddedDiscriminators(schema, seen = new WeakSet()) {
16
16
  if (!schemaType.schema._applyDiscriminators) {
17
17
  continue;
18
18
  }
19
+ if (schemaType._appliedDiscriminators) {
20
+ continue;
21
+ }
19
22
  for (const disc of schemaType.schema._applyDiscriminators.keys()) {
20
- schemaType.discriminator(disc, schemaType.schema._applyDiscriminators.get(disc));
23
+ schemaType.discriminator(
24
+ disc,
25
+ schemaType.schema._applyDiscriminators.get(disc)
26
+ );
21
27
  }
28
+ schemaType._appliedDiscriminators = true;
22
29
  }
23
30
  }
@@ -1,5 +1,7 @@
1
1
  'use strict';
2
2
 
3
+ const isNestedProjection = require('../projection/isNestedProjection');
4
+
3
5
  module.exports = function applyDefaults(doc, fields, exclude, hasIncludedChildren, isBeforeSetters, pathsToSkip) {
4
6
  const paths = Object.keys(doc.$__schema.paths);
5
7
  const plen = paths.length;
@@ -32,7 +34,7 @@ module.exports = function applyDefaults(doc, fields, exclude, hasIncludedChildre
32
34
  }
33
35
  } else if (exclude === false && fields && !included) {
34
36
  const hasSubpaths = type.$isSingleNested || type.$isMongooseDocumentArray;
35
- if (curPath in fields || (j === len - 1 && hasSubpaths && hasIncludedChildren != null && hasIncludedChildren[curPath])) {
37
+ if ((curPath in fields && !isNestedProjection(fields[curPath])) || (j === len - 1 && hasSubpaths && hasIncludedChildren != null && hasIncludedChildren[curPath])) {
36
38
  included = true;
37
39
  } else if (hasIncludedChildren != null && !hasIncludedChildren[curPath]) {
38
40
  break;
@@ -21,6 +21,7 @@ module.exports = function hasIncludedChildren(fields) {
21
21
  const keys = Object.keys(fields);
22
22
 
23
23
  for (const key of keys) {
24
+
24
25
  if (key.indexOf('.') === -1) {
25
26
  hasIncludedChildren[key] = 1;
26
27
  continue;
@@ -0,0 +1,8 @@
1
+ 'use strict';
2
+
3
+ module.exports = function isNestedProjection(val) {
4
+ if (val == null || typeof val !== 'object') {
5
+ return false;
6
+ }
7
+ return val.$slice == null && val.$elemMatch == null && val.$meta == null && val.$ == null;
8
+ };
package/lib/schema.js CHANGED
@@ -25,6 +25,8 @@ const utils = require('./utils');
25
25
  const validateRef = require('./helpers/populate/validateRef');
26
26
  const util = require('util');
27
27
 
28
+ const hasNumericSubpathRegex = /\.\d+(\.|$)/;
29
+
28
30
  let MongooseTypes;
29
31
 
30
32
  const queryHooks = require('./helpers/query/applyQueryMiddleware').
@@ -1008,7 +1010,7 @@ Schema.prototype.path = function(path, obj) {
1008
1010
  }
1009
1011
 
1010
1012
  // subpaths?
1011
- return /\.\d+\.?.*$/.test(path)
1013
+ return hasNumericSubpathRegex.test(path)
1012
1014
  ? getPositionalPath(this, path, cleanPath)
1013
1015
  : undefined;
1014
1016
  }
@@ -182,7 +182,7 @@ Subdocument.prototype.markModified = function(path) {
182
182
  * ignore
183
183
  */
184
184
 
185
- Subdocument.prototype.isModified = function(paths, modifiedPaths) {
185
+ Subdocument.prototype.isModified = function(paths, options, modifiedPaths) {
186
186
  const parent = this.$parent();
187
187
  if (parent != null) {
188
188
  if (Array.isArray(paths) || typeof paths === 'string') {
@@ -192,10 +192,10 @@ Subdocument.prototype.isModified = function(paths, modifiedPaths) {
192
192
  paths = this.$__pathRelativeToParent();
193
193
  }
194
194
 
195
- return parent.$isModified(paths, modifiedPaths);
195
+ return parent.$isModified(paths, options, modifiedPaths);
196
196
  }
197
197
 
198
- return Document.prototype.isModified.call(this, paths, modifiedPaths);
198
+ return Document.prototype.isModified.call(this, paths, options, modifiedPaths);
199
199
  };
200
200
 
201
201
  /**
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "mongoose",
3
3
  "description": "Mongoose MongoDB ODM",
4
- "version": "7.6.7",
4
+ "version": "7.6.8",
5
5
  "author": "Guillermo Rauch <guillermo@learnboost.com>",
6
6
  "keywords": [
7
7
  "mongodb",
@@ -178,8 +178,8 @@ declare module 'mongoose' {
178
178
  * Returns true if any of the given paths are modified, else false. If no arguments, returns `true` if any path
179
179
  * in this document is modified.
180
180
  */
181
- isModified<T extends keyof DocType>(path?: T | Array<T>): boolean;
182
- isModified(path?: string | Array<string>): boolean;
181
+ isModified<T extends keyof DocType>(path?: T | Array<T>, options?: { ignoreAtomics?: boolean } | null): boolean;
182
+ isModified(path?: string | Array<string>, options?: { ignoreAtomics?: boolean } | null): boolean;
183
183
 
184
184
  /** Boolean flag specifying if the document is new. */
185
185
  isNew: boolean;
package/types/models.d.ts CHANGED
@@ -26,6 +26,8 @@ declare module 'mongoose' {
26
26
  interface MongooseBulkWriteOptions {
27
27
  skipValidation?: boolean;
28
28
  throwOnValidationError?: boolean;
29
+ strict?: boolean;
30
+ timestamps?: boolean | 'throw';
29
31
  }
30
32
 
31
33
  interface InsertManyOptions extends