mongoose 9.0.1 → 9.1.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/aggregate.js +1 -1
- package/lib/cast/string.js +1 -1
- package/lib/cast.js +7 -15
- package/lib/collection.js +2 -2
- package/lib/connection.js +20 -14
- package/lib/cursor/changeStream.js +5 -5
- package/lib/document.js +126 -79
- package/lib/drivers/node-mongodb-native/collection.js +33 -126
- package/lib/drivers/node-mongodb-native/connection.js +8 -23
- package/lib/error/cast.js +1 -1
- package/lib/helpers/aggregate/prepareDiscriminatorPipeline.js +4 -4
- package/lib/helpers/clone.js +8 -8
- package/lib/helpers/common.js +4 -4
- package/lib/helpers/cursor/eachAsync.js +1 -1
- package/lib/helpers/discriminator/getConstructor.js +1 -1
- package/lib/helpers/discriminator/getSchemaDiscriminatorByValue.js +1 -1
- package/lib/helpers/discriminator/mergeDiscriminatorSchema.js +2 -2
- package/lib/helpers/document/applyDefaults.js +1 -1
- package/lib/helpers/document/applyTimestamps.js +2 -1
- package/lib/helpers/document/applyVirtuals.js +4 -3
- package/lib/helpers/document/cleanModifiedSubpaths.js +1 -1
- package/lib/helpers/document/compile.js +4 -4
- package/lib/helpers/document/getDeepestSubdocumentForPath.js +1 -1
- package/lib/helpers/indexes/decorateDiscriminatorIndexOptions.js +1 -1
- package/lib/helpers/indexes/getRelatedIndexes.js +3 -3
- package/lib/helpers/model/castBulkWrite.js +5 -9
- package/lib/helpers/model/discriminator.js +1 -1
- package/lib/helpers/populate/assignRawDocsToIdStructure.js +1 -1
- package/lib/helpers/populate/assignVals.js +4 -4
- package/lib/helpers/populate/getModelsMapForPopulate.js +25 -23
- package/lib/helpers/populate/getSchemaTypes.js +6 -7
- package/lib/helpers/printJestWarning.js +1 -1
- package/lib/helpers/processConnectionOptions.js +1 -1
- package/lib/helpers/query/castUpdate.js +12 -12
- package/lib/helpers/query/getEmbeddedDiscriminatorPath.js +2 -2
- package/lib/helpers/query/handleImmutable.js +2 -2
- package/lib/helpers/query/sanitizeFilter.js +1 -1
- package/lib/helpers/schema/applyPlugins.js +1 -1
- package/lib/helpers/schema/applyReadConcern.js +1 -1
- package/lib/helpers/schema/applyWriteConcern.js +4 -2
- package/lib/helpers/schema/getIndexes.js +3 -3
- package/lib/helpers/schema/getSubdocumentStrictValue.js +1 -1
- package/lib/helpers/schema/handleIdOption.js +1 -1
- package/lib/helpers/schema/idGetter.js +1 -1
- package/lib/helpers/schematype/handleImmutable.js +1 -1
- package/lib/helpers/setDefaultsOnInsert.js +2 -5
- package/lib/helpers/timestamps/setDocumentTimestamps.js +2 -2
- package/lib/helpers/timestamps/setupTimestamps.js +2 -2
- package/lib/helpers/update/applyTimestampsToUpdate.js +10 -9
- package/lib/helpers/update/castArrayFilters.js +4 -4
- package/lib/helpers/update/decorateUpdateWithVersionKey.js +1 -1
- package/lib/helpers/updateValidators.js +4 -4
- package/lib/model.js +42 -48
- package/lib/mongoose.js +5 -5
- package/lib/options/virtualOptions.js +1 -1
- package/lib/plugins/saveSubdocs.js +2 -2
- package/lib/plugins/trackTransaction.js +3 -4
- package/lib/query.js +62 -59
- package/lib/queryHelpers.js +9 -12
- package/lib/schema/array.js +10 -12
- package/lib/schema/buffer.js +6 -6
- package/lib/schema/documentArray.js +15 -23
- package/lib/schema/documentArrayElement.js +3 -3
- package/lib/schema/map.js +1 -1
- package/lib/schema/mixed.js +2 -2
- package/lib/schema/number.js +22 -4
- package/lib/schema/objectId.js +1 -1
- package/lib/schema/operators/exists.js +1 -1
- package/lib/schema/operators/geospatial.js +1 -1
- package/lib/schema/string.js +2 -2
- package/lib/schema/subdocument.js +9 -12
- package/lib/schema/union.js +1 -1
- package/lib/schema.js +27 -28
- package/lib/schemaType.js +11 -11
- package/lib/types/array/index.js +2 -2
- package/lib/types/array/methods/index.js +38 -8
- package/lib/types/arraySubdocument.js +12 -2
- package/lib/types/buffer.js +1 -1
- package/lib/types/documentArray/index.js +2 -2
- package/lib/types/documentArray/methods/index.js +5 -5
- package/lib/types/map.js +8 -8
- package/lib/types/subdocument.js +15 -5
- package/lib/utils.js +23 -7
- package/package.json +3 -2
- package/types/index.d.ts +26 -9
- package/types/inferrawdoctype.d.ts +9 -3
- package/types/inferschematype.d.ts +20 -27
- package/types/middlewares.d.ts +11 -0
- package/types/models.d.ts +15 -5
- package/types/query.d.ts +1 -1
- package/types/schemaoptions.d.ts +4 -2
- package/types/utility.d.ts +1 -1
- package/types/virtuals.d.ts +3 -3
package/lib/document.js
CHANGED
|
@@ -149,7 +149,7 @@ function Document(obj, fields, options) {
|
|
|
149
149
|
|
|
150
150
|
// determine if this doc is a result of a query with
|
|
151
151
|
// excluded fields
|
|
152
|
-
if (utils.isPOJO(fields) &&
|
|
152
|
+
if (utils.isPOJO(fields) && utils.hasOwnKeys(fields)) {
|
|
153
153
|
exclude = isExclusive(fields);
|
|
154
154
|
this.$__.selected = fields;
|
|
155
155
|
this.$__.exclude = exclude;
|
|
@@ -648,6 +648,10 @@ Document.prototype.init = function(doc, opts, fn) {
|
|
|
648
648
|
opts = null;
|
|
649
649
|
}
|
|
650
650
|
|
|
651
|
+
if (doc == null) {
|
|
652
|
+
throw new ObjectParameterError(doc, 'doc', 'init');
|
|
653
|
+
}
|
|
654
|
+
|
|
651
655
|
this.$__init(doc, opts);
|
|
652
656
|
|
|
653
657
|
if (fn) {
|
|
@@ -677,6 +681,9 @@ Document.prototype.$init = function() {
|
|
|
677
681
|
*/
|
|
678
682
|
|
|
679
683
|
Document.prototype.$__init = function(doc, opts) {
|
|
684
|
+
if (doc == null) {
|
|
685
|
+
throw new ObjectParameterError(doc, 'doc', 'init');
|
|
686
|
+
}
|
|
680
687
|
this.$isNew = false;
|
|
681
688
|
opts = opts || {};
|
|
682
689
|
|
|
@@ -695,7 +702,7 @@ Document.prototype.$__init = function(doc, opts) {
|
|
|
695
702
|
continue;
|
|
696
703
|
}
|
|
697
704
|
for (const child of item._childDocs) {
|
|
698
|
-
if (child
|
|
705
|
+
if (child?.$__ == null) {
|
|
699
706
|
continue;
|
|
700
707
|
}
|
|
701
708
|
child.$__.parent = this;
|
|
@@ -794,7 +801,7 @@ function init(self, obj, doc, opts, prefix) {
|
|
|
794
801
|
|
|
795
802
|
if (schemaType && !wasPopulated && !opts.hydratedPopulatedDocs) {
|
|
796
803
|
try {
|
|
797
|
-
if (opts
|
|
804
|
+
if (opts?.setters) {
|
|
798
805
|
// Call applySetters with `init = false` because otherwise setters are a noop
|
|
799
806
|
const overrideInit = false;
|
|
800
807
|
doc[i] = schemaType.applySetters(value, self, overrideInit, null, opts);
|
|
@@ -813,7 +820,7 @@ function init(self, obj, doc, opts, prefix) {
|
|
|
813
820
|
} else if (schemaType && opts.hydratedPopulatedDocs) {
|
|
814
821
|
doc[i] = schemaType.cast(value, self, true, undefined, { hydratedPopulatedDocs: true });
|
|
815
822
|
|
|
816
|
-
if (doc[i]
|
|
823
|
+
if (doc[i]?.$__?.wasPopulated) {
|
|
817
824
|
self.$populated(path, doc[i].$__.wasPopulated.value, doc[i].$__.wasPopulated.options);
|
|
818
825
|
} else if (Array.isArray(doc[i]) && doc[i].length && doc[i][0]?.$__?.wasPopulated) {
|
|
819
826
|
self.$populated(path, doc[i].map(populatedDoc => populatedDoc?.$__?.wasPopulated?.value).filter(val => val != null), doc[i][0].$__.wasPopulated.options);
|
|
@@ -842,7 +849,7 @@ function init(self, obj, doc, opts, prefix) {
|
|
|
842
849
|
* - same as in [Model.updateOne](https://mongoosejs.com/docs/api/model.html#Model.updateOne)
|
|
843
850
|
*
|
|
844
851
|
* @see Model.updateOne https://mongoosejs.com/docs/api/model.html#Model.updateOne
|
|
845
|
-
* @param {Object}
|
|
852
|
+
* @param {Object} update
|
|
846
853
|
* @param {Object} [options] optional see [`Query.prototype.setOptions()`](https://mongoosejs.com/docs/api/query.html#Query.prototype.setOptions())
|
|
847
854
|
* @param {Object} [options.lean] if truthy, mongoose will return the document as a plain JavaScript object rather than a mongoose document. See [`Query.lean()`](https://mongoosejs.com/docs/api/query.html#Query.prototype.lean()) and the [Mongoose lean tutorial](https://mongoosejs.com/docs/tutorials/lean.html).
|
|
848
855
|
* @param {Boolean|String} [options.strict] overwrites the schema's [strict mode option](https://mongoosejs.com/docs/guide.html#strict)
|
|
@@ -853,33 +860,33 @@ function init(self, obj, doc, opts, prefix) {
|
|
|
853
860
|
* @instance
|
|
854
861
|
*/
|
|
855
862
|
|
|
856
|
-
Document.prototype.updateOne = function updateOne(
|
|
857
|
-
const query = this.constructor.updateOne(
|
|
863
|
+
Document.prototype.updateOne = function updateOne(update, options) {
|
|
864
|
+
const query = this.constructor.updateOne();
|
|
858
865
|
const self = this;
|
|
859
866
|
query.pre(async function queryPreUpdateOne() {
|
|
860
|
-
const res = await self._execDocumentPreHooks('updateOne', self);
|
|
867
|
+
const res = await self._execDocumentPreHooks('updateOne', self, update, options);
|
|
861
868
|
// `self` is passed to pre hooks as argument for backwards compatibility, but that
|
|
862
869
|
// isn't the actual arguments passed to the wrapped function.
|
|
863
|
-
if (res
|
|
870
|
+
if (res[0] !== self || res[1] !== update || res[2] !== options) {
|
|
864
871
|
throw new Error('Document updateOne pre hooks cannot overwrite arguments');
|
|
865
872
|
}
|
|
873
|
+
query.updateOne({ _id: self._doc._id }, update, options);
|
|
866
874
|
// Apply custom where conditions _after_ document updateOne middleware for
|
|
867
875
|
// consistency with save() - sharding plugin needs to set $where
|
|
868
876
|
if (self.$where != null) {
|
|
869
877
|
this.where(self.$where);
|
|
870
878
|
}
|
|
879
|
+
if (self.$session() != null) {
|
|
880
|
+
if (!('session' in query.options)) {
|
|
881
|
+
query.options.session = self.$session();
|
|
882
|
+
}
|
|
883
|
+
}
|
|
871
884
|
return res;
|
|
872
885
|
});
|
|
873
886
|
query.post(function queryPostUpdateOne() {
|
|
874
887
|
return self._execDocumentPostHooks('updateOne');
|
|
875
888
|
});
|
|
876
889
|
|
|
877
|
-
if (this.$session() != null) {
|
|
878
|
-
if (!('session' in query.options)) {
|
|
879
|
-
query.options.session = this.$session();
|
|
880
|
-
}
|
|
881
|
-
}
|
|
882
|
-
|
|
883
890
|
return query;
|
|
884
891
|
};
|
|
885
892
|
|
|
@@ -931,14 +938,14 @@ Document.prototype.replaceOne = function replaceOne() {
|
|
|
931
938
|
|
|
932
939
|
Document.prototype.$session = function $session(session) {
|
|
933
940
|
if (arguments.length === 0) {
|
|
934
|
-
if (this.$__.session
|
|
941
|
+
if (this.$__.session?.hasEnded) {
|
|
935
942
|
this.$__.session = null;
|
|
936
943
|
return null;
|
|
937
944
|
}
|
|
938
945
|
return this.$__.session;
|
|
939
946
|
}
|
|
940
947
|
|
|
941
|
-
if (session
|
|
948
|
+
if (session?.hasEnded) {
|
|
942
949
|
throw new MongooseError('Cannot set a document\'s session to a session that has ended. Make sure you haven\'t ' +
|
|
943
950
|
'called `endSession()` on the session you are passing to `$session()`.');
|
|
944
951
|
}
|
|
@@ -1015,17 +1022,21 @@ Document.prototype.$timestamps = function $timestamps(value) {
|
|
|
1015
1022
|
*/
|
|
1016
1023
|
|
|
1017
1024
|
Document.prototype.overwrite = function overwrite(obj) {
|
|
1018
|
-
const keys =
|
|
1025
|
+
const keys = new Set(Object.keys(this._doc));
|
|
1026
|
+
for (const key of Object.keys(obj)) {
|
|
1027
|
+
keys.add(key);
|
|
1028
|
+
}
|
|
1019
1029
|
|
|
1030
|
+
const schemaOptions = this.$__schema.options;
|
|
1020
1031
|
for (const key of keys) {
|
|
1021
1032
|
if (key === '_id') {
|
|
1022
1033
|
continue;
|
|
1023
1034
|
}
|
|
1024
1035
|
// Explicitly skip version key
|
|
1025
|
-
if (
|
|
1036
|
+
if (schemaOptions.versionKey && key === schemaOptions.versionKey) {
|
|
1026
1037
|
continue;
|
|
1027
1038
|
}
|
|
1028
|
-
if (
|
|
1039
|
+
if (schemaOptions.discriminatorKey && key === schemaOptions.discriminatorKey) {
|
|
1029
1040
|
continue;
|
|
1030
1041
|
}
|
|
1031
1042
|
this.$set(key, obj[key]);
|
|
@@ -1055,7 +1066,7 @@ Document.prototype.$set = function $set(path, val, type, options) {
|
|
|
1055
1066
|
type = undefined;
|
|
1056
1067
|
}
|
|
1057
1068
|
|
|
1058
|
-
const merge = options
|
|
1069
|
+
const merge = options?.merge;
|
|
1059
1070
|
const adhoc = type && type !== true;
|
|
1060
1071
|
const constructing = type === true;
|
|
1061
1072
|
let adhocs;
|
|
@@ -1101,7 +1112,7 @@ Document.prototype.$set = function $set(path, val, type, options) {
|
|
|
1101
1112
|
|
|
1102
1113
|
// `_skipMinimizeTopLevel` is because we may have deleted the top-level
|
|
1103
1114
|
// nested key to ensure key order.
|
|
1104
|
-
const _skipMinimizeTopLevel = options
|
|
1115
|
+
const _skipMinimizeTopLevel = options?._skipMinimizeTopLevel || false;
|
|
1105
1116
|
if (len === 0 && _skipMinimizeTopLevel) {
|
|
1106
1117
|
delete options._skipMinimizeTopLevel;
|
|
1107
1118
|
if (val) {
|
|
@@ -1415,7 +1426,7 @@ Document.prototype.$set = function $set(path, val, type, options) {
|
|
|
1415
1426
|
|
|
1416
1427
|
let didPopulate = false;
|
|
1417
1428
|
if (refMatches && val instanceof Document && (!val.$__.wasPopulated || utils.deepEqual(val.$__.wasPopulated.value, val._doc._id))) {
|
|
1418
|
-
const unpopulatedValue =
|
|
1429
|
+
const unpopulatedValue = schema?.$isSingleNested ? schema.cast(val, this) : val._doc._id;
|
|
1419
1430
|
this.$populated(path, unpopulatedValue, { [populateModelSymbol]: val.constructor });
|
|
1420
1431
|
val.$__.wasPopulated = { value: unpopulatedValue };
|
|
1421
1432
|
didPopulate = true;
|
|
@@ -1447,7 +1458,7 @@ Document.prototype.$set = function $set(path, val, type, options) {
|
|
|
1447
1458
|
if (this.$__schema.singleNestedPaths[path] != null && parts.length > 1) {
|
|
1448
1459
|
setterContext = getDeepestSubdocumentForPath(this, parts, this.schema);
|
|
1449
1460
|
}
|
|
1450
|
-
if (options
|
|
1461
|
+
if (options?.overwriteImmutable) {
|
|
1451
1462
|
val = schema.applySetters(val, setterContext, false, priorVal, { path, overwriteImmutable: true });
|
|
1452
1463
|
} else {
|
|
1453
1464
|
val = schema.applySetters(val, setterContext, false, priorVal, { path });
|
|
@@ -1458,9 +1469,7 @@ Document.prototype.$set = function $set(path, val, type, options) {
|
|
|
1458
1469
|
!Array.isArray(schema) &&
|
|
1459
1470
|
schema.$isMongooseDocumentArray &&
|
|
1460
1471
|
val.length !== 0 &&
|
|
1461
|
-
val[0] != null
|
|
1462
|
-
val[0].$__ != null &&
|
|
1463
|
-
val[0].$__.populated != null) {
|
|
1472
|
+
val[0]?.$__?.populated != null) {
|
|
1464
1473
|
const populatedPaths = Object.keys(val[0].$__.populated);
|
|
1465
1474
|
for (const populatedPath of populatedPaths) {
|
|
1466
1475
|
this.$populated(path + '.' + populatedPath,
|
|
@@ -1625,7 +1634,7 @@ Document.prototype.set = Document.prototype.$set;
|
|
|
1625
1634
|
*/
|
|
1626
1635
|
|
|
1627
1636
|
Document.prototype.$__shouldModify = function(pathToMark, path, options, constructing, parts, schema, val, priorVal) {
|
|
1628
|
-
if (options
|
|
1637
|
+
if (options?._skipMarkModified) {
|
|
1629
1638
|
return false;
|
|
1630
1639
|
}
|
|
1631
1640
|
if (this.$isNew) {
|
|
@@ -1695,9 +1704,9 @@ Document.prototype.$__set = function(pathToMark, path, options, constructing, pa
|
|
|
1695
1704
|
schema, val, priorVal);
|
|
1696
1705
|
|
|
1697
1706
|
if (shouldModify) {
|
|
1698
|
-
if (this.$__.primitiveAtomics
|
|
1707
|
+
if (this.$__.primitiveAtomics?.[path]) {
|
|
1699
1708
|
delete this.$__.primitiveAtomics[path];
|
|
1700
|
-
if (
|
|
1709
|
+
if (utils.hasOwnKeys(this.$__.primitiveAtomics) === false) {
|
|
1701
1710
|
delete this.$__.primitiveAtomics;
|
|
1702
1711
|
}
|
|
1703
1712
|
}
|
|
@@ -1939,7 +1948,7 @@ Document.prototype.get = function(path, type, options) {
|
|
|
1939
1948
|
return obj;
|
|
1940
1949
|
}
|
|
1941
1950
|
|
|
1942
|
-
if (schema
|
|
1951
|
+
if (schema?.instance === 'Mixed') {
|
|
1943
1952
|
const virtual = this.$__schema.virtualpath(path);
|
|
1944
1953
|
if (virtual != null) {
|
|
1945
1954
|
schema = virtual;
|
|
@@ -1956,7 +1965,7 @@ Document.prototype.get = function(path, type, options) {
|
|
|
1956
1965
|
}
|
|
1957
1966
|
|
|
1958
1967
|
for (let i = 0, l = pieces.length; i < l; i++) {
|
|
1959
|
-
if (obj
|
|
1968
|
+
if (obj?._doc) {
|
|
1960
1969
|
obj = obj._doc;
|
|
1961
1970
|
}
|
|
1962
1971
|
|
|
@@ -2284,7 +2293,7 @@ Document.prototype[documentModifiedPaths] = Document.prototype.modifiedPaths;
|
|
|
2284
2293
|
|
|
2285
2294
|
Document.prototype.isModified = function(paths, options, modifiedPaths) {
|
|
2286
2295
|
if (paths) {
|
|
2287
|
-
const ignoreAtomics = options
|
|
2296
|
+
const ignoreAtomics = options?.ignoreAtomics;
|
|
2288
2297
|
const directModifiedPathsObj = this.$__.activePaths.states.modify;
|
|
2289
2298
|
if (directModifiedPathsObj == null) {
|
|
2290
2299
|
return false;
|
|
@@ -2309,7 +2318,7 @@ Document.prototype.isModified = function(paths, options, modifiedPaths) {
|
|
|
2309
2318
|
if (ignoreAtomics) {
|
|
2310
2319
|
directModifiedPaths = directModifiedPaths.filter(path => {
|
|
2311
2320
|
const value = this.$__getValue(path);
|
|
2312
|
-
if (value
|
|
2321
|
+
if (value?.[arrayAtomicsSymbol] != null && value[arrayAtomicsSymbol].$set === undefined) {
|
|
2313
2322
|
return false;
|
|
2314
2323
|
}
|
|
2315
2324
|
return true;
|
|
@@ -2431,7 +2440,7 @@ Document.prototype.isDirectModified = function(path) {
|
|
|
2431
2440
|
for (let i = 0; i < pieces.length - 1; ++i) {
|
|
2432
2441
|
const subpath = pieces.slice(0, i + 1).join('.');
|
|
2433
2442
|
const subdoc = this.$get(subpath);
|
|
2434
|
-
if (subdoc
|
|
2443
|
+
if (subdoc?.$__ != null && subdoc.isDirectModified(pieces.slice(i + 1).join('.'))) {
|
|
2435
2444
|
return true;
|
|
2436
2445
|
}
|
|
2437
2446
|
}
|
|
@@ -2649,7 +2658,7 @@ Document.prototype.validate = async function validate(pathsToValidate, options)
|
|
|
2649
2658
|
const isOnePathOnly = options.pathsToSkip.indexOf(' ') === -1;
|
|
2650
2659
|
options.pathsToSkip = isOnePathOnly ? [options.pathsToSkip] : options.pathsToSkip.split(' ');
|
|
2651
2660
|
}
|
|
2652
|
-
const _skipParallelValidateCheck = options
|
|
2661
|
+
const _skipParallelValidateCheck = options?._skipParallelValidateCheck;
|
|
2653
2662
|
|
|
2654
2663
|
if (this.$isSubdocument != null) {
|
|
2655
2664
|
// Skip parallel validate check for subdocuments
|
|
@@ -2690,7 +2699,7 @@ function _evaluateRequiredFunctions(doc) {
|
|
|
2690
2699
|
|
|
2691
2700
|
const p = doc.$__schema.path(path);
|
|
2692
2701
|
|
|
2693
|
-
if (
|
|
2702
|
+
if (typeof p?.originalRequiredValue === 'function') {
|
|
2694
2703
|
doc.$__.cachedRequired = doc.$__.cachedRequired || {};
|
|
2695
2704
|
try {
|
|
2696
2705
|
doc.$__.cachedRequired[path] = p.originalRequiredValue.call(doc, doc);
|
|
@@ -2750,7 +2759,7 @@ function _getPathsToValidate(doc, pathsToValidate, pathsToSkip, isNestedValidate
|
|
|
2750
2759
|
}
|
|
2751
2760
|
} else if (schemaType.$isMongooseDocumentArray) {
|
|
2752
2761
|
const arr = doc.$get(path);
|
|
2753
|
-
if (arr
|
|
2762
|
+
if (arr?.length) {
|
|
2754
2763
|
for (const subdoc of arr) {
|
|
2755
2764
|
if (subdoc) {
|
|
2756
2765
|
topLevelSubdocs.push(subdoc);
|
|
@@ -2903,7 +2912,7 @@ function _addArrayPathsToValidate(doc, paths) {
|
|
|
2903
2912
|
// it unless we have a case of #6364
|
|
2904
2913
|
(!Array.isArray(_pathType) &&
|
|
2905
2914
|
_pathType.$isMongooseDocumentArray &&
|
|
2906
|
-
!
|
|
2915
|
+
!_pathType?.schemaOptions?.required)) {
|
|
2907
2916
|
continue;
|
|
2908
2917
|
}
|
|
2909
2918
|
|
|
@@ -2970,7 +2979,7 @@ Document.prototype.$__validate = async function $__validate(pathsToValidate, opt
|
|
|
2970
2979
|
(typeof options === 'object') &&
|
|
2971
2980
|
('validateModifiedOnly' in options);
|
|
2972
2981
|
|
|
2973
|
-
const pathsToSkip =
|
|
2982
|
+
const pathsToSkip = options?.pathsToSkip || null;
|
|
2974
2983
|
|
|
2975
2984
|
let shouldValidateModifiedOnly;
|
|
2976
2985
|
if (hasValidateModifiedOnlyOption) {
|
|
@@ -2979,7 +2988,7 @@ Document.prototype.$__validate = async function $__validate(pathsToValidate, opt
|
|
|
2979
2988
|
shouldValidateModifiedOnly = this.$__schema.options.validateModifiedOnly;
|
|
2980
2989
|
}
|
|
2981
2990
|
|
|
2982
|
-
const validateAllPaths = options
|
|
2991
|
+
const validateAllPaths = options?.validateAllPaths;
|
|
2983
2992
|
if (validateAllPaths) {
|
|
2984
2993
|
if (pathsToSkip) {
|
|
2985
2994
|
throw new TypeError('Cannot set both `validateAllPaths` and `pathsToSkip`');
|
|
@@ -3006,7 +3015,7 @@ Document.prototype.$__validate = async function $__validate(pathsToValidate, opt
|
|
|
3006
3015
|
delete validationError.errors[errPath];
|
|
3007
3016
|
}
|
|
3008
3017
|
}
|
|
3009
|
-
if (
|
|
3018
|
+
if (utils.hasOwnKeys(validationError.errors) === false) {
|
|
3010
3019
|
validationError = void 0;
|
|
3011
3020
|
}
|
|
3012
3021
|
}
|
|
@@ -3037,7 +3046,7 @@ Document.prototype.$__validate = async function $__validate(pathsToValidate, opt
|
|
|
3037
3046
|
// the children as well
|
|
3038
3047
|
for (const path of paths) {
|
|
3039
3048
|
const schemaType = this.$__schema.path(path);
|
|
3040
|
-
if (!schemaType
|
|
3049
|
+
if (!schemaType?.$isMongooseArray) {
|
|
3041
3050
|
continue;
|
|
3042
3051
|
}
|
|
3043
3052
|
const val = this.$__getValue(path);
|
|
@@ -3049,7 +3058,7 @@ Document.prototype.$__validate = async function $__validate(pathsToValidate, opt
|
|
|
3049
3058
|
paths = [...paths];
|
|
3050
3059
|
doValidateOptionsByPath = {};
|
|
3051
3060
|
} else {
|
|
3052
|
-
const pathDetails = _getPathsToValidate(this, pathsToValidate, pathsToSkip, options
|
|
3061
|
+
const pathDetails = _getPathsToValidate(this, pathsToValidate, pathsToSkip, options?._nestedValidate);
|
|
3053
3062
|
paths = shouldValidateModifiedOnly ?
|
|
3054
3063
|
pathDetails[0].filter((path) => this.$isModified(path)) :
|
|
3055
3064
|
pathDetails[0];
|
|
@@ -3117,7 +3126,7 @@ Document.prototype.$__validate = async function $__validate(pathsToValidate, opt
|
|
|
3117
3126
|
let pop;
|
|
3118
3127
|
if ((pop = _this.$populated(path))) {
|
|
3119
3128
|
val = pop;
|
|
3120
|
-
} else if (val
|
|
3129
|
+
} else if (val?.$__?.wasPopulated) {
|
|
3121
3130
|
// Array paths, like `somearray.1`, do not show up as populated with `$populated()`,
|
|
3122
3131
|
// so in that case pull out the document's id
|
|
3123
3132
|
val = val._doc._id;
|
|
@@ -3233,9 +3242,9 @@ Document.prototype.validateSync = function(pathsToValidate, options) {
|
|
|
3233
3242
|
shouldValidateModifiedOnly = this.$__schema.options.validateModifiedOnly;
|
|
3234
3243
|
}
|
|
3235
3244
|
|
|
3236
|
-
let pathsToSkip = options
|
|
3245
|
+
let pathsToSkip = options?.pathsToSkip;
|
|
3237
3246
|
|
|
3238
|
-
const validateAllPaths = options
|
|
3247
|
+
const validateAllPaths = options?.validateAllPaths;
|
|
3239
3248
|
if (validateAllPaths) {
|
|
3240
3249
|
if (pathsToSkip) {
|
|
3241
3250
|
throw new TypeError('Cannot set both `validateAllPaths` and `pathsToSkip`');
|
|
@@ -3261,7 +3270,7 @@ Document.prototype.validateSync = function(pathsToValidate, options) {
|
|
|
3261
3270
|
// the children as well
|
|
3262
3271
|
for (const path of paths) {
|
|
3263
3272
|
const schemaType = this.$__schema.path(path);
|
|
3264
|
-
if (!schemaType
|
|
3273
|
+
if (!schemaType?.$isMongooseArray) {
|
|
3265
3274
|
continue;
|
|
3266
3275
|
}
|
|
3267
3276
|
const val = this.$__getValue(path);
|
|
@@ -3402,12 +3411,12 @@ Document.prototype.invalidate = function(path, err, val, kind) {
|
|
|
3402
3411
|
*/
|
|
3403
3412
|
|
|
3404
3413
|
Document.prototype.$markValid = function(path) {
|
|
3405
|
-
if (!this.$__.validationError
|
|
3414
|
+
if (!this.$__.validationError?.errors[path]) {
|
|
3406
3415
|
return;
|
|
3407
3416
|
}
|
|
3408
3417
|
|
|
3409
3418
|
delete this.$__.validationError.errors[path];
|
|
3410
|
-
if (
|
|
3419
|
+
if (utils.hasOwnKeys(this.$__.validationError.errors) === false) {
|
|
3411
3420
|
this.$__.validationError = null;
|
|
3412
3421
|
}
|
|
3413
3422
|
};
|
|
@@ -3427,7 +3436,7 @@ function _markValidSubpaths(doc, path) {
|
|
|
3427
3436
|
delete doc.$__.validationError.errors[key];
|
|
3428
3437
|
}
|
|
3429
3438
|
}
|
|
3430
|
-
if (
|
|
3439
|
+
if (utils.hasOwnKeys(doc.$__.validationError.errors) === false) {
|
|
3431
3440
|
doc.$__.validationError = null;
|
|
3432
3441
|
}
|
|
3433
3442
|
}
|
|
@@ -3502,7 +3511,7 @@ function _checkImmutableSubpaths(subdoc, schematype, priorVal) {
|
|
|
3502
3511
|
*/
|
|
3503
3512
|
|
|
3504
3513
|
Document.prototype.$isValid = function(path) {
|
|
3505
|
-
if (this.$__.validationError == null ||
|
|
3514
|
+
if (this.$__.validationError == null || utils.hasOwnKeys(this.$__.validationError.errors) === false) {
|
|
3506
3515
|
return true;
|
|
3507
3516
|
}
|
|
3508
3517
|
if (path == null) {
|
|
@@ -3534,7 +3543,7 @@ Document.prototype.$__reset = function reset() {
|
|
|
3534
3543
|
|
|
3535
3544
|
// Skip for subdocuments
|
|
3536
3545
|
const subdocs = !this.$isSubdocument ? this.$getAllSubdocs({ useCache: true }) : null;
|
|
3537
|
-
if (subdocs
|
|
3546
|
+
if (subdocs?.length > 0) {
|
|
3538
3547
|
for (const subdoc of subdocs) {
|
|
3539
3548
|
subdoc.$__reset();
|
|
3540
3549
|
}
|
|
@@ -3544,7 +3553,9 @@ Document.prototype.$__reset = function reset() {
|
|
|
3544
3553
|
this.$__dirty().forEach(function(dirt) {
|
|
3545
3554
|
const type = dirt.value;
|
|
3546
3555
|
|
|
3547
|
-
if (type && type
|
|
3556
|
+
if (type && typeof type.clearAtomics === 'function') {
|
|
3557
|
+
type.clearAtomics();
|
|
3558
|
+
} else if (type && type[arrayAtomicsSymbol]) {
|
|
3548
3559
|
type[arrayAtomicsBackupSymbol] = type[arrayAtomicsSymbol];
|
|
3549
3560
|
type[arrayAtomicsSymbol] = {};
|
|
3550
3561
|
}
|
|
@@ -3576,7 +3587,7 @@ Document.prototype.$__reset = function reset() {
|
|
|
3576
3587
|
*/
|
|
3577
3588
|
|
|
3578
3589
|
Document.prototype.$__undoReset = function $__undoReset() {
|
|
3579
|
-
if (this.$__.backup
|
|
3590
|
+
if (this.$__.backup?.activePaths == null) {
|
|
3580
3591
|
return;
|
|
3581
3592
|
}
|
|
3582
3593
|
|
|
@@ -3589,7 +3600,7 @@ Document.prototype.$__undoReset = function $__undoReset() {
|
|
|
3589
3600
|
for (const dirt of this.$__dirty()) {
|
|
3590
3601
|
const type = dirt.value;
|
|
3591
3602
|
|
|
3592
|
-
if (type
|
|
3603
|
+
if (type?.[arrayAtomicsSymbol] && type[arrayAtomicsBackupSymbol]) {
|
|
3593
3604
|
type[arrayAtomicsSymbol] = type[arrayAtomicsBackupSymbol];
|
|
3594
3605
|
}
|
|
3595
3606
|
}
|
|
@@ -3757,14 +3768,14 @@ Document.prototype.$getAllSubdocs = function(options) {
|
|
|
3757
3768
|
}
|
|
3758
3769
|
if (Array.isArray(val)) {
|
|
3759
3770
|
for (const el of val) {
|
|
3760
|
-
if (el
|
|
3771
|
+
if (el?.$__) {
|
|
3761
3772
|
newSubdocs.push(el);
|
|
3762
3773
|
}
|
|
3763
3774
|
}
|
|
3764
3775
|
}
|
|
3765
3776
|
if (val instanceof Map) {
|
|
3766
3777
|
for (const el of val.values()) {
|
|
3767
|
-
if (el
|
|
3778
|
+
if (el?.$__) {
|
|
3768
3779
|
newSubdocs.push(el);
|
|
3769
3780
|
}
|
|
3770
3781
|
}
|
|
@@ -3811,7 +3822,7 @@ Document.prototype.$__handleReject = function handleReject(err) {
|
|
|
3811
3822
|
// emit on the Model if listening
|
|
3812
3823
|
if (this.$listeners('error').length) {
|
|
3813
3824
|
this.$emit('error', err);
|
|
3814
|
-
} else if (this.constructor.listeners
|
|
3825
|
+
} else if (this.constructor.listeners?.('error').length) {
|
|
3815
3826
|
this.constructor.emit('error', err);
|
|
3816
3827
|
}
|
|
3817
3828
|
};
|
|
@@ -3840,7 +3851,7 @@ Document.prototype.$toObject = function(options, json) {
|
|
|
3840
3851
|
_minimize = options.minimize;
|
|
3841
3852
|
} else if (this.$__schemaTypeOptions?.minimize != null) {
|
|
3842
3853
|
_minimize = this.$__schemaTypeOptions.minimize;
|
|
3843
|
-
} else if (defaultOptions
|
|
3854
|
+
} else if (defaultOptions?.minimize != null) {
|
|
3844
3855
|
_minimize = defaultOptions.minimize;
|
|
3845
3856
|
} else {
|
|
3846
3857
|
_minimize = this.$__schema.options.minimize;
|
|
@@ -4164,7 +4175,7 @@ function applyVirtuals(self, json, options, toObjectOptions) {
|
|
|
4164
4175
|
let assignPath;
|
|
4165
4176
|
let cur = self._doc;
|
|
4166
4177
|
let v;
|
|
4167
|
-
const aliases = typeof
|
|
4178
|
+
const aliases = typeof toObjectOptions?.aliases === 'boolean'
|
|
4168
4179
|
? toObjectOptions.aliases
|
|
4169
4180
|
: true;
|
|
4170
4181
|
|
|
@@ -4172,7 +4183,7 @@ function applyVirtuals(self, json, options, toObjectOptions) {
|
|
|
4172
4183
|
let virtualsToApply = null;
|
|
4173
4184
|
if (Array.isArray(options.virtuals)) {
|
|
4174
4185
|
virtualsToApply = new Set(options.virtuals);
|
|
4175
|
-
} else if (options.virtuals
|
|
4186
|
+
} else if (options.virtuals?.pathsToSkip) {
|
|
4176
4187
|
virtualsToApply = new Set(paths);
|
|
4177
4188
|
for (let i = 0; i < options.virtuals.pathsToSkip.length; i++) {
|
|
4178
4189
|
if (virtualsToApply.has(options.virtuals.pathsToSkip[i])) {
|
|
@@ -4380,7 +4391,7 @@ function omitDeselectedFields(self, json) {
|
|
|
4380
4391
|
selected = {};
|
|
4381
4392
|
queryhelpers.applyPaths(selected, schema);
|
|
4382
4393
|
}
|
|
4383
|
-
if (selected == null ||
|
|
4394
|
+
if (selected == null || utils.hasOwnKeys(selected) === false) {
|
|
4384
4395
|
return json;
|
|
4385
4396
|
}
|
|
4386
4397
|
|
|
@@ -4462,6 +4473,20 @@ Document.prototype.parent = function() {
|
|
|
4462
4473
|
|
|
4463
4474
|
Document.prototype.$parent = Document.prototype.parent;
|
|
4464
4475
|
|
|
4476
|
+
/**
|
|
4477
|
+
* Set the parent of this document.
|
|
4478
|
+
*
|
|
4479
|
+
* @param {Document} parent
|
|
4480
|
+
* @api private
|
|
4481
|
+
* @method $__setParent
|
|
4482
|
+
* @memberOf Document
|
|
4483
|
+
* @instance
|
|
4484
|
+
*/
|
|
4485
|
+
|
|
4486
|
+
Document.prototype.$__setParent = function $__setParent(parent) {
|
|
4487
|
+
this.$__.parent = parent;
|
|
4488
|
+
};
|
|
4489
|
+
|
|
4465
4490
|
/**
|
|
4466
4491
|
* Helper for console.log
|
|
4467
4492
|
*
|
|
@@ -4717,7 +4742,7 @@ Document.prototype.populated = function(path, val, options) {
|
|
|
4717
4742
|
for (let i = 0; i < pieces.length - 1; ++i) {
|
|
4718
4743
|
const subpath = pieces.slice(0, i + 1).join('.');
|
|
4719
4744
|
const subdoc = this.$get(subpath);
|
|
4720
|
-
if (subdoc
|
|
4745
|
+
if (subdoc?.$__ != null && this.$populated(subpath)) {
|
|
4721
4746
|
const rest = pieces.slice(i + 1).join('.');
|
|
4722
4747
|
subdoc.$populated(rest, val, options);
|
|
4723
4748
|
// No need to continue because the above recursion should take care of
|
|
@@ -4808,7 +4833,7 @@ Document.prototype.depopulate = function(path) {
|
|
|
4808
4833
|
|
|
4809
4834
|
let populatedIds;
|
|
4810
4835
|
const virtualKeys = this.$$populatedVirtuals ? Object.keys(this.$$populatedVirtuals) : [];
|
|
4811
|
-
const populated = this.$__
|
|
4836
|
+
const populated = this.$__?.populated || {};
|
|
4812
4837
|
|
|
4813
4838
|
if (arguments.length === 0) {
|
|
4814
4839
|
// Depopulate all
|
|
@@ -4957,7 +4982,13 @@ Document.prototype.$__delta = function $__delta() {
|
|
|
4957
4982
|
if (Array.isArray(optimisticConcurrency)) {
|
|
4958
4983
|
const optCon = new Set(optimisticConcurrency);
|
|
4959
4984
|
const modPaths = this.modifiedPaths();
|
|
4960
|
-
if (modPaths.
|
|
4985
|
+
if (modPaths.some(path => optCon.has(path))) {
|
|
4986
|
+
this.$__.version = dirty.length ? VERSION_ALL : VERSION_WHERE;
|
|
4987
|
+
}
|
|
4988
|
+
} else if (Array.isArray(optimisticConcurrency?.exclude)) {
|
|
4989
|
+
const excluded = new Set(optimisticConcurrency.exclude);
|
|
4990
|
+
const modPaths = this.modifiedPaths();
|
|
4991
|
+
if (modPaths.some(path => !excluded.has(path))) {
|
|
4961
4992
|
this.$__.version = dirty.length ? VERSION_ALL : VERSION_WHERE;
|
|
4962
4993
|
}
|
|
4963
4994
|
} else {
|
|
@@ -4977,7 +5008,7 @@ Document.prototype.$__delta = function $__delta() {
|
|
|
4977
5008
|
where._id = this._doc._id;
|
|
4978
5009
|
// If `_id` is an object, need to depopulate, but also need to be careful
|
|
4979
5010
|
// because `_id` can technically be null (see gh-6406)
|
|
4980
|
-
if (
|
|
5011
|
+
if (where?._id?.$__ != null) {
|
|
4981
5012
|
where._id = where._id.toObject({ transform: false, depopulate: true });
|
|
4982
5013
|
}
|
|
4983
5014
|
for (; d < len; ++d) {
|
|
@@ -5028,15 +5059,15 @@ Document.prototype.$__delta = function $__delta() {
|
|
|
5028
5059
|
operand(this, where, delta, data, 1, '$unset');
|
|
5029
5060
|
} else if (value === null) {
|
|
5030
5061
|
operand(this, where, delta, data, null);
|
|
5031
|
-
} else if (
|
|
5032
|
-
// arrays and other custom types
|
|
5062
|
+
} else if (typeof value.getAtomics === 'function') {
|
|
5063
|
+
// arrays and other custom container types
|
|
5033
5064
|
handleAtomics(this, where, delta, data, value);
|
|
5034
5065
|
} else if (value[MongooseBuffer.pathSymbol] && Buffer.isBuffer(value)) {
|
|
5035
5066
|
// MongooseBuffer
|
|
5036
5067
|
value = value.toObject();
|
|
5037
5068
|
operand(this, where, delta, data, value);
|
|
5038
5069
|
} else {
|
|
5039
|
-
if (this.$__.primitiveAtomics
|
|
5070
|
+
if (this.$__.primitiveAtomics?.[data.path] != null) {
|
|
5040
5071
|
const val = this.$__.primitiveAtomics[data.path];
|
|
5041
5072
|
const op = firstKey(val);
|
|
5042
5073
|
operand(this, where, delta, data, val[op], op);
|
|
@@ -5062,7 +5093,7 @@ Document.prototype.$__delta = function $__delta() {
|
|
|
5062
5093
|
this.$__version(where, delta);
|
|
5063
5094
|
}
|
|
5064
5095
|
|
|
5065
|
-
if (
|
|
5096
|
+
if (utils.hasOwnKeys(delta) === false) {
|
|
5066
5097
|
return [where, null];
|
|
5067
5098
|
}
|
|
5068
5099
|
|
|
@@ -5107,14 +5138,14 @@ function checkDivergentArray(doc, path, array) {
|
|
|
5107
5138
|
// elements of the array and potentially would overwrite data.
|
|
5108
5139
|
const check = pop.options.match ||
|
|
5109
5140
|
pop.options.options && Object.hasOwn(pop.options.options, 'limit') || // 0 is not permitted
|
|
5110
|
-
pop.options.options
|
|
5141
|
+
pop.options.options?.skip || // 0 is permitted
|
|
5111
5142
|
pop.options.select && // deselected _id?
|
|
5112
5143
|
(pop.options.select._id === 0 ||
|
|
5113
5144
|
/\s?-_id\s?/.test(pop.options.select));
|
|
5114
5145
|
|
|
5115
5146
|
if (check) {
|
|
5116
5147
|
const atomics = array[arrayAtomicsSymbol];
|
|
5117
|
-
if (
|
|
5148
|
+
if (utils.hasOwnKeys(atomics) === false || atomics.$set || atomics.$pop) {
|
|
5118
5149
|
return path;
|
|
5119
5150
|
}
|
|
5120
5151
|
}
|
|
@@ -5147,7 +5178,11 @@ function operand(self, where, delta, data, val, op) {
|
|
|
5147
5178
|
// already marked for versioning?
|
|
5148
5179
|
if (VERSION_ALL === (VERSION_ALL & self.$__.version)) return;
|
|
5149
5180
|
|
|
5150
|
-
if (
|
|
5181
|
+
if (
|
|
5182
|
+
self.$__schema.options.optimisticConcurrency === true ||
|
|
5183
|
+
Array.isArray(self.$__schema.options.optimisticConcurrency) ||
|
|
5184
|
+
Array.isArray(self.$__schema.options.optimisticConcurrency?.exclude)
|
|
5185
|
+
) {
|
|
5151
5186
|
return;
|
|
5152
5187
|
}
|
|
5153
5188
|
|
|
@@ -5174,7 +5209,7 @@ function operand(self, where, delta, data, val, op) {
|
|
|
5174
5209
|
if (/\.\d+\.|\.\d+$/.test(data.path)) {
|
|
5175
5210
|
self.$__.version = VERSION_ALL;
|
|
5176
5211
|
} else {
|
|
5177
|
-
self.$__.version
|
|
5212
|
+
self.$__.version |= VERSION_INC;
|
|
5178
5213
|
}
|
|
5179
5214
|
} else if (/^\$p/.test(op)) {
|
|
5180
5215
|
// potentially changing array positions
|
|
@@ -5185,7 +5220,7 @@ function operand(self, where, delta, data, val, op) {
|
|
|
5185
5220
|
} else if (/\.\d+\.|\.\d+$/.test(data.path)) {
|
|
5186
5221
|
// now handling $set, $unset
|
|
5187
5222
|
// subpath of array
|
|
5188
|
-
self.$__.version
|
|
5223
|
+
self.$__.version |= VERSION_WHERE;
|
|
5189
5224
|
}
|
|
5190
5225
|
}
|
|
5191
5226
|
|
|
@@ -5201,11 +5236,20 @@ function operand(self, where, delta, data, val, op) {
|
|
|
5201
5236
|
*/
|
|
5202
5237
|
|
|
5203
5238
|
function handleAtomics(self, where, delta, data, value) {
|
|
5204
|
-
if (delta.$set
|
|
5239
|
+
if (delta.$set?.[data.path]) {
|
|
5205
5240
|
// $set has precedence over other atomics
|
|
5206
5241
|
return;
|
|
5207
5242
|
}
|
|
5208
5243
|
|
|
5244
|
+
if (typeof value.getAtomics === 'function') {
|
|
5245
|
+
value.getAtomics().forEach(function(atomic) {
|
|
5246
|
+
const op = atomic[0];
|
|
5247
|
+
const val = atomic[1];
|
|
5248
|
+
operand(self, where, delta, data, val, op);
|
|
5249
|
+
});
|
|
5250
|
+
return;
|
|
5251
|
+
}
|
|
5252
|
+
|
|
5209
5253
|
if (typeof value.$__getAtomics === 'function') {
|
|
5210
5254
|
value.$__getAtomics().forEach(function(atomic) {
|
|
5211
5255
|
const op = atomic[0];
|
|
@@ -5294,7 +5338,7 @@ Document.prototype.$clone = function() {
|
|
|
5294
5338
|
const clonedDoc = new Model();
|
|
5295
5339
|
clonedDoc.$isNew = this.$isNew;
|
|
5296
5340
|
if (this._doc) {
|
|
5297
|
-
clonedDoc._doc = clone(this._doc, { retainDocuments: true });
|
|
5341
|
+
clonedDoc._doc = clone(this._doc, { retainDocuments: true, parentDoc: clonedDoc });
|
|
5298
5342
|
}
|
|
5299
5343
|
if (this.$__) {
|
|
5300
5344
|
const Cache = this.$__.constructor;
|
|
@@ -5305,7 +5349,10 @@ Document.prototype.$clone = function() {
|
|
|
5305
5349
|
}
|
|
5306
5350
|
clonedCache[key] = clone(this.$__[key]);
|
|
5307
5351
|
}
|
|
5308
|
-
Object.assign(
|
|
5352
|
+
Object.assign(
|
|
5353
|
+
clonedCache.activePaths,
|
|
5354
|
+
clone({ ...this.$__.activePaths })
|
|
5355
|
+
);
|
|
5309
5356
|
clonedDoc.$__ = clonedCache;
|
|
5310
5357
|
}
|
|
5311
5358
|
return clonedDoc;
|