mongoose 8.20.0 → 9.0.0-rc1
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/eslint.config.mjs +198 -0
- package/lib/aggregate.js +17 -73
- package/lib/cast/bigint.js +1 -1
- package/lib/cast/double.js +1 -1
- package/lib/cast/uuid.js +5 -48
- package/lib/cast.js +2 -2
- package/lib/connection.js +0 -1
- package/lib/cursor/aggregationCursor.js +14 -24
- package/lib/cursor/queryCursor.js +7 -14
- package/lib/document.js +125 -121
- package/lib/drivers/node-mongodb-native/connection.js +3 -10
- package/lib/error/objectParameter.js +1 -2
- package/lib/error/validation.js +0 -8
- package/lib/helpers/clone.js +1 -1
- package/lib/helpers/common.js +1 -1
- package/lib/helpers/indexes/isIndexEqual.js +0 -1
- package/lib/helpers/model/applyDefaultsToPOJO.js +2 -2
- package/lib/helpers/model/applyHooks.js +43 -53
- package/lib/helpers/model/applyMethods.js +2 -2
- package/lib/helpers/model/applyStaticHooks.js +1 -48
- package/lib/helpers/model/castBulkWrite.js +1 -1
- package/lib/helpers/parallelLimit.js +18 -36
- package/lib/helpers/pluralize.js +3 -3
- package/lib/helpers/populate/assignRawDocsToIdStructure.js +1 -8
- package/lib/helpers/populate/createPopulateQueryFilter.js +1 -1
- package/lib/helpers/populate/getModelsMapForPopulate.js +17 -9
- package/lib/helpers/populate/getSchemaTypes.js +5 -5
- package/lib/helpers/query/cast$expr.js +8 -10
- package/lib/helpers/query/castFilterPath.js +1 -1
- package/lib/helpers/query/castUpdate.js +14 -12
- package/lib/helpers/query/getEmbeddedDiscriminatorPath.js +1 -1
- package/lib/helpers/schema/applyPlugins.js +1 -1
- package/lib/helpers/schema/getIndexes.js +1 -7
- package/lib/helpers/timestamps/setupTimestamps.js +3 -6
- package/lib/helpers/updateValidators.js +57 -111
- package/lib/model.js +419 -607
- package/lib/mongoose.js +41 -13
- package/lib/plugins/saveSubdocs.js +24 -51
- package/lib/plugins/sharding.js +5 -4
- package/lib/plugins/validateBeforeSave.js +3 -13
- package/lib/query.js +101 -145
- package/lib/queryHelpers.js +2 -2
- package/lib/schema/array.js +41 -84
- package/lib/schema/documentArray.js +57 -94
- package/lib/schema/documentArrayElement.js +16 -11
- package/lib/schema/string.js +1 -1
- package/lib/schema/subdocument.js +22 -28
- package/lib/schema/uuid.js +0 -21
- package/lib/schema.js +81 -39
- package/lib/schemaType.js +39 -57
- package/lib/types/array/index.js +2 -2
- package/lib/types/array/methods/index.js +4 -4
- package/lib/types/arraySubdocument.js +1 -1
- package/lib/types/buffer.js +10 -10
- package/lib/types/decimal128.js +1 -1
- package/lib/types/documentArray/index.js +1 -1
- package/lib/types/documentArray/methods/index.js +5 -3
- package/lib/types/double.js +1 -1
- package/lib/types/objectid.js +1 -1
- package/lib/types/subdocument.js +15 -43
- package/lib/types/uuid.js +1 -1
- package/lib/utils.js +1 -8
- package/lib/validOptions.js +3 -3
- package/package.json +11 -24
- package/types/connection.d.ts +20 -11
- package/types/document.d.ts +95 -26
- package/types/index.d.ts +143 -39
- package/types/inferhydrateddoctype.d.ts +115 -0
- package/types/inferrawdoctype.d.ts +99 -75
- package/types/inferschematype.d.ts +17 -3
- package/types/middlewares.d.ts +0 -2
- package/types/models.d.ts +131 -199
- package/types/mongooseoptions.d.ts +6 -5
- package/types/pipelinestage.d.ts +1 -1
- package/types/query.d.ts +71 -139
- package/types/schemaoptions.d.ts +1 -1
- package/types/schematypes.d.ts +14 -10
- package/types/types.d.ts +3 -4
- package/types/utility.d.ts +68 -48
- package/types/validation.d.ts +18 -14
- package/browser.js +0 -8
- package/dist/browser.umd.js +0 -2
- package/lib/browser.js +0 -141
- package/lib/browserDocument.js +0 -101
- package/lib/documentProvider.js +0 -30
- package/lib/drivers/browser/binary.js +0 -14
- package/lib/drivers/browser/decimal128.js +0 -7
- package/lib/drivers/browser/index.js +0 -13
- package/lib/drivers/browser/objectid.js +0 -29
- package/lib/helpers/promiseOrCallback.js +0 -54
package/lib/mongoose.js
CHANGED
|
@@ -39,7 +39,7 @@ require('./helpers/printJestWarning');
|
|
|
39
39
|
|
|
40
40
|
const objectIdHexRegexp = /^[0-9A-Fa-f]{24}$/;
|
|
41
41
|
|
|
42
|
-
const { AsyncLocalStorage } = require('
|
|
42
|
+
const { AsyncLocalStorage } = require('async_hooks');
|
|
43
43
|
|
|
44
44
|
/**
|
|
45
45
|
* Mongoose constructor.
|
|
@@ -230,7 +230,6 @@ Mongoose.prototype.setDriver = function setDriver(driver) {
|
|
|
230
230
|
* - `cloneSchemas`: `false` by default. Set to `true` to `clone()` all schemas before compiling into a model.
|
|
231
231
|
* - `debug`: If `true`, prints the operations mongoose sends to MongoDB to the console. If a writable stream is passed, it will log to that stream, without colorization. If a callback function is passed, it will receive the collection name, the method name, then all arguments passed to the method. For example, if you wanted to replicate the default logging, you could output from the callback `Mongoose: ${collectionName}.${methodName}(${methodArgs.join(', ')})`.
|
|
232
232
|
* - `id`: If `true`, adds a `id` virtual to all schemas unless overwritten on a per-schema basis.
|
|
233
|
-
* - `timestamps.createdAt.immutable`: `true` by default. If `false`, it will change the `createdAt` field to be [`immutable: false`](https://mongoosejs.com/docs/api/schematype.html#SchemaType.prototype.immutable) which means you can update the `createdAt`
|
|
234
233
|
* - `maxTimeMS`: If set, attaches [maxTimeMS](https://www.mongodb.com/docs/manual/reference/operator/meta/maxTimeMS/) to every query
|
|
235
234
|
* - `objectIdGetter`: `true` by default. Mongoose adds a getter to MongoDB ObjectId's called `_id` that returns `this` for convenience with populate. Set this to false to remove the getter.
|
|
236
235
|
* - `overwriteModels`: Set to `true` to default to overwriting models with the same name when calling `mongoose.model()`, as opposed to throwing an `OverwriteModelError`.
|
|
@@ -238,10 +237,12 @@ Mongoose.prototype.setDriver = function setDriver(driver) {
|
|
|
238
237
|
* - `runValidators`: `false` by default. Set to true to enable [update validators](https://mongoosejs.com/docs/validation.html#update-validators) for all validators by default.
|
|
239
238
|
* - `sanitizeFilter`: `false` by default. Set to true to enable the [sanitization of the query filters](https://mongoosejs.com/docs/api/mongoose.html#Mongoose.prototype.sanitizeFilter()) against query selector injection attacks by wrapping any nested objects that have a property whose name starts with `$` in a `$eq`.
|
|
240
239
|
* - `selectPopulatedPaths`: `true` by default. Set to false to opt out of Mongoose adding all fields that you `populate()` to your `select()`. The schema-level option `selectPopulatedPaths` overwrites this one.
|
|
241
|
-
* - `strict`: `true` by default, may be `false`, `true`, or `'throw'`. Sets the default strict mode for schemas.
|
|
242
240
|
* - `strictQuery`: `false` by default. May be `false`, `true`, or `'throw'`. Sets the default [strictQuery](https://mongoosejs.com/docs/guide.html#strictQuery) mode for schemas.
|
|
241
|
+
* - `strict`: `true` by default, may be `false`, `true`, or `'throw'`. Sets the default strict mode for schemas.
|
|
242
|
+
* - `timestamps.createdAt.immutable`: `true` by default. If `false`, it will change the `createdAt` field to be [`immutable: false`](https://mongoosejs.com/docs/api/schematype.html#SchemaType.prototype.immutable) which means you can update the `createdAt`
|
|
243
243
|
* - `toJSON`: `{ transform: true, flattenDecimals: true }` by default. Overwrites default objects to [`toJSON()`](https://mongoosejs.com/docs/api/document.html#Document.prototype.toJSON()), for determining how Mongoose documents get serialized by `JSON.stringify()`
|
|
244
244
|
* - `toObject`: `{ transform: true, flattenDecimals: true }` by default. Overwrites default objects to [`toObject()`](https://mongoosejs.com/docs/api/document.html#Document.prototype.toObject())
|
|
245
|
+
* - `updatePipeline`: `false` by default. If `true`, allows passing update pipelines (arrays) to update operations by default without explicitly setting `updatePipeline: true` in each query.
|
|
245
246
|
*
|
|
246
247
|
* @param {String|Object} key The name of the option or a object of multiple key-value pairs
|
|
247
248
|
* @param {String|Function|Boolean} value The value of the option, unused if "key" is a object
|
|
@@ -1051,16 +1052,6 @@ Mongoose.prototype.Model = Model;
|
|
|
1051
1052
|
|
|
1052
1053
|
Mongoose.prototype.Document = Document;
|
|
1053
1054
|
|
|
1054
|
-
/**
|
|
1055
|
-
* The Mongoose DocumentProvider constructor. Mongoose users should not have to
|
|
1056
|
-
* use this directly
|
|
1057
|
-
*
|
|
1058
|
-
* @method DocumentProvider
|
|
1059
|
-
* @api public
|
|
1060
|
-
*/
|
|
1061
|
-
|
|
1062
|
-
Mongoose.prototype.DocumentProvider = require('./documentProvider');
|
|
1063
|
-
|
|
1064
1055
|
/**
|
|
1065
1056
|
* The Mongoose ObjectId [SchemaType](https://mongoosejs.com/docs/schematypes.html). Used for
|
|
1066
1057
|
* declaring paths in your schema that should be
|
|
@@ -1337,6 +1328,43 @@ Mongoose.prototype.skipMiddlewareFunction = Kareem.skipWrappedFunction;
|
|
|
1337
1328
|
|
|
1338
1329
|
Mongoose.prototype.overwriteMiddlewareResult = Kareem.overwriteResult;
|
|
1339
1330
|
|
|
1331
|
+
/**
|
|
1332
|
+
* Use this function in `pre()` middleware to replace the arguments passed to the next middleware or hook.
|
|
1333
|
+
*
|
|
1334
|
+
* #### Example:
|
|
1335
|
+
*
|
|
1336
|
+
* // Suppose you have a schema for time in "HH:MM" string format, but you want to store it as an object { hours, minutes }
|
|
1337
|
+
* const timeStringToObject = (time) => {
|
|
1338
|
+
* if (typeof time !== 'string') return time;
|
|
1339
|
+
* const [hours, minutes] = time.split(':');
|
|
1340
|
+
* return { hours: parseInt(hours), minutes: parseInt(minutes) };
|
|
1341
|
+
* };
|
|
1342
|
+
*
|
|
1343
|
+
* const timeSchema = new Schema({
|
|
1344
|
+
* hours: { type: Number, required: true },
|
|
1345
|
+
* minutes: { type: Number, required: true },
|
|
1346
|
+
* });
|
|
1347
|
+
*
|
|
1348
|
+
* // In a pre('init') hook, replace raw string doc with custom object form
|
|
1349
|
+
* timeSchema.pre('init', function(doc) {
|
|
1350
|
+
* if (typeof doc === 'string') {
|
|
1351
|
+
* return mongoose.overwriteMiddlewareArguments(timeStringToObject(doc));
|
|
1352
|
+
* }
|
|
1353
|
+
* });
|
|
1354
|
+
*
|
|
1355
|
+
* // Now, initializing with a time string gets auto-converted by the hook
|
|
1356
|
+
* const userSchema = new Schema({ time: timeSchema });
|
|
1357
|
+
* const User = mongoose.model('User', userSchema);
|
|
1358
|
+
* const doc = new User({});
|
|
1359
|
+
* doc.$init({ time: '12:30' });
|
|
1360
|
+
*
|
|
1361
|
+
* @method overwriteMiddlewareArguments
|
|
1362
|
+
* @param {...any} args The new arguments to be passed to the next middleware. Pass multiple arguments as a spread, **not** as an array.
|
|
1363
|
+
* @api public
|
|
1364
|
+
*/
|
|
1365
|
+
|
|
1366
|
+
Mongoose.prototype.overwriteMiddlewareArguments = Kareem.overwriteArguments;
|
|
1367
|
+
|
|
1340
1368
|
/**
|
|
1341
1369
|
* Takes in an object and deletes any keys from the object whose values
|
|
1342
1370
|
* are strictly equal to `undefined`.
|
|
@@ -1,45 +1,44 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const each = require('../helpers/each');
|
|
4
|
-
|
|
5
3
|
/*!
|
|
6
4
|
* ignore
|
|
7
5
|
*/
|
|
8
6
|
|
|
9
7
|
module.exports = function saveSubdocs(schema) {
|
|
10
8
|
const unshift = true;
|
|
11
|
-
schema.s.hooks.pre('save', false, function saveSubdocsPreSave(
|
|
9
|
+
schema.s.hooks.pre('save', false, async function saveSubdocsPreSave() {
|
|
12
10
|
if (this.$isSubdocument) {
|
|
13
|
-
next();
|
|
14
11
|
return;
|
|
15
12
|
}
|
|
16
13
|
|
|
17
|
-
const _this = this;
|
|
18
14
|
const subdocs = this.$getAllSubdocs({ useCache: true });
|
|
19
15
|
|
|
20
16
|
if (!subdocs.length) {
|
|
21
|
-
next();
|
|
22
17
|
return;
|
|
23
18
|
}
|
|
24
19
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
if (_this.$__.saveOptions) {
|
|
32
|
-
_this.$__.saveOptions.__subdocs = null;
|
|
33
|
-
}
|
|
34
|
-
if (error) {
|
|
35
|
-
return _this.$__schema.s.hooks.execPost('save:error', _this, [_this], { error: error }, function(error) {
|
|
36
|
-
next(error);
|
|
37
|
-
});
|
|
38
|
-
}
|
|
39
|
-
next();
|
|
40
|
-
});
|
|
20
|
+
await Promise.all(subdocs.map(subdoc => subdoc._execDocumentPreHooks('save')));
|
|
21
|
+
|
|
22
|
+
// Invalidate subdocs cache because subdoc pre hooks can add new subdocuments
|
|
23
|
+
if (this.$__.saveOptions) {
|
|
24
|
+
this.$__.saveOptions.__subdocs = null;
|
|
25
|
+
}
|
|
41
26
|
}, null, unshift);
|
|
42
27
|
|
|
28
|
+
schema.s.hooks.pre('save', async function saveSubdocsPreDeleteOne() {
|
|
29
|
+
const removedSubdocs = this.$__.removedSubdocs;
|
|
30
|
+
if (!removedSubdocs || !removedSubdocs.length) {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const promises = [];
|
|
35
|
+
for (const subdoc of removedSubdocs) {
|
|
36
|
+
promises.push(subdoc._execDocumentPreHooks('deleteOne'));
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
await Promise.all(promises);
|
|
40
|
+
});
|
|
41
|
+
|
|
43
42
|
schema.s.hooks.post('save', async function saveSubdocsPostDeleteOne() {
|
|
44
43
|
const removedSubdocs = this.$__.removedSubdocs;
|
|
45
44
|
if (!removedSubdocs || !removedSubdocs.length) {
|
|
@@ -48,14 +47,7 @@ module.exports = function saveSubdocs(schema) {
|
|
|
48
47
|
|
|
49
48
|
const promises = [];
|
|
50
49
|
for (const subdoc of removedSubdocs) {
|
|
51
|
-
promises.push(
|
|
52
|
-
subdoc.$__schema.s.hooks.execPost('deleteOne', subdoc, [subdoc], function(err) {
|
|
53
|
-
if (err) {
|
|
54
|
-
return reject(err);
|
|
55
|
-
}
|
|
56
|
-
resolve();
|
|
57
|
-
});
|
|
58
|
-
}));
|
|
50
|
+
promises.push(subdoc._execDocumentPostHooks('deleteOne'));
|
|
59
51
|
}
|
|
60
52
|
|
|
61
53
|
this.$__.removedSubdocs = null;
|
|
@@ -67,7 +59,6 @@ module.exports = function saveSubdocs(schema) {
|
|
|
67
59
|
return;
|
|
68
60
|
}
|
|
69
61
|
|
|
70
|
-
const _this = this;
|
|
71
62
|
const subdocs = this.$getAllSubdocs({ useCache: true });
|
|
72
63
|
|
|
73
64
|
if (!subdocs.length) {
|
|
@@ -76,27 +67,9 @@ module.exports = function saveSubdocs(schema) {
|
|
|
76
67
|
|
|
77
68
|
const promises = [];
|
|
78
69
|
for (const subdoc of subdocs) {
|
|
79
|
-
promises.push(
|
|
80
|
-
subdoc.$__schema.s.hooks.execPost('save', subdoc, [subdoc], function(err) {
|
|
81
|
-
if (err) {
|
|
82
|
-
return reject(err);
|
|
83
|
-
}
|
|
84
|
-
resolve();
|
|
85
|
-
});
|
|
86
|
-
}));
|
|
70
|
+
promises.push(subdoc._execDocumentPostHooks('save'));
|
|
87
71
|
}
|
|
88
72
|
|
|
89
|
-
|
|
90
|
-
await Promise.all(promises);
|
|
91
|
-
} catch (error) {
|
|
92
|
-
await new Promise((resolve, reject) => {
|
|
93
|
-
this.$__schema.s.hooks.execPost('save:error', _this, [_this], { error: error }, function(error) {
|
|
94
|
-
if (error) {
|
|
95
|
-
return reject(error);
|
|
96
|
-
}
|
|
97
|
-
resolve();
|
|
98
|
-
});
|
|
99
|
-
});
|
|
100
|
-
}
|
|
73
|
+
await Promise.all(promises);
|
|
101
74
|
}, null, unshift);
|
|
102
75
|
};
|
package/lib/plugins/sharding.js
CHANGED
|
@@ -12,13 +12,14 @@ module.exports = function shardingPlugin(schema) {
|
|
|
12
12
|
storeShard.call(this);
|
|
13
13
|
return this;
|
|
14
14
|
});
|
|
15
|
-
schema.pre('save', function shardingPluginPreSave(
|
|
15
|
+
schema.pre('save', function shardingPluginPreSave() {
|
|
16
16
|
applyWhere.call(this);
|
|
17
|
-
next();
|
|
18
17
|
});
|
|
19
|
-
schema.pre('deleteOne', { document: true, query: false }, function
|
|
18
|
+
schema.pre('deleteOne', { document: true, query: false }, function shardingPluginPreDeleteOne() {
|
|
19
|
+
applyWhere.call(this);
|
|
20
|
+
});
|
|
21
|
+
schema.pre('updateOne', { document: true, query: false }, function shardingPluginPreUpdateOne() {
|
|
20
22
|
applyWhere.call(this);
|
|
21
|
-
next();
|
|
22
23
|
});
|
|
23
24
|
schema.post('save', function shardingPluginPostSave() {
|
|
24
25
|
storeShard.call(this);
|
|
@@ -6,11 +6,10 @@
|
|
|
6
6
|
|
|
7
7
|
module.exports = function validateBeforeSave(schema) {
|
|
8
8
|
const unshift = true;
|
|
9
|
-
schema.pre('save', false, function validateBeforeSave(
|
|
10
|
-
const _this = this;
|
|
9
|
+
schema.pre('save', false, async function validateBeforeSave(options) {
|
|
11
10
|
// Nested docs have their own presave
|
|
12
11
|
if (this.$isSubdocument) {
|
|
13
|
-
return
|
|
12
|
+
return;
|
|
14
13
|
}
|
|
15
14
|
|
|
16
15
|
const hasValidateBeforeSaveOption = options &&
|
|
@@ -32,20 +31,11 @@ module.exports = function validateBeforeSave(schema) {
|
|
|
32
31
|
const validateOptions = hasValidateModifiedOnlyOption ?
|
|
33
32
|
{ validateModifiedOnly: options.validateModifiedOnly } :
|
|
34
33
|
null;
|
|
35
|
-
this.$validate(validateOptions).then(
|
|
34
|
+
await this.$validate(validateOptions).then(
|
|
36
35
|
() => {
|
|
37
36
|
this.$op = 'save';
|
|
38
|
-
next();
|
|
39
|
-
},
|
|
40
|
-
error => {
|
|
41
|
-
_this.$__schema.s.hooks.execPost('save:error', _this, [_this], { error: error }, function(error) {
|
|
42
|
-
_this.$op = 'save';
|
|
43
|
-
next(error);
|
|
44
|
-
});
|
|
45
37
|
}
|
|
46
38
|
);
|
|
47
|
-
} else {
|
|
48
|
-
next();
|
|
49
39
|
}
|
|
50
40
|
}, null, unshift);
|
|
51
41
|
};
|