mongoose 6.4.7 → 6.5.2

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.
Files changed (47) hide show
  1. package/lib/connection.js +23 -3
  2. package/lib/cursor/ChangeStream.js +39 -1
  3. package/lib/document.js +129 -154
  4. package/lib/error/index.js +1 -0
  5. package/lib/error/validation.js +9 -0
  6. package/lib/helpers/document/applyDefaults.js +115 -0
  7. package/lib/helpers/document/cleanModifiedSubpaths.js +3 -3
  8. package/lib/helpers/document/compile.js +7 -6
  9. package/lib/helpers/firstKey.js +8 -0
  10. package/lib/helpers/model/applyDefaultsToPOJO.js +52 -0
  11. package/lib/helpers/model/castBulkWrite.js +1 -1
  12. package/lib/helpers/model/pushNestedArrayPaths.js +15 -0
  13. package/lib/helpers/populate/markArraySubdocsPopulated.js +1 -0
  14. package/lib/helpers/projection/hasIncludedChildren.js +1 -0
  15. package/lib/helpers/promiseOrCallback.js +24 -15
  16. package/lib/helpers/update/applyTimestampsToChildren.js +6 -2
  17. package/lib/index.js +2 -1
  18. package/lib/internal.js +3 -1
  19. package/lib/model.js +237 -95
  20. package/lib/options/SchemaArrayOptions.js +19 -0
  21. package/lib/options/SchemaNumberOptions.js +2 -0
  22. package/lib/options/SchemaObjectIdOptions.js +1 -0
  23. package/lib/plugins/trackTransaction.js +2 -2
  24. package/lib/query.js +30 -11
  25. package/lib/schema/SubdocumentPath.js +10 -0
  26. package/lib/schema/array.js +2 -1
  27. package/lib/schema/documentarray.js +14 -1
  28. package/lib/schema/string.js +3 -0
  29. package/lib/schema.js +22 -3
  30. package/lib/schematype.js +5 -1
  31. package/lib/statemachine.js +23 -9
  32. package/lib/types/buffer.js +23 -21
  33. package/lib/types/map.js +2 -0
  34. package/lib/utils.js +8 -0
  35. package/lib/validoptions.js +1 -0
  36. package/package.json +14 -14
  37. package/{build-browser.js → scripts/build-browser.js} +1 -1
  38. package/types/connection.d.ts +7 -1
  39. package/types/document.d.ts +8 -1
  40. package/types/expressions.d.ts +1 -1
  41. package/types/index.d.ts +31 -28
  42. package/types/inferschematype.d.ts +3 -20
  43. package/types/models.d.ts +53 -49
  44. package/types/mongooseoptions.d.ts +6 -0
  45. package/types/schemaoptions.d.ts +15 -4
  46. package/types/utility.d.ts +19 -0
  47. package/types/virtuals.d.ts +14 -0
