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
package/lib/aggregate.js
CHANGED
|
@@ -103,7 +103,7 @@ Aggregate.prototype._optionsForExec = function() {
|
|
|
103
103
|
const options = this.options || {};
|
|
104
104
|
|
|
105
105
|
const asyncLocalStorage = this.model()?.db?.base.transactionAsyncLocalStorage?.getStore();
|
|
106
|
-
if (!
|
|
106
|
+
if (!Object.hasOwn(options, 'session') && asyncLocalStorage?.session != null) {
|
|
107
107
|
options.session = asyncLocalStorage.session;
|
|
108
108
|
}
|
|
109
109
|
|
package/lib/cast/double.js
CHANGED
|
@@ -34,7 +34,7 @@ module.exports = function castDouble(val) {
|
|
|
34
34
|
// ex: { a: 'im an object, valueOf: () => 'helloworld' } // throw an error
|
|
35
35
|
if (typeof tempVal === 'string') {
|
|
36
36
|
try {
|
|
37
|
-
coercedVal = BSON.Double.fromString(
|
|
37
|
+
coercedVal = BSON.Double.fromString(tempVal);
|
|
38
38
|
return coercedVal;
|
|
39
39
|
} catch {
|
|
40
40
|
assert.ok(false);
|
package/lib/cast.js
CHANGED
|
@@ -107,7 +107,7 @@ module.exports = function cast(schema, obj, options, context) {
|
|
|
107
107
|
val = cast(schema, val, options, context);
|
|
108
108
|
} else if (path === '$text') {
|
|
109
109
|
val = castTextSearch(val, path);
|
|
110
|
-
} else if (path === '$comment' && !schema.paths
|
|
110
|
+
} else if (path === '$comment' && !Object.hasOwn(schema.paths, '$comment')) {
|
|
111
111
|
val = castString(val, path);
|
|
112
112
|
obj[path] = val;
|
|
113
113
|
} else {
|
package/lib/connection.js
CHANGED
|
@@ -164,7 +164,7 @@ Object.defineProperty(Connection.prototype, 'readyState', {
|
|
|
164
164
|
*/
|
|
165
165
|
|
|
166
166
|
Connection.prototype.get = function getOption(key) {
|
|
167
|
-
if (this.config
|
|
167
|
+
if (Object.hasOwn(this.config, key)) {
|
|
168
168
|
return this.config[key];
|
|
169
169
|
}
|
|
170
170
|
|
|
@@ -192,7 +192,7 @@ Connection.prototype.get = function getOption(key) {
|
|
|
192
192
|
*/
|
|
193
193
|
|
|
194
194
|
Connection.prototype.set = function setOption(key, val) {
|
|
195
|
-
if (this.config
|
|
195
|
+
if (Object.hasOwn(this.config, key)) {
|
|
196
196
|
this.config[key] = val;
|
|
197
197
|
return val;
|
|
198
198
|
}
|
|
@@ -459,7 +459,7 @@ Connection.prototype.bulkWrite = async function bulkWrite(ops, options) {
|
|
|
459
459
|
|
|
460
460
|
const ordered = options.ordered == null ? true : options.ordered;
|
|
461
461
|
const asyncLocalStorage = this.base.transactionAsyncLocalStorage?.getStore();
|
|
462
|
-
if ((!options || !
|
|
462
|
+
if ((!options || !Object.hasOwn(options, 'session')) && asyncLocalStorage?.session != null) {
|
|
463
463
|
options = { ...options, session: asyncLocalStorage.session };
|
|
464
464
|
}
|
|
465
465
|
|
|
@@ -477,7 +477,7 @@ Connection.prototype.bulkWrite = async function bulkWrite(ops, options) {
|
|
|
477
477
|
if (op.name == null) {
|
|
478
478
|
throw new MongooseError('Must specify operation name in Connection.prototype.bulkWrite()');
|
|
479
479
|
}
|
|
480
|
-
if (!castBulkWrite.cast
|
|
480
|
+
if (!Object.hasOwn(castBulkWrite.cast, op.name)) {
|
|
481
481
|
throw new MongooseError(`Unrecognized bulkWrite() operation name ${op.name}`);
|
|
482
482
|
}
|
|
483
483
|
|
|
@@ -513,7 +513,7 @@ Connection.prototype.bulkWrite = async function bulkWrite(ops, options) {
|
|
|
513
513
|
results[i] = error;
|
|
514
514
|
continue;
|
|
515
515
|
}
|
|
516
|
-
if (!castBulkWrite.cast
|
|
516
|
+
if (!Object.hasOwn(castBulkWrite.cast, op.name)) {
|
|
517
517
|
const error = new MongooseError(`Unrecognized bulkWrite() operation name ${op.name}`);
|
|
518
518
|
validationErrors.push({ index: i, error: error });
|
|
519
519
|
results[i] = error;
|
|
@@ -772,10 +772,10 @@ async function _wrapUserTransaction(fn, session, mongoose) {
|
|
|
772
772
|
function _resetSessionDocuments(session) {
|
|
773
773
|
for (const doc of session[sessionNewDocuments].keys()) {
|
|
774
774
|
const state = session[sessionNewDocuments].get(doc);
|
|
775
|
-
if (
|
|
775
|
+
if (Object.hasOwn(state, 'isNew')) {
|
|
776
776
|
doc.$isNew = state.isNew;
|
|
777
777
|
}
|
|
778
|
-
if (
|
|
778
|
+
if (Object.hasOwn(state, 'versionKey')) {
|
|
779
779
|
doc.set(doc.schema.options.versionKey, state.versionKey);
|
|
780
780
|
}
|
|
781
781
|
|
|
@@ -1013,7 +1013,7 @@ Connection.prototype.onOpen = function() {
|
|
|
1013
1013
|
// avoid having the collection subscribe to our event emitter
|
|
1014
1014
|
// to prevent 0.3 warning
|
|
1015
1015
|
for (const i in this.collections) {
|
|
1016
|
-
if (
|
|
1016
|
+
if (Object.hasOwn(this.collections, i)) {
|
|
1017
1017
|
this.collections[i].onOpen();
|
|
1018
1018
|
}
|
|
1019
1019
|
}
|
|
@@ -1321,7 +1321,7 @@ Connection.prototype.onClose = function onClose(force) {
|
|
|
1321
1321
|
// avoid having the collection subscribe to our event emitter
|
|
1322
1322
|
// to prevent 0.3 warning
|
|
1323
1323
|
for (const i in this.collections) {
|
|
1324
|
-
if (
|
|
1324
|
+
if (Object.hasOwn(this.collections, i)) {
|
|
1325
1325
|
this.collections[i].onClose(force);
|
|
1326
1326
|
}
|
|
1327
1327
|
}
|
|
@@ -1782,7 +1782,7 @@ Connection.prototype.syncIndexes = async function syncIndexes(options = {}) {
|
|
|
1782
1782
|
};
|
|
1783
1783
|
|
|
1784
1784
|
/**
|
|
1785
|
-
* Switches to a different database using the same [connection pool](https://mongoosejs.com/docs/
|
|
1785
|
+
* Switches to a different database using the same [connection pool](https://mongoosejs.com/docs/connections.html#connection_pools).
|
|
1786
1786
|
*
|
|
1787
1787
|
* Returns a new connection object, with the new db.
|
|
1788
1788
|
*
|
package/lib/document.js
CHANGED
|
@@ -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
|
|
|
@@ -784,7 +791,7 @@ function init(self, obj, doc, opts, prefix) {
|
|
|
784
791
|
}
|
|
785
792
|
} else {
|
|
786
793
|
// Retain order when overwriting defaults
|
|
787
|
-
if (
|
|
794
|
+
if (Object.hasOwn(doc, i) && value !== void 0 && !opts.hydratedPopulatedDocs) {
|
|
788
795
|
delete doc[i];
|
|
789
796
|
}
|
|
790
797
|
if (value === null) {
|
|
@@ -1167,7 +1174,7 @@ Document.prototype.$set = function $set(path, val, type, options) {
|
|
|
1167
1174
|
const orderedKeys = Object.keys(this.$__schema.tree);
|
|
1168
1175
|
for (let i = 0, len = orderedKeys.length; i < len; ++i) {
|
|
1169
1176
|
(key = orderedKeys[i]) &&
|
|
1170
|
-
(this._doc
|
|
1177
|
+
(Object.hasOwn(this._doc, key)) &&
|
|
1171
1178
|
(orderedDoc[key] = undefined);
|
|
1172
1179
|
}
|
|
1173
1180
|
this._doc = Object.assign(orderedDoc, this._doc);
|
|
@@ -1217,8 +1224,8 @@ Document.prototype.$set = function $set(path, val, type, options) {
|
|
|
1217
1224
|
return this;
|
|
1218
1225
|
}
|
|
1219
1226
|
const wasModified = this.$isModified(path);
|
|
1220
|
-
const hasInitialVal = this.$__.savedState != null && this.$__.savedState
|
|
1221
|
-
if (this.$__.savedState != null && !this.$isNew && !this.$__.savedState
|
|
1227
|
+
const hasInitialVal = this.$__.savedState != null && Object.hasOwn(this.$__.savedState, path);
|
|
1228
|
+
if (this.$__.savedState != null && !this.$isNew && !Object.hasOwn(this.$__.savedState, path)) {
|
|
1222
1229
|
const initialVal = this.$__getValue(path);
|
|
1223
1230
|
this.$__.savedState[path] = initialVal;
|
|
1224
1231
|
|
|
@@ -1523,7 +1530,7 @@ Document.prototype.$set = function $set(path, val, type, options) {
|
|
|
1523
1530
|
this.$__.session[sessionNewDocuments].get(this).modifiedPaths &&
|
|
1524
1531
|
!this.$__.session[sessionNewDocuments].get(this).modifiedPaths.has(savedStatePath);
|
|
1525
1532
|
if (savedState != null &&
|
|
1526
|
-
|
|
1533
|
+
Object.hasOwn(savedState, savedStatePath) &&
|
|
1527
1534
|
(!isInTransaction || isModifiedWithinTransaction) &&
|
|
1528
1535
|
utils.deepEqual(val, savedState[savedStatePath])) {
|
|
1529
1536
|
this.unmarkModified(path);
|
|
@@ -2005,7 +2012,7 @@ Document.prototype.$get = Document.prototype.get;
|
|
|
2005
2012
|
|
|
2006
2013
|
Document.prototype.$__path = function(path) {
|
|
2007
2014
|
const adhocs = this.$__.adhocPaths;
|
|
2008
|
-
const adhocType = adhocs &&
|
|
2015
|
+
const adhocType = adhocs && Object.hasOwn(adhocs, path) ? adhocs[path] : null;
|
|
2009
2016
|
|
|
2010
2017
|
if (adhocType) {
|
|
2011
2018
|
return adhocType;
|
|
@@ -2049,7 +2056,7 @@ Document.prototype.$__saveInitialState = function $__saveInitialState(path) {
|
|
|
2049
2056
|
if (savedState != null) {
|
|
2050
2057
|
const firstDot = savedStatePath.indexOf('.');
|
|
2051
2058
|
const topLevelPath = firstDot === -1 ? savedStatePath : savedStatePath.slice(0, firstDot);
|
|
2052
|
-
if (!
|
|
2059
|
+
if (!Object.hasOwn(savedState, topLevelPath)) {
|
|
2053
2060
|
savedState[topLevelPath] = clone(this.$__getValue(topLevelPath));
|
|
2054
2061
|
}
|
|
2055
2062
|
}
|
|
@@ -2360,7 +2367,7 @@ Document.prototype.$isDefault = function(path) {
|
|
|
2360
2367
|
}
|
|
2361
2368
|
|
|
2362
2369
|
if (typeof path === 'string' && path.indexOf(' ') === -1) {
|
|
2363
|
-
return this.$__.activePaths.getStatePaths('default')
|
|
2370
|
+
return Object.hasOwn(this.$__.activePaths.getStatePaths('default'), path);
|
|
2364
2371
|
}
|
|
2365
2372
|
|
|
2366
2373
|
let paths = path;
|
|
@@ -2368,7 +2375,7 @@ Document.prototype.$isDefault = function(path) {
|
|
|
2368
2375
|
paths = paths.split(' ');
|
|
2369
2376
|
}
|
|
2370
2377
|
|
|
2371
|
-
return paths.some(path => this.$__.activePaths.getStatePaths('default')
|
|
2378
|
+
return paths.some(path => Object.hasOwn(this.$__.activePaths.getStatePaths('default'), path));
|
|
2372
2379
|
};
|
|
2373
2380
|
|
|
2374
2381
|
/**
|
|
@@ -2422,7 +2429,7 @@ Document.prototype.isDirectModified = function(path) {
|
|
|
2422
2429
|
}
|
|
2423
2430
|
|
|
2424
2431
|
if (typeof path === 'string' && path.indexOf(' ') === -1) {
|
|
2425
|
-
const res = this.$__.activePaths.getStatePaths('modify')
|
|
2432
|
+
const res = Object.hasOwn(this.$__.activePaths.getStatePaths('modify'), path);
|
|
2426
2433
|
if (res || path.indexOf('.') === -1) {
|
|
2427
2434
|
return res;
|
|
2428
2435
|
}
|
|
@@ -2461,7 +2468,7 @@ Document.prototype.isInit = function(path) {
|
|
|
2461
2468
|
}
|
|
2462
2469
|
|
|
2463
2470
|
if (typeof path === 'string' && path.indexOf(' ') === -1) {
|
|
2464
|
-
return this.$__.activePaths.getStatePaths('init')
|
|
2471
|
+
return Object.hasOwn(this.$__.activePaths.getStatePaths('init'), path);
|
|
2465
2472
|
}
|
|
2466
2473
|
|
|
2467
2474
|
let paths = path;
|
|
@@ -2469,7 +2476,7 @@ Document.prototype.isInit = function(path) {
|
|
|
2469
2476
|
paths = paths.split(' ');
|
|
2470
2477
|
}
|
|
2471
2478
|
|
|
2472
|
-
return paths.some(path => this.$__.activePaths.getStatePaths('init')
|
|
2479
|
+
return paths.some(path => Object.hasOwn(this.$__.activePaths.getStatePaths('init'), path));
|
|
2473
2480
|
};
|
|
2474
2481
|
|
|
2475
2482
|
/**
|
|
@@ -2607,7 +2614,7 @@ Document.prototype.isDirectSelected = function isDirectSelected(path) {
|
|
|
2607
2614
|
return true;
|
|
2608
2615
|
}
|
|
2609
2616
|
|
|
2610
|
-
if (this.$__.selected
|
|
2617
|
+
if (Object.hasOwn(this.$__.selected, path)) {
|
|
2611
2618
|
return inclusive;
|
|
2612
2619
|
}
|
|
2613
2620
|
|
|
@@ -2779,7 +2786,7 @@ function _getPathsToValidate(doc, pathsToValidate, pathsToSkip, isNestedValidate
|
|
|
2779
2786
|
if (doc.$isModified(fullPathToSubdoc, null, modifiedPaths) &&
|
|
2780
2787
|
// Avoid using isDirectModified() here because that does additional checks on whether the parent path
|
|
2781
2788
|
// is direct modified, which can cause performance issues re: gh-14897
|
|
2782
|
-
!subdocParent.$__.activePaths.getStatePaths('modify')
|
|
2789
|
+
!Object.hasOwn(subdocParent.$__.activePaths.getStatePaths('modify'), fullPathToSubdoc) &&
|
|
2783
2790
|
!subdocParent.$isDefault(fullPathToSubdoc)) {
|
|
2784
2791
|
paths.add(fullPathToSubdoc);
|
|
2785
2792
|
|
|
@@ -2850,7 +2857,12 @@ function _getPathsToValidate(doc, pathsToValidate, pathsToSkip, isNestedValidate
|
|
|
2850
2857
|
// Single nested paths (paths embedded under single nested subdocs) will
|
|
2851
2858
|
// be validated on their own when we call `validate()` on the subdoc itself.
|
|
2852
2859
|
// Re: gh-8468
|
|
2853
|
-
|
|
2860
|
+
const singleNestedPaths = doc.$__schema.singleNestedPaths;
|
|
2861
|
+
for (const path of Object.keys(flat)) {
|
|
2862
|
+
if (!Object.hasOwn(singleNestedPaths, path)) {
|
|
2863
|
+
addToPaths(path);
|
|
2864
|
+
}
|
|
2865
|
+
}
|
|
2854
2866
|
}
|
|
2855
2867
|
}
|
|
2856
2868
|
|
|
@@ -4188,7 +4200,7 @@ function applyVirtuals(self, json, options, toObjectOptions) {
|
|
|
4188
4200
|
}
|
|
4189
4201
|
|
|
4190
4202
|
// Allow skipping aliases with `toObject({ virtuals: true, aliases: false })`
|
|
4191
|
-
if (!aliases && schema.aliases
|
|
4203
|
+
if (!aliases && Object.hasOwn(schema.aliases, path)) {
|
|
4192
4204
|
continue;
|
|
4193
4205
|
}
|
|
4194
4206
|
|
|
@@ -5101,7 +5113,7 @@ function checkDivergentArray(doc, path, array) {
|
|
|
5101
5113
|
// would be similarly destructive as we never received all
|
|
5102
5114
|
// elements of the array and potentially would overwrite data.
|
|
5103
5115
|
const check = pop.options.match ||
|
|
5104
|
-
pop.options.options &&
|
|
5116
|
+
pop.options.options && Object.hasOwn(pop.options.options, 'limit') || // 0 is not permitted
|
|
5105
5117
|
pop.options.options && pop.options.options.skip || // 0 is permitted
|
|
5106
5118
|
pop.options.select && // deselected _id?
|
|
5107
5119
|
(pop.options.select._id === 0 ||
|
|
@@ -5169,7 +5181,7 @@ function operand(self, where, delta, data, val, op) {
|
|
|
5169
5181
|
if (/\.\d+\.|\.\d+$/.test(data.path)) {
|
|
5170
5182
|
self.$__.version = VERSION_ALL;
|
|
5171
5183
|
} else {
|
|
5172
|
-
self.$__.version
|
|
5184
|
+
self.$__.version |= VERSION_INC;
|
|
5173
5185
|
}
|
|
5174
5186
|
} else if (/^\$p/.test(op)) {
|
|
5175
5187
|
// potentially changing array positions
|
|
@@ -5180,7 +5192,7 @@ function operand(self, where, delta, data, val, op) {
|
|
|
5180
5192
|
} else if (/\.\d+\.|\.\d+$/.test(data.path)) {
|
|
5181
5193
|
// now handling $set, $unset
|
|
5182
5194
|
// subpath of array
|
|
5183
|
-
self.$__.version
|
|
5195
|
+
self.$__.version |= VERSION_WHERE;
|
|
5184
5196
|
}
|
|
5185
5197
|
}
|
|
5186
5198
|
|
|
@@ -5426,6 +5438,38 @@ Document.prototype.$__hasOnlyPrimitiveValues = function $__hasOnlyPrimitiveValue
|
|
|
5426
5438
|
}));
|
|
5427
5439
|
};
|
|
5428
5440
|
|
|
5441
|
+
/*!
|
|
5442
|
+
* Increment this document's version if necessary.
|
|
5443
|
+
*/
|
|
5444
|
+
|
|
5445
|
+
Document.prototype._applyVersionIncrement = function _applyVersionIncrement() {
|
|
5446
|
+
if (!this.$__.version) return;
|
|
5447
|
+
const doIncrement = VERSION_INC === (VERSION_INC & this.$__.version);
|
|
5448
|
+
|
|
5449
|
+
this.$__.version = undefined;
|
|
5450
|
+
if (doIncrement) {
|
|
5451
|
+
const key = this.$__schema.options.versionKey;
|
|
5452
|
+
const version = this.$__getValue(key) || 0;
|
|
5453
|
+
this.$__setValue(key, version + 1); // increment version if was successful
|
|
5454
|
+
}
|
|
5455
|
+
};
|
|
5456
|
+
|
|
5457
|
+
/*!
|
|
5458
|
+
* Increment this document's version if necessary.
|
|
5459
|
+
*/
|
|
5460
|
+
|
|
5461
|
+
Document.prototype._applyVersionIncrement = function _applyVersionIncrement() {
|
|
5462
|
+
if (!this.$__.version) return;
|
|
5463
|
+
const doIncrement = VERSION_INC === (VERSION_INC & this.$__.version);
|
|
5464
|
+
|
|
5465
|
+
this.$__.version = undefined;
|
|
5466
|
+
if (doIncrement) {
|
|
5467
|
+
const key = this.$__schema.options.versionKey;
|
|
5468
|
+
const version = this.$__getValue(key) || 0;
|
|
5469
|
+
this.$__setValue(key, version + 1); // increment version if was successful
|
|
5470
|
+
}
|
|
5471
|
+
};
|
|
5472
|
+
|
|
5429
5473
|
/*!
|
|
5430
5474
|
* Module exports.
|
|
5431
5475
|
*/
|
|
@@ -80,12 +80,6 @@ NativeCollection.prototype._getCollection = function _getCollection() {
|
|
|
80
80
|
return null;
|
|
81
81
|
};
|
|
82
82
|
|
|
83
|
-
/*!
|
|
84
|
-
* ignore
|
|
85
|
-
*/
|
|
86
|
-
|
|
87
|
-
const syncCollectionMethods = { watch: true, find: true, aggregate: true };
|
|
88
|
-
|
|
89
83
|
/**
|
|
90
84
|
* Copy the collection methods and make them subject to queues
|
|
91
85
|
* @param {Number|String} I
|
|
@@ -107,7 +101,6 @@ function iter(i) {
|
|
|
107
101
|
_this.conn.options &&
|
|
108
102
|
_this.conn.options.debug;
|
|
109
103
|
const debug = connectionDebug == null ? globalDebug : connectionDebug;
|
|
110
|
-
const lastArg = arguments[arguments.length - 1];
|
|
111
104
|
const opId = new ObjectId();
|
|
112
105
|
|
|
113
106
|
// If user force closed, queueing will hang forever. See #5664
|
|
@@ -122,8 +115,8 @@ function iter(i) {
|
|
|
122
115
|
}
|
|
123
116
|
}
|
|
124
117
|
|
|
125
|
-
let
|
|
126
|
-
let
|
|
118
|
+
let timeout = null;
|
|
119
|
+
let waitForBufferPromise = null;
|
|
127
120
|
if (this._shouldBufferCommands() && this.buffer) {
|
|
128
121
|
this.conn.emit('buffer', {
|
|
129
122
|
_id: opId,
|
|
@@ -133,79 +126,28 @@ function iter(i) {
|
|
|
133
126
|
args: args
|
|
134
127
|
});
|
|
135
128
|
|
|
136
|
-
let callback;
|
|
137
|
-
let _args = args;
|
|
138
|
-
let promise = null;
|
|
139
|
-
let timeout = null;
|
|
140
|
-
if (syncCollectionMethods[i] && typeof lastArg === 'function') {
|
|
141
|
-
this.addQueue(i, _args);
|
|
142
|
-
callback = lastArg;
|
|
143
|
-
} else if (syncCollectionMethods[i]) {
|
|
144
|
-
promise = new this.Promise((resolve, reject) => {
|
|
145
|
-
callback = function collectionOperationCallback(err, res) {
|
|
146
|
-
if (timeout != null) {
|
|
147
|
-
clearTimeout(timeout);
|
|
148
|
-
}
|
|
149
|
-
if (err != null) {
|
|
150
|
-
return reject(err);
|
|
151
|
-
}
|
|
152
|
-
resolve(res);
|
|
153
|
-
};
|
|
154
|
-
_args = args.concat([callback]);
|
|
155
|
-
this.addQueue(i, _args);
|
|
156
|
-
});
|
|
157
|
-
} else if (typeof lastArg === 'function') {
|
|
158
|
-
callback = function collectionOperationCallback() {
|
|
159
|
-
if (timeout != null) {
|
|
160
|
-
clearTimeout(timeout);
|
|
161
|
-
}
|
|
162
|
-
return lastArg.apply(this, arguments);
|
|
163
|
-
};
|
|
164
|
-
_args = args.slice(0, args.length - 1).concat([callback]);
|
|
165
|
-
} else {
|
|
166
|
-
promise = new Promise((resolve, reject) => {
|
|
167
|
-
callback = function collectionOperationCallback(err, res) {
|
|
168
|
-
if (timeout != null) {
|
|
169
|
-
clearTimeout(timeout);
|
|
170
|
-
}
|
|
171
|
-
if (err != null) {
|
|
172
|
-
return reject(err);
|
|
173
|
-
}
|
|
174
|
-
resolve(res);
|
|
175
|
-
};
|
|
176
|
-
_args = args.concat([callback]);
|
|
177
|
-
this.addQueue(i, _args);
|
|
178
|
-
});
|
|
179
|
-
}
|
|
180
|
-
|
|
181
129
|
const bufferTimeoutMS = this._getBufferTimeoutMS();
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
}
|
|
130
|
+
waitForBufferPromise = new Promise((resolve, reject) => {
|
|
131
|
+
this.addQueue(resolve);
|
|
132
|
+
|
|
133
|
+
timeout = setTimeout(() => {
|
|
134
|
+
const removed = this.removeQueue(resolve);
|
|
135
|
+
if (removed) {
|
|
136
|
+
const message = 'Operation `' + this.name + '.' + i + '()` buffering timed out after ' +
|
|
137
|
+
bufferTimeoutMS + 'ms';
|
|
138
|
+
const err = new MongooseError(message);
|
|
139
|
+
this.conn.emit('buffer-end', { _id: opId, modelName: _this.modelName, collectionName: _this.name, method: i, error: err });
|
|
140
|
+
reject(err);
|
|
141
|
+
}
|
|
142
|
+
}, bufferTimeoutMS);
|
|
143
|
+
});
|
|
197
144
|
|
|
198
|
-
return
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
if (err != null) {
|
|
202
|
-
_this.conn.emit('operation-end', { _id: opId, modelName: _this.modelName, collectionName: _this.name, method: i, error: err });
|
|
203
|
-
} else {
|
|
204
|
-
_this.conn.emit('operation-end', { _id: opId, modelName: _this.modelName, collectionName: _this.name, method: i, result: res });
|
|
145
|
+
return waitForBufferPromise.then(() => {
|
|
146
|
+
if (timeout) {
|
|
147
|
+
clearTimeout(timeout);
|
|
205
148
|
}
|
|
206
|
-
return
|
|
207
|
-
};
|
|
208
|
-
_args = args.slice(0, args.length - 1).concat([callback]);
|
|
149
|
+
return this[i].apply(this, args);
|
|
150
|
+
});
|
|
209
151
|
}
|
|
210
152
|
|
|
211
153
|
if (debug) {
|
|
@@ -227,7 +169,7 @@ function iter(i) {
|
|
|
227
169
|
}
|
|
228
170
|
}
|
|
229
171
|
|
|
230
|
-
this.conn.emit('operation-start', { _id: opId, modelName: _this.modelName, collectionName: this.name, method: i, params:
|
|
172
|
+
this.conn.emit('operation-start', { _id: opId, modelName: _this.modelName, collectionName: this.name, method: i, params: args });
|
|
231
173
|
|
|
232
174
|
try {
|
|
233
175
|
if (collection == null) {
|
|
@@ -237,45 +179,37 @@ function iter(i) {
|
|
|
237
179
|
throw new MongooseError(message);
|
|
238
180
|
}
|
|
239
181
|
|
|
240
|
-
|
|
241
|
-
const result = collection[i].apply(collection, _args.slice(0, _args.length - 1));
|
|
242
|
-
this.conn.emit('operation-end', { _id: opId, modelName: _this.modelName, collectionName: this.name, method: i, result });
|
|
243
|
-
return lastArg.call(this, null, result);
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
const ret = collection[i].apply(collection, _args);
|
|
182
|
+
const ret = collection[i].apply(collection, args);
|
|
247
183
|
if (ret != null && typeof ret.then === 'function') {
|
|
248
184
|
return ret.then(
|
|
249
185
|
result => {
|
|
250
|
-
if (
|
|
251
|
-
|
|
252
|
-
} else {
|
|
253
|
-
this.conn.emit('operation-end', { _id: opId, modelName: _this.modelName, collectionName: this.name, method: i, result });
|
|
186
|
+
if (timeout != null) {
|
|
187
|
+
clearTimeout(timeout);
|
|
254
188
|
}
|
|
189
|
+
this.conn.emit('operation-end', { _id: opId, modelName: _this.modelName, collectionName: this.name, method: i, result });
|
|
255
190
|
return result;
|
|
256
191
|
},
|
|
257
192
|
error => {
|
|
258
|
-
if (
|
|
259
|
-
|
|
260
|
-
return;
|
|
261
|
-
} else {
|
|
262
|
-
this.conn.emit('operation-end', { _id: opId, modelName: _this.modelName, collectionName: this.name, method: i, error });
|
|
193
|
+
if (timeout != null) {
|
|
194
|
+
clearTimeout(timeout);
|
|
263
195
|
}
|
|
196
|
+
this.conn.emit('operation-end', { _id: opId, modelName: _this.modelName, collectionName: this.name, method: i, error });
|
|
264
197
|
throw error;
|
|
265
198
|
}
|
|
266
199
|
);
|
|
267
200
|
}
|
|
201
|
+
|
|
202
|
+
this.conn.emit('operation-end', { _id: opId, modelName: _this.modelName, collectionName: this.name, method: i, result: ret });
|
|
203
|
+
if (timeout != null) {
|
|
204
|
+
clearTimeout(timeout);
|
|
205
|
+
}
|
|
268
206
|
return ret;
|
|
269
207
|
} catch (error) {
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
if (typeof lastArg === 'function') {
|
|
273
|
-
return lastArg(error);
|
|
274
|
-
} else {
|
|
275
|
-
this.conn.emit('operation-end', { _id: opId, modelName: _this.modelName, collectionName: this.name, method: i, error: error });
|
|
276
|
-
|
|
277
|
-
throw error;
|
|
208
|
+
if (timeout != null) {
|
|
209
|
+
clearTimeout(timeout);
|
|
278
210
|
}
|
|
211
|
+
this.conn.emit('operation-end', { _id: opId, modelName: _this.modelName, collectionName: this.name, method: i, error: error });
|
|
212
|
+
throw error;
|
|
279
213
|
}
|
|
280
214
|
};
|
|
281
215
|
}
|
|
@@ -508,7 +508,7 @@ function _setClient(conn, client, options, dbName) {
|
|
|
508
508
|
conn.onOpen();
|
|
509
509
|
|
|
510
510
|
for (const i in conn.collections) {
|
|
511
|
-
if (
|
|
511
|
+
if (Object.hasOwn(conn.collections, i)) {
|
|
512
512
|
conn.collections[i].onOpen();
|
|
513
513
|
}
|
|
514
514
|
}
|
package/lib/helpers/common.js
CHANGED
|
@@ -55,7 +55,7 @@ function flatten(update, path, options, schema) {
|
|
|
55
55
|
if (isNested) {
|
|
56
56
|
const paths = Object.keys(schema.paths);
|
|
57
57
|
for (const p of paths) {
|
|
58
|
-
if (p.startsWith(path + key + '.') && !
|
|
58
|
+
if (p.startsWith(path + key + '.') && !Object.hasOwn(result, p)) {
|
|
59
59
|
result[p] = void 0;
|
|
60
60
|
}
|
|
61
61
|
}
|
|
@@ -7,7 +7,7 @@ module.exports = function applySchemaCollation(indexKeys, indexOptions, schemaOp
|
|
|
7
7
|
return;
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
if (
|
|
10
|
+
if (Object.hasOwn(schemaOptions, 'collation') && !Object.hasOwn(indexOptions, 'collation')) {
|
|
11
11
|
indexOptions.collation = schemaOptions.collation;
|
|
12
12
|
}
|
|
13
13
|
};
|
|
@@ -28,7 +28,7 @@ module.exports = function applyMethods(model, schema) {
|
|
|
28
28
|
}
|
|
29
29
|
for (const method of Object.keys(schema.methods)) {
|
|
30
30
|
const fn = schema.methods[method];
|
|
31
|
-
if (schema.tree
|
|
31
|
+
if (Object.hasOwn(schema.tree, method)) {
|
|
32
32
|
throw new Error('You have a method and a property in your schema both ' +
|
|
33
33
|
'named "' + method + '"');
|
|
34
34
|
}
|
|
@@ -118,7 +118,10 @@ module.exports.castUpdateOne = function castUpdateOne(originalModel, updateOne,
|
|
|
118
118
|
if (model.schema.$timestamps != null && doInitTimestamps) {
|
|
119
119
|
const createdAt = model.schema.$timestamps.createdAt;
|
|
120
120
|
const updatedAt = model.schema.$timestamps.updatedAt;
|
|
121
|
-
applyTimestampsToUpdate(now, createdAt, updatedAt, update, {
|
|
121
|
+
applyTimestampsToUpdate(now, createdAt, updatedAt, update, {
|
|
122
|
+
timestamps: updateOne.timestamps,
|
|
123
|
+
overwriteImmutable: updateOne.overwriteImmutable
|
|
124
|
+
});
|
|
122
125
|
}
|
|
123
126
|
|
|
124
127
|
if (doInitTimestamps) {
|
|
@@ -150,7 +153,8 @@ module.exports.castUpdateOne = function castUpdateOne(originalModel, updateOne,
|
|
|
150
153
|
strict: strict,
|
|
151
154
|
upsert: updateOne.upsert,
|
|
152
155
|
arrayFilters: updateOne.arrayFilters,
|
|
153
|
-
overwriteDiscriminatorKey: updateOne.overwriteDiscriminatorKey
|
|
156
|
+
overwriteDiscriminatorKey: updateOne.overwriteDiscriminatorKey,
|
|
157
|
+
overwriteImmutable: updateOne.overwriteImmutable
|
|
154
158
|
}, model, updateOne['filter']);
|
|
155
159
|
|
|
156
160
|
return updateOne;
|
|
@@ -185,7 +189,10 @@ module.exports.castUpdateMany = function castUpdateMany(originalModel, updateMan
|
|
|
185
189
|
if (model.schema.$timestamps != null && doInitTimestamps) {
|
|
186
190
|
const createdAt = model.schema.$timestamps.createdAt;
|
|
187
191
|
const updatedAt = model.schema.$timestamps.updatedAt;
|
|
188
|
-
applyTimestampsToUpdate(now, createdAt, updatedAt, updateMany['update'], {
|
|
192
|
+
applyTimestampsToUpdate(now, createdAt, updatedAt, updateMany['update'], {
|
|
193
|
+
timestamps: updateMany.timestamps,
|
|
194
|
+
overwriteImmutable: updateMany.overwriteImmutable
|
|
195
|
+
});
|
|
189
196
|
}
|
|
190
197
|
if (doInitTimestamps) {
|
|
191
198
|
applyTimestampsToChildren(now, updateMany['update'], model.schema);
|
|
@@ -208,7 +215,8 @@ module.exports.castUpdateMany = function castUpdateMany(originalModel, updateMan
|
|
|
208
215
|
strict: strict,
|
|
209
216
|
upsert: updateMany.upsert,
|
|
210
217
|
arrayFilters: updateMany.arrayFilters,
|
|
211
|
-
overwriteDiscriminatorKey: updateMany.overwriteDiscriminatorKey
|
|
218
|
+
overwriteDiscriminatorKey: updateMany.overwriteDiscriminatorKey,
|
|
219
|
+
overwriteImmutable: updateMany.overwriteImmutable
|
|
212
220
|
}, model, updateMany['filter']);
|
|
213
221
|
};
|
|
214
222
|
|
|
@@ -289,13 +297,12 @@ function _addDiscriminatorToObject(schema, obj) {
|
|
|
289
297
|
|
|
290
298
|
function decideModelByObject(model, object) {
|
|
291
299
|
const discriminatorKey = model.schema.options.discriminatorKey;
|
|
292
|
-
if (object != null &&
|
|
300
|
+
if (object != null && Object.hasOwn(object, discriminatorKey)) {
|
|
293
301
|
model = getDiscriminatorByValue(model.discriminators, object[discriminatorKey]) || model;
|
|
294
302
|
}
|
|
295
303
|
return model;
|
|
296
304
|
}
|
|
297
305
|
|
|
298
|
-
|
|
299
306
|
/**
|
|
300
307
|
* gets timestamps option for a given operation. If the option is set within an individual operation, use it. Otherwise, use the global timestamps option configured in the `bulkWrite` options. Overall default is `true`.
|
|
301
308
|
* @api private
|
|
@@ -386,13 +386,13 @@ function _virtualPopulate(model, docs, options, _virtualRes) {
|
|
|
386
386
|
}
|
|
387
387
|
data.count = virtual.options.count;
|
|
388
388
|
|
|
389
|
-
if (virtual.options.skip != null && !
|
|
389
|
+
if (virtual.options.skip != null && !Object.hasOwn(options, 'skip')) {
|
|
390
390
|
options.skip = virtual.options.skip;
|
|
391
391
|
}
|
|
392
|
-
if (virtual.options.limit != null && !
|
|
392
|
+
if (virtual.options.limit != null && !Object.hasOwn(options, 'limit')) {
|
|
393
393
|
options.limit = virtual.options.limit;
|
|
394
394
|
}
|
|
395
|
-
if (virtual.options.perDocumentLimit != null && !
|
|
395
|
+
if (virtual.options.perDocumentLimit != null && !Object.hasOwn(options, 'perDocumentLimit')) {
|
|
396
396
|
options.perDocumentLimit = virtual.options.perDocumentLimit;
|
|
397
397
|
}
|
|
398
398
|
let foreignField = virtual.options.foreignField;
|