mongoose 8.6.0 → 8.6.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/dist/browser.umd.js +1 -1
- package/lib/connection.js +3 -0
- package/lib/cursor/changeStream.js +43 -9
- package/lib/cursor/queryCursor.js +1 -1
- package/lib/document.js +8 -8
- package/lib/drivers/node-mongodb-native/connection.js +1 -1
- package/lib/helpers/clone.js +0 -5
- package/lib/model.js +35 -14
- package/lib/plugins/trackTransaction.js +0 -7
- package/package.json +7 -7
- package/types/cursor.d.ts +1 -0
- package/types/inferrawdoctype.d.ts +2 -2
- package/types/inferschematype.d.ts +2 -2
- package/types/query.d.ts +4 -5
- package/types/schematypes.d.ts +3 -0
package/lib/connection.js
CHANGED
|
@@ -71,6 +71,9 @@ function Connection(base) {
|
|
|
71
71
|
} else {
|
|
72
72
|
this.id = base.nextConnectionId;
|
|
73
73
|
}
|
|
74
|
+
|
|
75
|
+
// Internal queue of objects `{ fn, ctx, args }` that Mongoose calls when this connection is successfully
|
|
76
|
+
// opened. In `onOpen()`, Mongoose calls every entry in `_queue` and empties the queue.
|
|
74
77
|
this._queue = [];
|
|
75
78
|
}
|
|
76
79
|
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
const EventEmitter = require('events').EventEmitter;
|
|
8
|
+
const MongooseError = require('../error/mongooseError');
|
|
8
9
|
|
|
9
10
|
/*!
|
|
10
11
|
* ignore
|
|
@@ -25,6 +26,7 @@ class ChangeStream extends EventEmitter {
|
|
|
25
26
|
this.bindedEvents = false;
|
|
26
27
|
this.pipeline = pipeline;
|
|
27
28
|
this.options = options;
|
|
29
|
+
this.errored = false;
|
|
28
30
|
|
|
29
31
|
if (options && options.hydrate && !options.model) {
|
|
30
32
|
throw new Error(
|
|
@@ -33,19 +35,36 @@ class ChangeStream extends EventEmitter {
|
|
|
33
35
|
);
|
|
34
36
|
}
|
|
35
37
|
|
|
38
|
+
let syncError = null;
|
|
36
39
|
this.$driverChangeStreamPromise = new Promise((resolve, reject) => {
|
|
37
40
|
// This wrapper is necessary because of buffering.
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
try {
|
|
42
|
+
changeStreamThunk((err, driverChangeStream) => {
|
|
43
|
+
if (err != null) {
|
|
44
|
+
this.errored = true;
|
|
45
|
+
this.emit('error', err);
|
|
46
|
+
return reject(err);
|
|
47
|
+
}
|
|
43
48
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
49
|
+
this.driverChangeStream = driverChangeStream;
|
|
50
|
+
this.emit('ready');
|
|
51
|
+
resolve();
|
|
52
|
+
});
|
|
53
|
+
} catch (err) {
|
|
54
|
+
syncError = err;
|
|
55
|
+
this.errored = true;
|
|
56
|
+
this.emit('error', err);
|
|
57
|
+
reject(err);
|
|
58
|
+
}
|
|
48
59
|
});
|
|
60
|
+
|
|
61
|
+
// Because a ChangeStream is an event emitter, there's no way to register an 'error' handler
|
|
62
|
+
// that catches errors which occur in the constructor, unless we force sync errors into async
|
|
63
|
+
// errors with setImmediate(). For cleaner stack trace, we just immediately throw any synchronous
|
|
64
|
+
// errors that occurred with changeStreamThunk().
|
|
65
|
+
if (syncError != null) {
|
|
66
|
+
throw syncError;
|
|
67
|
+
}
|
|
49
68
|
}
|
|
50
69
|
|
|
51
70
|
_bindEvents() {
|
|
@@ -92,10 +111,16 @@ class ChangeStream extends EventEmitter {
|
|
|
92
111
|
}
|
|
93
112
|
|
|
94
113
|
hasNext(cb) {
|
|
114
|
+
if (this.errored) {
|
|
115
|
+
throw new MongooseError('Cannot call hasNext() on errored ChangeStream');
|
|
116
|
+
}
|
|
95
117
|
return this.driverChangeStream.hasNext(cb);
|
|
96
118
|
}
|
|
97
119
|
|
|
98
120
|
next(cb) {
|
|
121
|
+
if (this.errored) {
|
|
122
|
+
throw new MongooseError('Cannot call next() on errored ChangeStream');
|
|
123
|
+
}
|
|
99
124
|
if (this.options && this.options.hydrate) {
|
|
100
125
|
if (cb != null) {
|
|
101
126
|
const originalCb = cb;
|
|
@@ -126,16 +151,25 @@ class ChangeStream extends EventEmitter {
|
|
|
126
151
|
}
|
|
127
152
|
|
|
128
153
|
addListener(event, handler) {
|
|
154
|
+
if (this.errored) {
|
|
155
|
+
throw new MongooseError('Cannot call addListener() on errored ChangeStream');
|
|
156
|
+
}
|
|
129
157
|
this._bindEvents();
|
|
130
158
|
return super.addListener(event, handler);
|
|
131
159
|
}
|
|
132
160
|
|
|
133
161
|
on(event, handler) {
|
|
162
|
+
if (this.errored) {
|
|
163
|
+
throw new MongooseError('Cannot call on() on errored ChangeStream');
|
|
164
|
+
}
|
|
134
165
|
this._bindEvents();
|
|
135
166
|
return super.on(event, handler);
|
|
136
167
|
}
|
|
137
168
|
|
|
138
169
|
once(event, handler) {
|
|
170
|
+
if (this.errored) {
|
|
171
|
+
throw new MongooseError('Cannot call once() on errored ChangeStream');
|
|
172
|
+
}
|
|
139
173
|
this._bindEvents();
|
|
140
174
|
return super.once(event, handler);
|
|
141
175
|
}
|
|
@@ -10,7 +10,7 @@ const eachAsync = require('../helpers/cursor/eachAsync');
|
|
|
10
10
|
const helpers = require('../queryHelpers');
|
|
11
11
|
const kareem = require('kareem');
|
|
12
12
|
const immediate = require('../helpers/immediate');
|
|
13
|
-
const { once } = require('
|
|
13
|
+
const { once } = require('events');
|
|
14
14
|
const util = require('util');
|
|
15
15
|
|
|
16
16
|
/**
|
package/lib/document.js
CHANGED
|
@@ -1213,7 +1213,7 @@ Document.prototype.$set = function $set(path, val, type, options) {
|
|
|
1213
1213
|
this.$__setValue(path, null);
|
|
1214
1214
|
cleanModifiedSubpaths(this, path);
|
|
1215
1215
|
} else {
|
|
1216
|
-
return this.$set(val, path, constructing);
|
|
1216
|
+
return this.$set(val, path, constructing, options);
|
|
1217
1217
|
}
|
|
1218
1218
|
|
|
1219
1219
|
const keys = getKeysInSchemaOrder(this.$__schema, val, path);
|
|
@@ -3856,7 +3856,6 @@ Document.prototype.$toObject = function(options, json) {
|
|
|
3856
3856
|
// Parent options should only bubble down for subdocuments, not populated docs
|
|
3857
3857
|
options._parentOptions = this.$isSubdocument ? options : null;
|
|
3858
3858
|
|
|
3859
|
-
options._skipSingleNestedGetters = false;
|
|
3860
3859
|
// remember the root transform function
|
|
3861
3860
|
// to save it from being overwritten by sub-transform functions
|
|
3862
3861
|
// const originalTransform = options.transform;
|
|
@@ -3870,13 +3869,13 @@ Document.prototype.$toObject = function(options, json) {
|
|
|
3870
3869
|
ret = clone(this._doc, options) || {};
|
|
3871
3870
|
}
|
|
3872
3871
|
|
|
3873
|
-
options._skipSingleNestedGetters = true;
|
|
3874
3872
|
const getters = options._calledWithOptions.getters
|
|
3875
3873
|
?? options.getters
|
|
3876
3874
|
?? defaultOptions.getters
|
|
3877
3875
|
?? false;
|
|
3876
|
+
|
|
3878
3877
|
if (getters) {
|
|
3879
|
-
applyGetters(this, ret
|
|
3878
|
+
applyGetters(this, ret);
|
|
3880
3879
|
|
|
3881
3880
|
if (options.minimize) {
|
|
3882
3881
|
ret = minimize(ret) || {};
|
|
@@ -4187,12 +4186,11 @@ function applyVirtuals(self, json, options, toObjectOptions) {
|
|
|
4187
4186
|
*
|
|
4188
4187
|
* @param {Document} self
|
|
4189
4188
|
* @param {Object} json
|
|
4190
|
-
* @param {Object} [options]
|
|
4191
4189
|
* @return {Object} `json`
|
|
4192
4190
|
* @api private
|
|
4193
4191
|
*/
|
|
4194
4192
|
|
|
4195
|
-
function applyGetters(self, json
|
|
4193
|
+
function applyGetters(self, json) {
|
|
4196
4194
|
const schema = self.$__schema;
|
|
4197
4195
|
const paths = Object.keys(schema.paths);
|
|
4198
4196
|
let i = paths.length;
|
|
@@ -4228,8 +4226,10 @@ function applyGetters(self, json, options) {
|
|
|
4228
4226
|
if (branch != null && typeof branch !== 'object') {
|
|
4229
4227
|
break;
|
|
4230
4228
|
} else if (ii === last) {
|
|
4231
|
-
|
|
4232
|
-
|
|
4229
|
+
branch[part] = schema.paths[path].applyGetters(
|
|
4230
|
+
branch[part],
|
|
4231
|
+
self
|
|
4232
|
+
);
|
|
4233
4233
|
if (Array.isArray(branch[part]) && schema.paths[path].$embeddedSchemaType) {
|
|
4234
4234
|
for (let i = 0; i < branch[part].length; ++i) {
|
|
4235
4235
|
branch[part][i] = schema.paths[path].$embeddedSchemaType.applyGetters(
|
package/lib/helpers/clone.js
CHANGED
|
@@ -40,11 +40,6 @@ function clone(obj, options, isArrayChild) {
|
|
|
40
40
|
|
|
41
41
|
if (isMongooseObject(obj)) {
|
|
42
42
|
if (options) {
|
|
43
|
-
// Single nested subdocs should apply getters later in `applyGetters()`
|
|
44
|
-
// when calling `toObject()`. See gh-7442, gh-8295
|
|
45
|
-
if (options._skipSingleNestedGetters && obj.$isSingleNested) {
|
|
46
|
-
options._calledWithOptions = Object.assign({}, options._calledWithOptions || {}, { getters: false });
|
|
47
|
-
}
|
|
48
43
|
if (options.retainDocuments && obj.$__ != null) {
|
|
49
44
|
const clonedDoc = obj.$clone();
|
|
50
45
|
if (obj.__index != null) {
|
package/lib/model.js
CHANGED
|
@@ -3368,11 +3368,19 @@ Model.bulkWrite = async function bulkWrite(ops, options) {
|
|
|
3368
3368
|
};
|
|
3369
3369
|
|
|
3370
3370
|
/**
|
|
3371
|
-
*
|
|
3372
|
-
*
|
|
3371
|
+
* Takes an array of documents, gets the changes and inserts/updates documents in the database
|
|
3372
|
+
* according to whether or not the document is new, or whether it has changes or not.
|
|
3373
3373
|
*
|
|
3374
3374
|
* `bulkSave` uses `bulkWrite` under the hood, so it's mostly useful when dealing with many documents (10K+)
|
|
3375
3375
|
*
|
|
3376
|
+
* `bulkSave()` throws errors under the following conditions:
|
|
3377
|
+
*
|
|
3378
|
+
* - one of the provided documents fails validation. In this case, `bulkSave()` does not send a `bulkWrite()`, and throws the first validation error.
|
|
3379
|
+
* - `bulkWrite()` fails (for example, due to being unable to connect to MongoDB or due to duplicate key error)
|
|
3380
|
+
* - `bulkWrite()` did not insert or update **any** documents. In this case, `bulkSave()` will throw a DocumentNotFound error.
|
|
3381
|
+
*
|
|
3382
|
+
* Note that `bulkSave()` will **not** throw an error if only some of the `save()` calls succeeded.
|
|
3383
|
+
*
|
|
3376
3384
|
* @param {Array<Document>} documents
|
|
3377
3385
|
* @param {Object} [options] options passed to the underlying `bulkWrite()`
|
|
3378
3386
|
* @param {Boolean} [options.timestamps] defaults to `null`, when set to false, mongoose will not add/update timestamps to the documents.
|
|
@@ -3380,7 +3388,7 @@ Model.bulkWrite = async function bulkWrite(ops, options) {
|
|
|
3380
3388
|
* @param {String|number} [options.w=1] The [write concern](https://www.mongodb.com/docs/manual/reference/write-concern/). See [`Query#w()`](https://mongoosejs.com/docs/api/query.html#Query.prototype.w()) for more information.
|
|
3381
3389
|
* @param {number} [options.wtimeout=null] The [write concern timeout](https://www.mongodb.com/docs/manual/reference/write-concern/#wtimeout).
|
|
3382
3390
|
* @param {Boolean} [options.j=true] If false, disable [journal acknowledgement](https://www.mongodb.com/docs/manual/reference/write-concern/#j-option)
|
|
3383
|
-
*
|
|
3391
|
+
* @return {BulkWriteResult} the return value from `bulkWrite()`
|
|
3384
3392
|
*/
|
|
3385
3393
|
Model.bulkSave = async function bulkSave(documents, options) {
|
|
3386
3394
|
options = options || {};
|
|
@@ -3408,18 +3416,31 @@ Model.bulkSave = async function bulkSave(documents, options) {
|
|
|
3408
3416
|
(err) => ({ bulkWriteResult: null, bulkWriteError: err })
|
|
3409
3417
|
);
|
|
3410
3418
|
|
|
3411
|
-
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
|
|
3416
|
-
|
|
3419
|
+
const matchedCount = bulkWriteResult?.matchedCount ?? 0;
|
|
3420
|
+
const insertedCount = bulkWriteResult?.insertedCount ?? 0;
|
|
3421
|
+
if (writeOperations.length > 0 && matchedCount + insertedCount === 0 && !bulkWriteError) {
|
|
3422
|
+
throw new DocumentNotFoundError(
|
|
3423
|
+
writeOperations.filter(op => op.updateOne).map(op => op.updateOne.filter),
|
|
3424
|
+
this.modelName,
|
|
3425
|
+
writeOperations.length,
|
|
3426
|
+
bulkWriteResult
|
|
3427
|
+
);
|
|
3428
|
+
}
|
|
3417
3429
|
|
|
3418
|
-
|
|
3419
|
-
|
|
3420
|
-
|
|
3421
|
-
|
|
3422
|
-
|
|
3430
|
+
const successfulDocuments = [];
|
|
3431
|
+
for (let i = 0; i < documents.length; i++) {
|
|
3432
|
+
const document = documents[i];
|
|
3433
|
+
const documentError = bulkWriteError && bulkWriteError.writeErrors.find(writeError => {
|
|
3434
|
+
const writeErrorDocumentId = writeError.err.op._id || writeError.err.op.q._id;
|
|
3435
|
+
return writeErrorDocumentId.toString() === document._doc._id.toString();
|
|
3436
|
+
});
|
|
3437
|
+
|
|
3438
|
+
if (documentError == null) {
|
|
3439
|
+
successfulDocuments.push(document);
|
|
3440
|
+
}
|
|
3441
|
+
}
|
|
3442
|
+
|
|
3443
|
+
await Promise.all(successfulDocuments.map(document => handleSuccessfulWrite(document)));
|
|
3423
3444
|
|
|
3424
3445
|
if (bulkWriteError && bulkWriteError.writeErrors && bulkWriteError.writeErrors.length) {
|
|
3425
3446
|
throw bulkWriteError;
|
|
@@ -27,13 +27,6 @@ module.exports = function trackTransaction(schema) {
|
|
|
27
27
|
initialState.atomics = _getAtomics(this);
|
|
28
28
|
|
|
29
29
|
session[sessionNewDocuments].set(this, initialState);
|
|
30
|
-
} else {
|
|
31
|
-
const state = session[sessionNewDocuments].get(this);
|
|
32
|
-
|
|
33
|
-
for (const path of Object.keys(this.$__.activePaths.getStatePaths('modify'))) {
|
|
34
|
-
state.modifiedPaths.add(path);
|
|
35
|
-
}
|
|
36
|
-
state.atomics = _getAtomics(this, state.atomics);
|
|
37
30
|
}
|
|
38
31
|
});
|
|
39
32
|
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mongoose",
|
|
3
3
|
"description": "Mongoose MongoDB ODM",
|
|
4
|
-
"version": "8.6.
|
|
4
|
+
"version": "8.6.2",
|
|
5
5
|
"author": "Guillermo Rauch <guillermo@learnboost.com>",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"mongodb",
|
|
@@ -29,9 +29,9 @@
|
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
31
|
"@babel/core": "7.24.7",
|
|
32
|
-
"@babel/preset-env": "7.25.
|
|
33
|
-
"@typescript-eslint/eslint-plugin": "^
|
|
34
|
-
"@typescript-eslint/parser": "^
|
|
32
|
+
"@babel/preset-env": "7.25.4",
|
|
33
|
+
"@typescript-eslint/eslint-plugin": "^8.4.0",
|
|
34
|
+
"@typescript-eslint/parser": "^8.4.0",
|
|
35
35
|
"acquit": "1.3.0",
|
|
36
36
|
"acquit-ignore": "0.2.1",
|
|
37
37
|
"acquit-require": "0.1.1",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"babel-loader": "8.2.5",
|
|
41
41
|
"broken-link-checker": "^0.7.8",
|
|
42
42
|
"buffer": "^5.6.0",
|
|
43
|
-
"cheerio": "1.0.0
|
|
43
|
+
"cheerio": "1.0.0",
|
|
44
44
|
"crypto-browserify": "3.12.0",
|
|
45
45
|
"dotenv": "16.4.5",
|
|
46
46
|
"dox": "1.0.0",
|
|
@@ -53,9 +53,9 @@
|
|
|
53
53
|
"lodash.isequal": "4.5.0",
|
|
54
54
|
"lodash.isequalwith": "4.4.0",
|
|
55
55
|
"markdownlint-cli2": "^0.13.0",
|
|
56
|
-
"marked": "14.
|
|
56
|
+
"marked": "14.1.0",
|
|
57
57
|
"mkdirp": "^3.0.1",
|
|
58
|
-
"mocha": "10.7.
|
|
58
|
+
"mocha": "10.7.3",
|
|
59
59
|
"moment": "2.30.1",
|
|
60
60
|
"mongodb-memory-server": "10.0.0",
|
|
61
61
|
"ncp": "^2.0.0",
|
package/types/cursor.d.ts
CHANGED
|
@@ -91,8 +91,8 @@ declare module 'mongoose' {
|
|
|
91
91
|
IfEquals<PathValueType, String> extends true ? PathEnumOrString<Options['enum']> :
|
|
92
92
|
PathValueType extends NumberSchemaDefinition ? Options['enum'] extends ReadonlyArray<any> ? Options['enum'][number] : number :
|
|
93
93
|
IfEquals<PathValueType, Schema.Types.Number> extends true ? number :
|
|
94
|
-
PathValueType extends DateSchemaDefinition ?
|
|
95
|
-
IfEquals<PathValueType, Schema.Types.Date> extends true ?
|
|
94
|
+
PathValueType extends DateSchemaDefinition ? NativeDate :
|
|
95
|
+
IfEquals<PathValueType, Schema.Types.Date> extends true ? NativeDate :
|
|
96
96
|
PathValueType extends typeof Buffer | 'buffer' | 'Buffer' | typeof Schema.Types.Buffer ? Buffer :
|
|
97
97
|
PathValueType extends BooleanSchemaDefinition ? boolean :
|
|
98
98
|
IfEquals<PathValueType, Schema.Types.Boolean> extends true ? boolean :
|
|
@@ -281,8 +281,8 @@ type ResolvePathType<PathValueType, Options extends SchemaTypeOptions<PathValueT
|
|
|
281
281
|
IfEquals<PathValueType, String> extends true ? PathEnumOrString<Options['enum']> :
|
|
282
282
|
PathValueType extends NumberSchemaDefinition ? Options['enum'] extends ReadonlyArray<any> ? Options['enum'][number] : number :
|
|
283
283
|
IfEquals<PathValueType, Schema.Types.Number> extends true ? number :
|
|
284
|
-
PathValueType extends DateSchemaDefinition ?
|
|
285
|
-
IfEquals<PathValueType, Schema.Types.Date> extends true ?
|
|
284
|
+
PathValueType extends DateSchemaDefinition ? NativeDate :
|
|
285
|
+
IfEquals<PathValueType, Schema.Types.Date> extends true ? NativeDate :
|
|
286
286
|
PathValueType extends typeof Buffer | 'buffer' | 'Buffer' | typeof Schema.Types.Buffer ? Buffer :
|
|
287
287
|
PathValueType extends BooleanSchemaDefinition ? boolean :
|
|
288
288
|
IfEquals<PathValueType, Schema.Types.Boolean> extends true ? boolean :
|
package/types/query.d.ts
CHANGED
|
@@ -12,7 +12,7 @@ declare module 'mongoose' {
|
|
|
12
12
|
*/
|
|
13
13
|
type RootFilterQuery<T> = FilterQuery<T> | Query<any, any> | Types.ObjectId;
|
|
14
14
|
|
|
15
|
-
type FilterQuery<T> ={
|
|
15
|
+
type FilterQuery<T> = {
|
|
16
16
|
[P in keyof T]?: Condition<T[P]>;
|
|
17
17
|
} & RootQuerySelector<T> & { _id?: Condition<string>; };
|
|
18
18
|
|
|
@@ -116,10 +116,9 @@ declare module 'mongoose' {
|
|
|
116
116
|
$where?: string | Function;
|
|
117
117
|
/** @see https://www.mongodb.com/docs/manual/reference/operator/query/comment/#op._S_comment */
|
|
118
118
|
$comment?: string;
|
|
119
|
-
|
|
120
|
-
// this will mark all unrecognized properties as any (including nested queries)
|
|
121
|
-
|
|
122
|
-
[nestedSelector: `${string}.${string}`]: any;
|
|
119
|
+
$expr?: Record<string, any>;
|
|
120
|
+
// this will mark all unrecognized properties as any (including nested queries)
|
|
121
|
+
[key: string]: any;
|
|
123
122
|
};
|
|
124
123
|
|
|
125
124
|
interface QueryTimestampsConfig {
|
package/types/schematypes.d.ts
CHANGED
|
@@ -216,6 +216,9 @@ declare module 'mongoose' {
|
|
|
216
216
|
/** Attaches a getter for all instances of this schema type. */
|
|
217
217
|
static get(getter: (value: any) => any): void;
|
|
218
218
|
|
|
219
|
+
/** Array containing default setters for all instances of this SchemaType */
|
|
220
|
+
static setters: ((val?: unknown, priorVal?: unknown, doc?: Document<unknown>, options?: Record<string, any> | null) => unknown)[];
|
|
221
|
+
|
|
219
222
|
/** The class that Mongoose uses internally to instantiate this SchemaType's `options` property. */
|
|
220
223
|
OptionsConstructor: SchemaTypeOptions<T>;
|
|
221
224
|
|