@@ -0,0 +1,115 @@
1
+ 'use strict';
2
+
3
+ module.exports = function applyDefaults(doc, fields, exclude, hasIncludedChildren, isBeforeSetters, pathsToSkip) {
4
+ const paths = Object.keys(doc.$__schema.paths);
5
+ const plen = paths.length;
6
+
7
+ for (let i = 0; i < plen; ++i) {
8
+ let def;
9
+ let curPath = '';
10
+ const p = paths[i];
11
+
12
+ if (p === '_id' && doc.$__.skipId) {
13
+ continue;
14
+ }
15
+
16
+ const type = doc.$__schema.paths[p];
17
+ const path = type.splitPath();
18
+ const len = path.length;
19
+ let included = false;
20
+ let doc_ = doc._doc;
21
+ for (let j = 0; j < len; ++j) {
22
+ if (doc_ == null) {
23
+ break;
24
+ }
25
+
26
+ const piece = path[j];
27
+ curPath += (!curPath.length ? '' : '.') + piece;
28
+
29
+ if (exclude === true) {
30
+ if (curPath in fields) {
31
+ break;
32
+ }
33
+ } else if (exclude === false && fields && !included) {
34
+ const hasSubpaths = type.$isSingleNested || type.$isMongooseDocumentArray;
35
+ if (curPath in fields || (hasSubpaths && hasIncludedChildren != null && hasIncludedChildren[curPath])) {
36
+ included = true;
37
+ } else if (hasIncludedChildren != null && !hasIncludedChildren[curPath]) {
38
+ break;
39
+ }
40
+ }
41
+
42
+ if (j === len - 1) {
43
+ if (doc_[piece] !== void 0) {
44
+ break;
45
+ }
46
+
47
+ if (isBeforeSetters != null) {
48
+ if (typeof type.defaultValue === 'function') {
49
+ if (!type.defaultValue.$runBeforeSetters && isBeforeSetters) {
50
+ break;
51
+ }
52
+ if (type.defaultValue.$runBeforeSetters && !isBeforeSetters) {
53
+ break;
54
+ }
55
+ } else if (!isBeforeSetters) {
56
+ // Non-function defaults should always run **before** setters
57
+ continue;
58
+ }
59
+ }
60
+
61
+ if (pathsToSkip && pathsToSkip[curPath]) {
62
+ break;
63
+ }
64
+
65
+ if (fields && exclude !== null) {
66
+ if (exclude === true) {
67
+ // apply defaults to all non-excluded fields
68
+ if (p in fields) {
69
+ continue;
70
+ }
71
+
72
+ try {
73
+ def = type.getDefault(doc, false);
74
+ } catch (err) {
75
+ doc.invalidate(p, err);
76
+ break;
77
+ }
78
+
79
+ if (typeof def !== 'undefined') {
80
+ doc_[piece] = def;
81
+ doc.$__.activePaths.default(p);
82
+ }
83
+ } else if (included) {
84
+ // selected field
85
+ try {
86
+ def = type.getDefault(doc, false);
87
+ } catch (err) {
88
+ doc.invalidate(p, err);
89
+ break;
90
+ }
91
+
92
+ if (typeof def !== 'undefined') {
93
+ doc_[piece] = def;
94
+ doc.$__.activePaths.default(p);
95
+ }
96
+ }
97
+ } else {
98
+ try {
99
+ def = type.getDefault(doc, false);
100
+ } catch (err) {
101
+ doc.invalidate(p, err);
102
+ break;
103
+ }
104
+
105
+ if (typeof def !== 'undefined') {
106
+ doc_[piece] = def;
107
+ doc.$__.activePaths.default(p);
108
+ }
109
+ }
110
+ } else {
111
+ doc_ = doc_[piece];
112
+ }
113
+ }
114
+ }
115
+ };
@@ -13,7 +13,7 @@ module.exports = function cleanModifiedSubpaths(doc, path, options) {
13
13
  return deleted;
14
14
  }
15
15
 
