mongoose 9.3.3 → 9.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/connection.js +19 -7
- package/lib/document.js +108 -48
- package/lib/drivers/node-mongodb-native/collection.js +37 -10
- package/lib/drivers/node-mongodb-native/connection.js +13 -0
- package/lib/error/index.js +1 -1
- package/lib/helpers/setDefaultsOnInsert.js +1 -1
- package/lib/model.js +6 -3
- package/lib/schema/array.js +1 -3
- package/lib/schema/bigint.js +1 -3
- package/lib/schema/boolean.js +1 -3
- package/lib/schema/buffer.js +1 -3
- package/lib/schema/date.js +1 -3
- package/lib/schema/decimal128.js +1 -3
- package/lib/schema/documentArray.js +2 -4
- package/lib/schema/double.js +1 -3
- package/lib/schema/int32.js +1 -3
- package/lib/schema/map.js +1 -4
- package/lib/schema/number.js +2 -4
- package/lib/schema/objectId.js +1 -3
- package/lib/schema/string.js +1 -3
- package/lib/schema/subdocument.js +1 -3
- package/lib/schema/union.js +50 -0
- package/lib/schema/uuid.js +1 -3
- package/lib/schema.js +2 -2
- package/lib/schemaType.js +37 -4
- package/lib/types/array/methods/index.js +4 -4
- package/lib/utils.js +12 -2
- package/package.json +6 -6
- package/types/document.d.ts +40 -3
- package/types/index.d.ts +17 -2
- package/types/models.d.ts +2 -2
- package/types/populate.d.ts +44 -0
- package/types/query.d.ts +26 -9
- package/types/utility.d.ts +2 -2
- package/lib/helpers/createJSONSchemaTypeDefinition.js +0 -24
- /package/{tstyche.config.json → tstyche.json} +0 -0
package/lib/connection.js
CHANGED
|
@@ -1005,10 +1005,7 @@ Connection.prototype.error = function error(err, callback) {
|
|
|
1005
1005
|
Connection.prototype.onOpen = function() {
|
|
1006
1006
|
this.readyState = STATES.connected;
|
|
1007
1007
|
|
|
1008
|
-
|
|
1009
|
-
d.fn.apply(d.ctx, d.args);
|
|
1010
|
-
}
|
|
1011
|
-
this._queue = [];
|
|
1008
|
+
this._flushQueue();
|
|
1012
1009
|
|
|
1013
1010
|
// avoid having the collection subscribe to our event emitter
|
|
1014
1011
|
// to prevent 0.3 warning
|
|
@@ -1021,6 +1018,21 @@ Connection.prototype.onOpen = function() {
|
|
|
1021
1018
|
this.emit('open');
|
|
1022
1019
|
};
|
|
1023
1020
|
|
|
1021
|
+
/**
|
|
1022
|
+
* Flush all buffered operations in `_queue`. Called by `onOpen()` and
|
|
1023
|
+
* by the heartbeat handler when a previously-stale connection recovers.
|
|
1024
|
+
*
|
|
1025
|
+
* @api private
|
|
1026
|
+
*/
|
|
1027
|
+
|
|
1028
|
+
Connection.prototype._flushQueue = function _flushQueue() {
|
|
1029
|
+
const queue = this._queue;
|
|
1030
|
+
this._queue = [];
|
|
1031
|
+
for (const d of queue) {
|
|
1032
|
+
d.fn.apply(d.ctx, d.args);
|
|
1033
|
+
}
|
|
1034
|
+
};
|
|
1035
|
+
|
|
1024
1036
|
/**
|
|
1025
1037
|
* Opens the connection with a URI using `MongoClient.connect()`.
|
|
1026
1038
|
*
|
|
@@ -1033,11 +1045,11 @@ Connection.prototype.onOpen = function() {
|
|
|
1033
1045
|
* @param {string} [options.pass] password for authentication, equivalent to `options.auth.password`. Maintained for backwards compatibility.
|
|
1034
1046
|
* @param {number} [options.maxPoolSize=100] 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).
|
|
1035
1047
|
* @param {number} [options.minPoolSize=0] 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).
|
|
1036
|
-
* @param {number} [options.serverSelectionTimeoutMS]
|
|
1037
|
-
* @param {number} [options.heartbeatFrequencyMS]
|
|
1048
|
+
* @param {number} [options.serverSelectionTimeoutMS] The MongoDB driver will try to find a server to send any given operation to, and keep retrying for `serverSelectionTimeoutMS` milliseconds before erroring out. If not set, the MongoDB driver defaults to using `30000` (30 seconds).
|
|
1049
|
+
* @param {number} [options.heartbeatFrequencyMS] 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.
|
|
1038
1050
|
* @param {boolean} [options.autoIndex=true] Mongoose-specific option. Set to false to disable automatic index creation for all models associated with this connection.
|
|
1039
1051
|
* @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.
|
|
1040
|
-
* @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
|
|
1052
|
+
* @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.
|
|
1041
1053
|
* @param {boolean} [options.autoCreate=false] Set to `true` to make Mongoose automatically call `createCollection()` on every model created on this connection.
|
|
1042
1054
|
* @returns {Promise<Connection>}
|
|
1043
1055
|
* @api public
|
package/lib/document.js
CHANGED
|
@@ -2981,9 +2981,40 @@ function _getPathsToValidate(doc, pathsToValidate, pathsToSkip, isNestedValidate
|
|
|
2981
2981
|
// Skip $* paths - they represent map schemas, not actual document paths
|
|
2982
2982
|
return;
|
|
2983
2983
|
}
|
|
2984
|
+
|
|
2985
|
+
const _pathType = doc.$__schema.path(p);
|
|
2986
|
+
|
|
2987
|
+
// Optimization: if primitive path with no validators, or array of primitives
|
|
2988
|
+
// with no validators, skip validating this path entirely.
|
|
2989
|
+
// Note: paths with no _pathType (e.g. sub-paths under Mixed) must still be
|
|
2990
|
+
// added, as they trigger validation of the parent Mixed path.
|
|
2991
|
+
if (_pathType) {
|
|
2992
|
+
if (!_pathType.schema &&
|
|
2993
|
+
!_pathType.embeddedSchemaType &&
|
|
2994
|
+
_pathType.validators.length === 0 &&
|
|
2995
|
+
!_pathType.$parentSchemaDocArray &&
|
|
2996
|
+
// gh-15957: skip this optimization for SchemaMap as maps can contain subdocuments
|
|
2997
|
+
// that need validation even if the map itself has no validators
|
|
2998
|
+
!_pathType.$isSchemaMap &&
|
|
2999
|
+
!_pathType.$isSchemaUnion) {
|
|
3000
|
+
return;
|
|
3001
|
+
} else if (_pathType.$isMongooseArray &&
|
|
3002
|
+
!_pathType.$isMongooseDocumentArray && // Skip document arrays...
|
|
3003
|
+
!_pathType.embeddedSchemaType.$isMongooseArray && // and arrays of arrays
|
|
3004
|
+
_pathType.validators.length === 0 && // and arrays with top-level validators
|
|
3005
|
+
_pathType.embeddedSchemaType.validators.length === 0) {
|
|
3006
|
+
return;
|
|
3007
|
+
}
|
|
3008
|
+
}
|
|
3009
|
+
|
|
2984
3010
|
paths.add(p);
|
|
2985
3011
|
}
|
|
2986
3012
|
|
|
3013
|
+
const onlyPrimitiveValues = doc.$__hasOnlyPrimitiveValues();
|
|
3014
|
+
if (onlyPrimitiveValues && paths.size === 0) {
|
|
3015
|
+
return [[], doValidateOptions];
|
|
3016
|
+
}
|
|
3017
|
+
|
|
2987
3018
|
if (!isNestedValidate) {
|
|
2988
3019
|
// If we're validating a subdocument, all this logic will run anyway on the top-level document, so skip for subdocuments.
|
|
2989
3020
|
// But only run for top-level subdocuments, because we're looking for subdocuments that are not modified at top-level but
|
|
@@ -3048,37 +3079,17 @@ function _getPathsToValidate(doc, pathsToValidate, pathsToSkip, isNestedValidate
|
|
|
3048
3079
|
}
|
|
3049
3080
|
}
|
|
3050
3081
|
|
|
3051
|
-
|
|
3052
|
-
const
|
|
3053
|
-
|
|
3054
|
-
|
|
3055
|
-
|
|
3056
|
-
|
|
3057
|
-
|
|
3058
|
-
|
|
3059
|
-
if (p == null || p.startsWith(_pathType.path + '.')) {
|
|
3060
|
-
paths.delete(p);
|
|
3082
|
+
if (!onlyPrimitiveValues) {
|
|
3083
|
+
for (const path of paths) {
|
|
3084
|
+
const _pathType = doc.$__schema.path(path);
|
|
3085
|
+
if (_pathType && _pathType.$isMongooseDocumentArray) {
|
|
3086
|
+
for (const p of paths) {
|
|
3087
|
+
if (p == null || p.startsWith(_pathType.path + '.')) {
|
|
3088
|
+
paths.delete(p);
|
|
3089
|
+
}
|
|
3061
3090
|
}
|
|
3062
3091
|
}
|
|
3063
3092
|
}
|
|
3064
|
-
|
|
3065
|
-
// Optimization: if primitive path with no validators, or array of primitives
|
|
3066
|
-
// with no validators, skip validating this path entirely.
|
|
3067
|
-
if (!_pathType.schema &&
|
|
3068
|
-
!_pathType.embeddedSchemaType &&
|
|
3069
|
-
_pathType.validators.length === 0 &&
|
|
3070
|
-
!_pathType.$parentSchemaDocArray &&
|
|
3071
|
-
// gh-15957: skip this optimization for SchemaMap as maps can contain subdocuments
|
|
3072
|
-
// that need validation even if the map itself has no validators
|
|
3073
|
-
!_pathType.$isSchemaMap) {
|
|
3074
|
-
paths.delete(path);
|
|
3075
|
-
} else if (_pathType.$isMongooseArray &&
|
|
3076
|
-
!_pathType.$isMongooseDocumentArray && // Skip document arrays...
|
|
3077
|
-
!_pathType.embeddedSchemaType.$isMongooseArray && // and arrays of arrays
|
|
3078
|
-
_pathType.validators.length === 0 && // and arrays with top-level validators
|
|
3079
|
-
_pathType.embeddedSchemaType.validators.length === 0) {
|
|
3080
|
-
paths.delete(path);
|
|
3081
|
-
}
|
|
3082
3093
|
}
|
|
3083
3094
|
|
|
3084
3095
|
|
|
@@ -3595,25 +3606,21 @@ Document.prototype.$isValid = function(path) {
|
|
|
3595
3606
|
Document.prototype.$__reset = function reset() {
|
|
3596
3607
|
let _this = this;
|
|
3597
3608
|
|
|
3598
|
-
|
|
3599
|
-
|
|
3609
|
+
const onlyPrimitiveValues = this.$__hasOnlyPrimitiveValues();
|
|
3610
|
+
|
|
3611
|
+
// Skip for subdocuments. Also skip if doc only has primitive values,
|
|
3612
|
+
// because primitives can't be subdocs.
|
|
3613
|
+
const subdocs = !this.$isSubdocument && !onlyPrimitiveValues ? this.$getAllSubdocs({ useCache: true }) : null;
|
|
3600
3614
|
if (subdocs?.length > 0) {
|
|
3601
3615
|
for (const subdoc of subdocs) {
|
|
3602
3616
|
subdoc.$__reset();
|
|
3603
3617
|
}
|
|
3604
3618
|
}
|
|
3605
3619
|
|
|
3606
|
-
//
|
|
3607
|
-
|
|
3608
|
-
|
|
3609
|
-
|
|
3610
|
-
if (type && typeof type.clearAtomics === 'function') {
|
|
3611
|
-
type.clearAtomics();
|
|
3612
|
-
} else if (type && type[arrayAtomicsSymbol]) {
|
|
3613
|
-
type[arrayAtomicsBackupSymbol] = type[arrayAtomicsSymbol];
|
|
3614
|
-
type[arrayAtomicsSymbol] = {};
|
|
3615
|
-
}
|
|
3616
|
-
});
|
|
3620
|
+
// Clear atomics on dirty paths. Walk the modified and default paths
|
|
3621
|
+
// directly instead of calling $__dirty(), which builds intermediate
|
|
3622
|
+
// arrays, a Map, and does parent-path deduplication we don't need here.
|
|
3623
|
+
this.$__resetAtomics();
|
|
3617
3624
|
|
|
3618
3625
|
this.$__.backup = {};
|
|
3619
3626
|
this.$__.backup.activePaths = {
|
|
@@ -3636,6 +3643,40 @@ Document.prototype.$__reset = function reset() {
|
|
|
3636
3643
|
return this;
|
|
3637
3644
|
};
|
|
3638
3645
|
|
|
3646
|
+
/*!
|
|
3647
|
+
* Clear atomics on all dirty (modified + default) paths. This is a lighter
|
|
3648
|
+
* alternative to calling `$__dirty()` when we only need to clear atomics
|
|
3649
|
+
* and don't need the full {path, value, schema} objects or parent-path
|
|
3650
|
+
* deduplication.
|
|
3651
|
+
*/
|
|
3652
|
+
|
|
3653
|
+
Document.prototype.$__resetAtomics = function $__resetAtomics() {
|
|
3654
|
+
const activePaths = this.$__.activePaths;
|
|
3655
|
+
const modifyPaths = activePaths.getStatePaths('modify');
|
|
3656
|
+
const defaultPaths = activePaths.getStatePaths('default');
|
|
3657
|
+
|
|
3658
|
+
_clearAtomicsOnPaths(this, modifyPaths);
|
|
3659
|
+
_clearAtomicsOnPaths(this, defaultPaths);
|
|
3660
|
+
};
|
|
3661
|
+
|
|
3662
|
+
function _clearAtomicsOnPaths(doc, paths) {
|
|
3663
|
+
if (paths == null) {
|
|
3664
|
+
return;
|
|
3665
|
+
}
|
|
3666
|
+
const keys = Object.keys(paths);
|
|
3667
|
+
for (let i = 0; i < keys.length; ++i) {
|
|
3668
|
+
const type = doc.$__getValue(keys[i]);
|
|
3669
|
+
if (type != null) {
|
|
3670
|
+
if (typeof type.clearAtomics === 'function') {
|
|
3671
|
+
type.clearAtomics();
|
|
3672
|
+
} else if (type[arrayAtomicsSymbol]) {
|
|
3673
|
+
type[arrayAtomicsBackupSymbol] = type[arrayAtomicsSymbol];
|
|
3674
|
+
type[arrayAtomicsSymbol] = {};
|
|
3675
|
+
}
|
|
3676
|
+
}
|
|
3677
|
+
}
|
|
3678
|
+
}
|
|
3679
|
+
|
|
3639
3680
|
/*!
|
|
3640
3681
|
* ignore
|
|
3641
3682
|
*/
|
|
@@ -4995,34 +5036,53 @@ Document.prototype.$__fullPath = function(path) {
|
|
|
4995
5036
|
* });
|
|
4996
5037
|
*
|
|
4997
5038
|
* // returns an empty object, no changes happened yet
|
|
4998
|
-
* user
|
|
5039
|
+
* user.$getChanges(); // { }
|
|
4999
5040
|
*
|
|
5000
5041
|
* user.country = undefined;
|
|
5001
5042
|
* user.age = 26;
|
|
5002
5043
|
*
|
|
5003
|
-
* user
|
|
5044
|
+
* user.$getChanges(); // { $set: { age: 26 }, { $unset: { country: 1 } } }
|
|
5004
5045
|
*
|
|
5005
5046
|
* await user.save();
|
|
5006
5047
|
*
|
|
5007
|
-
* user
|
|
5048
|
+
* user.$getChanges(); // { }
|
|
5008
5049
|
*
|
|
5009
|
-
* Modifying the object that
|
|
5010
|
-
* change tracking state. Even if you `delete user
|
|
5050
|
+
* Modifying the object that `$getChanges()` returns does not affect the document's
|
|
5051
|
+
* change tracking state. Even if you `delete user.$getChanges().$set`, Mongoose
|
|
5011
5052
|
* will still send a `$set` to the server.
|
|
5012
5053
|
*
|
|
5013
5054
|
* @return {object}
|
|
5014
5055
|
* @api public
|
|
5015
|
-
* @method getChanges
|
|
5056
|
+
* @method $getChanges
|
|
5016
5057
|
* @memberOf Document
|
|
5017
5058
|
* @instance
|
|
5018
5059
|
*/
|
|
5019
5060
|
|
|
5020
|
-
Document.prototype
|
|
5061
|
+
Document.prototype.$getChanges = function() {
|
|
5021
5062
|
const delta = this.$__delta();
|
|
5022
5063
|
const changes = delta ? delta[1] : {};
|
|
5023
5064
|
return changes;
|
|
5024
5065
|
};
|
|
5025
5066
|
|
|
5067
|
+
/**
|
|
5068
|
+
* **Deprecated.** Use `$getChanges()` instead.
|
|
5069
|
+
*
|
|
5070
|
+
* Returns the changes that happened to the document
|
|
5071
|
+
* in the format that will be sent to MongoDB.
|
|
5072
|
+
*
|
|
5073
|
+
* @return {Object}
|
|
5074
|
+
* @deprecated Use `$getChanges()` instead. `getChanges` does not use the `$` prefix convention and may conflict with user-defined schema methods/properties.
|
|
5075
|
+
* @api public
|
|
5076
|
+
* @method getChanges
|
|
5077
|
+
* @memberOf Document
|
|
5078
|
+
* @instance
|
|
5079
|
+
*/
|
|
5080
|
+
|
|
5081
|
+
Document.prototype.getChanges = function() {
|
|
5082
|
+
utils.warn('`getChanges()` is deprecated, use `$getChanges()` instead.');
|
|
5083
|
+
return this.$getChanges();
|
|
5084
|
+
};
|
|
5085
|
+
|
|
5026
5086
|
/**
|
|
5027
5087
|
* Produces a special query document of the modified properties used in updates.
|
|
5028
5088
|
*
|
|
@@ -89,12 +89,11 @@ NativeCollection.prototype._getCollection = function _getCollection() {
|
|
|
89
89
|
function iter(i) {
|
|
90
90
|
NativeCollection.prototype[i] = function() {
|
|
91
91
|
const collection = this._getCollection();
|
|
92
|
-
const args =
|
|
92
|
+
const args = arguments;
|
|
93
93
|
const _this = this;
|
|
94
94
|
const globalDebug = _this?.conn?.base?.options?.debug;
|
|
95
95
|
const connectionDebug = _this?.conn?.options?.debug;
|
|
96
96
|
const debug = connectionDebug == null ? globalDebug : connectionDebug;
|
|
97
|
-
const opId = new ObjectId();
|
|
98
97
|
|
|
99
98
|
// If user force closed, queueing will hang forever. See #5664
|
|
100
99
|
if (this.conn.$wasForceClosed) {
|
|
@@ -108,9 +107,21 @@ function iter(i) {
|
|
|
108
107
|
}
|
|
109
108
|
}
|
|
110
109
|
|
|
110
|
+
// Lazily generate opId and argsArray only if necessary because they have
|
|
111
|
+
// a non-trivial performance cost.
|
|
112
|
+
let opId = null;
|
|
113
|
+
let argsArray = null;
|
|
114
|
+
const hasOperationListeners = this.conn.listenerCount('operation-start') > 0 || this.conn.listenerCount('operation-end') > 0;
|
|
115
|
+
if (hasOperationListeners || debug) {
|
|
116
|
+
opId = new ObjectId();
|
|
117
|
+
}
|
|
118
|
+
|
|
111
119
|
let timeout = null;
|
|
112
120
|
let waitForBufferPromise = null;
|
|
113
121
|
if (this._shouldBufferCommands() && this.buffer) {
|
|
122
|
+
if (opId == null) {
|
|
123
|
+
opId = new ObjectId();
|
|
124
|
+
}
|
|
114
125
|
this.conn.emit('buffer', {
|
|
115
126
|
_id: opId,
|
|
116
127
|
modelName: _this.modelName,
|
|
@@ -145,11 +156,14 @@ function iter(i) {
|
|
|
145
156
|
|
|
146
157
|
if (debug) {
|
|
147
158
|
if (typeof debug === 'function') {
|
|
159
|
+
if (argsArray == null) {
|
|
160
|
+
argsArray = Array.from(args);
|
|
161
|
+
}
|
|
148
162
|
let argsToAdd = null;
|
|
149
|
-
if (typeof
|
|
150
|
-
argsToAdd =
|
|
163
|
+
if (typeof argsArray[argsArray.length - 1] == 'function') {
|
|
164
|
+
argsToAdd = argsArray.slice(0, argsArray.length - 1);
|
|
151
165
|
} else {
|
|
152
|
-
argsToAdd =
|
|
166
|
+
argsToAdd = argsArray;
|
|
153
167
|
}
|
|
154
168
|
debug.apply(_this,
|
|
155
169
|
[_this.name, i].concat(argsToAdd));
|
|
@@ -162,7 +176,12 @@ function iter(i) {
|
|
|
162
176
|
}
|
|
163
177
|
}
|
|
164
178
|
|
|
165
|
-
|
|
179
|
+
if (hasOperationListeners) {
|
|
180
|
+
if (argsArray == null) {
|
|
181
|
+
argsArray = Array.from(args);
|
|
182
|
+
}
|
|
183
|
+
this.conn.emit('operation-start', { _id: opId, modelName: _this.modelName, collectionName: this.name, method: i, params: argsArray });
|
|
184
|
+
}
|
|
166
185
|
|
|
167
186
|
try {
|
|
168
187
|
if (collection == null) {
|
|
@@ -179,20 +198,26 @@ function iter(i) {
|
|
|
179
198
|
if (timeout != null) {
|
|
180
199
|
clearTimeout(timeout);
|
|
181
200
|
}
|
|
182
|
-
|
|
201
|
+
if (hasOperationListeners) {
|
|
202
|
+
this.conn.emit('operation-end', { _id: opId, modelName: _this.modelName, collectionName: this.name, method: i, result });
|
|
203
|
+
}
|
|
183
204
|
return result;
|
|
184
205
|
},
|
|
185
206
|
error => {
|
|
186
207
|
if (timeout != null) {
|
|
187
208
|
clearTimeout(timeout);
|
|
188
209
|
}
|
|
189
|
-
|
|
210
|
+
if (hasOperationListeners) {
|
|
211
|
+
this.conn.emit('operation-end', { _id: opId, modelName: _this.modelName, collectionName: this.name, method: i, error });
|
|
212
|
+
}
|
|
190
213
|
throw error;
|
|
191
214
|
}
|
|
192
215
|
);
|
|
193
216
|
}
|
|
194
217
|
|
|
195
|
-
|
|
218
|
+
if (hasOperationListeners) {
|
|
219
|
+
this.conn.emit('operation-end', { _id: opId, modelName: _this.modelName, collectionName: this.name, method: i, result: ret });
|
|
220
|
+
}
|
|
196
221
|
if (timeout != null) {
|
|
197
222
|
clearTimeout(timeout);
|
|
198
223
|
}
|
|
@@ -201,7 +226,9 @@ function iter(i) {
|
|
|
201
226
|
if (timeout != null) {
|
|
202
227
|
clearTimeout(timeout);
|
|
203
228
|
}
|
|
204
|
-
|
|
229
|
+
if (hasOperationListeners) {
|
|
230
|
+
this.conn.emit('operation-end', { _id: opId, modelName: _this.modelName, collectionName: this.name, method: i, error: error });
|
|
231
|
+
}
|
|
205
232
|
throw error;
|
|
206
233
|
}
|
|
207
234
|
};
|
|
@@ -14,6 +14,10 @@ const setTimeout = require('../../helpers/timers').setTimeout;
|
|
|
14
14
|
const utils = require('../../utils');
|
|
15
15
|
const Schema = require('../../schema');
|
|
16
16
|
|
|
17
|
+
// Snapshot the native Date constructor to ensure Date.now()
|
|
18
|
+
// bypasses timer mocks such as those set up by useFakeTimers().
|
|
19
|
+
const Date = globalThis.Date;
|
|
20
|
+
|
|
17
21
|
/**
|
|
18
22
|
* A [node-mongodb-native](https://github.com/mongodb/node-mongodb-native) connection implementation.
|
|
19
23
|
*
|
|
@@ -482,6 +486,15 @@ function _setClient(conn, client, options, dbName) {
|
|
|
482
486
|
for (const otherDb of conn.otherDbs) {
|
|
483
487
|
otherDb._lastHeartbeatAt = conn._lastHeartbeatAt;
|
|
484
488
|
}
|
|
489
|
+
// Flush buffered operations if the connection is no longer stale (gh-16183)
|
|
490
|
+
if (conn._queue.length > 0 && conn.readyState === STATES.connected) {
|
|
491
|
+
conn._flushQueue();
|
|
492
|
+
}
|
|
493
|
+
for (const otherDb of conn.otherDbs) {
|
|
494
|
+
if (otherDb._queue.length > 0 && otherDb.readyState === STATES.connected) {
|
|
495
|
+
otherDb._flushQueue();
|
|
496
|
+
}
|
|
497
|
+
}
|
|
485
498
|
});
|
|
486
499
|
|
|
487
500
|
if (options.monitorCommands) {
|
package/lib/error/index.js
CHANGED
|
@@ -32,7 +32,7 @@ const MongooseError = require('./mongooseError');
|
|
|
32
32
|
* - `ValidationError`: error returned from [`validate()`](https://mongoosejs.com/docs/api/document.html#Document.prototype.validate()) or [`validateSync()`](https://mongoosejs.com/docs/api/document.html#Document.prototype.validateSync()). Contains zero or more `ValidatorError` instances in `.errors` property.
|
|
33
33
|
* - `MissingSchemaError`: You called `mongoose.Document()` without a schema
|
|
34
34
|
* - `ObjectExpectedError`: Thrown when you set a nested path to a non-object value with [strict mode set](https://mongoosejs.com/docs/guide.html#strict).
|
|
35
|
-
* - `ObjectParameterError`: Thrown when you pass a non-object value to a function which expects an object as a
|
|
35
|
+
* - `ObjectParameterError`: Thrown when you pass a non-object value to a function which expects an object as a parameter
|
|
36
36
|
* - `OverwriteModelError`: Thrown when you call [`mongoose.model()`](https://mongoosejs.com/docs/api/mongoose.html#Mongoose.model()) to re-define a model that was already defined.
|
|
37
37
|
* - `ParallelSaveError`: Thrown when you call [`save()`](https://mongoosejs.com/docs/api/model.html#Model.prototype.save()) on a document when the same document instance is already saving.
|
|
38
38
|
* - `StrictModeError`: Thrown when you set a path that isn't the schema and [strict mode](https://mongoosejs.com/docs/guide.html#strict) is set to `throw`.
|
|
@@ -84,7 +84,7 @@ module.exports = function(filter, schema, castedDoc, options, queryMongooseOptio
|
|
|
84
84
|
if (schemaType.path === '_id' && schemaType.options.auto) {
|
|
85
85
|
return;
|
|
86
86
|
}
|
|
87
|
-
const def = schemaType.getDefault(null,
|
|
87
|
+
const def = schemaType.getDefault(null, false, { context });
|
|
88
88
|
if (typeof def === 'undefined') {
|
|
89
89
|
return;
|
|
90
90
|
}
|
package/lib/model.js
CHANGED
|
@@ -189,8 +189,11 @@ Model.prototype.db;
|
|
|
189
189
|
*/
|
|
190
190
|
|
|
191
191
|
Model.useConnection = function useConnection(connection) {
|
|
192
|
-
if (
|
|
193
|
-
throw new MongooseError('
|
|
192
|
+
if (typeof connection?.model !== 'function' || typeof connection.collection !== 'function' || typeof connection.base?.version !== 'string') {
|
|
193
|
+
throw new MongooseError('`useConnection()` requires a Mongoose connection.');
|
|
194
|
+
}
|
|
195
|
+
if (this.db?.base?.version && this.db?.base?.version !== connection.base?.version) {
|
|
196
|
+
throw new MongooseError(`The connection passed to \`useConnection()\` has a different version of Mongoose (${connection.base?.version}) than the model you are using (${this.db?.base?.version}).`);
|
|
194
197
|
}
|
|
195
198
|
if (this.db) {
|
|
196
199
|
delete this.db.models[this.modelName];
|
|
@@ -635,7 +638,7 @@ Model.prototype.save = async function save(options) {
|
|
|
635
638
|
if (this.$__.saving) {
|
|
636
639
|
parallelSave = new ParallelSaveError(this);
|
|
637
640
|
} else {
|
|
638
|
-
this.$__.saving =
|
|
641
|
+
this.$__.saving = true;
|
|
639
642
|
}
|
|
640
643
|
|
|
641
644
|
options = new SaveOptions(options);
|
package/lib/schema/array.js
CHANGED
|
@@ -21,7 +21,6 @@ const isOperator = require('../helpers/query/isOperator');
|
|
|
21
21
|
const util = require('util');
|
|
22
22
|
const utils = require('../utils');
|
|
23
23
|
const castToNumber = require('./operators/helpers').castToNumber;
|
|
24
|
-
const createJSONSchemaTypeDefinition = require('../helpers/createJSONSchemaTypeDefinition');
|
|
25
24
|
const geospatial = require('./operators/geospatial');
|
|
26
25
|
const getDiscriminatorByValue = require('../helpers/discriminator/getDiscriminatorByValue');
|
|
27
26
|
|
|
@@ -684,9 +683,8 @@ handle.$in = SchemaType.prototype.$conditionalHandlers.$in;
|
|
|
684
683
|
|
|
685
684
|
SchemaArray.prototype.toJSONSchema = function toJSONSchema(options) {
|
|
686
685
|
const embeddedSchemaType = this.getEmbeddedSchemaType();
|
|
687
|
-
const isRequired = this.options.required && typeof this.options.required !== 'function';
|
|
688
686
|
return {
|
|
689
|
-
...
|
|
687
|
+
...this._createJSONSchemaTypeDefinition('array', 'array', options),
|
|
690
688
|
items: embeddedSchemaType.toJSONSchema(options)
|
|
691
689
|
};
|
|
692
690
|
};
|
package/lib/schema/bigint.js
CHANGED
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
const CastError = require('../error/cast');
|
|
8
8
|
const SchemaType = require('../schemaType');
|
|
9
9
|
const castBigInt = require('../cast/bigint');
|
|
10
|
-
const createJSONSchemaTypeDefinition = require('../helpers/createJSONSchemaTypeDefinition');
|
|
11
10
|
|
|
12
11
|
/**
|
|
13
12
|
* BigInt SchemaType constructor.
|
|
@@ -267,8 +266,7 @@ SchemaBigInt.prototype._castNullish = function _castNullish(v) {
|
|
|
267
266
|
*/
|
|
268
267
|
|
|
269
268
|
SchemaBigInt.prototype.toJSONSchema = function toJSONSchema(options) {
|
|
270
|
-
|
|
271
|
-
return createJSONSchemaTypeDefinition('string', 'long', options?.useBsonType, isRequired);
|
|
269
|
+
return this._createJSONSchemaTypeDefinition('string', 'long', options);
|
|
272
270
|
};
|
|
273
271
|
|
|
274
272
|
SchemaBigInt.prototype.autoEncryptionType = function autoEncryptionType() {
|
package/lib/schema/boolean.js
CHANGED
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
const CastError = require('../error/cast');
|
|
8
8
|
const SchemaType = require('../schemaType');
|
|
9
9
|
const castBoolean = require('../cast/boolean');
|
|
10
|
-
const createJSONSchemaTypeDefinition = require('../helpers/createJSONSchemaTypeDefinition');
|
|
11
10
|
|
|
12
11
|
/**
|
|
13
12
|
* Boolean SchemaType constructor.
|
|
@@ -317,8 +316,7 @@ SchemaBoolean.prototype._castNullish = function _castNullish(v) {
|
|
|
317
316
|
*/
|
|
318
317
|
|
|
319
318
|
SchemaBoolean.prototype.toJSONSchema = function toJSONSchema(options) {
|
|
320
|
-
|
|
321
|
-
return createJSONSchemaTypeDefinition('boolean', 'bool', options?.useBsonType, isRequired);
|
|
319
|
+
return this._createJSONSchemaTypeDefinition('boolean', 'bool', options);
|
|
322
320
|
};
|
|
323
321
|
|
|
324
322
|
SchemaBoolean.prototype.autoEncryptionType = function autoEncryptionType() {
|
package/lib/schema/buffer.js
CHANGED
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
const MongooseBuffer = require('../types/buffer');
|
|
8
8
|
const SchemaBufferOptions = require('../options/schemaBufferOptions');
|
|
9
9
|
const SchemaType = require('../schemaType');
|
|
10
|
-
const createJSONSchemaTypeDefinition = require('../helpers/createJSONSchemaTypeDefinition');
|
|
11
10
|
const handleBitwiseOperator = require('./operators/bitwise');
|
|
12
11
|
const utils = require('../utils');
|
|
13
12
|
|
|
@@ -328,8 +327,7 @@ SchemaBuffer.prototype.castForQuery = function($conditional, val, context) {
|
|
|
328
327
|
*/
|
|
329
328
|
|
|
330
329
|
SchemaBuffer.prototype.toJSONSchema = function toJSONSchema(options) {
|
|
331
|
-
|
|
332
|
-
return createJSONSchemaTypeDefinition('string', 'binData', options?.useBsonType, isRequired);
|
|
330
|
+
return this._createJSONSchemaTypeDefinition('string', 'binData', options);
|
|
333
331
|
};
|
|
334
332
|
|
|
335
333
|
SchemaBuffer.prototype.autoEncryptionType = function autoEncryptionType() {
|
package/lib/schema/date.js
CHANGED
|
@@ -8,7 +8,6 @@ const MongooseError = require('../error/index');
|
|
|
8
8
|
const SchemaDateOptions = require('../options/schemaDateOptions');
|
|
9
9
|
const SchemaType = require('../schemaType');
|
|
10
10
|
const castDate = require('../cast/date');
|
|
11
|
-
const createJSONSchemaTypeDefinition = require('../helpers/createJSONSchemaTypeDefinition');
|
|
12
11
|
const getConstructorName = require('../helpers/getConstructorName');
|
|
13
12
|
const utils = require('../utils');
|
|
14
13
|
|
|
@@ -452,8 +451,7 @@ SchemaDate.prototype.castForQuery = function($conditional, val, context) {
|
|
|
452
451
|
*/
|
|
453
452
|
|
|
454
453
|
SchemaDate.prototype.toJSONSchema = function toJSONSchema(options) {
|
|
455
|
-
|
|
456
|
-
return createJSONSchemaTypeDefinition('string', 'date', options?.useBsonType, isRequired);
|
|
454
|
+
return this._createJSONSchemaTypeDefinition('string', 'date', options);
|
|
457
455
|
};
|
|
458
456
|
|
|
459
457
|
SchemaDate.prototype.autoEncryptionType = function autoEncryptionType() {
|
package/lib/schema/decimal128.js
CHANGED
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
const SchemaType = require('../schemaType');
|
|
8
8
|
const CastError = SchemaType.CastError;
|
|
9
9
|
const castDecimal128 = require('../cast/decimal128');
|
|
10
|
-
const createJSONSchemaTypeDefinition = require('../helpers/createJSONSchemaTypeDefinition');
|
|
11
10
|
const isBsonType = require('../helpers/isBsonType');
|
|
12
11
|
|
|
13
12
|
/**
|
|
@@ -248,8 +247,7 @@ Object.defineProperty(SchemaDecimal128.prototype, '$conditionalHandlers', {
|
|
|
248
247
|
*/
|
|
249
248
|
|
|
250
249
|
SchemaDecimal128.prototype.toJSONSchema = function toJSONSchema(options) {
|
|
251
|
-
|
|
252
|
-
return createJSONSchemaTypeDefinition('string', 'decimal', options?.useBsonType, isRequired);
|
|
250
|
+
return this._createJSONSchemaTypeDefinition('string', 'decimal', options);
|
|
253
251
|
};
|
|
254
252
|
|
|
255
253
|
SchemaDecimal128.prototype.autoEncryptionType = function autoEncryptionType() {
|
|
@@ -12,7 +12,6 @@ const SchemaDocumentArrayOptions =
|
|
|
12
12
|
require('../options/schemaDocumentArrayOptions');
|
|
13
13
|
const SchemaType = require('../schemaType');
|
|
14
14
|
const cast = require('../cast');
|
|
15
|
-
const createJSONSchemaTypeDefinition = require('../helpers/createJSONSchemaTypeDefinition');
|
|
16
15
|
const discriminator = require('../helpers/model/discriminator');
|
|
17
16
|
const handleIdOption = require('../helpers/schema/handleIdOption');
|
|
18
17
|
const handleSpreadDoc = require('../helpers/document/handleSpreadDoc');
|
|
@@ -651,10 +650,9 @@ function cast$elemMatch(val, context) {
|
|
|
651
650
|
*/
|
|
652
651
|
|
|
653
652
|
SchemaDocumentArray.prototype.toJSONSchema = function toJSONSchema(options) {
|
|
654
|
-
const itemsTypeDefinition =
|
|
655
|
-
const isRequired = this.options.required && typeof this.options.required !== 'function';
|
|
653
|
+
const itemsTypeDefinition = this._createJSONSchemaTypeDefinition('object', 'object', { ...options, _overrideRequired: false });
|
|
656
654
|
return {
|
|
657
|
-
...
|
|
655
|
+
...this._createJSONSchemaTypeDefinition('array', 'array', options),
|
|
658
656
|
items: { ...itemsTypeDefinition, ...this.schema.toJSONSchema(options) }
|
|
659
657
|
};
|
|
660
658
|
};
|
package/lib/schema/double.js
CHANGED
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
const CastError = require('../error/cast');
|
|
8
8
|
const SchemaType = require('../schemaType');
|
|
9
9
|
const castDouble = require('../cast/double');
|
|
10
|
-
const createJSONSchemaTypeDefinition = require('../helpers/createJSONSchemaTypeDefinition');
|
|
11
10
|
|
|
12
11
|
/**
|
|
13
12
|
* Double SchemaType constructor.
|
|
@@ -231,8 +230,7 @@ Object.defineProperty(SchemaDouble.prototype, '$conditionalHandlers', {
|
|
|
231
230
|
*/
|
|
232
231
|
|
|
233
232
|
SchemaDouble.prototype.toJSONSchema = function toJSONSchema(options) {
|
|
234
|
-
|
|
235
|
-
return createJSONSchemaTypeDefinition('number', 'double', options?.useBsonType, isRequired);
|
|
233
|
+
return this._createJSONSchemaTypeDefinition('number', 'double', options);
|
|
236
234
|
};
|
|
237
235
|
|
|
238
236
|
SchemaDouble.prototype.autoEncryptionType = function autoEncryptionType() {
|
package/lib/schema/int32.js
CHANGED
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
const CastError = require('../error/cast');
|
|
8
8
|
const SchemaType = require('../schemaType');
|
|
9
9
|
const castInt32 = require('../cast/int32');
|
|
10
|
-
const createJSONSchemaTypeDefinition = require('../helpers/createJSONSchemaTypeDefinition');
|
|
11
10
|
const handleBitwiseOperator = require('./operators/bitwise');
|
|
12
11
|
|
|
13
12
|
/**
|
|
@@ -273,8 +272,7 @@ SchemaInt32.prototype.castForQuery = function($conditional, val, context) {
|
|
|
273
272
|
*/
|
|
274
273
|
|
|
275
274
|
SchemaInt32.prototype.toJSONSchema = function toJSONSchema(options) {
|
|
276
|
-
|
|
277
|
-
return createJSONSchemaTypeDefinition('number', 'int', options?.useBsonType, isRequired);
|
|
275
|
+
return this._createJSONSchemaTypeDefinition('number', 'int', options);
|
|
278
276
|
};
|
|
279
277
|
|
|
280
278
|
SchemaInt32.prototype.autoEncryptionType = function autoEncryptionType() {
|
package/lib/schema/map.js
CHANGED
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
const MongooseMap = require('../types/map');
|
|
8
8
|
const SchemaMapOptions = require('../options/schemaMapOptions');
|
|
9
9
|
const SchemaType = require('../schemaType');
|
|
10
|
-
const createJSONSchemaTypeDefinition = require('../helpers/createJSONSchemaTypeDefinition');
|
|
11
10
|
const MongooseError = require('../error/mongooseError');
|
|
12
11
|
const Schema = require('../schema');
|
|
13
12
|
const utils = require('../utils');
|
|
@@ -125,11 +124,9 @@ class SchemaMap extends SchemaType {
|
|
|
125
124
|
*/
|
|
126
125
|
|
|
127
126
|
toJSONSchema(options) {
|
|
128
|
-
const useBsonType = options?.useBsonType;
|
|
129
127
|
const embeddedSchemaType = this.getEmbeddedSchemaType();
|
|
130
128
|
|
|
131
|
-
const
|
|
132
|
-
const result = createJSONSchemaTypeDefinition('object', 'object', useBsonType, isRequired);
|
|
129
|
+
const result = this._createJSONSchemaTypeDefinition('object', 'object', options);
|
|
133
130
|
result.additionalProperties = embeddedSchemaType.toJSONSchema(options);
|
|
134
131
|
|
|
135
132
|
return result;
|