mongoose 6.2.0 → 6.2.1
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/.eslintrc.json +150 -0
- package/CHANGELOG.md +21 -0
- package/dist/browser.umd.js +113 -112
- package/lib/aggregate.js +1 -1
- package/lib/document.js +83 -64
- package/lib/helpers/clone.js +40 -27
- package/lib/helpers/common.js +2 -2
- package/lib/helpers/getFunctionName.js +6 -4
- package/lib/helpers/isMongooseObject.js +9 -8
- package/lib/helpers/isObject.js +4 -4
- package/lib/helpers/path/parentPaths.js +10 -5
- package/lib/helpers/populate/assignRawDocsToIdStructure.js +4 -2
- package/lib/helpers/populate/assignVals.js +8 -4
- package/lib/helpers/populate/getModelsMapForPopulate.js +4 -4
- package/lib/helpers/populate/markArraySubdocsPopulated.js +3 -1
- package/lib/helpers/populate/modelNamesFromRefPath.js +4 -3
- package/lib/helpers/query/castUpdate.js +6 -2
- package/lib/helpers/schema/getPath.js +4 -2
- package/lib/helpers/timestamps/setupTimestamps.js +3 -8
- package/lib/index.js +2 -0
- package/lib/internal.js +1 -1
- package/lib/model.js +22 -8
- package/lib/plugins/trackTransaction.js +4 -3
- package/lib/query.js +3 -2
- package/lib/queryhelpers.js +1 -1
- package/lib/schema/array.js +17 -15
- package/lib/schema/documentarray.js +5 -8
- package/lib/schema/objectid.js +1 -1
- package/lib/schematype.js +29 -26
- package/lib/types/ArraySubdocument.js +2 -1
- package/lib/types/DocumentArray/index.js +9 -26
- package/lib/types/DocumentArray/isMongooseDocumentArray.js +5 -0
- package/lib/types/DocumentArray/methods/index.js +15 -3
- package/lib/types/array/index.js +21 -20
- package/lib/types/array/isMongooseArray.js +5 -0
- package/lib/types/array/methods/index.js +12 -12
- package/lib/utils.js +7 -0
- package/package.json +18 -147
- package/tools/repl.js +1 -1
- package/tsconfig.json +10 -0
- package/{index.d.ts → types/index.d.ts} +84 -75
package/lib/aggregate.js
CHANGED
|
@@ -39,7 +39,7 @@ const readConcern = Query.prototype.readConcern;
|
|
|
39
39
|
* ```javascript
|
|
40
40
|
* new Aggregate([{ $match: { _id: '00000000000000000000000a' } }]);
|
|
41
41
|
* // Do this instead to cast to an ObjectId
|
|
42
|
-
* new Aggregate([{ $match: { _id: mongoose.Types.ObjectId('00000000000000000000000a') } }]);
|
|
42
|
+
* new Aggregate([{ $match: { _id: new mongoose.Types.ObjectId('00000000000000000000000a') } }]);
|
|
43
43
|
* ```
|
|
44
44
|
*
|
|
45
45
|
* @see MongoDB http://docs.mongodb.org/manual/applications/aggregation/
|
package/lib/document.js
CHANGED
|
@@ -90,7 +90,7 @@ function Document(obj, fields, skipId, options) {
|
|
|
90
90
|
options = arguments[4] || {};
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
-
this.$__ = new InternalCache;
|
|
93
|
+
this.$__ = new InternalCache();
|
|
94
94
|
this.$isNew = 'isNew' in options ? options.isNew : true;
|
|
95
95
|
|
|
96
96
|
if ('priorDoc' in options) {
|
|
@@ -479,7 +479,7 @@ function $__applyDefaults(doc, fields, exclude, hasIncludedChildren, isBeforeSet
|
|
|
479
479
|
break;
|
|
480
480
|
}
|
|
481
481
|
} else if (exclude === false && fields && !included) {
|
|
482
|
-
if (curPath in fields) {
|
|
482
|
+
if (curPath in fields || type.$isSingleNested && hasIncludedChildren[curPath]) {
|
|
483
483
|
included = true;
|
|
484
484
|
} else if (!hasIncludedChildren[curPath]) {
|
|
485
485
|
break;
|
|
@@ -795,11 +795,12 @@ function init(self, obj, doc, opts, prefix) {
|
|
|
795
795
|
|
|
796
796
|
const keys = Object.keys(obj);
|
|
797
797
|
const len = keys.length;
|
|
798
|
-
let
|
|
798
|
+
let schemaType;
|
|
799
799
|
let path;
|
|
800
800
|
let i;
|
|
801
801
|
let index = 0;
|
|
802
802
|
const strict = self.$__.strictMode;
|
|
803
|
+
const docSchema = self.$__schema;
|
|
803
804
|
|
|
804
805
|
while (index < len) {
|
|
805
806
|
_init(index++);
|
|
@@ -808,25 +809,27 @@ function init(self, obj, doc, opts, prefix) {
|
|
|
808
809
|
function _init(index) {
|
|
809
810
|
i = keys[index];
|
|
810
811
|
path = prefix + i;
|
|
811
|
-
|
|
812
|
+
schemaType = docSchema.path(path);
|
|
812
813
|
|
|
813
814
|
// Should still work if not a model-level discriminator, but should not be
|
|
814
815
|
// necessary. This is *only* to catch the case where we queried using the
|
|
815
816
|
// base model and the discriminated model has a projection
|
|
816
|
-
if (
|
|
817
|
+
if (docSchema.$isRootDiscriminator && !self.$__isSelected(path)) {
|
|
817
818
|
return;
|
|
818
819
|
}
|
|
819
820
|
|
|
820
|
-
if (!
|
|
821
|
+
if (!schemaType && utils.isPOJO(obj[i])) {
|
|
821
822
|
// assume nested object
|
|
822
823
|
if (!doc[i]) {
|
|
823
824
|
doc[i] = {};
|
|
825
|
+
if (!strict && !(i in docSchema.tree) && !(i in docSchema.methods) && !(i in docSchema.virtuals)) {
|
|
826
|
+
self[i] = doc[i];
|
|
827
|
+
}
|
|
824
828
|
}
|
|
825
829
|
init(self, obj[i], doc[i], opts, path + '.');
|
|
826
|
-
} else if (!
|
|
830
|
+
} else if (!schemaType) {
|
|
827
831
|
doc[i] = obj[i];
|
|
828
|
-
if (!strict
|
|
829
|
-
// Set top-level properties that aren't in the schema if strict is false
|
|
832
|
+
if (!strict) {
|
|
830
833
|
self[i] = obj[i];
|
|
831
834
|
}
|
|
832
835
|
} else {
|
|
@@ -835,13 +838,13 @@ function init(self, obj, doc, opts, prefix) {
|
|
|
835
838
|
delete doc[i];
|
|
836
839
|
}
|
|
837
840
|
if (obj[i] === null) {
|
|
838
|
-
doc[i] =
|
|
841
|
+
doc[i] = schemaType._castNullish(null);
|
|
839
842
|
} else if (obj[i] !== undefined) {
|
|
840
843
|
const wasPopulated = obj[i].$__ == null ? null : obj[i].$__.wasPopulated;
|
|
841
844
|
|
|
842
|
-
if (
|
|
845
|
+
if (schemaType && !wasPopulated) {
|
|
843
846
|
try {
|
|
844
|
-
doc[i] =
|
|
847
|
+
doc[i] = schemaType.cast(obj[i], self, true);
|
|
845
848
|
} catch (e) {
|
|
846
849
|
self.invalidate(e.path, new ValidatorError({
|
|
847
850
|
path: e.path,
|
|
@@ -1135,7 +1138,7 @@ Document.prototype.$set = function $set(path, val, type, options) {
|
|
|
1135
1138
|
// them to ensure we keep the user's key order.
|
|
1136
1139
|
if (type === true &&
|
|
1137
1140
|
!prefix &&
|
|
1138
|
-
|
|
1141
|
+
valForKey != null &&
|
|
1139
1142
|
pathtype === 'nested' &&
|
|
1140
1143
|
this._doc[key] != null) {
|
|
1141
1144
|
delete this._doc[key];
|
|
@@ -1313,7 +1316,7 @@ Document.prototype.$set = function $set(path, val, type, options) {
|
|
|
1313
1316
|
let curPath = '';
|
|
1314
1317
|
for (i = 0; i < parts.length - 1; ++i) {
|
|
1315
1318
|
cur = cur[parts[i]];
|
|
1316
|
-
curPath += (curPath.length
|
|
1319
|
+
curPath += (curPath.length !== 0 ? '.' : '') + parts[i];
|
|
1317
1320
|
if (!cur) {
|
|
1318
1321
|
this.$set(curPath, {});
|
|
1319
1322
|
// Hack re: gh-5800. If nested field is not selected, it probably exists
|
|
@@ -1336,7 +1339,8 @@ Document.prototype.$set = function $set(path, val, type, options) {
|
|
|
1336
1339
|
if (parts.length <= 1) {
|
|
1337
1340
|
pathToMark = path;
|
|
1338
1341
|
} else {
|
|
1339
|
-
|
|
1342
|
+
const len = parts.length;
|
|
1343
|
+
for (i = 0; i < len; ++i) {
|
|
1340
1344
|
const subpath = parts.slice(0, i + 1).join('.');
|
|
1341
1345
|
if (this.$get(subpath, null, { getters: false }) === null) {
|
|
1342
1346
|
pathToMark = subpath;
|
|
@@ -1361,7 +1365,7 @@ Document.prototype.$set = function $set(path, val, type, options) {
|
|
|
1361
1365
|
_markValidSubpaths(this, path);
|
|
1362
1366
|
}
|
|
1363
1367
|
|
|
1364
|
-
if (
|
|
1368
|
+
if (val != null && merge && schema.$isSingleNested) {
|
|
1365
1369
|
if (val instanceof Document) {
|
|
1366
1370
|
val = val.toObject({ virtuals: false, transform: false });
|
|
1367
1371
|
}
|
|
@@ -1431,9 +1435,10 @@ Document.prototype.$set = function $set(path, val, type, options) {
|
|
|
1431
1435
|
val = schema.applySetters(val, this, false, priorVal);
|
|
1432
1436
|
}
|
|
1433
1437
|
|
|
1434
|
-
if (
|
|
1435
|
-
Array.isArray(
|
|
1436
|
-
|
|
1438
|
+
if (Array.isArray(val) &&
|
|
1439
|
+
!Array.isArray(schema) &&
|
|
1440
|
+
schema.$isMongooseDocumentArray &&
|
|
1441
|
+
val.length !== 0 &&
|
|
1437
1442
|
val[0] != null &&
|
|
1438
1443
|
val[0].$__ != null &&
|
|
1439
1444
|
val[0].$__.populated != null) {
|
|
@@ -1459,7 +1464,7 @@ Document.prototype.$set = function $set(path, val, type, options) {
|
|
|
1459
1464
|
delete this.$__.populated[path];
|
|
1460
1465
|
}
|
|
1461
1466
|
|
|
1462
|
-
if (
|
|
1467
|
+
if (val != null && schema.$isSingleNested) {
|
|
1463
1468
|
_checkImmutableSubpaths(val, schema, priorVal);
|
|
1464
1469
|
}
|
|
1465
1470
|
|
|
@@ -1652,11 +1657,11 @@ Document.prototype.$__set = function(pathToMark, path, options, constructing, pa
|
|
|
1652
1657
|
|
|
1653
1658
|
// handle directly setting arrays (gh-1126)
|
|
1654
1659
|
MongooseArray || (MongooseArray = require('./types/array'));
|
|
1655
|
-
if (val &&
|
|
1660
|
+
if (val && utils.isMongooseArray(val)) {
|
|
1656
1661
|
val._registerAtomic('$set', val);
|
|
1657
1662
|
|
|
1658
1663
|
// Update embedded document parent references (gh-5189)
|
|
1659
|
-
if (
|
|
1664
|
+
if (utils.isMongooseDocumentArray(val)) {
|
|
1660
1665
|
val.forEach(function(item) {
|
|
1661
1666
|
item && item.__parentArray && (item.__parentArray = val);
|
|
1662
1667
|
});
|
|
@@ -1670,10 +1675,10 @@ Document.prototype.$__set = function(pathToMark, path, options, constructing, pa
|
|
|
1670
1675
|
}
|
|
1671
1676
|
});
|
|
1672
1677
|
}
|
|
1673
|
-
} else if (Array.isArray(val) &&
|
|
1678
|
+
} else if (Array.isArray(val) && Array.isArray(priorVal) && utils.isMongooseArray(val) && utils.isMongooseArray(priorVal)) {
|
|
1674
1679
|
val[arrayAtomicsSymbol] = priorVal[arrayAtomicsSymbol];
|
|
1675
1680
|
val[arrayAtomicsBackupSymbol] = priorVal[arrayAtomicsBackupSymbol];
|
|
1676
|
-
if (
|
|
1681
|
+
if (utils.isMongooseDocumentArray(val)) {
|
|
1677
1682
|
val.forEach(doc => { doc.isNew = false; });
|
|
1678
1683
|
}
|
|
1679
1684
|
}
|
|
@@ -1702,7 +1707,7 @@ Document.prototype.$__set = function(pathToMark, path, options, constructing, pa
|
|
|
1702
1707
|
obj = obj[parts[i]];
|
|
1703
1708
|
} else if (obj[parts[i]] && obj[parts[i]] instanceof Embedded) {
|
|
1704
1709
|
obj = obj[parts[i]];
|
|
1705
|
-
} else if (obj[parts[i]] && obj[parts[i]].$isSingleNested) {
|
|
1710
|
+
} else if (obj[parts[i]] && !Array.isArray(obj[parts[i]]) && obj[parts[i]].$isSingleNested) {
|
|
1706
1711
|
obj = obj[parts[i]];
|
|
1707
1712
|
} else if (obj[parts[i]] && Array.isArray(obj[parts[i]])) {
|
|
1708
1713
|
obj = obj[parts[i]];
|
|
@@ -1963,7 +1968,7 @@ Document.prototype.$isEmpty = function(path) {
|
|
|
1963
1968
|
transform: false
|
|
1964
1969
|
};
|
|
1965
1970
|
|
|
1966
|
-
if (arguments.length
|
|
1971
|
+
if (arguments.length !== 0) {
|
|
1967
1972
|
const v = this.$get(path);
|
|
1968
1973
|
if (v == null) {
|
|
1969
1974
|
return true;
|
|
@@ -2006,51 +2011,60 @@ function _isEmpty(v) {
|
|
|
2006
2011
|
|
|
2007
2012
|
Document.prototype.modifiedPaths = function(options) {
|
|
2008
2013
|
options = options || {};
|
|
2014
|
+
|
|
2009
2015
|
const directModifiedPaths = Object.keys(this.$__.activePaths.states.modify);
|
|
2010
|
-
const
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2016
|
+
const result = new Set();
|
|
2017
|
+
|
|
2018
|
+
let i = 0;
|
|
2019
|
+
let j = 0;
|
|
2020
|
+
const len = directModifiedPaths.length;
|
|
2021
|
+
|
|
2022
|
+
for (i = 0; i < len; ++i) {
|
|
2023
|
+
const path = directModifiedPaths[i];
|
|
2024
|
+
const parts = parentPaths(path);
|
|
2025
|
+
const pLen = parts.length;
|
|
2026
|
+
|
|
2027
|
+
for (j = 0; j < pLen; ++j) {
|
|
2028
|
+
result.add(parts[j]);
|
|
2029
|
+
}
|
|
2018
2030
|
|
|
2019
2031
|
if (!options.includeChildren) {
|
|
2020
|
-
|
|
2032
|
+
continue;
|
|
2021
2033
|
}
|
|
2022
2034
|
|
|
2023
|
-
let
|
|
2024
|
-
|
|
2035
|
+
let ii = 0;
|
|
2036
|
+
let cur = this.$get(path);
|
|
2037
|
+
if (typeof cur === 'object' && cur !== null) {
|
|
2025
2038
|
if (cur._doc) {
|
|
2026
2039
|
cur = cur._doc;
|
|
2027
2040
|
}
|
|
2041
|
+
const len = cur.length;
|
|
2028
2042
|
if (Array.isArray(cur)) {
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
if (
|
|
2032
|
-
|
|
2033
|
-
if (cur[
|
|
2034
|
-
const modified = cur[
|
|
2035
|
-
|
|
2036
|
-
|
|
2043
|
+
for (ii = 0; ii < len; ++ii) {
|
|
2044
|
+
const subPath = path + '.' + ii;
|
|
2045
|
+
if (!result.has(subPath)) {
|
|
2046
|
+
result.add(subPath);
|
|
2047
|
+
if (cur[ii] != null && cur[ii].$__) {
|
|
2048
|
+
const modified = cur[ii].modifiedPaths();
|
|
2049
|
+
let iii = 0;
|
|
2050
|
+
const iiiLen = modified.length;
|
|
2051
|
+
for (iii = 0; iii < iiiLen; ++iii) {
|
|
2052
|
+
result.add(subPath + '.' + modified[iii]);
|
|
2037
2053
|
}
|
|
2038
2054
|
}
|
|
2039
2055
|
}
|
|
2040
2056
|
}
|
|
2041
2057
|
} else {
|
|
2042
|
-
Object.keys(cur)
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
});
|
|
2058
|
+
const keys = Object.keys(cur);
|
|
2059
|
+
let ii = 0;
|
|
2060
|
+
const len = keys.length;
|
|
2061
|
+
for (ii = 0; ii < len; ++ii) {
|
|
2062
|
+
result.add(path + '.' + keys[ii]);
|
|
2063
|
+
}
|
|
2049
2064
|
}
|
|
2050
2065
|
}
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
}, []);
|
|
2066
|
+
}
|
|
2067
|
+
return Array.from(result);
|
|
2054
2068
|
};
|
|
2055
2069
|
|
|
2056
2070
|
Document.prototype[documentModifiedPaths] = Document.prototype.modifiedPaths;
|
|
@@ -2448,7 +2462,12 @@ Document.prototype.$validate = Document.prototype.validate;
|
|
|
2448
2462
|
*/
|
|
2449
2463
|
|
|
2450
2464
|
function _evaluateRequiredFunctions(doc) {
|
|
2451
|
-
Object.keys(doc.$__.activePaths.states.require)
|
|
2465
|
+
const requiredFields = Object.keys(doc.$__.activePaths.states.require);
|
|
2466
|
+
let i = 0;
|
|
2467
|
+
const len = requiredFields.length;
|
|
2468
|
+
for (i = 0; i < len; ++i) {
|
|
2469
|
+
const path = requiredFields[i];
|
|
2470
|
+
|
|
2452
2471
|
const p = doc.$__schema.path(path);
|
|
2453
2472
|
|
|
2454
2473
|
if (p != null && typeof p.originalRequiredValue === 'function') {
|
|
@@ -2459,7 +2478,7 @@ function _evaluateRequiredFunctions(doc) {
|
|
|
2459
2478
|
doc.invalidate(path, err);
|
|
2460
2479
|
}
|
|
2461
2480
|
}
|
|
2462
|
-
}
|
|
2481
|
+
}
|
|
2463
2482
|
}
|
|
2464
2483
|
|
|
2465
2484
|
/*!
|
|
@@ -2520,7 +2539,7 @@ function _getPathsToValidate(doc) {
|
|
|
2520
2539
|
// To avoid potential performance issues, skip doc arrays whose children
|
|
2521
2540
|
// are not required. `getPositionalPathType()` may be slow, so avoid
|
|
2522
2541
|
// it unless we have a case of #6364
|
|
2523
|
-
(_pathType.$isMongooseDocumentArray && !get(_pathType, 'schemaOptions.required'))) {
|
|
2542
|
+
(!Array.isArray(_pathType) && _pathType.$isMongooseDocumentArray && !get(_pathType, 'schemaOptions.required'))) {
|
|
2524
2543
|
continue;
|
|
2525
2544
|
}
|
|
2526
2545
|
|
|
@@ -3112,7 +3131,7 @@ Document.prototype.$__reset = function reset() {
|
|
|
3112
3131
|
return _this.$__getValue(i);
|
|
3113
3132
|
})
|
|
3114
3133
|
.filter(function(val) {
|
|
3115
|
-
return val && val instanceof Array &&
|
|
3134
|
+
return val && val instanceof Array && utils.isMongooseDocumentArray(val) && val.length;
|
|
3116
3135
|
})
|
|
3117
3136
|
.forEach(function(array) {
|
|
3118
3137
|
let i = array.length;
|
|
@@ -3135,7 +3154,7 @@ Document.prototype.$__reset = function reset() {
|
|
|
3135
3154
|
return _this.$__getValue(i);
|
|
3136
3155
|
}).
|
|
3137
3156
|
filter(function(val) {
|
|
3138
|
-
return val && val.$isSingleNested;
|
|
3157
|
+
return val && !Array.isArray(val) && val.$isSingleNested;
|
|
3139
3158
|
}).
|
|
3140
3159
|
forEach(function(doc) {
|
|
3141
3160
|
doc.$__reset();
|
|
@@ -3315,7 +3334,7 @@ Document.prototype.$__getArrayPathsToValidate = function() {
|
|
|
3315
3334
|
return this.$__getValue(i);
|
|
3316
3335
|
}.bind(this))
|
|
3317
3336
|
.filter(function(val) {
|
|
3318
|
-
return val && val instanceof Array &&
|
|
3337
|
+
return val && val instanceof Array && utils.isMongooseDocumentArray(val) && val.length;
|
|
3319
3338
|
}).reduce(function(seed, array) {
|
|
3320
3339
|
return seed.concat(array);
|
|
3321
3340
|
}, [])
|
|
@@ -3357,12 +3376,12 @@ Document.prototype.$getAllSubdocs = function() {
|
|
|
3357
3376
|
seed = Array.from(val.keys()).reduce(function(seed, path) {
|
|
3358
3377
|
return docReducer(val.get(path), seed, null);
|
|
3359
3378
|
}, seed);
|
|
3360
|
-
} else if (val && val.$isSingleNested) {
|
|
3379
|
+
} else if (val && !Array.isArray(val) && val.$isSingleNested) {
|
|
3361
3380
|
seed = Object.keys(val._doc).reduce(function(seed, path) {
|
|
3362
3381
|
return docReducer(val._doc, seed, path);
|
|
3363
3382
|
}, seed);
|
|
3364
3383
|
seed.push(val);
|
|
3365
|
-
} else if (val &&
|
|
3384
|
+
} else if (val && utils.isMongooseDocumentArray(val)) {
|
|
3366
3385
|
val.forEach(function _docReduce(doc) {
|
|
3367
3386
|
if (!doc || !doc._doc) {
|
|
3368
3387
|
return;
|
|
@@ -4139,7 +4158,7 @@ Document.prototype.populate = function populate() {
|
|
|
4139
4158
|
const args = [...arguments];
|
|
4140
4159
|
let fn;
|
|
4141
4160
|
|
|
4142
|
-
if (args.length
|
|
4161
|
+
if (args.length !== 0) {
|
|
4143
4162
|
if (typeof args[args.length - 1] === 'function') {
|
|
4144
4163
|
fn = args.pop();
|
|
4145
4164
|
}
|
package/lib/helpers/clone.js
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
const cloneRegExp = require('regexp-clone');
|
|
5
3
|
const Decimal = require('../types/decimal128');
|
|
6
4
|
const ObjectId = require('../types/objectid');
|
|
7
5
|
const specialProperties = require('./specialProperties');
|
|
@@ -34,7 +32,7 @@ function clone(obj, options, isArrayChild) {
|
|
|
34
32
|
}
|
|
35
33
|
|
|
36
34
|
if (Array.isArray(obj)) {
|
|
37
|
-
return cloneArray(obj, options);
|
|
35
|
+
return cloneArray(utils.isMongooseArray(obj) ? obj.__array : obj, options);
|
|
38
36
|
}
|
|
39
37
|
|
|
40
38
|
if (isMongooseObject(obj)) {
|
|
@@ -54,12 +52,14 @@ function clone(obj, options, isArrayChild) {
|
|
|
54
52
|
return obj.toObject(options);
|
|
55
53
|
}
|
|
56
54
|
|
|
57
|
-
|
|
58
|
-
|
|
55
|
+
const objConstructor = obj.constructor;
|
|
56
|
+
|
|
57
|
+
if (objConstructor) {
|
|
58
|
+
switch (getFunctionName(objConstructor)) {
|
|
59
59
|
case 'Object':
|
|
60
60
|
return cloneObject(obj, options, isArrayChild);
|
|
61
61
|
case 'Date':
|
|
62
|
-
return new
|
|
62
|
+
return new objConstructor(+obj);
|
|
63
63
|
case 'RegExp':
|
|
64
64
|
return cloneRegExp(obj);
|
|
65
65
|
default:
|
|
@@ -79,12 +79,12 @@ function clone(obj, options, isArrayChild) {
|
|
|
79
79
|
return Decimal.fromString(obj.toString());
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
-
|
|
83
|
-
|
|
82
|
+
// object created with Object.create(null)
|
|
83
|
+
if (!objConstructor && isObject(obj)) {
|
|
84
84
|
return cloneObject(obj, options, isArrayChild);
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
-
if (obj[symbols.schemaTypeSymbol]) {
|
|
87
|
+
if (typeof obj === 'object' && obj[symbols.schemaTypeSymbol]) {
|
|
88
88
|
return obj.clone();
|
|
89
89
|
}
|
|
90
90
|
|
|
@@ -95,7 +95,7 @@ function clone(obj, options, isArrayChild) {
|
|
|
95
95
|
return obj;
|
|
96
96
|
}
|
|
97
97
|
|
|
98
|
-
if (obj.valueOf
|
|
98
|
+
if (typeof obj.valueOf === 'function') {
|
|
99
99
|
return obj.valueOf();
|
|
100
100
|
}
|
|
101
101
|
|
|
@@ -112,25 +112,28 @@ function cloneObject(obj, options, isArrayChild) {
|
|
|
112
112
|
const ret = {};
|
|
113
113
|
let hasKeys;
|
|
114
114
|
|
|
115
|
-
if (obj
|
|
115
|
+
if (trustedSymbol in obj) {
|
|
116
116
|
ret[trustedSymbol] = obj[trustedSymbol];
|
|
117
117
|
}
|
|
118
118
|
|
|
119
|
-
|
|
120
|
-
|
|
119
|
+
let i = 0;
|
|
120
|
+
let key = '';
|
|
121
|
+
const keys = Object.keys(obj);
|
|
122
|
+
const len = keys.length;
|
|
123
|
+
|
|
124
|
+
for (i = 0; i < len; ++i) {
|
|
125
|
+
if (specialProperties.has(key = keys[i])) {
|
|
121
126
|
continue;
|
|
122
127
|
}
|
|
123
128
|
|
|
124
129
|
// Don't pass `isArrayChild` down
|
|
125
|
-
const val = clone(obj[
|
|
126
|
-
|
|
127
|
-
if (
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
ret[k] = val;
|
|
133
|
-
}
|
|
130
|
+
const val = clone(obj[key], options, false);
|
|
131
|
+
|
|
132
|
+
if (minimize === false && typeof val === 'undefined') {
|
|
133
|
+
delete ret[key];
|
|
134
|
+
} else if (minimize !== true || (typeof val !== 'undefined')) {
|
|
135
|
+
hasKeys || (hasKeys = true);
|
|
136
|
+
ret[key] = val;
|
|
134
137
|
}
|
|
135
138
|
}
|
|
136
139
|
|
|
@@ -138,11 +141,21 @@ function cloneObject(obj, options, isArrayChild) {
|
|
|
138
141
|
}
|
|
139
142
|
|
|
140
143
|
function cloneArray(arr, options) {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
144
|
+
let i = 0;
|
|
145
|
+
const len = arr.length;
|
|
146
|
+
const ret = new Array(len);
|
|
147
|
+
for (i = 0; i < len; ++i) {
|
|
148
|
+
ret[i] = clone(arr[i], options, true);
|
|
145
149
|
}
|
|
146
150
|
|
|
147
151
|
return ret;
|
|
148
|
-
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function cloneRegExp(regexp) {
|
|
155
|
+
const ret = new RegExp(regexp.source, regexp.flags);
|
|
156
|
+
|
|
157
|
+
if (ret.lastIndex !== regexp.lastIndex) {
|
|
158
|
+
ret.lastIndex = regexp.lastIndex;
|
|
159
|
+
}
|
|
160
|
+
return ret;
|
|
161
|
+
}
|
package/lib/helpers/common.js
CHANGED
|
@@ -88,7 +88,7 @@ function modifiedPaths(update, path, result) {
|
|
|
88
88
|
cur += '.' + sp[i];
|
|
89
89
|
}
|
|
90
90
|
}
|
|
91
|
-
if (
|
|
91
|
+
if (!Buffer.isBuffer(val) && isMongooseObject(val)) {
|
|
92
92
|
val = val.toObject({ transform: false, virtuals: false });
|
|
93
93
|
}
|
|
94
94
|
if (shouldFlatten(val)) {
|
|
@@ -108,7 +108,7 @@ function shouldFlatten(val) {
|
|
|
108
108
|
typeof val === 'object' &&
|
|
109
109
|
!(val instanceof Date) &&
|
|
110
110
|
!(val instanceof ObjectId) &&
|
|
111
|
-
(!Array.isArray(val) || val.length
|
|
111
|
+
(!Array.isArray(val) || val.length !== 0) &&
|
|
112
112
|
!(val instanceof Buffer) &&
|
|
113
113
|
!(val instanceof Decimal128) &&
|
|
114
114
|
!(val instanceof Binary);
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const functionNameRE = /^function\s*([^\s(]+)/;
|
|
4
|
+
|
|
3
5
|
module.exports = function(fn) {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
return (
|
|
7
|
+
fn.name ||
|
|
8
|
+
(fn.toString().trim().match(functionNameRE) || [])[1]
|
|
9
|
+
);
|
|
8
10
|
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const isMongooseArray = require('../types/array/isMongooseArray').isMongooseArray;
|
|
3
4
|
/*!
|
|
4
5
|
* Returns if `v` is a mongoose object that has a `toObject()` method we can use.
|
|
5
6
|
*
|
|
@@ -10,12 +11,12 @@
|
|
|
10
11
|
*/
|
|
11
12
|
|
|
12
13
|
module.exports = function(v) {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
14
|
+
return (
|
|
15
|
+
v != null && (
|
|
16
|
+
isMongooseArray(v) || // Array or Document Array
|
|
17
|
+
v.$__ != null || // Document
|
|
18
|
+
v.isMongooseBuffer || // Buffer
|
|
19
|
+
v.$isMongooseMap // Map
|
|
20
|
+
)
|
|
21
|
+
);
|
|
21
22
|
};
|
package/lib/helpers/isObject.js
CHANGED
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
module.exports = function(arg) {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
return (
|
|
13
|
+
Buffer.isBuffer(arg) ||
|
|
14
|
+
Object.prototype.toString.call(arg) === '[object Object]'
|
|
15
|
+
);
|
|
16
16
|
};
|
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const dotRE = /\./g;
|
|
3
4
|
module.exports = function parentPaths(path) {
|
|
4
|
-
|
|
5
|
+
if (path.indexOf('.') === -1) {
|
|
6
|
+
return [path];
|
|
7
|
+
}
|
|
8
|
+
const pieces = path.split(dotRE);
|
|
9
|
+
const len = pieces.length;
|
|
10
|
+
const ret = new Array(len);
|
|
5
11
|
let cur = '';
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
ret.push(cur);
|
|
12
|
+
for (let i = 0; i < len; ++i) {
|
|
13
|
+
cur += (cur.length !== 0) ? '.' + pieces[i] : pieces[i];
|
|
14
|
+
ret[i] = cur;
|
|
10
15
|
}
|
|
11
16
|
|
|
12
17
|
return ret;
|
|
@@ -35,11 +35,13 @@ function assignRawDocsToIdStructure(rawIds, resultDocs, resultOrder, options, re
|
|
|
35
35
|
let sid;
|
|
36
36
|
let id;
|
|
37
37
|
|
|
38
|
-
if (rawIds
|
|
38
|
+
if (utils.isMongooseArray(rawIds)) {
|
|
39
39
|
rawIds = rawIds.__array;
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
|
|
42
|
+
let i = 0;
|
|
43
|
+
const len = rawIds.length;
|
|
44
|
+
for (i = 0; i < len; ++i) {
|
|
43
45
|
id = rawIds[i];
|
|
44
46
|
|
|
45
47
|
if (Array.isArray(id)) {
|
|
@@ -241,15 +241,19 @@ function valueFilter(val, assignmentOpts, populateOptions, allIds) {
|
|
|
241
241
|
}
|
|
242
242
|
}
|
|
243
243
|
|
|
244
|
+
const rLen = ret.length;
|
|
244
245
|
// Since we don't want to have to create a new mongoosearray, make sure to
|
|
245
246
|
// modify the array in place
|
|
246
|
-
while (val.length >
|
|
247
|
+
while (val.length > rLen) {
|
|
247
248
|
Array.prototype.pop.apply(val, []);
|
|
248
249
|
}
|
|
249
|
-
|
|
250
|
-
|
|
250
|
+
let i = 0;
|
|
251
|
+
if (utils.isMongooseArray(val)) {
|
|
252
|
+
for (i = 0; i < rLen; ++i) {
|
|
251
253
|
val.set(i, ret[i], true);
|
|
252
|
-
}
|
|
254
|
+
}
|
|
255
|
+
} else {
|
|
256
|
+
for (i = 0; i < rLen; ++i) {
|
|
253
257
|
val[i] = ret[i];
|
|
254
258
|
}
|
|
255
259
|
}
|
|
@@ -43,7 +43,7 @@ module.exports = function getModelsMapForPopulate(model, docs, options) {
|
|
|
43
43
|
let allSchemaTypes = getSchemaTypes(model, modelSchema, null, options.path);
|
|
44
44
|
allSchemaTypes = Array.isArray(allSchemaTypes) ? allSchemaTypes : [allSchemaTypes].filter(v => v != null);
|
|
45
45
|
|
|
46
|
-
if (allSchemaTypes.length
|
|
46
|
+
if (allSchemaTypes.length === 0 && options.strictPopulate !== false && options._localModel != null) {
|
|
47
47
|
return new MongooseError('Cannot populate path `' + (options._fullPath || options.path) +
|
|
48
48
|
'` because it is not in your schema. Set the `strictPopulate` option ' +
|
|
49
49
|
'to false to override.');
|
|
@@ -607,7 +607,7 @@ function _getLocalFieldValues(doc, localField, model, options, virtual, schema)
|
|
|
607
607
|
const getters = 'getters' in _populateOptions ?
|
|
608
608
|
_populateOptions.getters :
|
|
609
609
|
get(virtual, 'options.getters', false);
|
|
610
|
-
if (localFieldGetters.length
|
|
610
|
+
if (localFieldGetters.length !== 0 && getters) {
|
|
611
611
|
const hydratedDoc = (doc.$__ != null) ? doc : model.hydrate(doc);
|
|
612
612
|
const localFieldValue = utils.getValue(localField, doc);
|
|
613
613
|
if (Array.isArray(localFieldValue)) {
|
|
@@ -644,7 +644,7 @@ function convertTo_id(val, schema) {
|
|
|
644
644
|
rawVal[i] = rawVal[i]._id;
|
|
645
645
|
}
|
|
646
646
|
}
|
|
647
|
-
if (
|
|
647
|
+
if (utils.isMongooseArray(val) && val.$schema()) {
|
|
648
648
|
return val.$schema()._castForPopulate(val, val.$parent());
|
|
649
649
|
}
|
|
650
650
|
|
|
@@ -694,7 +694,7 @@ function _findRefPathForDiscriminators(doc, modelSchema, data, options, normaliz
|
|
|
694
694
|
if (schematype != null &&
|
|
695
695
|
schematype.$isMongooseArray &&
|
|
696
696
|
schematype.caster.discriminators != null &&
|
|
697
|
-
Object.keys(schematype.caster.discriminators).length
|
|
697
|
+
Object.keys(schematype.caster.discriminators).length !== 0) {
|
|
698
698
|
const subdocs = utils.getValue(cur, doc);
|
|
699
699
|
const remnant = options.path.substring(cur.length + 1);
|
|
700
700
|
const discriminatorKey = schematype.caster.schema.options.discriminatorKey;
|