16
- for (const modifiedPath of Object.keys(doc.$__.activePaths.states.modify)) {
16
+ for (const modifiedPath of Object.keys(doc.$__.activePaths.getStatePaths('modify'))) {
17
17
  if (skipDocArrays) {
18
18
  const schemaType = doc.$__schema.path(modifiedPath);
19
19
  if (schemaType && schemaType.$isMongooseDocumentArray) {
@@ -21,13 +21,13 @@ module.exports = function cleanModifiedSubpaths(doc, path, options) {
21
21
  }
22
22
  }
23
23
  if (modifiedPath.startsWith(path + '.')) {
24
- delete doc.$__.activePaths.states.modify[modifiedPath];
24
+ doc.$__.activePaths.clearPath(modifiedPath);
25
25
  ++deleted;
26
26
 
27
27
  if (doc.$isSubdocument) {
28
28
  const owner = doc.ownerDocument();
29
29
  const fullPath = doc.$__fullPath(modifiedPath);
30
- delete owner.$__.activePaths.states.modify[fullPath];
30
+ owner.$__.activePaths.clearPath(fullPath);
31
31
  }
32
32
  }
33
33
  }
@@ -17,6 +17,13 @@ const isPOJO = utils.isPOJO;
17
17
  exports.compile = compile;
18
18
  exports.defineKey = defineKey;
19
19
 
20
+ const _isEmptyOptions = Object.freeze({
21
+ minimize: true,
22
+ virtuals: false,
23
+ getters: false,
24
+ transform: false
25
+ });
26
+
20
27
  /*!
21
28
  * Compiles schemas.
22
29
  */
@@ -130,12 +137,6 @@ function defineKey({ prop, subprops, prototype, prefix, options }) {
130
137
  value: true
131
138
  });
132
139
 
133
- const _isEmptyOptions = Object.freeze({
134
- minimize: true,
135
- virtuals: false,
136
- getters: false,
137
- transform: false
138
- });
139
140
  Object.defineProperty(nested, '$isEmpty', {
140
141
  enumerable: false,
141
142
  configurable: true,
@@ -0,0 +1,8 @@
1
+ 'use strict';
2
+
3
+ module.exports = function firstKey(obj) {
4
+ if (obj == null) {
5
+ return null;
6
+ }
7
+ return Object.keys(obj)[0];
8
+ };
@@ -0,0 +1,52 @@
1
+ 'use strict';
2
+
3
+ module.exports = function applyDefaultsToPOJO(doc, schema) {
4
+ const paths = Object.keys(schema.paths);
5
+ const plen = paths.length;
6
+
7
+ for (let i = 0; i < plen; ++i) {
8
+ let curPath = '';
9
+ const p = paths[i];
10
+
11
+ const type = schema.paths[p];
12
+ const path = type.splitPath();
13
+ const len = path.length;
14
+ let doc_ = doc;
15
+ for (let j = 0; j < len; ++j) {
16
+ if (doc_ == null) {
17
+ break;
18
+ }
19
+
20
+ const piece = path[j];
21
+ curPath += (!curPath.length ? '' : '.') + piece;
22
+
23
+ if (j === len - 1) {
24
+ if (typeof doc_[piece] !== 'undefined') {
25
+ if (type.$isSingleNested) {
26
+ applyDefaultsToPOJO(doc_[piece], type.caster.schema);
27
+ } else if (type.$isMongooseDocumentArray && Array.isArray(doc_[piece])) {
28
+ doc_[piece].forEach(el => applyDefaultsToPOJO(el, type.schema));
29
+ }
30
+
31
+ break;
32
+ }
33
+
34
+ const def = type.getDefault(doc, false, { skipCast: true });
35
+ if (typeof def !== 'undefined') {
36
+ doc_[piece] = def;
37
+
38
+ if (type.$isSingleNested) {
39
+ applyDefaultsToPOJO(def, type.caster.schema);
40
+ } else if (type.$isMongooseDocumentArray && Array.isArray(def)) {
41
+ def.forEach(el => applyDefaultsToPOJO(el, type.schema));
42
+ }
43
+ }
44
+ } else {
45
+ if (doc_[piece] == null) {
46
+ doc_[piece] = {};
47
+ }
48
+ doc_ = doc_[piece];
49
+ }
50
+ }
51
+ }
52
+ };
@@ -20,7 +20,7 @@ module.exports = function castBulkWrite(originalModel, op, options) {
20
20
  const model = decideModelByObject(originalModel, op['insertOne']['document']);
21
21
 
22
22
  const doc = new model(op['insertOne']['document']);
23
- if (model.schema.options.timestamps) {
23
+ if (model.schema.options.timestamps && options.timestamps !== false) {
24
24
  doc.initializeTimestamps();
25
25
  }
26
26
  if (options.session != null) {
@@ -0,0 +1,15 @@
1
+ 'use strict';
2
+
3
+ module.exports = function pushNestedArrayPaths(paths, nestedArray, path) {
4
+ if (nestedArray == null) {
5
+ return;
6
+ }
7
+
8
+ for (let i = 0; i < nestedArray.length; ++i) {
9
+ if (Array.isArray(nestedArray[i])) {
10
+ pushNestedArrayPaths(paths, nestedArray[i], path + '.' + i);
11
+ } else {
12
+ paths.push(path + '.' + i);
13
+ }
14
+ }
15
+ };
@@ -7,6 +7,7 @@ const utils = require('../../utils');
7
7
  * subdoc within the array knows its subpaths are populated.
8
8
  *
9
9
  * #### Example:
10
+ *
10
11
  * const doc = await Article.findOne().populate('comments.author');
11
12
  * doc.comments[0].populated('author'); // Should be set
12
13
  */
@@ -5,6 +5,7 @@
5
5
  * the projection.
6
6
  *
7
7
  * #### Example:
8
+ *
8
9
  * const res = hasIncludedChildren({ 'a.b.c': 0 });
9
10
  * res.a; // 1
10
11
  * res['a.b']; // 1
@@ -7,23 +7,32 @@ const emittedSymbol = Symbol('mongoose:emitted');
7
7
 
8
8
  module.exports = function promiseOrCallback(callback, fn, ee, Promise) {
9
9
  if (typeof callback === 'function') {
10
- return fn(function(error) {
11
- if (error != null) {
12
- if (ee != null && ee.listeners != null && ee.listeners('error').length > 0 && !error[emittedSymbol]) {
13
- error[emittedSymbol] = true;
14
- ee.emit('error', error);
10
+ try {
11
+ return fn(function(error) {
12
+ if (error != null) {
13
+ if (ee != null && ee.listeners != null && ee.listeners('error').length > 0 && !error[emittedSymbol]) {
14
+ error[emittedSymbol] = true;
15
+ ee.emit('error', error);
16
+ }
17
+ try {
18
+ callback(error);
19
+ } catch (error) {
20
+ return immediate(() => {
21
+ throw error;
22
+ });
23
+ }
24
+ return;
15
25
  }
16
- try {
17
- callback(error);
18
- } catch (error) {
19
- return immediate(() => {
20
- throw error;
21
- });
22
- }
23
- return;
26
+ callback.apply(this, arguments);
27
+ });
28
+ } catch (error) {
29
+ if (ee != null && ee.listeners != null && ee.listeners('error').length > 0 && !error[emittedSymbol]) {
30
+ error[emittedSymbol] = true;
31
+ ee.emit('error', error);
24
32
  }
25
- callback.apply(this, arguments);
26
- });
33
+
34
+ return callback(error);
35
+ }
27
36
  }
28
37
 
29
38
  Promise = Promise || PromiseProvider.get();
@@ -82,12 +82,15 @@ function applyTimestampsToChildren(now, update, schema) {
82
82
  function applyTimestampsToDocumentArray(arr, schematype, now) {
83
83
  const timestamps = schematype.schema.options.timestamps;
84
84
 
85
+ const len = arr.length;
86
+
85
87
  if (!timestamps) {
88
+ for (let i = 0; i < len; ++i) {
89
+ applyTimestampsToChildren(now, arr[i], schematype.schema);
90
+ }
86
91
  return;
87
92
  }
88
93
 
89
- const len = arr.length;
90
-
91
94
  const createdAt = handleTimestampOption(timestamps, 'createdAt');
92
95
  const updatedAt = handleTimestampOption(timestamps, 'updatedAt');
93
96
  for (let i = 0; i < len; ++i) {
@@ -105,6 +108,7 @@ function applyTimestampsToDocumentArray(arr, schematype, now) {
105
108
  function applyTimestampsToSingleNested(subdoc, schematype, now) {
106
109
  const timestamps = schematype.schema.options.timestamps;
107
110
  if (!timestamps) {
111
+ applyTimestampsToChildren(now, subdoc, schematype.schema);
108
112
  return;
109
113
  }
110
114
 
package/lib/index.js CHANGED
@@ -51,6 +51,7 @@ const objectIdHexRegexp = /^[0-9A-Fa-f]{24}$/;
51
51
  * Most apps will only use this one instance.
52
52
  *
53
53
  * #### Example:
54
+ *
54
55
  * const mongoose = require('mongoose');
55
56
  * mongoose instanceof mongoose.Mongoose; // true
56
57
  *
@@ -687,7 +688,7 @@ Mongoose.prototype._applyPlugins = function(schema, options) {
687
688
  * @param {Function} fn plugin callback
688
689
  * @param {Object} [opts] optional options
689
690
  * @return {Mongoose} this
690
- * @see plugins ./plugins.html
691
+ * @see plugins /docs/plugins
691
692
  * @api public
692
693
  */
693
694
 
package/lib/internal.js CHANGED
@@ -13,8 +13,9 @@ function InternalCache() {
13
13
  this.activePaths = new ActiveRoster();
14
14
  }
15
15
 
16
+ InternalCache.prototype.strictMode = true;
17
+
16
18
  InternalCache.prototype.fullPath = undefined;
17
- InternalCache.prototype.strictMode = undefined;
18
19
  InternalCache.prototype.selected = undefined;
19
20
  InternalCache.prototype.shardval = undefined;
20
21
  InternalCache.prototype.saveError = undefined;
@@ -28,6 +29,7 @@ InternalCache.prototype._id = undefined;
28
29
  InternalCache.prototype.ownerDocument = undefined;
29
30
  InternalCache.prototype.populate = undefined; // what we want to populate in this doc
30
31
  InternalCache.prototype.populated = undefined;// the _ids that have been populated
32
+ InternalCache.prototype.primitiveAtomics = undefined;
31
33
 
32
34
  /**
33
35
  * If `false`, this document was not the result of population.