mongoose 7.3.1 → 7.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.js +3 -1
- package/.markdownlint-cli2.cjs +69 -0
- package/README.md +24 -25
- package/dist/browser.umd.js +1 -1
- package/lib/connection.js +1 -2
- package/lib/cursor/QueryCursor.js +22 -14
- package/lib/document.js +25 -10
- package/lib/helpers/populate/getModelsMapForPopulate.js +2 -1
- package/lib/helpers/populate/getSchemaTypes.js +10 -14
- package/lib/index.js +2 -4
- package/lib/model.js +20 -15
- package/lib/query.js +21 -1
- package/lib/schema.js +10 -10
- package/lib/types/array/methods/index.js +3 -0
- package/package.json +16 -15
- package/types/index.d.ts +28 -21
- package/types/models.d.ts +17 -16
- package/types/schemaoptions.d.ts +4 -4
- package/types/utility.d.ts +8 -8
package/lib/connection.js
CHANGED
|
@@ -703,8 +703,7 @@ Connection.prototype.onOpen = function() {
|
|
|
703
703
|
* @param {Number} [options.heartbeatFrequencyMS] If `useUnifiedTopology = true`, the MongoDB driver sends a heartbeat every `heartbeatFrequencyMS` to check on the status of the connection. A heartbeat is subject to `serverSelectionTimeoutMS`, so the MongoDB driver will retry failed heartbeats for up to 30 seconds by default. Mongoose only emits a `'disconnected'` event after a heartbeat has failed, so you may want to decrease this setting to reduce the time between when your server goes down and when Mongoose emits `'disconnected'`. We recommend you do **not** set this setting below 1000, too many heartbeats can lead to performance degradation.
|
|
704
704
|
* @param {Boolean} [options.autoIndex=true] Mongoose-specific option. Set to false to disable automatic index creation for all models associated with this connection.
|
|
705
705
|
* @param {Class} [options.promiseLibrary] Sets the [underlying driver's promise library](https://mongodb.github.io/node-mongodb-native/4.9/interfaces/MongoClientOptions.html#promiseLibrary).
|
|
706
|
-
* @param {Number} [options.
|
|
707
|
-
* @param {Number} [options.socketTimeoutMS=30000] How long the MongoDB driver will wait before killing a socket due to inactivity _after initial connection_. A socket may be inactive because of either no activity or a long-running operation. This is set to `30000` by default, you should set this to 2-3x your longest running operation if you expect some of your database operations to run longer than 20 seconds. This option is passed to [Node.js `socket#setTimeout()` function](https://nodejs.org/api/net.html#net_socket_settimeout_timeout_callback) after the MongoDB driver successfully completes.
|
|
706
|
+
* @param {Number} [options.socketTimeoutMS=0] How long the MongoDB driver will wait before killing a socket due to inactivity _after initial connection_. A socket may be inactive because of either no activity or a long-running operation. `socketTimeoutMS` defaults to 0, which means Node.js will not time out the socket due to inactivity. This option is passed to [Node.js `socket#setTimeout()` function](https://nodejs.org/api/net.html#net_socket_settimeout_timeout_callback) after the MongoDB driver successfully completes.
|
|
708
707
|
* @param {Number} [options.family=0] Passed transparently to [Node.js' `dns.lookup()`](https://nodejs.org/api/dns.html#dns_dns_lookup_hostname_options_callback) function. May be either `0, `4`, or `6`. `4` means use IPv4 only, `6` means use IPv6 only, `0` means try both.
|
|
709
708
|
* @param {Boolean} [options.autoCreate=false] Set to `true` to make Mongoose automatically call `createCollection()` on every model created on this connection.
|
|
710
709
|
* @returns {Promise<Connection>}
|
|
@@ -84,25 +84,33 @@ function QueryCursor(query, options) {
|
|
|
84
84
|
this.options._populateBatchSize = Math.min(this.options.batchSize, 5000);
|
|
85
85
|
}
|
|
86
86
|
Object.assign(this.options, query._optionsForExec());
|
|
87
|
-
model.collection.
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
if (this._error) {
|
|
95
|
-
cursor.close(function() {});
|
|
96
|
-
this.listeners('error').length > 0 && this.emit('error', this._error);
|
|
97
|
-
}
|
|
98
|
-
this.cursor = cursor;
|
|
99
|
-
this.emit('cursor', cursor);
|
|
100
|
-
});
|
|
87
|
+
if (model.collection._shouldBufferCommands() && model.collection.buffer) {
|
|
88
|
+
model.collection.queue.push([
|
|
89
|
+
() => _getRawCursor(query, this)
|
|
90
|
+
]);
|
|
91
|
+
} else {
|
|
92
|
+
_getRawCursor(query, this);
|
|
93
|
+
}
|
|
101
94
|
});
|
|
102
95
|
}
|
|
103
96
|
|
|
104
97
|
util.inherits(QueryCursor, Readable);
|
|
105
98
|
|
|
99
|
+
/*!
|
|
100
|
+
* ignore
|
|
101
|
+
*/
|
|
102
|
+
|
|
103
|
+
function _getRawCursor(query, queryCursor) {
|
|
104
|
+
try {
|
|
105
|
+
const cursor = query.model.collection.find(query._conditions, queryCursor.options);
|
|
106
|
+
queryCursor.cursor = cursor;
|
|
107
|
+
queryCursor.emit('cursor', cursor);
|
|
108
|
+
} catch (err) {
|
|
109
|
+
queryCursor._markError(err);
|
|
110
|
+
queryCursor.listeners('error').length > 0 && queryCursor.emit('error', queryCursor._error);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
106
114
|
/**
|
|
107
115
|
* Necessary to satisfy the Readable API
|
|
108
116
|
* @method _read
|
package/lib/document.js
CHANGED
|
@@ -741,6 +741,10 @@ function init(self, obj, doc, opts, prefix) {
|
|
|
741
741
|
|
|
742
742
|
function _init(index) {
|
|
743
743
|
i = keys[index];
|
|
744
|
+
// avoid prototype pollution
|
|
745
|
+
if (i === '__proto__' || i === 'constructor') {
|
|
746
|
+
return;
|
|
747
|
+
}
|
|
744
748
|
path = prefix + i;
|
|
745
749
|
schemaType = docSchema.path(path);
|
|
746
750
|
|
|
@@ -2684,7 +2688,7 @@ function _getPathsToValidate(doc, pathsToValidate, pathsToSkip) {
|
|
|
2684
2688
|
|
|
2685
2689
|
// Optimization: if primitive path with no validators, or array of primitives
|
|
2686
2690
|
// with no validators, skip validating this path entirely.
|
|
2687
|
-
if (!_pathType.caster && _pathType.validators.length === 0) {
|
|
2691
|
+
if (!_pathType.caster && _pathType.validators.length === 0 && !_pathType.$parentSchemaDocArray) {
|
|
2688
2692
|
paths.delete(path);
|
|
2689
2693
|
} else if (_pathType.$isMongooseArray &&
|
|
2690
2694
|
!_pathType.$isMongooseDocumentArray && // Skip document arrays...
|
|
@@ -2771,7 +2775,19 @@ function _getPathsToValidate(doc, pathsToValidate, pathsToSkip) {
|
|
|
2771
2775
|
|
|
2772
2776
|
for (const path of paths) {
|
|
2773
2777
|
const _pathType = doc.$__schema.path(path);
|
|
2774
|
-
|
|
2778
|
+
|
|
2779
|
+
if (!_pathType) {
|
|
2780
|
+
continue;
|
|
2781
|
+
}
|
|
2782
|
+
|
|
2783
|
+
// If underneath a document array, may need to re-validate the parent
|
|
2784
|
+
// array re: gh-6818. Do this _after_ adding subpaths, because
|
|
2785
|
+
// we don't want to add every array subpath.
|
|
2786
|
+
if (_pathType.$parentSchemaDocArray && typeof _pathType.$parentSchemaDocArray.path === 'string') {
|
|
2787
|
+
paths.add(_pathType.$parentSchemaDocArray.path);
|
|
2788
|
+
}
|
|
2789
|
+
|
|
2790
|
+
if (!_pathType.$isSchemaMap) {
|
|
2775
2791
|
continue;
|
|
2776
2792
|
}
|
|
2777
2793
|
|
|
@@ -3318,14 +3334,7 @@ Document.prototype.$__reset = function reset() {
|
|
|
3318
3334
|
if (this.isModified(fullPathWithIndexes) || isParentInit(fullPathWithIndexes)) {
|
|
3319
3335
|
subdoc.$__reset();
|
|
3320
3336
|
if (subdoc.$isDocumentArrayElement) {
|
|
3321
|
-
|
|
3322
|
-
const array = subdoc.parentArray();
|
|
3323
|
-
this.$__.activePaths.clearPath(fullPathWithIndexes.replace(/\.\d+$/, '').slice(-subdoc.$basePath - 1));
|
|
3324
|
-
array[arrayAtomicsBackupSymbol] = array[arrayAtomicsSymbol];
|
|
3325
|
-
array[arrayAtomicsSymbol] = {};
|
|
3326
|
-
|
|
3327
|
-
resetArrays.add(array);
|
|
3328
|
-
}
|
|
3337
|
+
resetArrays.add(subdoc.parentArray());
|
|
3329
3338
|
} else {
|
|
3330
3339
|
if (subdoc.$parent() === this) {
|
|
3331
3340
|
this.$__.activePaths.clearPath(subdoc.$basePath);
|
|
@@ -3338,6 +3347,12 @@ Document.prototype.$__reset = function reset() {
|
|
|
3338
3347
|
}
|
|
3339
3348
|
}
|
|
3340
3349
|
|
|
3350
|
+
for (const array of resetArrays) {
|
|
3351
|
+
this.$__.activePaths.clearPath(array.$path());
|
|
3352
|
+
array[arrayAtomicsBackupSymbol] = array[arrayAtomicsSymbol];
|
|
3353
|
+
array[arrayAtomicsSymbol] = {};
|
|
3354
|
+
}
|
|
3355
|
+
|
|
3341
3356
|
function isParentInit(path) {
|
|
3342
3357
|
path = path.indexOf('.') === -1 ? [path] : path.split('.');
|
|
3343
3358
|
let cur = '';
|
|
@@ -64,7 +64,7 @@ module.exports = function getModelsMapForPopulate(model, docs, options) {
|
|
|
64
64
|
schema.options.refPath == null) {
|
|
65
65
|
continue;
|
|
66
66
|
}
|
|
67
|
-
const isUnderneathDocArray = schema && schema.$
|
|
67
|
+
const isUnderneathDocArray = schema && schema.$parentSchemaDocArray;
|
|
68
68
|
if (isUnderneathDocArray && get(options, 'options.sort') != null) {
|
|
69
69
|
return new MongooseError('Cannot populate with `sort` on path ' + options.path +
|
|
70
70
|
' because it is a subproperty of a document array');
|
|
@@ -540,6 +540,7 @@ function addModelNamesToMap(model, map, available, modelNames, options, data, re
|
|
|
540
540
|
// Used internally for checking what model was used to populate this
|
|
541
541
|
// path.
|
|
542
542
|
options[populateModelSymbol] = Model;
|
|
543
|
+
currentOptions[populateModelSymbol] = Model;
|
|
543
544
|
available[modelName] = {
|
|
544
545
|
model: Model,
|
|
545
546
|
options: currentOptions,
|
|
@@ -101,8 +101,8 @@ module.exports = function getSchemaTypes(model, schema, doc, path) {
|
|
|
101
101
|
nestedPath.concat(parts.slice(0, p))
|
|
102
102
|
);
|
|
103
103
|
if (ret) {
|
|
104
|
-
ret.$
|
|
105
|
-
|
|
104
|
+
ret.$parentSchemaDocArray = ret.$parentSchemaDocArray ||
|
|
105
|
+
(foundschema.schema.$isSingleNested ? null : foundschema);
|
|
106
106
|
}
|
|
107
107
|
return ret;
|
|
108
108
|
}
|
|
@@ -117,10 +117,10 @@ module.exports = function getSchemaTypes(model, schema, doc, path) {
|
|
|
117
117
|
nestedPath.concat(parts.slice(0, p))
|
|
118
118
|
);
|
|
119
119
|
if (_ret != null) {
|
|
120
|
-
_ret.$
|
|
121
|
-
|
|
122
|
-
if (_ret.$
|
|
123
|
-
ret.$
|
|
120
|
+
_ret.$parentSchemaDocArray = _ret.$parentSchemaDocArray ||
|
|
121
|
+
(foundschema.schema.$isSingleNested ? null : foundschema);
|
|
122
|
+
if (_ret.$parentSchemaDocArray) {
|
|
123
|
+
ret.$parentSchemaDocArray = _ret.$parentSchemaDocArray;
|
|
124
124
|
}
|
|
125
125
|
ret.push(_ret);
|
|
126
126
|
}
|
|
@@ -135,8 +135,8 @@ module.exports = function getSchemaTypes(model, schema, doc, path) {
|
|
|
135
135
|
);
|
|
136
136
|
|
|
137
137
|
if (ret) {
|
|
138
|
-
ret.$
|
|
139
|
-
|
|
138
|
+
ret.$parentSchemaDocArray = ret.$parentSchemaDocArray ||
|
|
139
|
+
(foundschema.schema.$isSingleNested ? null : foundschema);
|
|
140
140
|
}
|
|
141
141
|
return ret;
|
|
142
142
|
}
|
|
@@ -188,10 +188,6 @@ module.exports = function getSchemaTypes(model, schema, doc, path) {
|
|
|
188
188
|
nestedPath.concat(parts.slice(0, p))
|
|
189
189
|
);
|
|
190
190
|
|
|
191
|
-
if (ret) {
|
|
192
|
-
ret.$isUnderneathDocArray = ret.$isUnderneathDocArray ||
|
|
193
|
-
!model.schema.$isSingleNested;
|
|
194
|
-
}
|
|
195
191
|
return ret;
|
|
196
192
|
}
|
|
197
193
|
}
|
|
@@ -212,8 +208,8 @@ module.exports = function getSchemaTypes(model, schema, doc, path) {
|
|
|
212
208
|
);
|
|
213
209
|
|
|
214
210
|
if (ret != null) {
|
|
215
|
-
ret.$
|
|
216
|
-
|
|
211
|
+
ret.$parentSchemaDocArray = ret.$parentSchemaDocArray ||
|
|
212
|
+
(schema.$isSingleNested ? null : schema);
|
|
217
213
|
return ret;
|
|
218
214
|
}
|
|
219
215
|
}
|
package/lib/index.js
CHANGED
|
@@ -329,8 +329,7 @@ Mongoose.prototype.get = Mongoose.prototype.set;
|
|
|
329
329
|
* @param {Class} [options.promiseLibrary] Sets the [underlying driver's promise library](https://mongodb.github.io/node-mongodb-native/4.9/interfaces/MongoClientOptions.html#promiseLibrary).
|
|
330
330
|
* @param {Number} [options.maxPoolSize=5] The maximum number of sockets the MongoDB driver will keep open for this connection. Keep in mind that MongoDB only allows one operation per socket at a time, so you may want to increase this if you find you have a few slow queries that are blocking faster queries from proceeding. See [Slow Trains in MongoDB and Node.js](https://thecodebarbarian.com/slow-trains-in-mongodb-and-nodejs).
|
|
331
331
|
* @param {Number} [options.minPoolSize=1] The minimum number of sockets the MongoDB driver will keep open for this connection. Keep in mind that MongoDB only allows one operation per socket at a time, so you may want to increase this if you find you have a few slow queries that are blocking faster queries from proceeding. See [Slow Trains in MongoDB and Node.js](https://thecodebarbarian.com/slow-trains-in-mongodb-and-nodejs).
|
|
332
|
-
* @param {Number} [options.
|
|
333
|
-
* @param {Number} [options.socketTimeoutMS=30000] How long the MongoDB driver will wait before killing a socket due to inactivity _after initial connection_. A socket may be inactive because of either no activity or a long-running operation. This is set to `30000` by default, you should set this to 2-3x your longest running operation if you expect some of your database operations to run longer than 20 seconds. This option is passed to [Node.js `socket#setTimeout()` function](https://nodejs.org/api/net.html#net_socket_settimeout_timeout_callback) after the MongoDB driver successfully completes.
|
|
332
|
+
* @param {Number} [options.socketTimeoutMS=0] How long the MongoDB driver will wait before killing a socket due to inactivity _after initial connection_. Defaults to 0, which means Node.js will not time out the socket due to inactivity. A socket may be inactive because of either no activity or a long-running operation. This option is passed to [Node.js `socket#setTimeout()` function](https://nodejs.org/api/net.html#net_socket_settimeout_timeout_callback) after the MongoDB driver successfully completes.
|
|
334
333
|
* @param {Number} [options.family=0] Passed transparently to [Node.js' `dns.lookup()`](https://nodejs.org/api/dns.html#dns_dns_lookup_hostname_options_callback) function. May be either `0`, `4`, or `6`. `4` means use IPv4 only, `6` means use IPv6 only, `0` means try both.
|
|
335
334
|
* @return {Connection} the created Connection object. Connections are not thenable, so you can't do `await mongoose.createConnection()`. To await use `mongoose.createConnection(uri).asPromise()` instead.
|
|
336
335
|
* @api public
|
|
@@ -385,8 +384,7 @@ Mongoose.prototype.createConnection = function(uri, options) {
|
|
|
385
384
|
* @param {Number} [options.heartbeatFrequencyMS] If `useUnifiedTopology = true`, the MongoDB driver sends a heartbeat every `heartbeatFrequencyMS` to check on the status of the connection. A heartbeat is subject to `serverSelectionTimeoutMS`, so the MongoDB driver will retry failed heartbeats for up to 30 seconds by default. Mongoose only emits a `'disconnected'` event after a heartbeat has failed, so you may want to decrease this setting to reduce the time between when your server goes down and when Mongoose emits `'disconnected'`. We recommend you do **not** set this setting below 1000, too many heartbeats can lead to performance degradation.
|
|
386
385
|
* @param {Boolean} [options.autoIndex=true] Mongoose-specific option. Set to false to disable automatic index creation for all models associated with this connection.
|
|
387
386
|
* @param {Class} [options.promiseLibrary] Sets the [underlying driver's promise library](https://mongodb.github.io/node-mongodb-native/4.9/interfaces/MongoClientOptions.html#promiseLibrary).
|
|
388
|
-
* @param {Number} [options.
|
|
389
|
-
* @param {Number} [options.socketTimeoutMS=30000] How long the MongoDB driver will wait before killing a socket due to inactivity _after initial connection_. A socket may be inactive because of either no activity or a long-running operation. This is set to `30000` by default, you should set this to 2-3x your longest running operation if you expect some of your database operations to run longer than 20 seconds. This option is passed to [Node.js `socket#setTimeout()` function](https://nodejs.org/api/net.html#net_socket_settimeout_timeout_callback) after the MongoDB driver successfully completes.
|
|
387
|
+
* @param {Number} [options.socketTimeoutMS=0] How long the MongoDB driver will wait before killing a socket due to inactivity _after initial connection_. A socket may be inactive because of either no activity or a long-running operation. `socketTimeoutMS` defaults to 0, which means Node.js will not time out the socket due to inactivity. This option is passed to [Node.js `socket#setTimeout()` function](https://nodejs.org/api/net.html#net_socket_settimeout_timeout_callback) after the MongoDB driver successfully completes.
|
|
390
388
|
* @param {Number} [options.family=0] Passed transparently to [Node.js' `dns.lookup()`](https://nodejs.org/api/dns.html#dns_dns_lookup_hostname_options_callback) function. May be either `0`, `4`, or `6`. `4` means use IPv4 only, `6` means use IPv6 only, `0` means try both.
|
|
391
389
|
* @param {Boolean} [options.autoCreate=false] Set to `true` to make Mongoose automatically call `createCollection()` on every model created on this connection.
|
|
392
390
|
* @param {Function} [callback]
|
package/lib/model.js
CHANGED
|
@@ -1046,16 +1046,18 @@ Model.prototype.$__deleteOne = function $__deleteOne(options, cb) {
|
|
|
1046
1046
|
options.session = session;
|
|
1047
1047
|
}
|
|
1048
1048
|
|
|
1049
|
-
this[modelCollectionSymbol].deleteOne(where, options
|
|
1050
|
-
|
|
1049
|
+
this[modelCollectionSymbol].deleteOne(where, options).then(
|
|
1050
|
+
() => {
|
|
1051
1051
|
this.$__.isDeleted = true;
|
|
1052
1052
|
this.$emit('deleteOne', this);
|
|
1053
1053
|
this.constructor.emit('deleteOne', this);
|
|
1054
1054
|
return cb(null, this);
|
|
1055
|
+
},
|
|
1056
|
+
err => {
|
|
1057
|
+
this.$__.isDeleted = false;
|
|
1058
|
+
cb(err);
|
|
1055
1059
|
}
|
|
1056
|
-
|
|
1057
|
-
cb(err);
|
|
1058
|
-
});
|
|
1060
|
+
);
|
|
1059
1061
|
};
|
|
1060
1062
|
|
|
1061
1063
|
/**
|
|
@@ -3232,16 +3234,19 @@ Model.$__insertMany = function(arr, options, callback) {
|
|
|
3232
3234
|
}
|
|
3233
3235
|
|
|
3234
3236
|
// `insertedDocs` is a Mongoose-specific property
|
|
3237
|
+
const hasWriteErrors = error && error.writeErrors;
|
|
3235
3238
|
const erroredIndexes = new Set((error && error.writeErrors || []).map(err => err.index));
|
|
3236
3239
|
|
|
3237
|
-
|
|
3238
|
-
|
|
3239
|
-
|
|
3240
|
-
|
|
3241
|
-
|
|
3242
|
-
|
|
3243
|
-
|
|
3244
|
-
|
|
3240
|
+
if (error.writeErrors != null) {
|
|
3241
|
+
for (let i = 0; i < error.writeErrors.length; ++i) {
|
|
3242
|
+
const originalIndex = validDocIndexToOriginalIndex.get(error.writeErrors[i].index);
|
|
3243
|
+
error.writeErrors[i] = {
|
|
3244
|
+
...error.writeErrors[i],
|
|
3245
|
+
index: originalIndex
|
|
3246
|
+
};
|
|
3247
|
+
if (!ordered) {
|
|
3248
|
+
results[originalIndex] = error.writeErrors[i];
|
|
3249
|
+
}
|
|
3245
3250
|
}
|
|
3246
3251
|
}
|
|
3247
3252
|
|
|
@@ -3258,7 +3263,7 @@ Model.$__insertMany = function(arr, options, callback) {
|
|
|
3258
3263
|
let firstErroredIndex = -1;
|
|
3259
3264
|
error.insertedDocs = docAttributes.
|
|
3260
3265
|
filter((doc, i) => {
|
|
3261
|
-
const isErrored = erroredIndexes.has(i);
|
|
3266
|
+
const isErrored = !hasWriteErrors || erroredIndexes.has(i);
|
|
3262
3267
|
|
|
3263
3268
|
if (ordered) {
|
|
3264
3269
|
if (firstErroredIndex > -1) {
|
|
@@ -4262,7 +4267,7 @@ const excludeIdReg = /\s?-_id\s?/;
|
|
|
4262
4267
|
const excludeIdRegGlobal = /\s?-_id\s?/g;
|
|
4263
4268
|
|
|
4264
4269
|
function populate(model, docs, options, callback) {
|
|
4265
|
-
const populateOptions =
|
|
4270
|
+
const populateOptions = options;
|
|
4266
4271
|
if (options.strictPopulate == null) {
|
|
4267
4272
|
if (options._localModel != null && options._localModel.schema._userProvidedOptions.strictPopulate != null) {
|
|
4268
4273
|
populateOptions.strictPopulate = options._localModel.schema._userProvidedOptions.strictPopulate;
|
package/lib/query.js
CHANGED
|
@@ -3281,6 +3281,12 @@ Query.prototype.findOneAndUpdate = function(filter, doc, options) {
|
|
|
3281
3281
|
*/
|
|
3282
3282
|
|
|
3283
3283
|
Query.prototype._findOneAndUpdate = async function _findOneAndUpdate() {
|
|
3284
|
+
// For backwards compability with Mongoose 6 re: #13550
|
|
3285
|
+
if (this._mongooseOptions.overwrite) {
|
|
3286
|
+
this.op = 'findOneAndReplace';
|
|
3287
|
+
return this._findOneAndReplace();
|
|
3288
|
+
}
|
|
3289
|
+
|
|
3284
3290
|
this._castConditions();
|
|
3285
3291
|
|
|
3286
3292
|
_castArrayFilters(this);
|
|
@@ -4354,7 +4360,10 @@ Query.prototype.exec = async function exec(op) {
|
|
|
4354
4360
|
}
|
|
4355
4361
|
|
|
4356
4362
|
if (this.op == null) {
|
|
4357
|
-
throw new
|
|
4363
|
+
throw new MongooseError('Query must have `op` before executing');
|
|
4364
|
+
}
|
|
4365
|
+
if (this.model == null) {
|
|
4366
|
+
throw new MongooseError('Query must have an associated model before executing');
|
|
4358
4367
|
}
|
|
4359
4368
|
this._validateOp();
|
|
4360
4369
|
|
|
@@ -4434,6 +4443,13 @@ function _executePostExecHooks(query) {
|
|
|
4434
4443
|
*/
|
|
4435
4444
|
|
|
4436
4445
|
function _executePostHooks(query, res, error, op) {
|
|
4446
|
+
if (query._queryMiddleware == null) {
|
|
4447
|
+
if (error != null) {
|
|
4448
|
+
throw error;
|
|
4449
|
+
}
|
|
4450
|
+
return res;
|
|
4451
|
+
}
|
|
4452
|
+
|
|
4437
4453
|
return new Promise((resolve, reject) => {
|
|
4438
4454
|
const opts = error ? { error } : {};
|
|
4439
4455
|
|
|
@@ -4467,6 +4483,10 @@ function _executePreExecHooks(query) {
|
|
|
4467
4483
|
*/
|
|
4468
4484
|
|
|
4469
4485
|
function _executePreHooks(query, op) {
|
|
4486
|
+
if (query._queryMiddleware == null) {
|
|
4487
|
+
return;
|
|
4488
|
+
}
|
|
4489
|
+
|
|
4470
4490
|
return new Promise((resolve, reject) => {
|
|
4471
4491
|
query._queryMiddleware.execPre(op || query.op, query, [], (error) => {
|
|
4472
4492
|
if (error != null) {
|
package/lib/schema.js
CHANGED
|
@@ -1131,22 +1131,22 @@ Schema.prototype.path = function(path, obj) {
|
|
|
1131
1131
|
for (const key of Object.keys(schemaType.schema.paths)) {
|
|
1132
1132
|
const _schemaType = schemaType.schema.paths[key];
|
|
1133
1133
|
this.subpaths[path + '.' + key] = _schemaType;
|
|
1134
|
-
if (typeof _schemaType === 'object' && _schemaType != null) {
|
|
1135
|
-
_schemaType.$
|
|
1134
|
+
if (typeof _schemaType === 'object' && _schemaType != null && _schemaType.$parentSchemaDocArray == null) {
|
|
1135
|
+
_schemaType.$parentSchemaDocArray = schemaType;
|
|
1136
1136
|
}
|
|
1137
1137
|
}
|
|
1138
1138
|
for (const key of Object.keys(schemaType.schema.subpaths)) {
|
|
1139
1139
|
const _schemaType = schemaType.schema.subpaths[key];
|
|
1140
1140
|
this.subpaths[path + '.' + key] = _schemaType;
|
|
1141
|
-
if (typeof _schemaType === 'object' && _schemaType != null) {
|
|
1142
|
-
_schemaType.$
|
|
1141
|
+
if (typeof _schemaType === 'object' && _schemaType != null && _schemaType.$parentSchemaDocArray == null) {
|
|
1142
|
+
_schemaType.$parentSchemaDocArray = schemaType;
|
|
1143
1143
|
}
|
|
1144
1144
|
}
|
|
1145
1145
|
for (const key of Object.keys(schemaType.schema.singleNestedPaths)) {
|
|
1146
1146
|
const _schemaType = schemaType.schema.singleNestedPaths[key];
|
|
1147
1147
|
this.subpaths[path + '.' + key] = _schemaType;
|
|
1148
|
-
if (typeof _schemaType === 'object' && _schemaType != null) {
|
|
1149
|
-
_schemaType.$
|
|
1148
|
+
if (typeof _schemaType === 'object' && _schemaType != null && _schemaType.$parentSchemaDocArray == null) {
|
|
1149
|
+
_schemaType.$parentSchemaDocArray = schemaType;
|
|
1150
1150
|
}
|
|
1151
1151
|
}
|
|
1152
1152
|
}
|
|
@@ -2556,16 +2556,16 @@ Schema.prototype._getSchema = function(path) {
|
|
|
2556
2556
|
// comments.$.comments.$.title
|
|
2557
2557
|
ret = search(parts.slice(p + 1), foundschema.schema);
|
|
2558
2558
|
if (ret) {
|
|
2559
|
-
ret.$
|
|
2560
|
-
|
|
2559
|
+
ret.$parentSchemaDocArray = ret.$parentSchemaDocArray ||
|
|
2560
|
+
(foundschema.schema.$isSingleNested ? null : foundschema);
|
|
2561
2561
|
}
|
|
2562
2562
|
return ret;
|
|
2563
2563
|
}
|
|
2564
2564
|
// this is the last path of the selector
|
|
2565
2565
|
ret = search(parts.slice(p), foundschema.schema);
|
|
2566
2566
|
if (ret) {
|
|
2567
|
-
ret.$
|
|
2568
|
-
|
|
2567
|
+
ret.$parentSchemaDocArray = ret.$parentSchemaDocArray ||
|
|
2568
|
+
(foundschema.schema.$isSingleNested ? null : foundschema);
|
|
2569
2569
|
}
|
|
2570
2570
|
return ret;
|
|
2571
2571
|
}
|
|
@@ -226,6 +226,9 @@ const methods = {
|
|
|
226
226
|
if (populated && value !== null && value !== undefined) {
|
|
227
227
|
// cast to the populated Models schema
|
|
228
228
|
Model = populated.options[populateModelSymbol];
|
|
229
|
+
if (Model == null) {
|
|
230
|
+
throw new MongooseError('No populated model found for path `' + this[arrayPathSymbol] + '`. This is likely a bug in Mongoose, please report an issue on github.com/Automattic/mongoose.');
|
|
231
|
+
}
|
|
229
232
|
|
|
230
233
|
// only objects are permitted so we can safely assume that
|
|
231
234
|
// non-objects are to be interpreted as _id
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mongoose",
|
|
3
3
|
"description": "Mongoose MongoDB ODM",
|
|
4
|
-
"version": "7.3.
|
|
4
|
+
"version": "7.3.3",
|
|
5
5
|
"author": "Guillermo Rauch <guillermo@learnboost.com>",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"mongodb",
|
|
@@ -28,10 +28,10 @@
|
|
|
28
28
|
"sift": "16.0.1"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
|
-
"@babel/core": "7.22.
|
|
32
|
-
"@babel/preset-env": "7.22.
|
|
33
|
-
"@typescript-eslint/eslint-plugin": "5.
|
|
34
|
-
"@typescript-eslint/parser": "5.
|
|
31
|
+
"@babel/core": "7.22.5",
|
|
32
|
+
"@babel/preset-env": "7.22.5",
|
|
33
|
+
"@typescript-eslint/eslint-plugin": "5.61.0",
|
|
34
|
+
"@typescript-eslint/parser": "5.61.0",
|
|
35
35
|
"acquit": "1.3.0",
|
|
36
36
|
"acquit-ignore": "0.2.1",
|
|
37
37
|
"acquit-require": "0.1.1",
|
|
@@ -44,31 +44,32 @@
|
|
|
44
44
|
"buffer": "^5.6.0",
|
|
45
45
|
"cheerio": "1.0.0-rc.12",
|
|
46
46
|
"crypto-browserify": "3.12.0",
|
|
47
|
-
"dotenv": "16.1
|
|
47
|
+
"dotenv": "16.3.1",
|
|
48
48
|
"dox": "1.0.0",
|
|
49
|
-
"eslint": "8.
|
|
49
|
+
"eslint": "8.44.0",
|
|
50
50
|
"eslint-plugin-markdown": "^3.0.0",
|
|
51
51
|
"eslint-plugin-mocha-no-only": "1.1.1",
|
|
52
52
|
"express": "^4.18.1",
|
|
53
|
+
"fs-extra": "~11.1.1",
|
|
53
54
|
"highlight.js": "11.8.0",
|
|
54
55
|
"lodash.isequal": "4.5.0",
|
|
55
56
|
"lodash.isequalwith": "4.4.0",
|
|
57
|
+
"markdownlint-cli2": "^0.8.1",
|
|
56
58
|
"marked": "4.3.0",
|
|
57
|
-
"mkdirp": "^
|
|
59
|
+
"mkdirp": "^3.0.1",
|
|
58
60
|
"mocha": "10.2.0",
|
|
59
61
|
"moment": "2.x",
|
|
60
|
-
"mongodb-memory-server": "8.
|
|
62
|
+
"mongodb-memory-server": "8.13.0",
|
|
61
63
|
"ncp": "^2.0.0",
|
|
62
64
|
"nyc": "15.1.0",
|
|
63
65
|
"pug": "3.0.2",
|
|
64
66
|
"q": "1.5.1",
|
|
65
|
-
"sinon": "15.
|
|
67
|
+
"sinon": "15.2.0",
|
|
66
68
|
"stream-browserify": "3.0.0",
|
|
67
69
|
"tsd": "0.28.1",
|
|
68
|
-
"typescript": "5.1.
|
|
70
|
+
"typescript": "5.1.6",
|
|
69
71
|
"uuid": "9.0.0",
|
|
70
|
-
"webpack": "5.
|
|
71
|
-
"fs-extra": "~11.1.1"
|
|
72
|
+
"webpack": "5.88.1"
|
|
72
73
|
},
|
|
73
74
|
"directories": {
|
|
74
75
|
"lib": "./lib/mongoose"
|
|
@@ -98,9 +99,9 @@
|
|
|
98
99
|
"docs:prepare:publish:6x": "npm run docs:checkout:6x && npm run docs:merge:6x && npm run docs:clean:stable && env DOCS_DEPLOY=true npm run docs:generate && npm run docs:move:6x:tmp && npm run docs:checkout:gh-pages && npm run docs:copy:tmp:6x",
|
|
99
100
|
"docs:check-links": "blc http://127.0.0.1:8089 -ro",
|
|
100
101
|
"lint": "eslint .",
|
|
101
|
-
"lint-js": "eslint . --ext .js",
|
|
102
|
+
"lint-js": "eslint . --ext .js --ext .cjs",
|
|
102
103
|
"lint-ts": "eslint . --ext .ts",
|
|
103
|
-
"lint-md": "
|
|
104
|
+
"lint-md": "markdownlint-cli2 \"**/*.md\"",
|
|
104
105
|
"build-browser": "(rm ./dist/* || true) && node ./scripts/build-browser.js",
|
|
105
106
|
"prepublishOnly": "npm run build-browser",
|
|
106
107
|
"release": "git pull && git push origin master --tags && npm publish",
|
package/types/index.d.ts
CHANGED
|
@@ -141,12 +141,16 @@ declare module 'mongoose' {
|
|
|
141
141
|
> = IfAny<
|
|
142
142
|
DocType,
|
|
143
143
|
any,
|
|
144
|
-
|
|
145
|
-
Require_id<DocType
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
144
|
+
TOverrides extends Record<string, never> ?
|
|
145
|
+
Document<unknown, TQueryHelpers, DocType> & Require_id<DocType> :
|
|
146
|
+
IfAny<
|
|
147
|
+
TOverrides,
|
|
148
|
+
Document<unknown, TQueryHelpers, DocType> & Require_id<DocType>,
|
|
149
|
+
Document<unknown, TQueryHelpers, DocType> & MergeType<
|
|
150
|
+
Require_id<DocType>,
|
|
151
|
+
TOverrides
|
|
152
|
+
>
|
|
153
|
+
>
|
|
150
154
|
>;
|
|
151
155
|
export type HydratedSingleSubdocument<DocType, TOverrides = {}> = Types.Subdocument<unknown> & Require_id<DocType> & TOverrides;
|
|
152
156
|
export type HydratedArraySubdocument<DocType, TOverrides = {}> = Types.ArraySubdocument<unknown> & Require_id<DocType> & TOverrides;
|
|
@@ -197,7 +201,7 @@ declare module 'mongoose' {
|
|
|
197
201
|
|
|
198
202
|
export type DiscriminatorSchema<DocType, M, TInstanceMethods, TQueryHelpers, TVirtuals, TStaticMethods, DisSchema> =
|
|
199
203
|
DisSchema extends Schema<infer DisSchemaEDocType, infer DisSchemaM, infer DisSchemaInstanceMethods, infer DisSchemaQueryhelpers, infer DisSchemaVirtuals, infer DisSchemaStatics>
|
|
200
|
-
? Schema<
|
|
204
|
+
? Schema<MergeType<DocType, DisSchemaEDocType>, DiscriminatorModel<DisSchemaM, M>, DisSchemaInstanceMethods | TInstanceMethods, DisSchemaQueryhelpers | TQueryHelpers, DisSchemaVirtuals | TVirtuals, DisSchemaStatics & TStaticMethods>
|
|
201
205
|
: Schema<DocType, M, TInstanceMethods, TQueryHelpers, TVirtuals, TStaticMethods>;
|
|
202
206
|
|
|
203
207
|
type QueryResultType<T> = T extends Query<infer ResultType, any> ? ResultType : never;
|
|
@@ -212,7 +216,7 @@ declare module 'mongoose' {
|
|
|
212
216
|
|
|
213
217
|
export class Schema<
|
|
214
218
|
EnforcedDocType = any,
|
|
215
|
-
|
|
219
|
+
TModelType = Model<EnforcedDocType, any, any, any>,
|
|
216
220
|
TInstanceMethods = {},
|
|
217
221
|
TQueryHelpers = {},
|
|
218
222
|
TVirtuals = {},
|
|
@@ -225,13 +229,13 @@ declare module 'mongoose' {
|
|
|
225
229
|
ObtainDocumentType<any, EnforcedDocType, ResolveSchemaOptions<TSchemaOptions>>,
|
|
226
230
|
ResolveSchemaOptions<TSchemaOptions>
|
|
227
231
|
>,
|
|
228
|
-
THydratedDocumentType = HydratedDocument<
|
|
232
|
+
THydratedDocumentType = HydratedDocument<DocType, TVirtuals & TInstanceMethods>
|
|
229
233
|
>
|
|
230
234
|
extends events.EventEmitter {
|
|
231
235
|
/**
|
|
232
236
|
* Create a new schema
|
|
233
237
|
*/
|
|
234
|
-
constructor(definition?: SchemaDefinition<SchemaDefinitionType<EnforcedDocType>> | DocType, options?: SchemaOptions<
|
|
238
|
+
constructor(definition?: SchemaDefinition<SchemaDefinitionType<EnforcedDocType>> | DocType, options?: SchemaOptions<DocType, TInstanceMethods, TQueryHelpers, TStaticMethods, TVirtuals, THydratedDocumentType> | ResolveSchemaOptions<TSchemaOptions>);
|
|
235
239
|
|
|
236
240
|
/** Adds key path / schema type pairs to this schema. */
|
|
237
241
|
add(obj: SchemaDefinition<SchemaDefinitionType<EnforcedDocType>> | Schema, prefix?: string): this;
|
|
@@ -311,7 +315,7 @@ declare module 'mongoose' {
|
|
|
311
315
|
pathType(path: string): string;
|
|
312
316
|
|
|
313
317
|
/** Registers a plugin for this schema. */
|
|
314
|
-
plugin<PFunc extends PluginFunction<DocType,
|
|
318
|
+
plugin<PFunc extends PluginFunction<DocType, TModelType, any, any, any, any>, POptions extends Parameters<PFunc>[1] = Parameters<PFunc>[1]>(fn: PFunc, opts?: POptions): this;
|
|
315
319
|
|
|
316
320
|
/** Defines a post hook for the model. */
|
|
317
321
|
|
|
@@ -320,7 +324,7 @@ declare module 'mongoose' {
|
|
|
320
324
|
post<T = Query<any, any>>(method: MongooseQueryMiddleware | MongooseQueryMiddleware[] | RegExp, options: SchemaPostOptions & { errorHandler: true }, fn: ErrorHandlingMiddlewareWithOption<T>): this;
|
|
321
325
|
post<T = THydratedDocumentType>(method: MongooseDocumentMiddleware | MongooseDocumentMiddleware[] | RegExp, options: SchemaPostOptions & { errorHandler: true }, fn: ErrorHandlingMiddlewareWithOption<T>): this;
|
|
322
326
|
post<T extends Aggregate<any>>(method: 'aggregate' | RegExp, options: SchemaPostOptions & { errorHandler: true }, fn: ErrorHandlingMiddlewareWithOption<T, Array<any>>): this;
|
|
323
|
-
post<T =
|
|
327
|
+
post<T = TModelType>(method: 'insertMany' | RegExp, options: SchemaPostOptions & { errorHandler: true }, fn: ErrorHandlingMiddlewareWithOption<T>): this;
|
|
324
328
|
|
|
325
329
|
// this = never since it never happens
|
|
326
330
|
post<T = never>(method: MongooseQueryOrDocumentMiddleware | MongooseQueryOrDocumentMiddleware[] | RegExp, options: SchemaPostOptions & { document: false, query: false }, fn: PostMiddlewareFunction<never, never>): this;
|
|
@@ -358,14 +362,14 @@ declare module 'mongoose' {
|
|
|
358
362
|
// method aggregate and insertMany with PostMiddlewareFunction
|
|
359
363
|
post<T extends Aggregate<any>>(method: 'aggregate' | RegExp, fn: PostMiddlewareFunction<T, Array<AggregateExtract<T>>>): this;
|
|
360
364
|
post<T extends Aggregate<any>>(method: 'aggregate' | RegExp, options: SchemaPostOptions, fn: PostMiddlewareFunction<T, Array<AggregateExtract<T>>>): this;
|
|
361
|
-
post<T =
|
|
362
|
-
post<T =
|
|
365
|
+
post<T = TModelType>(method: 'insertMany' | RegExp, fn: PostMiddlewareFunction<T, T>): this;
|
|
366
|
+
post<T = TModelType>(method: 'insertMany' | RegExp, options: SchemaPostOptions, fn: PostMiddlewareFunction<T, T>): this;
|
|
363
367
|
|
|
364
368
|
// method aggregate and insertMany with ErrorHandlingMiddlewareFunction
|
|
365
369
|
post<T extends Aggregate<any>>(method: 'aggregate' | RegExp, fn: ErrorHandlingMiddlewareFunction<T, Array<any>>): this;
|
|
366
370
|
post<T extends Aggregate<any>>(method: 'aggregate' | RegExp, options: SchemaPostOptions, fn: ErrorHandlingMiddlewareFunction<T, Array<any>>): this;
|
|
367
|
-
post<T =
|
|
368
|
-
post<T =
|
|
371
|
+
post<T = TModelType>(method: 'insertMany' | RegExp, fn: ErrorHandlingMiddlewareFunction<T>): this;
|
|
372
|
+
post<T = TModelType>(method: 'insertMany' | RegExp, options: SchemaPostOptions, fn: ErrorHandlingMiddlewareFunction<T>): this;
|
|
369
373
|
|
|
370
374
|
/** Defines a pre hook for the model. */
|
|
371
375
|
// this = never since it never happens
|
|
@@ -390,8 +394,8 @@ declare module 'mongoose' {
|
|
|
390
394
|
pre<T extends Aggregate<any>>(method: 'aggregate' | RegExp, fn: PreMiddlewareFunction<T>): this;
|
|
391
395
|
pre<T extends Aggregate<any>>(method: 'aggregate' | RegExp, options: SchemaPreOptions, fn: PreMiddlewareFunction<T>): this;
|
|
392
396
|
/* method insertMany */
|
|
393
|
-
pre<T =
|
|
394
|
-
pre<T =
|
|
397
|
+
pre<T = TModelType>(method: 'insertMany' | RegExp, fn: (this: T, next: (err?: CallbackError) => void, docs: any | Array<any>) => void | Promise<void>): this;
|
|
398
|
+
pre<T = TModelType>(method: 'insertMany' | RegExp, options: SchemaPreOptions, fn: (this: T, next: (err?: CallbackError) => void, docs: any | Array<any>) => void | Promise<void>): this;
|
|
395
399
|
|
|
396
400
|
/** Object of currently defined query helpers on this schema. */
|
|
397
401
|
query: TQueryHelpers;
|
|
@@ -413,11 +417,12 @@ declare module 'mongoose' {
|
|
|
413
417
|
|
|
414
418
|
/** Adds static "class" methods to Models compiled from this schema. */
|
|
415
419
|
static<K extends keyof TStaticMethods>(name: K, fn: TStaticMethods[K]): this;
|
|
416
|
-
static(obj: { [F in keyof TStaticMethods]: TStaticMethods[F] } & { [name: string]: (this:
|
|
417
|
-
static(name: string, fn: (this:
|
|
420
|
+
static(obj: { [F in keyof TStaticMethods]: TStaticMethods[F] } & { [name: string]: (this: TModelType, ...args: any[]) => any }): this;
|
|
421
|
+
static(name: string, fn: (this: TModelType, ...args: any[]) => any): this;
|
|
418
422
|
|
|
419
423
|
/** Object of currently defined statics on this schema. */
|
|
420
|
-
statics: { [F in keyof TStaticMethods]: TStaticMethods[F] } &
|
|
424
|
+
statics: { [F in keyof TStaticMethods]: TStaticMethods[F] } &
|
|
425
|
+
{ [name: string]: (this: TModelType, ...args: any[]) => unknown };
|
|
421
426
|
|
|
422
427
|
/** Creates a virtual type with the given name. */
|
|
423
428
|
virtual<T = HydratedDocument<DocType, TVirtuals & TInstanceMethods, TQueryHelpers>>(
|
|
@@ -430,6 +435,8 @@ declare module 'mongoose' {
|
|
|
430
435
|
|
|
431
436
|
/** Returns the virtual type with the given `name`. */
|
|
432
437
|
virtualpath<T = THydratedDocumentType>(name: string): VirtualType<T> | null;
|
|
438
|
+
|
|
439
|
+
static ObjectId: typeof Schema.Types.ObjectId;
|
|
433
440
|
}
|
|
434
441
|
|
|
435
442
|
export type NumberSchemaDefinition = typeof Number | 'number' | 'Number' | typeof Schema.Types.Number;
|