mongoose 9.3.0 → 9.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/aggregate.js +7 -7
- package/lib/cursor/queryCursor.js +1 -1
- package/lib/helpers/projection/parseProjection.js +9 -4
- package/lib/model.js +10 -8
- 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/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');
|
|
@@ -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/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.
|