mongoose 9.3.0 → 9.3.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/README.md +16 -18
- package/lib/aggregate.js +7 -7
- package/lib/cast/number.js +4 -4
- package/lib/cast.js +1 -1
- package/lib/connection.js +6 -6
- package/lib/cursor/queryCursor.js +1 -1
- package/lib/helpers/get.js +1 -1
- package/lib/helpers/projection/parseProjection.js +9 -4
- package/lib/model.js +10 -8
- package/lib/mongoose.js +6 -0
- package/lib/query.js +6 -6
- package/lib/schema.js +15 -15
- package/package.json +1 -1
- package/types/index.d.ts +7 -1
- package/types/schemaoptions.d.ts +8 -6
package/README.md
CHANGED
|
@@ -11,7 +11,7 @@ Mongoose is a [MongoDB](https://www.mongodb.org/) object modeling tool designed
|
|
|
11
11
|
|
|
12
12
|
## Documentation
|
|
13
13
|
|
|
14
|
-
The official documentation website is [mongoosejs.com](
|
|
14
|
+
The official documentation website is [mongoosejs.com](https://mongoosejs.com/).
|
|
15
15
|
|
|
16
16
|
Mongoose 9.0.0 was released on November 21, 2025. You can find more details on [backwards breaking changes in 9.0.0 on our docs site](https://mongoosejs.com/docs/migrating_to_9.html).
|
|
17
17
|
|
|
@@ -25,7 +25,7 @@ Mongoose 9.0.0 was released on November 21, 2025. You can find more details on [
|
|
|
25
25
|
|
|
26
26
|
## Plugins
|
|
27
27
|
|
|
28
|
-
Check out the [plugins search site](
|
|
28
|
+
Check out the [plugins search site](https://plugins.mongoosejs.io/) to see hundreds of related modules from the community. Next, learn how to write your own plugin from the [docs](https://mongoosejs.com/docs/plugins.html) or [this blog post](http://thecodebarbarian.com/2015/03/06/guide-to-mongoose-plugins).
|
|
29
29
|
|
|
30
30
|
## Contributors
|
|
31
31
|
|
|
@@ -40,9 +40,7 @@ View all 400+ [contributors](https://github.com/Automattic/mongoose/graphs/contr
|
|
|
40
40
|
|
|
41
41
|
## Installation
|
|
42
42
|
|
|
43
|
-
First install [Node.js](
|
|
44
|
-
|
|
45
|
-
Then install the `mongoose` package using your preferred package manager:
|
|
43
|
+
First install [Node.js](https://nodejs.org/) and [MongoDB](https://www.mongodb.org/downloads), then install the `mongoose` package using your preferred package manager:
|
|
46
44
|
|
|
47
45
|
### Using npm
|
|
48
46
|
|
|
@@ -140,16 +138,16 @@ const BlogPost = new Schema({
|
|
|
140
138
|
|
|
141
139
|
Aside from defining the structure of your documents and the types of data you're storing, a Schema handles the definition of:
|
|
142
140
|
|
|
143
|
-
* [Validators](
|
|
144
|
-
* [Defaults](
|
|
145
|
-
* [Getters](
|
|
146
|
-
* [Setters](
|
|
147
|
-
* [Indexes](
|
|
148
|
-
* [Middleware](
|
|
149
|
-
* [Methods](
|
|
150
|
-
* [Statics](
|
|
151
|
-
* [Plugins](
|
|
152
|
-
* [pseudo-JOINs](
|
|
141
|
+
* [Validators](https://mongoosejs.com/docs/validation.html) (async and sync)
|
|
142
|
+
* [Defaults](https://mongoosejs.com/docs/api/schematype.html#schematype_SchemaType-default)
|
|
143
|
+
* [Getters](https://mongoosejs.com/docs/api/schematype.html#schematype_SchemaType-get)
|
|
144
|
+
* [Setters](https://mongoosejs.com/docs/api/schematype.html#schematype_SchemaType-set)
|
|
145
|
+
* [Indexes](https://mongoosejs.com/docs/guide.html#indexes)
|
|
146
|
+
* [Middleware](https://mongoosejs.com/docs/middleware.html)
|
|
147
|
+
* [Methods](https://mongoosejs.com/docs/guide.html#methods) definition
|
|
148
|
+
* [Statics](https://mongoosejs.com/docs/guide.html#statics) definition
|
|
149
|
+
* [Plugins](https://mongoosejs.com/docs/plugins.html)
|
|
150
|
+
* [pseudo-JOINs](https://mongoosejs.com/docs/populate.html)
|
|
153
151
|
|
|
154
152
|
The following example shows some of these features:
|
|
155
153
|
|
|
@@ -219,7 +217,7 @@ const instance = await MyModel.findOne({ /* ... */ });
|
|
|
219
217
|
console.log(instance.my.key); // 'hello'
|
|
220
218
|
```
|
|
221
219
|
|
|
222
|
-
For more details check out [the docs](
|
|
220
|
+
For more details check out [the docs](https://mongoosejs.com/docs/queries.html).
|
|
223
221
|
|
|
224
222
|
**Important!** If you opened a separate connection using `mongoose.createConnection()` but attempt to access the model through `mongoose.model('ModelName')` it will not work as expected since it is not hooked up to an active db connection. In this case access your model through the connection you created:
|
|
225
223
|
|
|
@@ -274,7 +272,7 @@ Embedded documents enjoy all the same features as your models. Defaults, validat
|
|
|
274
272
|
|
|
275
273
|
### Middleware
|
|
276
274
|
|
|
277
|
-
See the [docs](
|
|
275
|
+
See the [docs](https://mongoosejs.com/docs/middleware.html) page.
|
|
278
276
|
|
|
279
277
|
#### Intercepting and mutating method arguments
|
|
280
278
|
|
|
@@ -347,7 +345,7 @@ return a cursor.
|
|
|
347
345
|
|
|
348
346
|
## API Docs
|
|
349
347
|
|
|
350
|
-
[Mongoose API documentation](
|
|
348
|
+
[Mongoose API documentation](https://mongoosejs.com/docs/api/mongoose.html), generated using [dox](https://github.com/tj/dox)
|
|
351
349
|
and [acquit](https://github.com/vkarpov15/acquit).
|
|
352
350
|
|
|
353
351
|
## Related Projects
|
package/lib/aggregate.js
CHANGED
|
@@ -170,7 +170,7 @@ Aggregate.prototype.append = function() {
|
|
|
170
170
|
: [...arguments];
|
|
171
171
|
|
|
172
172
|
if (!args.every(isOperator)) {
|
|
173
|
-
throw new
|
|
173
|
+
throw new MongooseError('Arguments must be aggregate pipeline operators');
|
|
174
174
|
}
|
|
175
175
|
|
|
176
176
|
this._pipeline = this._pipeline.concat(args);
|
|
@@ -203,7 +203,7 @@ Aggregate.prototype.append = function() {
|
|
|
203
203
|
*/
|
|
204
204
|
Aggregate.prototype.addFields = function(arg) {
|
|
205
205
|
if (typeof arg !== 'object' || arg === null || Array.isArray(arg)) {
|
|
206
|
-
throw new
|
|
206
|
+
throw new MongooseError('Invalid addFields() argument. Must be an object');
|
|
207
207
|
}
|
|
208
208
|
return this.append({ $addFields: Object.assign({}, arg) });
|
|
209
209
|
};
|
|
@@ -259,7 +259,7 @@ Aggregate.prototype.project = function(arg) {
|
|
|
259
259
|
fields[field] = include;
|
|
260
260
|
});
|
|
261
261
|
} else {
|
|
262
|
-
throw new
|
|
262
|
+
throw new MongooseError('Invalid project() argument. Must be string or object');
|
|
263
263
|
}
|
|
264
264
|
|
|
265
265
|
return this.append({ $project: fields });
|
|
@@ -462,7 +462,7 @@ Aggregate.prototype.unwind = function() {
|
|
|
462
462
|
$unwind: (arg[0] === '$') ? arg : '$' + arg
|
|
463
463
|
});
|
|
464
464
|
} else {
|
|
465
|
-
throw new
|
|
465
|
+
throw new MongooseError('Invalid arg "' + arg + '" to unwind(), ' +
|
|
466
466
|
'must be string or object');
|
|
467
467
|
}
|
|
468
468
|
}
|
|
@@ -761,7 +761,7 @@ Aggregate.prototype.redact = function(expression, thenExpr, elseExpr) {
|
|
|
761
761
|
if (arguments.length === 3) {
|
|
762
762
|
if ((typeof thenExpr === 'string' && !validRedactStringValues.has(thenExpr)) ||
|
|
763
763
|
(typeof elseExpr === 'string' && !validRedactStringValues.has(elseExpr))) {
|
|
764
|
-
throw new
|
|
764
|
+
throw new MongooseError('If thenExpr or elseExpr is string, it must be either $$DESCEND, $$PRUNE or $$KEEP');
|
|
765
765
|
}
|
|
766
766
|
|
|
767
767
|
expression = {
|
|
@@ -796,7 +796,7 @@ Aggregate.prototype.explain = async function explain(verbosity) {
|
|
|
796
796
|
const model = this._model;
|
|
797
797
|
|
|
798
798
|
if (!this._pipeline.length) {
|
|
799
|
-
throw new
|
|
799
|
+
throw new MongooseError('Aggregate has empty pipeline');
|
|
800
800
|
}
|
|
801
801
|
|
|
802
802
|
prepareDiscriminatorPipeline(this._pipeline, this._model.schema);
|
|
@@ -1058,7 +1058,7 @@ Aggregate.prototype.pipelineForUnionWith = function pipelineForUnionWith() {
|
|
|
1058
1058
|
|
|
1059
1059
|
Aggregate.prototype.exec = async function exec() {
|
|
1060
1060
|
if (!this._model && !this._connection) {
|
|
1061
|
-
throw new
|
|
1061
|
+
throw new MongooseError('Aggregate not bound to any Model');
|
|
1062
1062
|
}
|
|
1063
1063
|
if (typeof arguments[0] === 'function') {
|
|
1064
1064
|
throw new MongooseError('Aggregate.prototype.exec() no longer accepts a callback');
|
package/lib/cast/number.js
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const assert = require('assert');
|
|
4
|
-
|
|
5
3
|
/**
|
|
6
4
|
* Given a value, cast it to a number, or throw an `Error` if the value
|
|
7
5
|
* cannot be casted. `null` and `undefined` are considered valid.
|
|
@@ -24,7 +22,9 @@ module.exports = function castNumber(val) {
|
|
|
24
22
|
val = Number(val);
|
|
25
23
|
}
|
|
26
24
|
|
|
27
|
-
|
|
25
|
+
if (isNaN(val)) {
|
|
26
|
+
throw new Error('Cast to Number failed: value is not a valid number');
|
|
27
|
+
}
|
|
28
28
|
if (val instanceof Number) {
|
|
29
29
|
return val.valueOf();
|
|
30
30
|
}
|
|
@@ -38,5 +38,5 @@ module.exports = function castNumber(val) {
|
|
|
38
38
|
return Number(val);
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
|
|
41
|
+
throw new Error('Cast to Number failed: value is not a valid number');
|
|
42
42
|
};
|
package/lib/cast.js
CHANGED
|
@@ -35,7 +35,7 @@ const ALLOWED_GEOWITHIN_GEOJSON_TYPES = ['Polygon', 'MultiPolygon'];
|
|
|
35
35
|
*/
|
|
36
36
|
module.exports = function cast(schema, obj, options, context) {
|
|
37
37
|
if (Array.isArray(obj)) {
|
|
38
|
-
throw new Error('Query filter must be an object, got an array '
|
|
38
|
+
throw new Error('Query filter must be an object, got an array ' + util.inspect(obj));
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
if (obj == null) {
|
package/lib/connection.js
CHANGED
|
@@ -132,7 +132,7 @@ Object.defineProperty(Connection.prototype, 'readyState', {
|
|
|
132
132
|
},
|
|
133
133
|
set: function(val) {
|
|
134
134
|
if (!(val in STATES)) {
|
|
135
|
-
throw new
|
|
135
|
+
throw new MongooseError('Invalid connection state: ' + val);
|
|
136
136
|
}
|
|
137
137
|
|
|
138
138
|
if (this._readyState !== val) {
|
|
@@ -655,7 +655,7 @@ Connection.prototype.createCollections = async function createCollections(option
|
|
|
655
655
|
|
|
656
656
|
Connection.prototype.withSession = async function withSession(executor) {
|
|
657
657
|
if (arguments.length === 0) {
|
|
658
|
-
throw new
|
|
658
|
+
throw new MongooseError('Please provide an executor function');
|
|
659
659
|
}
|
|
660
660
|
return await this.client.withSession(executor);
|
|
661
661
|
};
|
|
@@ -713,7 +713,7 @@ Connection.prototype.startSession = async function startSession(options) {
|
|
|
713
713
|
* doc.isNew; // false
|
|
714
714
|
*
|
|
715
715
|
* // Throw an error to abort the transaction
|
|
716
|
-
* throw new
|
|
716
|
+
* throw new MongooseError('Oops!');
|
|
717
717
|
* },{ readPreference: 'primary' }).catch(() => {});
|
|
718
718
|
*
|
|
719
719
|
* // true, `transaction()` reset the document's state because the
|
|
@@ -1310,7 +1310,7 @@ Connection.prototype._close = async function _close(force, destroy) {
|
|
|
1310
1310
|
*/
|
|
1311
1311
|
|
|
1312
1312
|
Connection.prototype.doClose = function doClose() {
|
|
1313
|
-
throw new
|
|
1313
|
+
throw new MongooseError('Connection#doClose unimplemented by driver');
|
|
1314
1314
|
};
|
|
1315
1315
|
|
|
1316
1316
|
/**
|
|
@@ -1453,7 +1453,7 @@ Connection.prototype.model = function model(name, schema, collection, options) {
|
|
|
1453
1453
|
}
|
|
1454
1454
|
}
|
|
1455
1455
|
if (schema && !schema.instanceOfSchema) {
|
|
1456
|
-
throw new
|
|
1456
|
+
throw new MongooseError('The 2nd parameter to `mongoose.model()` should be a ' +
|
|
1457
1457
|
'schema or a POJO');
|
|
1458
1458
|
}
|
|
1459
1459
|
|
|
@@ -1566,7 +1566,7 @@ Connection.prototype.deleteModel = function deleteModel(name) {
|
|
|
1566
1566
|
}
|
|
1567
1567
|
}
|
|
1568
1568
|
} else {
|
|
1569
|
-
throw new
|
|
1569
|
+
throw new MongooseError('First parameter to `deleteModel()` must be a string ' +
|
|
1570
1570
|
'or regexp, got "' + name + '"');
|
|
1571
1571
|
}
|
|
1572
1572
|
|
package/lib/helpers/get.js
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Convert a string or array into a projection object
|
|
5
|
-
*
|
|
4
|
+
* Convert a string or array into a projection object. Treats `-foo` as
|
|
5
|
+
* equivalent to `foo: 0` depending on `retainMinusPaths`. If `retainMinusPaths`
|
|
6
|
+
* is true, then `-foo` will be included in the projection as `'-foo': 0`.
|
|
7
|
+
*
|
|
8
|
+
* @param {object|string|string[]} v
|
|
9
|
+
* @param {boolean} [retainMinusPaths]
|
|
10
|
+
* @return {object}
|
|
6
11
|
*/
|
|
7
12
|
|
|
8
13
|
module.exports = function parseProjection(v, retainMinusPaths) {
|
|
@@ -22,9 +27,9 @@ module.exports = function parseProjection(v, retainMinusPaths) {
|
|
|
22
27
|
if (!field) {
|
|
23
28
|
continue;
|
|
24
29
|
}
|
|
25
|
-
const include = '-'
|
|
30
|
+
const include = field.charAt(0) === '-' ? 0 : 1;
|
|
26
31
|
if (!retainMinusPaths && include === 0) {
|
|
27
|
-
field = field.
|
|
32
|
+
field = field.slice(1);
|
|
28
33
|
}
|
|
29
34
|
ret[field] = include;
|
|
30
35
|
}
|
package/lib/model.js
CHANGED
|
@@ -61,6 +61,7 @@ const decorateDiscriminatorIndexOptions = require('./helpers/indexes/decorateDis
|
|
|
61
61
|
const isPathSelectedInclusive = require('./helpers/projection/isPathSelectedInclusive');
|
|
62
62
|
const leanPopulateMap = require('./helpers/populate/leanPopulateMap');
|
|
63
63
|
const parallelLimit = require('./helpers/parallelLimit');
|
|
64
|
+
const parseProjection = require('./helpers/projection/parseProjection');
|
|
64
65
|
const prepareDiscriminatorPipeline = require('./helpers/aggregate/prepareDiscriminatorPipeline');
|
|
65
66
|
const pushNestedArrayPaths = require('./helpers/model/pushNestedArrayPaths');
|
|
66
67
|
const removeDeselectedForeignField = require('./helpers/populate/removeDeselectedForeignField');
|
|
@@ -189,7 +190,7 @@ Model.prototype.db;
|
|
|
189
190
|
|
|
190
191
|
Model.useConnection = function useConnection(connection) {
|
|
191
192
|
if (!connection) {
|
|
192
|
-
throw new
|
|
193
|
+
throw new MongooseError('Please provide a connection.');
|
|
193
194
|
}
|
|
194
195
|
if (this.db) {
|
|
195
196
|
delete this.db.models[this.modelName];
|
|
@@ -824,7 +825,7 @@ Model.prototype.deleteOne = function deleteOne(options) {
|
|
|
824
825
|
// `self` is passed to pre hooks as argument for backwards compatibility, but that
|
|
825
826
|
// isn't the actual arguments passed to the wrapped function.
|
|
826
827
|
if (res[0] !== self || res[1] !== options) {
|
|
827
|
-
throw new
|
|
828
|
+
throw new MongooseError('Document deleteOne pre hooks cannot overwrite arguments');
|
|
828
829
|
}
|
|
829
830
|
query.deleteOne(where, options);
|
|
830
831
|
// Apply custom where conditions _after_ document deleteOne middleware for
|
|
@@ -3458,7 +3459,7 @@ Model.bulkWrite = async function bulkWrite(ops, options) {
|
|
|
3458
3459
|
sort((v1, v2) => v1.index - v2.index).
|
|
3459
3460
|
map(v => v.error);
|
|
3460
3461
|
|
|
3461
|
-
const validOps = validOpIndexes.sort().map(index => ops[index]);
|
|
3462
|
+
const validOps = validOpIndexes.sort((a, b) => a - b).map(index => ops[index]);
|
|
3462
3463
|
|
|
3463
3464
|
if (validOps.length === 0) {
|
|
3464
3465
|
if (options.throwOnValidationError && validationErrors.length) {
|
|
@@ -3609,7 +3610,7 @@ async function buildPreSavePromise(document, options) {
|
|
|
3609
3610
|
const preFilter = buildMiddlewareFilter(options, 'pre');
|
|
3610
3611
|
const [newOptions] = await document.schema.s.hooks.execPre('save', document, [options], { filter: preFilter });
|
|
3611
3612
|
if (newOptions !== options) {
|
|
3612
|
-
throw new
|
|
3613
|
+
throw new MongooseError('Cannot overwrite options in pre("save") hook on bulkSave()');
|
|
3613
3614
|
}
|
|
3614
3615
|
}
|
|
3615
3616
|
|
|
@@ -3849,7 +3850,7 @@ Model.castObject = function castObject(obj, options) {
|
|
|
3849
3850
|
|
|
3850
3851
|
Model.buildBulkWriteOperations = function buildBulkWriteOperations(documents, options) {
|
|
3851
3852
|
if (!Array.isArray(documents)) {
|
|
3852
|
-
throw new
|
|
3853
|
+
throw new MongooseError(`bulkSave expects an array of documents to be passed, received \`${documents}\` instead`);
|
|
3853
3854
|
}
|
|
3854
3855
|
|
|
3855
3856
|
setDefaultOptions();
|
|
@@ -3857,7 +3858,7 @@ Model.buildBulkWriteOperations = function buildBulkWriteOperations(documents, op
|
|
|
3857
3858
|
const writeOperations = documents.map((document, i) => {
|
|
3858
3859
|
if (!options.skipValidation) {
|
|
3859
3860
|
if (!(document instanceof Document)) {
|
|
3860
|
-
throw new
|
|
3861
|
+
throw new MongooseError(`documents.${i} was not a mongoose document, documents must be an array of mongoose documents (instanceof mongoose.Document).`);
|
|
3861
3862
|
}
|
|
3862
3863
|
if (options.validateBeforeSave == null || options.validateBeforeSave) {
|
|
3863
3864
|
const err = document.validateSync();
|
|
@@ -3935,7 +3936,7 @@ Model.buildBulkWriteOperations = function buildBulkWriteOperations(documents, op
|
|
|
3935
3936
|
* @api public
|
|
3936
3937
|
*/
|
|
3937
3938
|
|
|
3938
|
-
Model.hydrate = function(obj, projection, options) {
|
|
3939
|
+
Model.hydrate = function hydrate(obj, projection, options) {
|
|
3939
3940
|
_checkContext(this, 'hydrate');
|
|
3940
3941
|
|
|
3941
3942
|
if (options?.virtuals && options?.hydratedPopulatedDocs === false) {
|
|
@@ -3946,6 +3947,7 @@ Model.hydrate = function(obj, projection, options) {
|
|
|
3946
3947
|
if (obj?.$__ != null) {
|
|
3947
3948
|
obj = obj.toObject(internalToObjectOptions);
|
|
3948
3949
|
}
|
|
3950
|
+
projection = parseProjection(projection);
|
|
3949
3951
|
obj = applyProjection(obj, projection);
|
|
3950
3952
|
}
|
|
3951
3953
|
const document = require('./queryHelpers').createModel(this, obj, projection, projection, options);
|
|
@@ -4947,7 +4949,7 @@ Model.compile = function compile(name, schema, collectionName, connection, base)
|
|
|
4947
4949
|
Model.clientEncryption = function clientEncryption() {
|
|
4948
4950
|
const ClientEncryption = this.base.driver.get().ClientEncryption;
|
|
4949
4951
|
if (!ClientEncryption) {
|
|
4950
|
-
throw new
|
|
4952
|
+
throw new MongooseError('The mongodb driver must be used to obtain a ClientEncryption object.');
|
|
4951
4953
|
}
|
|
4952
4954
|
|
|
4953
4955
|
const client = this.collection?.conn?.client;
|
package/lib/mongoose.js
CHANGED
|
@@ -256,6 +256,12 @@ Mongoose.prototype.setDriver = function setDriver(driver) {
|
|
|
256
256
|
Mongoose.prototype.set = function getsetOptions(key, value) {
|
|
257
257
|
const _mongoose = this instanceof Mongoose ? this : mongoose;
|
|
258
258
|
|
|
259
|
+
if (key == null) {
|
|
260
|
+
const error = new SetOptionError();
|
|
261
|
+
error.addError(String(key), new SetOptionError.SetOptionInnerError(String(key)));
|
|
262
|
+
throw error;
|
|
263
|
+
}
|
|
264
|
+
|
|
259
265
|
if (arguments.length === 1 && typeof key !== 'object') {
|
|
260
266
|
if (VALID_OPTIONS.indexOf(key) === -1) {
|
|
261
267
|
const error = new SetOptionError();
|
package/lib/query.js
CHANGED
|
@@ -185,7 +185,7 @@ function isEmptyFilter(obj) {
|
|
|
185
185
|
// Helper function to check for empty/invalid filter
|
|
186
186
|
function checkRequireFilter(filter, options) {
|
|
187
187
|
if (options?.requireFilter && isEmptyFilter(filter)) {
|
|
188
|
-
throw new
|
|
188
|
+
throw new MongooseError('Empty or invalid filter not allowed with requireFilter enabled');
|
|
189
189
|
}
|
|
190
190
|
}
|
|
191
191
|
|
|
@@ -1113,7 +1113,7 @@ Query.prototype.select = function select() {
|
|
|
1113
1113
|
if (!arg) return this;
|
|
1114
1114
|
|
|
1115
1115
|
if (arguments.length !== 1) {
|
|
1116
|
-
throw new
|
|
1116
|
+
throw new MongooseError('Invalid select: select only takes 1 argument');
|
|
1117
1117
|
}
|
|
1118
1118
|
|
|
1119
1119
|
this._validate('select');
|
|
@@ -1721,7 +1721,7 @@ Query.prototype.setOptions = function(options, overwrite) {
|
|
|
1721
1721
|
return this;
|
|
1722
1722
|
}
|
|
1723
1723
|
if (typeof options !== 'object') {
|
|
1724
|
-
throw new
|
|
1724
|
+
throw new MongooseError('Options must be an object, got "' + options + '"');
|
|
1725
1725
|
}
|
|
1726
1726
|
|
|
1727
1727
|
options = Object.assign({}, options);
|
|
@@ -3080,10 +3080,10 @@ Query.prototype.distinct = function(field, conditions, options) {
|
|
|
3080
3080
|
|
|
3081
3081
|
Query.prototype.sort = function(arg, options) {
|
|
3082
3082
|
if (arguments.length > 2) {
|
|
3083
|
-
throw new
|
|
3083
|
+
throw new MongooseError('sort() takes at most 2 arguments');
|
|
3084
3084
|
}
|
|
3085
3085
|
if (options != null && typeof options !== 'object') {
|
|
3086
|
-
throw new
|
|
3086
|
+
throw new MongooseError('sort() options argument must be an object or nullish');
|
|
3087
3087
|
}
|
|
3088
3088
|
|
|
3089
3089
|
if (this.options.sort == null) {
|
|
@@ -4695,7 +4695,7 @@ Query.prototype.exec = async function exec(op) {
|
|
|
4695
4695
|
}
|
|
4696
4696
|
|
|
4697
4697
|
if (this.options?.sort && typeof this.options.sort === 'object' && Object.hasOwn(this.options.sort, '')) {
|
|
4698
|
-
throw new
|
|
4698
|
+
throw new MongooseError('Invalid field "" passed to sort()');
|
|
4699
4699
|
}
|
|
4700
4700
|
|
|
4701
4701
|
if (this._execCount > 0) {
|
package/lib/schema.js
CHANGED
|
@@ -205,7 +205,7 @@ function aliasFields(schema, paths) {
|
|
|
205
205
|
if (Array.isArray(alias)) {
|
|
206
206
|
for (const a of alias) {
|
|
207
207
|
if (typeof a !== 'string') {
|
|
208
|
-
throw new
|
|
208
|
+
throw new MongooseError('Invalid value for alias option on ' + prop + ', got ' + a);
|
|
209
209
|
}
|
|
210
210
|
|
|
211
211
|
schema.aliases[a] = prop;
|
|
@@ -231,7 +231,7 @@ function aliasFields(schema, paths) {
|
|
|
231
231
|
}
|
|
232
232
|
|
|
233
233
|
if (typeof alias !== 'string') {
|
|
234
|
-
throw new
|
|
234
|
+
throw new MongooseError('Invalid value for alias option on ' + prop + ', got ' + alias);
|
|
235
235
|
}
|
|
236
236
|
|
|
237
237
|
schema.aliases[alias] = prop;
|
|
@@ -750,7 +750,7 @@ Schema.prototype.encryptionType = function encryptionType(encryptionType) {
|
|
|
750
750
|
return this.options.encryptionType;
|
|
751
751
|
}
|
|
752
752
|
if (!(typeof encryptionType === 'string' || encryptionType === null)) {
|
|
753
|
-
throw new
|
|
753
|
+
throw new MongooseError('invalid `encryptionType`: ${encryptionType}');
|
|
754
754
|
}
|
|
755
755
|
this.options.encryptionType = encryptionType;
|
|
756
756
|
};
|
|
@@ -909,7 +909,7 @@ Schema.prototype.add = function add(obj, prefix) {
|
|
|
909
909
|
if (val.instanceOfSchema && val.encryptionType() != null) {
|
|
910
910
|
// schema.add({ field: <instance of encrypted schema> })
|
|
911
911
|
if (this.encryptionType() != val.encryptionType()) {
|
|
912
|
-
throw new
|
|
912
|
+
throw new MongooseError('encryptionType of a nested schema must match the encryption type of the parent schema.');
|
|
913
913
|
}
|
|
914
914
|
|
|
915
915
|
for (const [encryptedField, encryptedFieldConfig] of Object.entries(val.encryptedFields)) {
|
|
@@ -921,7 +921,7 @@ Schema.prototype.add = function add(obj, prefix) {
|
|
|
921
921
|
const { encrypt } = val;
|
|
922
922
|
|
|
923
923
|
if (this.encryptionType() == null) {
|
|
924
|
-
throw new
|
|
924
|
+
throw new MongooseError('encryptionType must be provided');
|
|
925
925
|
}
|
|
926
926
|
|
|
927
927
|
this._addEncryptedField(fullPath, encrypt);
|
|
@@ -948,7 +948,7 @@ Schema.prototype.add = function add(obj, prefix) {
|
|
|
948
948
|
Schema.prototype._addEncryptedField = function _addEncryptedField(path, fieldConfig) {
|
|
949
949
|
const type = this.path(path).autoEncryptionType();
|
|
950
950
|
if (type == null) {
|
|
951
|
-
throw new
|
|
951
|
+
throw new MongooseError(`Invalid BSON type for FLE field: '${path}'`);
|
|
952
952
|
}
|
|
953
953
|
|
|
954
954
|
this.encryptedFields[path] = clone(fieldConfig);
|
|
@@ -1113,11 +1113,11 @@ Schema.prototype.alias = function alias(path, alias) {
|
|
|
1113
1113
|
|
|
1114
1114
|
Schema.prototype.removeIndex = function removeIndex(index) {
|
|
1115
1115
|
if (arguments.length > 1) {
|
|
1116
|
-
throw new
|
|
1116
|
+
throw new MongooseError('removeIndex() takes only 1 argument');
|
|
1117
1117
|
}
|
|
1118
1118
|
|
|
1119
1119
|
if (typeof index !== 'object' && typeof index !== 'string') {
|
|
1120
|
-
throw new
|
|
1120
|
+
throw new MongooseError('removeIndex() may only take either an object or a string as an argument');
|
|
1121
1121
|
}
|
|
1122
1122
|
|
|
1123
1123
|
if (typeof index === 'object') {
|
|
@@ -1318,7 +1318,7 @@ Schema.prototype.path = function(path, obj) {
|
|
|
1318
1318
|
|
|
1319
1319
|
for (const sub of subpaths) {
|
|
1320
1320
|
if (utils.specialProperties.has(sub)) {
|
|
1321
|
-
throw new
|
|
1321
|
+
throw new MongooseError('Cannot set special property `' + sub + '` on a schema');
|
|
1322
1322
|
}
|
|
1323
1323
|
fullPath = fullPath += (fullPath.length > 0 ? '.' : '') + sub;
|
|
1324
1324
|
if (!branch[sub]) {
|
|
@@ -1331,7 +1331,7 @@ Schema.prototype.path = function(path, obj) {
|
|
|
1331
1331
|
+ fullPath
|
|
1332
1332
|
+ '` already set to type ' + branch[sub].name
|
|
1333
1333
|
+ '.';
|
|
1334
|
-
throw new
|
|
1334
|
+
throw new MongooseError(msg);
|
|
1335
1335
|
}
|
|
1336
1336
|
branch = branch[sub];
|
|
1337
1337
|
}
|
|
@@ -2205,7 +2205,7 @@ Schema.prototype.post = function(name) {
|
|
|
2205
2205
|
|
|
2206
2206
|
Schema.prototype.plugin = function(fn, opts) {
|
|
2207
2207
|
if (typeof fn !== 'function') {
|
|
2208
|
-
throw new
|
|
2208
|
+
throw new MongooseError('First param to `schema.plugin()` must be a function, ' +
|
|
2209
2209
|
'got "' + (typeof fn) + '"');
|
|
2210
2210
|
}
|
|
2211
2211
|
|
|
@@ -2480,7 +2480,7 @@ Object.defineProperty(Schema, 'indexTypes', {
|
|
|
2480
2480
|
return indexTypes;
|
|
2481
2481
|
},
|
|
2482
2482
|
set: function() {
|
|
2483
|
-
throw new
|
|
2483
|
+
throw new MongooseError('Cannot overwrite Schema.indexTypes');
|
|
2484
2484
|
}
|
|
2485
2485
|
});
|
|
2486
2486
|
|
|
@@ -2542,11 +2542,11 @@ Schema.prototype.virtual = function(name, options) {
|
|
|
2542
2542
|
|
|
2543
2543
|
if (utils.hasUserDefinedProperty(options, ['ref', 'refPath'])) {
|
|
2544
2544
|
if (options.localField == null) {
|
|
2545
|
-
throw new
|
|
2545
|
+
throw new MongooseError('Reference virtuals require `localField` option');
|
|
2546
2546
|
}
|
|
2547
2547
|
|
|
2548
2548
|
if (options.foreignField == null) {
|
|
2549
|
-
throw new
|
|
2549
|
+
throw new MongooseError('Reference virtuals require `foreignField` option');
|
|
2550
2550
|
}
|
|
2551
2551
|
|
|
2552
2552
|
const virtual = this.virtual(name);
|
|
@@ -2642,7 +2642,7 @@ Schema.prototype.virtual = function(name, options) {
|
|
|
2642
2642
|
const parts = name.split('.');
|
|
2643
2643
|
|
|
2644
2644
|
if (this.pathType(name) === 'real') {
|
|
2645
|
-
throw new
|
|
2645
|
+
throw new MongooseError('Virtual path "' + name + '"' +
|
|
2646
2646
|
' conflicts with a real path in the schema');
|
|
2647
2647
|
}
|
|
2648
2648
|
|
package/package.json
CHANGED
package/types/index.d.ts
CHANGED
|
@@ -379,7 +379,12 @@ declare module 'mongoose' {
|
|
|
379
379
|
>,
|
|
380
380
|
TMethods = TSchemaOptions extends { methods: infer M } ? { [K in keyof M]: OmitThisParameter<M[K]> } : {},
|
|
381
381
|
TStatics = TSchemaOptions extends { statics: infer S } ? { [K in keyof S]: OmitThisParameter<S[K]> } : {}
|
|
382
|
-
>(def: TSchemaDefinition, options: TSchemaOptions
|
|
382
|
+
>(def: TSchemaDefinition, options: TSchemaOptions & {
|
|
383
|
+
statics?: SchemaOptionsStaticsPropertyType<
|
|
384
|
+
TStatics,
|
|
385
|
+
Model<RawDocType>
|
|
386
|
+
>
|
|
387
|
+
}): Schema<
|
|
383
388
|
RawDocType,
|
|
384
389
|
Model<RawDocType, any, any, any>,
|
|
385
390
|
TMethods,
|
|
@@ -497,6 +502,7 @@ declare module 'mongoose' {
|
|
|
497
502
|
|
|
498
503
|
/** Registers a plugin for this schema. */
|
|
499
504
|
plugin<PFunc extends PluginFunction<DocType, TModelType, any, any, any, any>, POptions extends Parameters<PFunc>[1] = Parameters<PFunc>[1]>(fn: PFunc, opts?: POptions): this;
|
|
505
|
+
plugin<PFunc extends PluginFunction<DocType, Model<DocType, any, any, any, any, any>, any, any, any, any>, POptions extends Parameters<PFunc>[1] = Parameters<PFunc>[1]>(fn: PFunc, opts?: POptions): this;
|
|
500
506
|
|
|
501
507
|
/** Defines a post hook for the model. */
|
|
502
508
|
|
package/types/schemaoptions.d.ts
CHANGED
|
@@ -7,6 +7,13 @@ declare module 'mongoose' {
|
|
|
7
7
|
currentTime?: () => (NativeDate | number);
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
+
type SchemaOptionsStaticsPropertyType<TStaticMethods, TModelType> = IfEquals<
|
|
11
|
+
TStaticMethods,
|
|
12
|
+
{},
|
|
13
|
+
Record<string, (...args: any[]) => unknown> & ThisType<TModelType>,
|
|
14
|
+
{ [K in keyof TStaticMethods]: OmitThisParameter<TStaticMethods[K]> } & ThisType<TModelType>
|
|
15
|
+
>;
|
|
16
|
+
|
|
10
17
|
type TypeKeyBaseType = string;
|
|
11
18
|
|
|
12
19
|
type DefaultTypeKey = 'type';
|
|
@@ -222,12 +229,7 @@ declare module 'mongoose' {
|
|
|
222
229
|
/**
|
|
223
230
|
* Model Statics methods.
|
|
224
231
|
*/
|
|
225
|
-
statics?:
|
|
226
|
-
TStaticMethods,
|
|
227
|
-
{},
|
|
228
|
-
{ [name: string]: (this: TModelType, ...args: any[]) => unknown },
|
|
229
|
-
AddThisParameter<TStaticMethods, TModelType>
|
|
230
|
-
>
|
|
232
|
+
statics?: SchemaOptionsStaticsPropertyType<TStaticMethods, TModelType>
|
|
231
233
|
|
|
232
234
|
/**
|
|
233
235
|
* Document instance methods.
|