mongoose 8.20.0 → 9.0.0-rc0
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/eslint.config.mjs +198 -0
- package/lib/aggregate.js +17 -73
- package/lib/cast/bigint.js +1 -1
- package/lib/cast/double.js +1 -1
- package/lib/cast/uuid.js +5 -48
- package/lib/cast.js +2 -2
- package/lib/connection.js +0 -1
- package/lib/cursor/aggregationCursor.js +14 -24
- package/lib/cursor/queryCursor.js +7 -14
- package/lib/document.js +125 -121
- package/lib/drivers/node-mongodb-native/connection.js +3 -10
- package/lib/error/objectParameter.js +1 -2
- package/lib/error/validation.js +0 -8
- package/lib/helpers/clone.js +1 -1
- package/lib/helpers/common.js +1 -1
- package/lib/helpers/indexes/isIndexEqual.js +0 -1
- package/lib/helpers/model/applyDefaultsToPOJO.js +2 -2
- package/lib/helpers/model/applyHooks.js +43 -53
- package/lib/helpers/model/applyMethods.js +2 -2
- package/lib/helpers/model/applyStaticHooks.js +1 -48
- package/lib/helpers/model/castBulkWrite.js +1 -1
- package/lib/helpers/parallelLimit.js +18 -36
- package/lib/helpers/pluralize.js +3 -3
- package/lib/helpers/populate/assignRawDocsToIdStructure.js +1 -8
- package/lib/helpers/populate/createPopulateQueryFilter.js +1 -1
- package/lib/helpers/populate/getModelsMapForPopulate.js +17 -9
- package/lib/helpers/populate/getSchemaTypes.js +5 -5
- package/lib/helpers/query/cast$expr.js +8 -10
- package/lib/helpers/query/castFilterPath.js +1 -1
- package/lib/helpers/query/castUpdate.js +14 -12
- package/lib/helpers/query/getEmbeddedDiscriminatorPath.js +1 -1
- package/lib/helpers/schema/applyPlugins.js +1 -1
- package/lib/helpers/schema/getIndexes.js +1 -7
- package/lib/helpers/timestamps/setupTimestamps.js +3 -6
- package/lib/helpers/updateValidators.js +57 -111
- package/lib/model.js +419 -607
- package/lib/mongoose.js +41 -13
- package/lib/plugins/saveSubdocs.js +24 -51
- package/lib/plugins/sharding.js +5 -4
- package/lib/plugins/validateBeforeSave.js +3 -13
- package/lib/query.js +101 -145
- package/lib/queryHelpers.js +2 -2
- package/lib/schema/array.js +41 -84
- package/lib/schema/documentArray.js +57 -94
- package/lib/schema/documentArrayElement.js +16 -11
- package/lib/schema/string.js +1 -1
- package/lib/schema/subdocument.js +22 -28
- package/lib/schema/uuid.js +0 -21
- package/lib/schema.js +81 -39
- package/lib/schemaType.js +39 -57
- package/lib/types/array/index.js +2 -2
- package/lib/types/array/methods/index.js +4 -4
- package/lib/types/arraySubdocument.js +1 -1
- package/lib/types/buffer.js +10 -10
- package/lib/types/decimal128.js +1 -1
- package/lib/types/documentArray/index.js +1 -1
- package/lib/types/documentArray/methods/index.js +5 -3
- package/lib/types/double.js +1 -1
- package/lib/types/objectid.js +1 -1
- package/lib/types/subdocument.js +15 -43
- package/lib/types/uuid.js +1 -1
- package/lib/utils.js +1 -8
- package/lib/validOptions.js +3 -3
- package/package.json +11 -24
- package/types/connection.d.ts +20 -11
- package/types/document.d.ts +95 -26
- package/types/index.d.ts +143 -39
- package/types/inferhydrateddoctype.d.ts +115 -0
- package/types/inferrawdoctype.d.ts +99 -75
- package/types/inferschematype.d.ts +17 -3
- package/types/middlewares.d.ts +0 -2
- package/types/models.d.ts +131 -199
- package/types/mongooseoptions.d.ts +6 -5
- package/types/pipelinestage.d.ts +1 -1
- package/types/query.d.ts +71 -139
- package/types/schemaoptions.d.ts +1 -1
- package/types/schematypes.d.ts +14 -10
- package/types/types.d.ts +3 -4
- package/types/utility.d.ts +68 -48
- package/types/validation.d.ts +18 -14
- package/browser.js +0 -8
- package/dist/browser.umd.js +0 -2
- package/lib/browser.js +0 -141
- package/lib/browserDocument.js +0 -101
- package/lib/documentProvider.js +0 -30
- package/lib/drivers/browser/binary.js +0 -14
- package/lib/drivers/browser/decimal128.js +0 -7
- package/lib/drivers/browser/index.js +0 -13
- package/lib/drivers/browser/objectid.js +0 -29
- package/lib/helpers/promiseOrCallback.js +0 -54
package/lib/document.js
CHANGED
|
@@ -30,7 +30,6 @@ const getEmbeddedDiscriminatorPath = require('./helpers/document/getEmbeddedDisc
|
|
|
30
30
|
const getKeysInSchemaOrder = require('./helpers/schema/getKeysInSchemaOrder');
|
|
31
31
|
const getSubdocumentStrictValue = require('./helpers/schema/getSubdocumentStrictValue');
|
|
32
32
|
const handleSpreadDoc = require('./helpers/document/handleSpreadDoc');
|
|
33
|
-
const immediate = require('./helpers/immediate');
|
|
34
33
|
const isBsonType = require('./helpers/isBsonType');
|
|
35
34
|
const isDefiningProjection = require('./helpers/projection/isDefiningProjection');
|
|
36
35
|
const isExclusive = require('./helpers/projection/isExclusive');
|
|
@@ -80,32 +79,33 @@ const VERSION_ALL = VERSION_WHERE | VERSION_INC;
|
|
|
80
79
|
* @param {Object} [fields] optional object containing the fields which were selected in the query returning this document and any populated paths data
|
|
81
80
|
* @param {Object} [options] various configuration options for the document
|
|
82
81
|
* @param {Boolean} [options.defaults=true] if `false`, skip applying default values to this document.
|
|
82
|
+
* @param {Boolean} [options.skipId=false] By default, Mongoose document if one is not provided and the document's schema does not override Mongoose's default `_id`. Set `skipId` to `true` to skip this generation step.
|
|
83
83
|
* @inherits NodeJS EventEmitter https://nodejs.org/api/events.html#class-eventemitter
|
|
84
84
|
* @event `init`: Emitted on a document after it has been retrieved from the db and fully hydrated by Mongoose.
|
|
85
85
|
* @event `save`: Emitted when the document is successfully saved
|
|
86
86
|
* @api private
|
|
87
87
|
*/
|
|
88
88
|
|
|
89
|
-
function Document(obj, fields,
|
|
90
|
-
if (typeof
|
|
91
|
-
options
|
|
92
|
-
skipId = options.skipId;
|
|
89
|
+
function Document(obj, fields, options) {
|
|
90
|
+
if (typeof options === 'boolean') {
|
|
91
|
+
throw new Error('The skipId parameter has been removed. Use { skipId: true } in the options parameter instead.');
|
|
93
92
|
}
|
|
94
93
|
options = Object.assign({}, options);
|
|
94
|
+
let skipId = options.skipId;
|
|
95
|
+
|
|
96
|
+
this.$__ = new InternalCache();
|
|
95
97
|
|
|
96
98
|
// Support `browserDocument.js` syntax
|
|
97
99
|
if (this.$__schema == null) {
|
|
98
100
|
const _schema = utils.isObject(fields) && !fields.instanceOfSchema ?
|
|
99
101
|
new Schema(fields) :
|
|
100
102
|
fields;
|
|
103
|
+
|
|
101
104
|
this.$__setSchema(_schema);
|
|
102
|
-
fields =
|
|
103
|
-
skipId = options;
|
|
104
|
-
options = arguments[4] || {};
|
|
105
|
+
fields = options;
|
|
106
|
+
skipId = options.skipId;
|
|
105
107
|
}
|
|
106
108
|
|
|
107
|
-
this.$__ = new InternalCache();
|
|
108
|
-
|
|
109
109
|
// Avoid setting `isNew` to `true`, because it is `true` by default
|
|
110
110
|
if (options.isNew != null && options.isNew !== true) {
|
|
111
111
|
this.$isNew = options.isNew;
|
|
@@ -733,6 +733,10 @@ Document.prototype.$__init = function(doc, opts) {
|
|
|
733
733
|
function init(self, obj, doc, opts, prefix) {
|
|
734
734
|
prefix = prefix || '';
|
|
735
735
|
|
|
736
|
+
if (typeof obj !== 'object' || Array.isArray(obj)) {
|
|
737
|
+
throw new ObjectExpectedError(self.$basePath, obj);
|
|
738
|
+
}
|
|
739
|
+
|
|
736
740
|
if (obj.$__ != null) {
|
|
737
741
|
obj = obj._doc;
|
|
738
742
|
}
|
|
@@ -849,14 +853,25 @@ function init(self, obj, doc, opts, prefix) {
|
|
|
849
853
|
* @instance
|
|
850
854
|
*/
|
|
851
855
|
|
|
852
|
-
Document.prototype.updateOne = function updateOne(doc, options
|
|
856
|
+
Document.prototype.updateOne = function updateOne(doc, options) {
|
|
853
857
|
const query = this.constructor.updateOne({ _id: this._doc._id }, doc, options);
|
|
854
858
|
const self = this;
|
|
855
|
-
query.pre(function queryPreUpdateOne(
|
|
856
|
-
self.
|
|
859
|
+
query.pre(async function queryPreUpdateOne() {
|
|
860
|
+
const res = await self._execDocumentPreHooks('updateOne', self);
|
|
861
|
+
// `self` is passed to pre hooks as argument for backwards compatibility, but that
|
|
862
|
+
// isn't the actual arguments passed to the wrapped function.
|
|
863
|
+
if (res?.length !== 1 || res[0] !== self) {
|
|
864
|
+
throw new Error('Document updateOne pre hooks cannot overwrite arguments');
|
|
865
|
+
}
|
|
866
|
+
// Apply custom where conditions _after_ document updateOne middleware for
|
|
867
|
+
// consistency with save() - sharding plugin needs to set $where
|
|
868
|
+
if (self.$where != null) {
|
|
869
|
+
this.where(self.$where);
|
|
870
|
+
}
|
|
871
|
+
return res;
|
|
857
872
|
});
|
|
858
|
-
query.post(function queryPostUpdateOne(
|
|
859
|
-
self.
|
|
873
|
+
query.post(function queryPostUpdateOne() {
|
|
874
|
+
return self._execDocumentPostHooks('updateOne');
|
|
860
875
|
});
|
|
861
876
|
|
|
862
877
|
if (this.$session() != null) {
|
|
@@ -865,10 +880,6 @@ Document.prototype.updateOne = function updateOne(doc, options, callback) {
|
|
|
865
880
|
}
|
|
866
881
|
}
|
|
867
882
|
|
|
868
|
-
if (callback != null) {
|
|
869
|
-
return query.exec(callback);
|
|
870
|
-
}
|
|
871
|
-
|
|
872
883
|
return query;
|
|
873
884
|
};
|
|
874
885
|
|
|
@@ -2648,16 +2659,12 @@ Document.prototype.validate = async function validate(pathsToValidate, options)
|
|
|
2648
2659
|
this.$__.validating = true;
|
|
2649
2660
|
}
|
|
2650
2661
|
|
|
2651
|
-
|
|
2652
|
-
this.$__validate(pathsToValidate, options
|
|
2653
|
-
|
|
2654
|
-
|
|
2655
|
-
|
|
2656
|
-
|
|
2657
|
-
}
|
|
2658
|
-
resolve();
|
|
2659
|
-
});
|
|
2660
|
-
});
|
|
2662
|
+
try {
|
|
2663
|
+
await this.$__validate(pathsToValidate, options);
|
|
2664
|
+
} finally {
|
|
2665
|
+
this.$op = null;
|
|
2666
|
+
this.$__.validating = null;
|
|
2667
|
+
}
|
|
2661
2668
|
};
|
|
2662
2669
|
|
|
2663
2670
|
/**
|
|
@@ -2808,13 +2815,13 @@ function _getPathsToValidate(doc, pathsToValidate, pathsToSkip, isNestedValidate
|
|
|
2808
2815
|
|
|
2809
2816
|
// Optimization: if primitive path with no validators, or array of primitives
|
|
2810
2817
|
// with no validators, skip validating this path entirely.
|
|
2811
|
-
if (!_pathType.
|
|
2818
|
+
if (!_pathType.schema && !_pathType.embeddedSchemaType && _pathType.validators.length === 0 && !_pathType.$parentSchemaDocArray) {
|
|
2812
2819
|
paths.delete(path);
|
|
2813
2820
|
} else if (_pathType.$isMongooseArray &&
|
|
2814
2821
|
!_pathType.$isMongooseDocumentArray && // Skip document arrays...
|
|
2815
|
-
!_pathType
|
|
2822
|
+
!_pathType.embeddedSchemaType.$isMongooseArray && // and arrays of arrays
|
|
2816
2823
|
_pathType.validators.length === 0 && // and arrays with top-level validators
|
|
2817
|
-
_pathType
|
|
2824
|
+
_pathType.embeddedSchemaType.validators.length === 0) {
|
|
2818
2825
|
paths.delete(path);
|
|
2819
2826
|
}
|
|
2820
2827
|
}
|
|
@@ -2899,8 +2906,8 @@ function _addArrayPathsToValidate(doc, paths) {
|
|
|
2899
2906
|
// on the array type, there's no need to run validation on the individual array elements.
|
|
2900
2907
|
if (_pathType.$isMongooseArray &&
|
|
2901
2908
|
!_pathType.$isMongooseDocumentArray && // Skip document arrays...
|
|
2902
|
-
!_pathType
|
|
2903
|
-
_pathType
|
|
2909
|
+
!_pathType.embeddedSchemaType.$isMongooseArray && // and arrays of arrays
|
|
2910
|
+
_pathType.embeddedSchemaType.validators.length === 0) {
|
|
2904
2911
|
continue;
|
|
2905
2912
|
}
|
|
2906
2913
|
|
|
@@ -2926,16 +2933,32 @@ function _pushNestedArrayPaths(val, paths, path) {
|
|
|
2926
2933
|
* ignore
|
|
2927
2934
|
*/
|
|
2928
2935
|
|
|
2929
|
-
Document.prototype
|
|
2936
|
+
Document.prototype._execDocumentPreHooks = async function _execDocumentPreHooks(opName, ...args) {
|
|
2937
|
+
return this.$__middleware.execPre(opName, this, [...args]);
|
|
2938
|
+
};
|
|
2939
|
+
|
|
2940
|
+
/*!
|
|
2941
|
+
* ignore
|
|
2942
|
+
*/
|
|
2943
|
+
|
|
2944
|
+
Document.prototype._execDocumentPostHooks = async function _execDocumentPostHooks(opName, error) {
|
|
2945
|
+
return this.$__middleware.execPost(opName, this, [this], { error });
|
|
2946
|
+
};
|
|
2947
|
+
|
|
2948
|
+
/*!
|
|
2949
|
+
* ignore
|
|
2950
|
+
*/
|
|
2951
|
+
|
|
2952
|
+
Document.prototype.$__validate = async function $__validate(pathsToValidate, options) {
|
|
2953
|
+
try {
|
|
2954
|
+
[options] = await this._execDocumentPreHooks('validate', options);
|
|
2955
|
+
} catch (error) {
|
|
2956
|
+
await this._execDocumentPostHooks('validate', error);
|
|
2957
|
+
return;
|
|
2958
|
+
}
|
|
2959
|
+
|
|
2930
2960
|
if (this.$__.saveOptions && this.$__.saveOptions.pathsToSave && !pathsToValidate) {
|
|
2931
2961
|
pathsToValidate = [...this.$__.saveOptions.pathsToSave];
|
|
2932
|
-
} else if (typeof pathsToValidate === 'function') {
|
|
2933
|
-
callback = pathsToValidate;
|
|
2934
|
-
options = null;
|
|
2935
|
-
pathsToValidate = null;
|
|
2936
|
-
} else if (typeof options === 'function') {
|
|
2937
|
-
callback = options;
|
|
2938
|
-
options = null;
|
|
2939
2962
|
}
|
|
2940
2963
|
|
|
2941
2964
|
const hasValidateModifiedOnlyOption = options &&
|
|
@@ -3033,110 +3056,90 @@ Document.prototype.$__validate = function(pathsToValidate, options, callback) {
|
|
|
3033
3056
|
}
|
|
3034
3057
|
|
|
3035
3058
|
if (paths.length === 0) {
|
|
3036
|
-
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
return _this.$__schema.s.hooks.execPost('validate:error', _this, [_this], { error: error }, function(error) {
|
|
3040
|
-
callback(error);
|
|
3041
|
-
});
|
|
3042
|
-
}
|
|
3043
|
-
callback(null, _this);
|
|
3044
|
-
});
|
|
3059
|
+
const error = _complete();
|
|
3060
|
+
await this._execDocumentPostHooks('validate', error);
|
|
3061
|
+
return;
|
|
3045
3062
|
}
|
|
3046
3063
|
|
|
3047
3064
|
const validated = {};
|
|
3048
|
-
let total = 0;
|
|
3049
3065
|
|
|
3050
3066
|
let pathsToSave = this.$__.saveOptions?.pathsToSave;
|
|
3067
|
+
const promises = [];
|
|
3051
3068
|
if (Array.isArray(pathsToSave)) {
|
|
3052
3069
|
pathsToSave = new Set(pathsToSave);
|
|
3053
3070
|
for (const path of paths) {
|
|
3054
3071
|
if (!pathsToSave.has(path)) {
|
|
3055
3072
|
continue;
|
|
3056
3073
|
}
|
|
3057
|
-
validatePath(path);
|
|
3074
|
+
promises.push(validatePath(path));
|
|
3058
3075
|
}
|
|
3059
3076
|
} else {
|
|
3060
3077
|
for (const path of paths) {
|
|
3061
|
-
validatePath(path);
|
|
3078
|
+
promises.push(validatePath(path));
|
|
3062
3079
|
}
|
|
3063
3080
|
}
|
|
3081
|
+
await Promise.all(promises);
|
|
3082
|
+
const error = _complete();
|
|
3083
|
+
await this._execDocumentPostHooks('validate', error);
|
|
3064
3084
|
|
|
3065
|
-
function validatePath(path) {
|
|
3085
|
+
async function validatePath(path) {
|
|
3066
3086
|
if (path == null || validated[path]) {
|
|
3067
3087
|
return;
|
|
3068
3088
|
}
|
|
3069
3089
|
|
|
3070
3090
|
validated[path] = true;
|
|
3071
|
-
|
|
3091
|
+
const schemaType = _this.$__schema.path(path);
|
|
3072
3092
|
|
|
3073
|
-
|
|
3074
|
-
|
|
3093
|
+
if (!schemaType) {
|
|
3094
|
+
return;
|
|
3095
|
+
}
|
|
3075
3096
|
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3097
|
+
// If user marked as invalid or there was a cast error, don't validate
|
|
3098
|
+
if (!_this.$isValid(path)) {
|
|
3099
|
+
return;
|
|
3100
|
+
}
|
|
3079
3101
|
|
|
3080
|
-
|
|
3081
|
-
|
|
3082
|
-
|
|
3083
|
-
|
|
3084
|
-
}
|
|
3102
|
+
// If setting a path under a mixed path, avoid using the mixed path validator (gh-10141)
|
|
3103
|
+
if (schemaType[schemaMixedSymbol] != null && path !== schemaType.path) {
|
|
3104
|
+
return;
|
|
3105
|
+
}
|
|
3085
3106
|
|
|
3086
|
-
|
|
3087
|
-
if (schemaType[schemaMixedSymbol] != null && path !== schemaType.path) {
|
|
3088
|
-
return --total || complete();
|
|
3089
|
-
}
|
|
3107
|
+
let val = _this.$__getValue(path);
|
|
3090
3108
|
|
|
3091
|
-
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
_this.$__.pathsToScopes[path] :
|
|
3106
|
-
_this;
|
|
3107
|
-
|
|
3108
|
-
const doValidateOptions = {
|
|
3109
|
-
...doValidateOptionsByPath[path],
|
|
3110
|
-
path: path,
|
|
3111
|
-
validateAllPaths,
|
|
3112
|
-
_nestedValidate: true
|
|
3113
|
-
};
|
|
3114
|
-
|
|
3115
|
-
schemaType.doValidate(val, function(err) {
|
|
3116
|
-
if (err) {
|
|
3117
|
-
const isSubdoc = schemaType.$isSingleNested ||
|
|
3118
|
-
schemaType.$isArraySubdocument ||
|
|
3119
|
-
schemaType.$isMongooseDocumentArray;
|
|
3120
|
-
if (isSubdoc && err instanceof ValidationError) {
|
|
3121
|
-
return --total || complete();
|
|
3122
|
-
}
|
|
3123
|
-
_this.invalidate(path, err, undefined, true);
|
|
3124
|
-
}
|
|
3125
|
-
--total || complete();
|
|
3126
|
-
}, scope, doValidateOptions);
|
|
3127
|
-
});
|
|
3128
|
-
}
|
|
3109
|
+
// If you `populate()` and get back a null value, required validators
|
|
3110
|
+
// shouldn't fail (gh-8018). We should always fall back to the populated
|
|
3111
|
+
// value.
|
|
3112
|
+
let pop;
|
|
3113
|
+
if ((pop = _this.$populated(path))) {
|
|
3114
|
+
val = pop;
|
|
3115
|
+
} else if (val != null && val.$__ != null && val.$__.wasPopulated) {
|
|
3116
|
+
// Array paths, like `somearray.1`, do not show up as populated with `$populated()`,
|
|
3117
|
+
// so in that case pull out the document's id
|
|
3118
|
+
val = val._doc._id;
|
|
3119
|
+
}
|
|
3120
|
+
const scope = _this.$__.pathsToScopes != null && path in _this.$__.pathsToScopes ?
|
|
3121
|
+
_this.$__.pathsToScopes[path] :
|
|
3122
|
+
_this;
|
|
3129
3123
|
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
|
|
3135
|
-
|
|
3124
|
+
const doValidateOptions = {
|
|
3125
|
+
...doValidateOptionsByPath[path],
|
|
3126
|
+
path: path,
|
|
3127
|
+
validateAllPaths,
|
|
3128
|
+
_nestedValidate: true
|
|
3129
|
+
};
|
|
3130
|
+
|
|
3131
|
+
try {
|
|
3132
|
+
await schemaType.doValidate(val, scope, doValidateOptions);
|
|
3133
|
+
} catch (err) {
|
|
3134
|
+
const isSubdoc = schemaType.$isSingleNested ||
|
|
3135
|
+
schemaType.$isArraySubdocument ||
|
|
3136
|
+
schemaType.$isMongooseDocumentArray;
|
|
3137
|
+
if (isSubdoc && err instanceof ValidationError) {
|
|
3138
|
+
return;
|
|
3139
|
+
}
|
|
3140
|
+
_this.invalidate(path, err, undefined, true);
|
|
3136
3141
|
}
|
|
3137
|
-
callback(null, _this);
|
|
3138
3142
|
}
|
|
3139
|
-
|
|
3140
3143
|
};
|
|
3141
3144
|
|
|
3142
3145
|
/*!
|
|
@@ -3681,6 +3684,7 @@ Document.prototype.$__setSchema = function(schema) {
|
|
|
3681
3684
|
this.schema = schema;
|
|
3682
3685
|
}
|
|
3683
3686
|
this.$__schema = schema;
|
|
3687
|
+
this.$__middleware = schema._getDocumentMiddleware();
|
|
3684
3688
|
this[documentSchemaSymbol] = schema;
|
|
3685
3689
|
};
|
|
3686
3690
|
|
|
@@ -4274,9 +4278,9 @@ function applyGetters(self, json) {
|
|
|
4274
4278
|
branch[part],
|
|
4275
4279
|
self
|
|
4276
4280
|
);
|
|
4277
|
-
if (Array.isArray(branch[part]) && schema.paths[path]
|
|
4281
|
+
if (Array.isArray(branch[part]) && schema.paths[path].embeddedSchemaType) {
|
|
4278
4282
|
for (let i = 0; i < branch[part].length; ++i) {
|
|
4279
|
-
branch[part][i] = schema.paths[path]
|
|
4283
|
+
branch[part][i] = schema.paths[path].embeddedSchemaType.applyGetters(
|
|
4280
4284
|
branch[part][i],
|
|
4281
4285
|
self
|
|
4282
4286
|
);
|
|
@@ -4318,8 +4322,8 @@ function applySchemaTypeTransforms(self, json) {
|
|
|
4318
4322
|
for (const path of paths) {
|
|
4319
4323
|
const schematype = schema.paths[path];
|
|
4320
4324
|
const topLevelTransformFunction = schematype.options.transform ?? schematype.constructor?.defaultOptions?.transform;
|
|
4321
|
-
const embeddedSchemaTypeTransformFunction = schematype
|
|
4322
|
-
?? schematype
|
|
4325
|
+
const embeddedSchemaTypeTransformFunction = schematype.embeddedSchemaType?.options?.transform
|
|
4326
|
+
?? schematype.embeddedSchemaType?.constructor?.defaultOptions?.transform;
|
|
4323
4327
|
if (typeof topLevelTransformFunction === 'function') {
|
|
4324
4328
|
const val = self.$get(path);
|
|
4325
4329
|
if (val === undefined) {
|
|
@@ -5046,7 +5050,7 @@ Document.prototype.$__delta = function $__delta() {
|
|
|
5046
5050
|
}
|
|
5047
5051
|
|
|
5048
5052
|
if (divergent.length) {
|
|
5049
|
-
|
|
5053
|
+
throw new DivergentArrayError(divergent);
|
|
5050
5054
|
}
|
|
5051
5055
|
|
|
5052
5056
|
if (this.$__.version) {
|
|
@@ -55,7 +55,6 @@ Object.setPrototypeOf(NativeConnection.prototype, MongooseConnection.prototype);
|
|
|
55
55
|
* @param {String} name The database name
|
|
56
56
|
* @param {Object} [options]
|
|
57
57
|
* @param {Boolean} [options.useCache=false] If true, cache results so calling `useDb()` multiple times with the same name only creates 1 connection object.
|
|
58
|
-
* @param {Boolean} [options.noListener=false] If true, the new connection object won't listen to any events on the base connection. This is better for memory usage in cases where you're calling `useDb()` for every request.
|
|
59
58
|
* @return {Connection} New Connection Object
|
|
60
59
|
* @api public
|
|
61
60
|
*/
|
|
@@ -107,21 +106,15 @@ NativeConnection.prototype.useDb = function(name, options) {
|
|
|
107
106
|
|
|
108
107
|
function wireup() {
|
|
109
108
|
newConn.client = _this.client;
|
|
110
|
-
|
|
111
|
-
if (options.hasOwnProperty('noListener')) {
|
|
112
|
-
_opts.noListener = options.noListener;
|
|
113
|
-
}
|
|
114
|
-
newConn.db = _this.client.db(name, _opts);
|
|
109
|
+
newConn.db = _this.client.db(name);
|
|
115
110
|
newConn._lastHeartbeatAt = _this._lastHeartbeatAt;
|
|
116
111
|
newConn.onOpen();
|
|
117
112
|
}
|
|
118
113
|
|
|
119
114
|
newConn.name = name;
|
|
120
115
|
|
|
121
|
-
// push onto the otherDbs stack, this is used when state changes
|
|
122
|
-
|
|
123
|
-
this.otherDbs.push(newConn);
|
|
124
|
-
}
|
|
116
|
+
// push onto the otherDbs stack, this is used when state changes
|
|
117
|
+
this.otherDbs.push(newConn);
|
|
125
118
|
newConn.otherDbs.push(this);
|
|
126
119
|
|
|
127
120
|
// push onto the relatedDbs cache, this is used when state changes
|
|
@@ -17,10 +17,9 @@ const MongooseError = require('./mongooseError');
|
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
19
|
class ObjectParameterError extends MongooseError {
|
|
20
|
-
|
|
21
20
|
constructor(value, paramName, fnName) {
|
|
22
21
|
super('Parameter "' + paramName + '" to ' + fnName +
|
|
23
|
-
'() must be an object, got "' + value.toString() + '" (type ' + typeof value + ')');
|
|
22
|
+
'() must be an object, got "' + (value == null ? value : value.toString()) + '" (type ' + typeof value + ')');
|
|
24
23
|
}
|
|
25
24
|
}
|
|
26
25
|
|
package/lib/error/validation.js
CHANGED
|
@@ -44,14 +44,6 @@ class ValidationError extends MongooseError {
|
|
|
44
44
|
return this.name + ': ' + combinePathErrors(this);
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
/**
|
|
48
|
-
* inspect helper
|
|
49
|
-
* @api private
|
|
50
|
-
*/
|
|
51
|
-
inspect() {
|
|
52
|
-
return Object.assign(new Error(this.message), this);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
47
|
/**
|
|
56
48
|
* add message
|
|
57
49
|
* @param {String} path
|
package/lib/helpers/clone.js
CHANGED
|
@@ -11,7 +11,7 @@ const isObject = require('./isObject');
|
|
|
11
11
|
const isPOJO = require('./isPOJO');
|
|
12
12
|
const symbols = require('./symbols');
|
|
13
13
|
const trustedSymbol = require('./query/trusted').trustedSymbol;
|
|
14
|
-
const BSON = require('bson');
|
|
14
|
+
const BSON = require('mongodb/lib/bson');
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
17
|
* Object clone with Mongoose natives support.
|
package/lib/helpers/common.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Module dependencies.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
const Binary = require('bson').Binary;
|
|
7
|
+
const Binary = require('mongodb/lib/bson').Binary;
|
|
8
8
|
const isBsonType = require('./isBsonType');
|
|
9
9
|
const isMongooseObject = require('./isMongooseObject');
|
|
10
10
|
const MongooseError = require('../error');
|
|
@@ -20,7 +20,6 @@ module.exports = function isIndexEqual(schemaIndexKeysObject, options, dbIndex)
|
|
|
20
20
|
// key: { _fts: 'text', _ftsx: 1 },
|
|
21
21
|
// name: 'name_text',
|
|
22
22
|
// ns: 'test.tests',
|
|
23
|
-
// background: true,
|
|
24
23
|
// weights: { name: 1 },
|
|
25
24
|
// default_language: 'english',
|
|
26
25
|
// language_override: 'language',
|
|
@@ -23,7 +23,7 @@ module.exports = function applyDefaultsToPOJO(doc, schema) {
|
|
|
23
23
|
if (j === len - 1) {
|
|
24
24
|
if (typeof doc_[piece] !== 'undefined') {
|
|
25
25
|
if (type.$isSingleNested) {
|
|
26
|
-
applyDefaultsToPOJO(doc_[piece], type.
|
|
26
|
+
applyDefaultsToPOJO(doc_[piece], type.schema);
|
|
27
27
|
} else if (type.$isMongooseDocumentArray && Array.isArray(doc_[piece])) {
|
|
28
28
|
doc_[piece].forEach(el => applyDefaultsToPOJO(el, type.schema));
|
|
29
29
|
}
|
|
@@ -36,7 +36,7 @@ module.exports = function applyDefaultsToPOJO(doc, schema) {
|
|
|
36
36
|
doc_[piece] = def;
|
|
37
37
|
|
|
38
38
|
if (type.$isSingleNested) {
|
|
39
|
-
applyDefaultsToPOJO(def, type.
|
|
39
|
+
applyDefaultsToPOJO(def, type.schema);
|
|
40
40
|
} else if (type.$isMongooseDocumentArray && Array.isArray(def)) {
|
|
41
41
|
def.forEach(el => applyDefaultsToPOJO(el, type.schema));
|
|
42
42
|
}
|
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const symbols = require('../../schema/symbols');
|
|
4
|
-
const promiseOrCallback = require('../promiseOrCallback');
|
|
5
|
-
|
|
6
3
|
/*!
|
|
7
4
|
* ignore
|
|
8
5
|
*/
|
|
@@ -15,10 +12,10 @@ module.exports = applyHooks;
|
|
|
15
12
|
|
|
16
13
|
applyHooks.middlewareFunctions = [
|
|
17
14
|
'deleteOne',
|
|
18
|
-
'save',
|
|
19
|
-
'validate',
|
|
20
15
|
'remove',
|
|
16
|
+
'save',
|
|
21
17
|
'updateOne',
|
|
18
|
+
'validate',
|
|
22
19
|
'init'
|
|
23
20
|
];
|
|
24
21
|
|
|
@@ -47,15 +44,15 @@ function applyHooks(model, schema, options) {
|
|
|
47
44
|
contextParameter: true
|
|
48
45
|
};
|
|
49
46
|
const objToDecorate = options.decorateDoc ? model : model.prototype;
|
|
50
|
-
|
|
51
47
|
model.$appliedHooks = true;
|
|
52
48
|
for (const key of Object.keys(schema.paths)) {
|
|
53
|
-
|
|
49
|
+
let type = schema.paths[key];
|
|
54
50
|
let childModel = null;
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
childModel =
|
|
51
|
+
|
|
52
|
+
const result = findChildModel(type);
|
|
53
|
+
if (result) {
|
|
54
|
+
childModel = result.childModel;
|
|
55
|
+
type = result.type;
|
|
59
56
|
} else {
|
|
60
57
|
continue;
|
|
61
58
|
}
|
|
@@ -64,7 +61,11 @@ function applyHooks(model, schema, options) {
|
|
|
64
61
|
continue;
|
|
65
62
|
}
|
|
66
63
|
|
|
67
|
-
applyHooks(childModel, type.schema, {
|
|
64
|
+
applyHooks(childModel, type.schema, {
|
|
65
|
+
...options,
|
|
66
|
+
decorateDoc: false,
|
|
67
|
+
isChildSchema: true
|
|
68
|
+
});
|
|
68
69
|
if (childModel.discriminators != null) {
|
|
69
70
|
const keys = Object.keys(childModel.discriminators);
|
|
70
71
|
for (const key of keys) {
|
|
@@ -78,39 +79,10 @@ function applyHooks(model, schema, options) {
|
|
|
78
79
|
// promises and make it so that `doc.save.toString()` provides meaningful
|
|
79
80
|
// information.
|
|
80
81
|
|
|
81
|
-
const middleware = schema.
|
|
82
|
-
filter(hook => {
|
|
83
|
-
if (hook.name === 'updateOne' || hook.name === 'deleteOne') {
|
|
84
|
-
return !!hook['document'];
|
|
85
|
-
}
|
|
86
|
-
if (hook.name === 'remove' || hook.name === 'init') {
|
|
87
|
-
return hook['document'] == null || !!hook['document'];
|
|
88
|
-
}
|
|
89
|
-
if (hook.query != null || hook.document != null) {
|
|
90
|
-
return hook.document !== false;
|
|
91
|
-
}
|
|
92
|
-
return true;
|
|
93
|
-
}).
|
|
94
|
-
filter(hook => {
|
|
95
|
-
// If user has overwritten the method, don't apply built-in middleware
|
|
96
|
-
if (schema.methods[hook.name]) {
|
|
97
|
-
return !hook.fn[symbols.builtInMiddleware];
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
return true;
|
|
101
|
-
});
|
|
82
|
+
const middleware = schema._getDocumentMiddleware();
|
|
102
83
|
|
|
103
84
|
model._middleware = middleware;
|
|
104
85
|
|
|
105
|
-
objToDecorate.$__originalValidate = objToDecorate.$__originalValidate || objToDecorate.$__validate;
|
|
106
|
-
|
|
107
|
-
const internalMethodsToWrap = options && options.isChildSchema ? ['save', 'validate', 'deleteOne'] : ['save', 'validate'];
|
|
108
|
-
for (const method of internalMethodsToWrap) {
|
|
109
|
-
const toWrap = method === 'validate' ? '$__originalValidate' : `$__${method}`;
|
|
110
|
-
const wrapped = middleware.
|
|
111
|
-
createWrapper(method, objToDecorate[toWrap], null, kareemOptions);
|
|
112
|
-
objToDecorate[`$__${method}`] = wrapped;
|
|
113
|
-
}
|
|
114
86
|
objToDecorate.$__init = middleware.
|
|
115
87
|
createWrapperSync('init', objToDecorate.$__init, null, kareemOptions);
|
|
116
88
|
|
|
@@ -134,17 +106,35 @@ function applyHooks(model, schema, options) {
|
|
|
134
106
|
continue;
|
|
135
107
|
}
|
|
136
108
|
const originalMethod = objToDecorate[method];
|
|
137
|
-
objToDecorate[method] =
|
|
138
|
-
|
|
139
|
-
const cb = args.slice(-1).pop();
|
|
140
|
-
const argsWithoutCallback = typeof cb === 'function' ?
|
|
141
|
-
args.slice(0, args.length - 1) : args;
|
|
142
|
-
return promiseOrCallback(cb, callback => {
|
|
143
|
-
return this[`$__${method}`].apply(this,
|
|
144
|
-
argsWithoutCallback.concat([callback]));
|
|
145
|
-
}, model.events);
|
|
146
|
-
};
|
|
147
|
-
objToDecorate[`$__${method}`] = middleware.
|
|
109
|
+
objToDecorate[`$__${method}`] = objToDecorate[method];
|
|
110
|
+
objToDecorate[method] = middleware.
|
|
148
111
|
createWrapper(method, originalMethod, null, customMethodOptions);
|
|
149
112
|
}
|
|
150
113
|
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Check if there is an embedded schematype in the given schematype. Handles drilling down into primitive
|
|
117
|
+
* arrays and maps in case of array of array of subdocs or map of subdocs.
|
|
118
|
+
*
|
|
119
|
+
* @param {SchemaType} curType
|
|
120
|
+
* @returns {{ childModel: Model | typeof Subdocument, curType: SchemaType } | null}
|
|
121
|
+
*/
|
|
122
|
+
|
|
123
|
+
function findChildModel(curType) {
|
|
124
|
+
if (curType.$isSingleNested || curType.$isMongooseDocumentArray) {
|
|
125
|
+
return { childModel: curType.Constructor, type: curType };
|
|
126
|
+
}
|
|
127
|
+
if (curType.instance === 'Array') {
|
|
128
|
+
const embedded = curType.getEmbeddedSchemaType();
|
|
129
|
+
if (embedded) {
|
|
130
|
+
return findChildModel(embedded);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
if (curType.instance === 'Map') {
|
|
134
|
+
const mapType = curType.getEmbeddedSchemaType();
|
|
135
|
+
if (mapType) {
|
|
136
|
+
return findChildModel(mapType);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
return null;
|
|
140
|
+
}
|
|
@@ -60,8 +60,8 @@ module.exports = function applyMethods(model, schema) {
|
|
|
60
60
|
model.$appliedMethods = true;
|
|
61
61
|
for (const key of Object.keys(schema.paths)) {
|
|
62
62
|
const type = schema.paths[key];
|
|
63
|
-
if (type.$isSingleNested && !type.
|
|
64
|
-
applyMethods(type.
|
|
63
|
+
if (type.$isSingleNested && !type.Constructor.$appliedMethods) {
|
|
64
|
+
applyMethods(type.Constructor, type.schema);
|
|
65
65
|
}
|
|
66
66
|
if (type.$isMongooseDocumentArray && !type.Constructor.$appliedMethods) {
|
|
67
67
|
applyMethods(type.Constructor, type.schema);
|