mongoose 9.0.0 → 9.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/aggregate.js +1 -1
- package/lib/cast/double.js +1 -1
- package/lib/cast.js +1 -1
- package/lib/connection.js +10 -10
- package/lib/document.js +63 -19
- package/lib/drivers/node-mongodb-native/collection.js +38 -104
- package/lib/drivers/node-mongodb-native/connection.js +1 -1
- package/lib/helpers/common.js +1 -1
- package/lib/helpers/indexes/applySchemaCollation.js +1 -1
- package/lib/helpers/indexes/isDefaultIdIndex.js +1 -1
- package/lib/helpers/model/applyMethods.js +1 -1
- package/lib/helpers/model/castBulkWrite.js +13 -6
- package/lib/helpers/populate/getModelsMapForPopulate.js +3 -3
- package/lib/helpers/populate/modelNamesFromRefPath.js +1 -1
- package/lib/helpers/populate/removeDeselectedForeignField.js +1 -1
- package/lib/helpers/projection/applyProjection.js +2 -2
- package/lib/helpers/query/getEmbeddedDiscriminatorPath.js +1 -1
- package/lib/helpers/setDefaultsOnInsert.js +2 -2
- package/lib/helpers/timestamps/setupTimestamps.js +1 -1
- package/lib/helpers/update/applyTimestampsToUpdate.js +38 -25
- package/lib/helpers/update/decorateUpdateWithVersionKey.js +1 -1
- package/lib/model.js +17 -11
- package/lib/mongoose.js +3 -4
- package/lib/query.js +3 -3
- package/lib/schema/array.js +1 -1
- package/lib/schema/number.js +14 -2
- package/lib/schema/operators/text.js +1 -1
- package/lib/schema.js +21 -21
- package/lib/schemaType.js +8 -8
- package/lib/types/array/index.js +5 -5
- package/lib/types/documentArray/index.js +6 -6
- package/lib/types/objectid.js +1 -1
- package/lib/utils.js +12 -24
- package/lib/virtualType.js +1 -1
- package/package.json +8 -7
- package/types/index.d.ts +11 -3
- package/types/inferrawdoctype.d.ts +9 -3
- package/types/inferschematype.d.ts +20 -27
- package/types/models.d.ts +313 -85
- package/types/query.d.ts +91 -1
- package/types/utility.d.ts +1 -1
- package/types/virtuals.d.ts +3 -3
|
@@ -56,7 +56,7 @@ module.exports = function modelNamesFromRefPath(refPath, doc, populatedPath, mod
|
|
|
56
56
|
const refValue = mpath.get(refPath, doc, lookupLocalFields);
|
|
57
57
|
|
|
58
58
|
let modelNames;
|
|
59
|
-
if (modelSchema != null && modelSchema.virtuals
|
|
59
|
+
if (modelSchema != null && Object.hasOwn(modelSchema.virtuals, refPath)) {
|
|
60
60
|
modelNames = [modelSchema.virtuals[refPath].applyGetters(void 0, doc)];
|
|
61
61
|
} else {
|
|
62
62
|
modelNames = Array.isArray(refValue) ? refValue : [refValue];
|
|
@@ -16,7 +16,7 @@ module.exports = function removeDeselectedForeignField(foreignFields, options, d
|
|
|
16
16
|
return;
|
|
17
17
|
}
|
|
18
18
|
for (const foreignField of foreignFields) {
|
|
19
|
-
if (!
|
|
19
|
+
if (!Object.hasOwn(projection, '-' + foreignField)) {
|
|
20
20
|
continue;
|
|
21
21
|
}
|
|
22
22
|
|
|
@@ -43,7 +43,7 @@ function applyExclusiveProjection(doc, projection, hasIncludedChildren, projecti
|
|
|
43
43
|
|
|
44
44
|
for (const key of Object.keys(ret)) {
|
|
45
45
|
const fullPath = prefix ? prefix + '.' + key : key;
|
|
46
|
-
if (
|
|
46
|
+
if (Object.hasOwn(projection, fullPath) || Object.hasOwn(projectionLimb, key)) {
|
|
47
47
|
if (isPOJO(projection[fullPath]) || isPOJO(projectionLimb[key])) {
|
|
48
48
|
ret[key] = applyExclusiveProjection(ret[key], projection, hasIncludedChildren, projectionLimb[key], fullPath);
|
|
49
49
|
} else {
|
|
@@ -68,7 +68,7 @@ function applyInclusiveProjection(doc, projection, hasIncludedChildren, projecti
|
|
|
68
68
|
|
|
69
69
|
for (const key of Object.keys(ret)) {
|
|
70
70
|
const fullPath = prefix ? prefix + '.' + key : key;
|
|
71
|
-
if (
|
|
71
|
+
if (Object.hasOwn(projection, fullPath) || Object.hasOwn(projectionLimb, key)) {
|
|
72
72
|
if (isPOJO(projection[fullPath]) || isPOJO(projectionLimb[key])) {
|
|
73
73
|
ret[key] = applyInclusiveProjection(ret[key], projection, hasIncludedChildren, projectionLimb[key], fullPath);
|
|
74
74
|
}
|
|
@@ -71,7 +71,7 @@ module.exports = function getEmbeddedDiscriminatorPath(schema, update, filter, p
|
|
|
71
71
|
const schemaKey = updatedPathsByFilter[filterKey] + '.' + key;
|
|
72
72
|
const arrayFilterKey = filterKey + '.' + key;
|
|
73
73
|
if (schemaKey === discriminatorFilterPath) {
|
|
74
|
-
const filter = arrayFilters.find(filter =>
|
|
74
|
+
const filter = arrayFilters.find(filter => Object.hasOwn(filter, arrayFilterKey));
|
|
75
75
|
if (filter != null) {
|
|
76
76
|
discriminatorKey = filter[arrayFilterKey];
|
|
77
77
|
}
|
|
@@ -136,14 +136,14 @@ function pathExistsInUpdate(update, targetPath, pathPieces) {
|
|
|
136
136
|
}
|
|
137
137
|
|
|
138
138
|
// Check exact match
|
|
139
|
-
if (
|
|
139
|
+
if (Object.hasOwn(update, targetPath)) {
|
|
140
140
|
return true;
|
|
141
141
|
}
|
|
142
142
|
|
|
143
143
|
// Check if any parent path exists
|
|
144
144
|
let cur = pathPieces[0];
|
|
145
145
|
for (let i = 1; i < pathPieces.length; ++i) {
|
|
146
|
-
if (
|
|
146
|
+
if (Object.hasOwn(update, cur)) {
|
|
147
147
|
return true;
|
|
148
148
|
}
|
|
149
149
|
cur += '.' + pathPieces[i];
|
|
@@ -23,7 +23,7 @@ module.exports = function setupTimestamps(schema, timestamps) {
|
|
|
23
23
|
}
|
|
24
24
|
const createdAt = handleTimestampOption(timestamps, 'createdAt');
|
|
25
25
|
const updatedAt = handleTimestampOption(timestamps, 'updatedAt');
|
|
26
|
-
const currentTime = timestamps != null &&
|
|
26
|
+
const currentTime = timestamps != null && Object.hasOwn(timestamps, 'currentTime') ?
|
|
27
27
|
timestamps.currentTime :
|
|
28
28
|
null;
|
|
29
29
|
const schemaAdditions = {};
|
|
@@ -74,39 +74,52 @@ function applyTimestampsToUpdate(now, createdAt, updatedAt, currentUpdate, optio
|
|
|
74
74
|
updates.$set[updatedAt] = now;
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
-
if (
|
|
77
|
+
if (Object.hasOwn(updates, updatedAt)) {
|
|
78
78
|
delete updates[updatedAt];
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
81
|
|
|
82
82
|
if (!skipCreatedAt && createdAt) {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
83
|
+
const overwriteImmutable = get(options, 'overwriteImmutable', false);
|
|
84
|
+
const hasUserCreatedAt = currentUpdate[createdAt] != null || currentUpdate?.$set[createdAt] != null;
|
|
85
|
+
|
|
86
|
+
// If overwriteImmutable is true and user provided createdAt, keep their value
|
|
87
|
+
if (overwriteImmutable && hasUserCreatedAt) {
|
|
88
|
+
// Move createdAt from top-level to $set if needed
|
|
89
|
+
if (currentUpdate[createdAt] != null) {
|
|
90
|
+
updates.$set[createdAt] = currentUpdate[createdAt];
|
|
91
|
+
delete currentUpdate[createdAt];
|
|
92
|
+
}
|
|
93
|
+
// User's value is already in $set, nothing more to do
|
|
94
|
+
} else {
|
|
95
|
+
if (currentUpdate[createdAt]) {
|
|
96
|
+
delete currentUpdate[createdAt];
|
|
97
|
+
}
|
|
98
|
+
if (currentUpdate.$set && currentUpdate.$set[createdAt]) {
|
|
99
|
+
delete currentUpdate.$set[createdAt];
|
|
100
|
+
}
|
|
101
|
+
let timestampSet = false;
|
|
102
|
+
if (createdAt.indexOf('.') !== -1) {
|
|
103
|
+
const pieces = createdAt.split('.');
|
|
104
|
+
for (let i = 1; i < pieces.length; ++i) {
|
|
105
|
+
const remnant = pieces.slice(-i).join('.');
|
|
106
|
+
const start = pieces.slice(0, -i).join('.');
|
|
107
|
+
if (currentUpdate[start] != null) {
|
|
108
|
+
currentUpdate[start][remnant] = now;
|
|
109
|
+
timestampSet = true;
|
|
110
|
+
break;
|
|
111
|
+
} else if (currentUpdate.$set && currentUpdate.$set[start]) {
|
|
112
|
+
currentUpdate.$set[start][remnant] = now;
|
|
113
|
+
timestampSet = true;
|
|
114
|
+
break;
|
|
115
|
+
}
|
|
103
116
|
}
|
|
104
117
|
}
|
|
105
|
-
}
|
|
106
118
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
119
|
+
if (!timestampSet) {
|
|
120
|
+
updates.$setOnInsert = updates.$setOnInsert || {};
|
|
121
|
+
updates.$setOnInsert[createdAt] = now;
|
|
122
|
+
}
|
|
110
123
|
}
|
|
111
124
|
}
|
|
112
125
|
|
package/lib/model.js
CHANGED
|
@@ -352,7 +352,7 @@ function _createSaveOptions(doc, options) {
|
|
|
352
352
|
const asyncLocalStorage = doc[modelDbSymbol].base.transactionAsyncLocalStorage?.getStore();
|
|
353
353
|
if (session != null) {
|
|
354
354
|
saveOptions.session = session;
|
|
355
|
-
} else if (!
|
|
355
|
+
} else if (!Object.hasOwn(options, 'session') && asyncLocalStorage?.session != null) {
|
|
356
356
|
// Only set session from asyncLocalStorage if `session` option wasn't originally passed in options
|
|
357
357
|
saveOptions.session = asyncLocalStorage.session;
|
|
358
358
|
}
|
|
@@ -586,7 +586,7 @@ Model.prototype.save = async function save(options) {
|
|
|
586
586
|
}
|
|
587
587
|
|
|
588
588
|
options = new SaveOptions(options);
|
|
589
|
-
if (
|
|
589
|
+
if (Object.hasOwn(options, 'session')) {
|
|
590
590
|
this.$session(options.session);
|
|
591
591
|
}
|
|
592
592
|
if (this.$__.timestamps != null) {
|
|
@@ -748,7 +748,7 @@ Model.prototype.deleteOne = function deleteOne(options) {
|
|
|
748
748
|
options = {};
|
|
749
749
|
}
|
|
750
750
|
|
|
751
|
-
if (
|
|
751
|
+
if (Object.hasOwn(options, 'session')) {
|
|
752
752
|
this.$session(options.session);
|
|
753
753
|
}
|
|
754
754
|
|
|
@@ -2944,7 +2944,7 @@ Model.insertMany = async function insertMany(arr, options) {
|
|
|
2944
2944
|
const lean = !!options.lean;
|
|
2945
2945
|
|
|
2946
2946
|
const asyncLocalStorage = this.db.base.transactionAsyncLocalStorage?.getStore();
|
|
2947
|
-
if ((!options || !
|
|
2947
|
+
if ((!options || !Object.hasOwn(options, 'session')) && asyncLocalStorage?.session != null) {
|
|
2948
2948
|
options = { ...options, session: asyncLocalStorage.session };
|
|
2949
2949
|
}
|
|
2950
2950
|
|
|
@@ -3248,12 +3248,14 @@ function _setIsNew(doc, val) {
|
|
|
3248
3248
|
* @param {Object} [ops.updateOne.update] An object containing [update operators](https://www.mongodb.com/docs/manual/reference/operator/update/)
|
|
3249
3249
|
* @param {Boolean} [ops.updateOne.upsert=false] If true, insert a doc if none match
|
|
3250
3250
|
* @param {Boolean} [ops.updateOne.timestamps=true] If false, do not apply [timestamps](https://mongoosejs.com/docs/guide.html#timestamps) to the operation
|
|
3251
|
+
* @param {Boolean} [ops.updateOne.overwriteImmutable=false] Mongoose removes updated immutable properties from `update` by default (excluding $setOnInsert). Set `overwriteImmutable` to `true` to allow updating immutable properties using other update operators.
|
|
3251
3252
|
* @param {Object} [ops.updateOne.collation] The [MongoDB collation](https://thecodebarbarian.com/a-nodejs-perspective-on-mongodb-34-collations) to use
|
|
3252
3253
|
* @param {Array} [ops.updateOne.arrayFilters] The [array filters](https://thecodebarbarian.com/a-nodejs-perspective-on-mongodb-36-array-filters.html) used in `update`
|
|
3253
3254
|
* @param {Object} [ops.updateMany.filter] Update all the documents that match this filter
|
|
3254
3255
|
* @param {Object} [ops.updateMany.update] An object containing [update operators](https://www.mongodb.com/docs/manual/reference/operator/update/)
|
|
3255
3256
|
* @param {Boolean} [ops.updateMany.upsert=false] If true, insert a doc if no documents match `filter`
|
|
3256
3257
|
* @param {Boolean} [ops.updateMany.timestamps=true] If false, do not apply [timestamps](https://mongoosejs.com/docs/guide.html#timestamps) to the operation
|
|
3258
|
+
* @param {Boolean} [ops.updateMany.overwriteImmutable=false] Mongoose removes updated immutable properties from `update` by default (excluding $setOnInsert). Set `overwriteImmutable` to `true` to allow updating immutable properties using other update operators.
|
|
3257
3259
|
* @param {Object} [ops.updateMany.collation] The [MongoDB collation](https://thecodebarbarian.com/a-nodejs-perspective-on-mongodb-34-collations) to use
|
|
3258
3260
|
* @param {Array} [ops.updateMany.arrayFilters] The [array filters](https://thecodebarbarian.com/a-nodejs-perspective-on-mongodb-36-array-filters.html) used in `update`
|
|
3259
3261
|
* @param {Object} [ops.deleteOne.filter] Delete the first document that matches this filter
|
|
@@ -3286,12 +3288,15 @@ Model.bulkWrite = async function bulkWrite(ops, options) {
|
|
|
3286
3288
|
}
|
|
3287
3289
|
options = options || {};
|
|
3288
3290
|
|
|
3289
|
-
|
|
3291
|
+
try {
|
|
3292
|
+
[ops, options] = await this.hooks.execPre('bulkWrite', this, [ops, options]);
|
|
3293
|
+
} catch (err) {
|
|
3290
3294
|
if (err instanceof Kareem.skipWrappedFunction) {
|
|
3291
|
-
|
|
3295
|
+
ops = err;
|
|
3296
|
+
} else {
|
|
3297
|
+
await this.hooks.execPost('bulkWrite', this, [null], { error: err });
|
|
3292
3298
|
}
|
|
3293
|
-
|
|
3294
|
-
});
|
|
3299
|
+
}
|
|
3295
3300
|
|
|
3296
3301
|
if (ops instanceof Kareem.skipWrappedFunction) {
|
|
3297
3302
|
return ops.args[0];
|
|
@@ -3309,7 +3314,7 @@ Model.bulkWrite = async function bulkWrite(ops, options) {
|
|
|
3309
3314
|
|
|
3310
3315
|
const validations = options?._skipCastBulkWrite ? [] : ops.map(op => castBulkWrite(this, op, options));
|
|
3311
3316
|
const asyncLocalStorage = this.db.base.transactionAsyncLocalStorage?.getStore();
|
|
3312
|
-
if ((!options || !
|
|
3317
|
+
if ((!options || !Object.hasOwn(options, 'session')) && asyncLocalStorage?.session != null) {
|
|
3313
3318
|
options = { ...options, session: asyncLocalStorage.session };
|
|
3314
3319
|
}
|
|
3315
3320
|
|
|
@@ -3517,6 +3522,7 @@ async function handleSuccessfulWrite(document) {
|
|
|
3517
3522
|
}
|
|
3518
3523
|
|
|
3519
3524
|
document.$__reset();
|
|
3525
|
+
document._applyVersionIncrement();
|
|
3520
3526
|
return document.schema.s.hooks.execPost('save', document, [document]);
|
|
3521
3527
|
}
|
|
3522
3528
|
|
|
@@ -4999,10 +5005,10 @@ Model._applyQueryMiddleware = function _applyQueryMiddleware() {
|
|
|
4999
5005
|
|
|
5000
5006
|
function _getContexts(hook) {
|
|
5001
5007
|
const ret = {};
|
|
5002
|
-
if (
|
|
5008
|
+
if (Object.hasOwn(hook, 'query')) {
|
|
5003
5009
|
ret.query = hook.query;
|
|
5004
5010
|
}
|
|
5005
|
-
if (
|
|
5011
|
+
if (Object.hasOwn(hook, 'document')) {
|
|
5006
5012
|
ret.document = hook.document;
|
|
5007
5013
|
}
|
|
5008
5014
|
return ret;
|
package/lib/mongoose.js
CHANGED
|
@@ -601,12 +601,11 @@ Mongoose.prototype.model = function model(name, schema, collection, options) {
|
|
|
601
601
|
|
|
602
602
|
// connection.model() may be passing a different schema for
|
|
603
603
|
// an existing model name. in this case don't read from cache.
|
|
604
|
-
const overwriteModels = _mongoose.options
|
|
604
|
+
const overwriteModels = Object.hasOwn(_mongoose.options, 'overwriteModels') ?
|
|
605
605
|
_mongoose.options.overwriteModels :
|
|
606
606
|
options.overwriteModels;
|
|
607
|
-
if (_mongoose.models
|
|
608
|
-
if (originalSchema &&
|
|
609
|
-
originalSchema.instanceOfSchema &&
|
|
607
|
+
if (Object.hasOwn(_mongoose.models, name) && options.cache !== false && overwriteModels !== true) {
|
|
608
|
+
if (originalSchema?.instanceOfSchema &&
|
|
610
609
|
originalSchema !== _mongoose.models[name].schema) {
|
|
611
610
|
throw new _mongoose.Error.OverwriteModelError(name);
|
|
612
611
|
}
|
package/lib/query.js
CHANGED
|
@@ -2100,7 +2100,7 @@ Query.prototype._optionsForExec = function(model) {
|
|
|
2100
2100
|
applyWriteConcern(model.schema, options);
|
|
2101
2101
|
|
|
2102
2102
|
const asyncLocalStorage = this.model?.db?.base.transactionAsyncLocalStorage?.getStore();
|
|
2103
|
-
if (!this.options
|
|
2103
|
+
if (!Object.hasOwn(this.options, 'session') && asyncLocalStorage?.session != null) {
|
|
2104
2104
|
options.session = asyncLocalStorage.session;
|
|
2105
2105
|
}
|
|
2106
2106
|
|
|
@@ -4595,7 +4595,7 @@ Query.prototype.exec = async function exec(op) {
|
|
|
4595
4595
|
throw new MongooseError('Query has invalid `op`: "' + this.op + '"');
|
|
4596
4596
|
}
|
|
4597
4597
|
|
|
4598
|
-
if (this.options && this.options.sort && typeof this.options.sort === 'object' && this.options.sort
|
|
4598
|
+
if (this.options && this.options.sort && typeof this.options.sort === 'object' && Object.hasOwn(this.options.sort, '')) {
|
|
4599
4599
|
throw new Error('Invalid field "" passed to sort()');
|
|
4600
4600
|
}
|
|
4601
4601
|
|
|
@@ -4995,7 +4995,7 @@ Query.prototype.cast = function(model, obj) {
|
|
|
4995
4995
|
model = model || this.model;
|
|
4996
4996
|
const discriminatorKey = model.schema.options.discriminatorKey;
|
|
4997
4997
|
if (obj != null &&
|
|
4998
|
-
|
|
4998
|
+
Object.hasOwn(obj, discriminatorKey)) {
|
|
4999
4999
|
model = getDiscriminatorByValue(model.discriminators, obj[discriminatorKey]) || model;
|
|
5000
5000
|
}
|
|
5001
5001
|
|
package/lib/schema/array.js
CHANGED
|
@@ -80,7 +80,7 @@ function SchemaArray(key, cast, options, schemaOptions, parentSchema) {
|
|
|
80
80
|
: utils.getFunctionName(cast);
|
|
81
81
|
|
|
82
82
|
const Types = require('./index.js');
|
|
83
|
-
const schemaTypeDefinition =
|
|
83
|
+
const schemaTypeDefinition = Object.hasOwn(Types, name) ? Types[name] : cast;
|
|
84
84
|
|
|
85
85
|
if (typeof schemaTypeDefinition === 'function') {
|
|
86
86
|
if (schemaTypeDefinition === SchemaArray) {
|
package/lib/schema/number.js
CHANGED
|
@@ -26,6 +26,7 @@ const CastError = SchemaType.CastError;
|
|
|
26
26
|
*/
|
|
27
27
|
|
|
28
28
|
function SchemaNumber(key, options, _schemaOptions, parentSchema) {
|
|
29
|
+
this.enumValues = [];
|
|
29
30
|
SchemaType.call(this, key, options, 'Number', parentSchema);
|
|
30
31
|
}
|
|
31
32
|
|
|
@@ -316,8 +317,12 @@ SchemaNumber.prototype.enum = function(values, message) {
|
|
|
316
317
|
this.validators = this.validators.filter(function(v) {
|
|
317
318
|
return v.validator !== this.enumValidator;
|
|
318
319
|
}, this);
|
|
320
|
+
this.enumValidator = false;
|
|
319
321
|
}
|
|
320
322
|
|
|
323
|
+
if (values === void 0 || values === false) {
|
|
324
|
+
return this;
|
|
325
|
+
}
|
|
321
326
|
|
|
322
327
|
if (!Array.isArray(values)) {
|
|
323
328
|
const isObjectSyntax = utils.isPOJO(values) && values.values != null;
|
|
@@ -337,12 +342,19 @@ SchemaNumber.prototype.enum = function(values, message) {
|
|
|
337
342
|
|
|
338
343
|
message = message == null ? MongooseError.messages.Number.enum : message;
|
|
339
344
|
|
|
340
|
-
|
|
345
|
+
for (const value of values) {
|
|
346
|
+
if (value !== undefined) {
|
|
347
|
+
this.enumValues.push(this.cast(value));
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
const vals = this.enumValues;
|
|
352
|
+
this.enumValidator = v => v == null || vals.indexOf(v) !== -1;
|
|
341
353
|
this.validators.push({
|
|
342
354
|
validator: this.enumValidator,
|
|
343
355
|
message: message,
|
|
344
356
|
type: 'enum',
|
|
345
|
-
enumValues:
|
|
357
|
+
enumValues: vals
|
|
346
358
|
});
|
|
347
359
|
|
|
348
360
|
return this;
|
|
@@ -28,7 +28,7 @@ module.exports = function castTextSearch(val, path) {
|
|
|
28
28
|
}
|
|
29
29
|
if (val.$caseSensitive != null) {
|
|
30
30
|
val.$caseSensitive = castBoolean(val.$caseSensitive,
|
|
31
|
-
path + '.$
|
|
31
|
+
path + '.$caseSensitive');
|
|
32
32
|
}
|
|
33
33
|
if (val.$diacriticSensitive != null) {
|
|
34
34
|
val.$diacriticSensitive = castBoolean(val.$diacriticSensitive,
|
package/lib/schema.js
CHANGED
|
@@ -1485,17 +1485,17 @@ Schema.prototype._gatherChildSchemas = function _gatherChildSchemas() {
|
|
|
1485
1485
|
*/
|
|
1486
1486
|
|
|
1487
1487
|
function _getPath(schema, path, cleanPath) {
|
|
1488
|
-
if (schema.paths
|
|
1488
|
+
if (Object.hasOwn(schema.paths, path)) {
|
|
1489
1489
|
return schema.paths[path];
|
|
1490
1490
|
}
|
|
1491
|
-
if (schema.subpaths
|
|
1491
|
+
if (Object.hasOwn(schema.subpaths, cleanPath)) {
|
|
1492
1492
|
const subpath = schema.subpaths[cleanPath];
|
|
1493
1493
|
if (subpath === 'nested') {
|
|
1494
1494
|
return undefined;
|
|
1495
1495
|
}
|
|
1496
1496
|
return subpath;
|
|
1497
1497
|
}
|
|
1498
|
-
if (schema.singleNestedPaths
|
|
1498
|
+
if (Object.hasOwn(schema.singleNestedPaths, cleanPath) && typeof schema.singleNestedPaths[cleanPath] === 'object') {
|
|
1499
1499
|
const singleNestedPath = schema.singleNestedPaths[cleanPath];
|
|
1500
1500
|
if (singleNestedPath === 'nested') {
|
|
1501
1501
|
return undefined;
|
|
@@ -1683,20 +1683,20 @@ Schema.prototype.interpretAsType = function(path, obj, options) {
|
|
|
1683
1683
|
childSchemaOptions.typeKey = options.typeKey;
|
|
1684
1684
|
}
|
|
1685
1685
|
// propagate 'strict' option to child schema
|
|
1686
|
-
if (
|
|
1686
|
+
if (Object.hasOwn(options, 'strict')) {
|
|
1687
1687
|
childSchemaOptions.strict = options.strict;
|
|
1688
1688
|
}
|
|
1689
|
-
if (
|
|
1689
|
+
if (Object.hasOwn(options, 'strictQuery')) {
|
|
1690
1690
|
childSchemaOptions.strictQuery = options.strictQuery;
|
|
1691
1691
|
}
|
|
1692
|
-
if (
|
|
1692
|
+
if (Object.hasOwn(options, 'toObject')) {
|
|
1693
1693
|
childSchemaOptions.toObject = utils.omit(options.toObject, ['transform']);
|
|
1694
1694
|
}
|
|
1695
|
-
if (
|
|
1695
|
+
if (Object.hasOwn(options, 'toJSON')) {
|
|
1696
1696
|
childSchemaOptions.toJSON = utils.omit(options.toJSON, ['transform']);
|
|
1697
1697
|
}
|
|
1698
1698
|
|
|
1699
|
-
if (this._userProvidedOptions
|
|
1699
|
+
if (Object.hasOwn(this._userProvidedOptions, '_id')) {
|
|
1700
1700
|
childSchemaOptions._id = this._userProvidedOptions._id;
|
|
1701
1701
|
} else if (Schema.Types.DocumentArray.defaultOptions._id != null) {
|
|
1702
1702
|
childSchemaOptions._id = Schema.Types.DocumentArray.defaultOptions._id;
|
|
@@ -1733,7 +1733,7 @@ Schema.prototype.interpretAsType = function(path, obj, options) {
|
|
|
1733
1733
|
`Could not determine the embedded type for array \`${path}\`. ` +
|
|
1734
1734
|
'See https://mongoosejs.com/docs/guide.html#definition for more info on supported schema syntaxes.');
|
|
1735
1735
|
}
|
|
1736
|
-
if (!
|
|
1736
|
+
if (!Object.hasOwn(MongooseTypes, name)) {
|
|
1737
1737
|
throw new TypeError('Invalid schema configuration: ' +
|
|
1738
1738
|
`\`${name}\` is not a valid type within the array \`${path}\`.` +
|
|
1739
1739
|
'See https://bit.ly/mongoose-schematypes for a list of valid schema types.');
|
|
@@ -1894,24 +1894,24 @@ Schema.prototype.indexedPaths = function indexedPaths() {
|
|
|
1894
1894
|
*/
|
|
1895
1895
|
|
|
1896
1896
|
Schema.prototype.pathType = function(path) {
|
|
1897
|
-
if (this.paths
|
|
1897
|
+
if (Object.hasOwn(this.paths, path)) {
|
|
1898
1898
|
return 'real';
|
|
1899
1899
|
}
|
|
1900
|
-
if (this.virtuals
|
|
1900
|
+
if (Object.hasOwn(this.virtuals, path)) {
|
|
1901
1901
|
return 'virtual';
|
|
1902
1902
|
}
|
|
1903
|
-
if (this.nested
|
|
1903
|
+
if (Object.hasOwn(this.nested, path)) {
|
|
1904
1904
|
return 'nested';
|
|
1905
1905
|
}
|
|
1906
1906
|
|
|
1907
1907
|
// Convert to '.$' to check subpaths re: gh-6405
|
|
1908
1908
|
const cleanPath = _pathToPositionalSyntax(path);
|
|
1909
1909
|
|
|
1910
|
-
if (this.subpaths
|
|
1910
|
+
if (Object.hasOwn(this.subpaths, cleanPath) || Object.hasOwn(this.subpaths, path)) {
|
|
1911
1911
|
return 'real';
|
|
1912
1912
|
}
|
|
1913
1913
|
|
|
1914
|
-
const singleNestedPath = this.singleNestedPaths
|
|
1914
|
+
const singleNestedPath = Object.hasOwn(this.singleNestedPaths, cleanPath) || Object.hasOwn(this.singleNestedPaths, path);
|
|
1915
1915
|
if (singleNestedPath) {
|
|
1916
1916
|
return singleNestedPath === 'nested' ? 'nested' : 'real';
|
|
1917
1917
|
}
|
|
@@ -1941,7 +1941,7 @@ Schema.prototype.hasMixedParent = function(path) {
|
|
|
1941
1941
|
path = '';
|
|
1942
1942
|
for (let i = 0; i < subpaths.length; ++i) {
|
|
1943
1943
|
path = i > 0 ? path + '.' + subpaths[i] : subpaths[i];
|
|
1944
|
-
if (this.paths
|
|
1944
|
+
if (Object.hasOwn(this.paths, path) &&
|
|
1945
1945
|
this.paths[path] instanceof MongooseTypes.Mixed) {
|
|
1946
1946
|
return this.paths[path];
|
|
1947
1947
|
}
|
|
@@ -1970,7 +1970,7 @@ Schema.prototype.setupTimestamp = function(timestamps) {
|
|
|
1970
1970
|
function getPositionalPathType(self, path, cleanPath) {
|
|
1971
1971
|
const subpaths = path.split(/\.(\d+)\.|\.(\d+)$/).filter(Boolean);
|
|
1972
1972
|
if (subpaths.length < 2) {
|
|
1973
|
-
return self.paths
|
|
1973
|
+
return Object.hasOwn(self.paths, subpaths[0]) ?
|
|
1974
1974
|
self.paths[subpaths[0]] :
|
|
1975
1975
|
'adhocOrUndefined';
|
|
1976
1976
|
}
|
|
@@ -2675,7 +2675,7 @@ Schema.prototype.virtual = function(name, options) {
|
|
|
2675
2675
|
*/
|
|
2676
2676
|
|
|
2677
2677
|
Schema.prototype.virtualpath = function(name) {
|
|
2678
|
-
return this.virtuals
|
|
2678
|
+
return Object.hasOwn(this.virtuals, name) ? this.virtuals[name] : null;
|
|
2679
2679
|
};
|
|
2680
2680
|
|
|
2681
2681
|
/**
|
|
@@ -2823,8 +2823,8 @@ Schema.prototype.loadClass = function(model, virtualsOnly) {
|
|
|
2823
2823
|
// Stop copying when hit certain base classes
|
|
2824
2824
|
if (model === Object.prototype ||
|
|
2825
2825
|
model === Function.prototype ||
|
|
2826
|
-
model.prototype
|
|
2827
|
-
model.prototype
|
|
2826
|
+
Object.hasOwn(model.prototype, '$isMongooseModelPrototype') ||
|
|
2827
|
+
Object.hasOwn(model.prototype, '$isMongooseDocumentPrototype')) {
|
|
2828
2828
|
return this;
|
|
2829
2829
|
}
|
|
2830
2830
|
|
|
@@ -2837,7 +2837,7 @@ Schema.prototype.loadClass = function(model, virtualsOnly) {
|
|
|
2837
2837
|
return;
|
|
2838
2838
|
}
|
|
2839
2839
|
const prop = Object.getOwnPropertyDescriptor(model, name);
|
|
2840
|
-
if (
|
|
2840
|
+
if (Object.hasOwn(prop, 'value')) {
|
|
2841
2841
|
this.static(name, prop.value);
|
|
2842
2842
|
}
|
|
2843
2843
|
}, this);
|
|
@@ -3063,7 +3063,7 @@ Schema.prototype._transformDuplicateKeyError = function _transformDuplicateKeyEr
|
|
|
3063
3063
|
return error;
|
|
3064
3064
|
}
|
|
3065
3065
|
const firstKey = keys[0];
|
|
3066
|
-
if (!this._duplicateKeyErrorMessagesByPath
|
|
3066
|
+
if (!Object.hasOwn(this._duplicateKeyErrorMessagesByPath, firstKey)) {
|
|
3067
3067
|
return error;
|
|
3068
3068
|
}
|
|
3069
3069
|
return new MongooseError(this._duplicateKeyErrorMessagesByPath[firstKey], { cause: error });
|
package/lib/schemaType.js
CHANGED
|
@@ -46,10 +46,10 @@ function SchemaType(path, options, instance, parentSchema) {
|
|
|
46
46
|
this.instance = instance;
|
|
47
47
|
this.schemaName = this.constructor.schemaName;
|
|
48
48
|
this.validators = [];
|
|
49
|
-
this.getters = this.constructor
|
|
49
|
+
this.getters = Object.hasOwn(this.constructor, 'getters') ?
|
|
50
50
|
this.constructor.getters.slice() :
|
|
51
51
|
[];
|
|
52
|
-
this.setters = this.constructor
|
|
52
|
+
this.setters = Object.hasOwn(this.constructor, 'setters') ?
|
|
53
53
|
this.constructor.setters.slice() :
|
|
54
54
|
[];
|
|
55
55
|
|
|
@@ -62,7 +62,7 @@ function SchemaType(path, options, instance, parentSchema) {
|
|
|
62
62
|
for (const option of defaultOptionsKeys) {
|
|
63
63
|
if (option === 'validate') {
|
|
64
64
|
this.validate(defaultOptions.validate);
|
|
65
|
-
} else if (
|
|
65
|
+
} else if (Object.hasOwn(defaultOptions, option) && !Object.hasOwn(options, option)) {
|
|
66
66
|
options[option] = defaultOptions[option];
|
|
67
67
|
}
|
|
68
68
|
}
|
|
@@ -339,7 +339,7 @@ SchemaType.prototype.cast = function cast() {
|
|
|
339
339
|
*/
|
|
340
340
|
|
|
341
341
|
SchemaType.set = function set(option, value) {
|
|
342
|
-
if (!
|
|
342
|
+
if (!Object.hasOwn(this, 'defaultOptions')) {
|
|
343
343
|
this.defaultOptions = Object.assign({}, this.defaultOptions);
|
|
344
344
|
}
|
|
345
345
|
this.defaultOptions[option] = value;
|
|
@@ -362,7 +362,7 @@ SchemaType.set = function set(option, value) {
|
|
|
362
362
|
*/
|
|
363
363
|
|
|
364
364
|
SchemaType.get = function(getter) {
|
|
365
|
-
this.getters =
|
|
365
|
+
this.getters = Object.hasOwn(this, 'getters') ? this.getters : [];
|
|
366
366
|
this.getters.push(getter);
|
|
367
367
|
};
|
|
368
368
|
|
|
@@ -496,7 +496,7 @@ SchemaType.prototype.unique = function unique(value, message) {
|
|
|
496
496
|
'false and `unique` set to true');
|
|
497
497
|
}
|
|
498
498
|
|
|
499
|
-
if (!this.options
|
|
499
|
+
if (!Object.hasOwn(this.options, 'index') && value === false) {
|
|
500
500
|
return this;
|
|
501
501
|
}
|
|
502
502
|
|
|
@@ -535,7 +535,7 @@ SchemaType.prototype.text = function(bool) {
|
|
|
535
535
|
'false and `text` set to true');
|
|
536
536
|
}
|
|
537
537
|
|
|
538
|
-
if (!this.options
|
|
538
|
+
if (!Object.hasOwn(this.options, 'index') && bool === false) {
|
|
539
539
|
return this;
|
|
540
540
|
}
|
|
541
541
|
|
|
@@ -572,7 +572,7 @@ SchemaType.prototype.sparse = function(bool) {
|
|
|
572
572
|
'false and `sparse` set to true');
|
|
573
573
|
}
|
|
574
574
|
|
|
575
|
-
if (!this.options
|
|
575
|
+
if (!Object.hasOwn(this.options, 'index') && bool === false) {
|
|
576
576
|
return this;
|
|
577
577
|
}
|
|
578
578
|
|
package/lib/types/array/index.js
CHANGED
|
@@ -79,13 +79,13 @@ function MongooseArray(values, path, doc, schematype) {
|
|
|
79
79
|
|
|
80
80
|
const proxy = new Proxy(__array, {
|
|
81
81
|
get: function(target, prop) {
|
|
82
|
-
if (
|
|
82
|
+
if (Object.hasOwn(internals, prop)) {
|
|
83
83
|
return internals[prop];
|
|
84
84
|
}
|
|
85
|
-
if (
|
|
85
|
+
if (Object.hasOwn(mongooseArrayMethods, prop)) {
|
|
86
86
|
return mongooseArrayMethods[prop];
|
|
87
87
|
}
|
|
88
|
-
if (schematype && schematype.virtuals && schematype.virtuals
|
|
88
|
+
if (schematype && schematype.virtuals && Object.hasOwn(schematype.virtuals, prop)) {
|
|
89
89
|
return schematype.virtuals[prop].applyGetters(undefined, target);
|
|
90
90
|
}
|
|
91
91
|
if (typeof prop === 'string' && numberRE.test(prop) && schematype?.embeddedSchemaType != null) {
|
|
@@ -97,9 +97,9 @@ function MongooseArray(values, path, doc, schematype) {
|
|
|
97
97
|
set: function(target, prop, value) {
|
|
98
98
|
if (typeof prop === 'string' && numberRE.test(prop)) {
|
|
99
99
|
mongooseArrayMethods.set.call(proxy, prop, value, false);
|
|
100
|
-
} else if (
|
|
100
|
+
} else if (Object.hasOwn(internals, prop)) {
|
|
101
101
|
internals[prop] = value;
|
|
102
|
-
} else if (schematype && schematype.virtuals
|
|
102
|
+
} else if (schematype?.virtuals && Object.hasOwn(schematype.virtuals, prop)) {
|
|
103
103
|
schematype.virtuals[prop].applySetters(value, target);
|
|
104
104
|
} else {
|
|
105
105
|
__array[prop] = value;
|
|
@@ -73,16 +73,16 @@ function MongooseDocumentArray(values, path, doc, schematype) {
|
|
|
73
73
|
prop === 'isMongooseDocumentArrayProxy') {
|
|
74
74
|
return true;
|
|
75
75
|
}
|
|
76
|
-
if (
|
|
76
|
+
if (Object.hasOwn(internals, prop)) {
|
|
77
77
|
return internals[prop];
|
|
78
78
|
}
|
|
79
|
-
if (
|
|
79
|
+
if (Object.hasOwn(DocumentArrayMethods, prop)) {
|
|
80
80
|
return DocumentArrayMethods[prop];
|
|
81
81
|
}
|
|
82
|
-
if (schematype && schematype.virtuals && schematype.virtuals
|
|
82
|
+
if (schematype && schematype.virtuals && Object.hasOwn(schematype.virtuals, prop)) {
|
|
83
83
|
return schematype.virtuals[prop].applyGetters(undefined, target);
|
|
84
84
|
}
|
|
85
|
-
if (
|
|
85
|
+
if (Object.hasOwn(ArrayMethods, prop)) {
|
|
86
86
|
return ArrayMethods[prop];
|
|
87
87
|
}
|
|
88
88
|
|
|
@@ -91,9 +91,9 @@ function MongooseDocumentArray(values, path, doc, schematype) {
|
|
|
91
91
|
set: function(target, prop, value) {
|
|
92
92
|
if (typeof prop === 'string' && numberRE.test(prop)) {
|
|
93
93
|
DocumentArrayMethods.set.call(proxy, prop, value, false);
|
|
94
|
-
} else if (
|
|
94
|
+
} else if (Object.hasOwn(internals, prop)) {
|
|
95
95
|
internals[prop] = value;
|
|
96
|
-
} else if (schematype && schematype.virtuals
|
|
96
|
+
} else if (schematype?.virtuals && Object.hasOwn(schematype.virtuals, prop)) {
|
|
97
97
|
schematype.virtuals[prop].applySetters(value, target);
|
|
98
98
|
} else {
|
|
99
99
|
__array[prop] = value;
|