mongoose 6.2.11 → 6.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/.eslintrc.json +157 -157
- package/README.md +1 -1
- package/dist/browser.umd.js +2 -1704
- package/lib/aggregate.js +4 -3
- package/lib/collection.js +0 -7
- package/lib/connection.js +2 -1
- package/lib/cursor/ChangeStream.js +42 -2
- package/lib/cursor/QueryCursor.js +2 -0
- package/lib/document.js +22 -26
- package/lib/error/cast.js +8 -2
- package/lib/error/eachAsyncMultiError.js +41 -0
- package/lib/helpers/common.js +0 -8
- package/lib/helpers/cursor/eachAsync.js +44 -12
- package/lib/helpers/immediate.js +3 -1
- package/lib/helpers/isAsyncFunction.js +19 -7
- package/lib/helpers/model/discriminator.js +1 -3
- package/lib/helpers/populate/getModelsMapForPopulate.js +13 -10
- package/lib/helpers/query/applyGlobalOption.js +29 -0
- package/lib/helpers/schematype/handleImmutable.js +4 -1
- package/lib/helpers/timestamps/setupTimestamps.js +2 -2
- package/lib/index.js +11 -4
- package/lib/internal.js +0 -1
- package/lib/model.js +39 -27
- package/lib/query.js +23 -4
- package/lib/queryhelpers.js +11 -1
- package/lib/schema/SubdocumentPath.js +3 -15
- package/lib/schema/documentarray.js +7 -7
- package/lib/schema/number.js +1 -5
- package/lib/schema/objectid.js +2 -4
- package/lib/schema/string.js +1 -5
- package/lib/schema.js +115 -2
- package/lib/schematype.js +2 -2
- package/lib/types/DocumentArray/methods/index.js +9 -1
- package/lib/types/array/methods/index.js +8 -9
- package/lib/validoptions.js +1 -0
- package/package.json +25 -18
- package/tools/repl.js +2 -1
- package/tsconfig.json +2 -2
- package/types/aggregate.d.ts +1 -2
- package/types/connection.d.ts +4 -5
- package/types/cursor.d.ts +13 -6
- package/types/document.d.ts +17 -14
- package/types/error.d.ts +124 -124
- package/types/index.d.ts +350 -202
- package/types/mongooseoptions.d.ts +11 -6
- package/types/schemaoptions.d.ts +1 -2
- package/CHANGELOG.md +0 -7238
- package/History.md +0 -1
- package/lib/helpers/query/applyGlobalMaxTimeMS.js +0 -15
package/lib/aggregate.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
const AggregationCursor = require('./cursor/AggregationCursor');
|
|
8
8
|
const Query = require('./query');
|
|
9
|
-
const applyGlobalMaxTimeMS = require('./helpers/query/
|
|
9
|
+
const { applyGlobalMaxTimeMS, applyGlobalDiskUse } = require('./helpers/query/applyGlobalOption');
|
|
10
10
|
const getConstructorName = require('./helpers/getConstructorName');
|
|
11
11
|
const prepareDiscriminatorPipeline = require('./helpers/aggregate/prepareDiscriminatorPipeline');
|
|
12
12
|
const promiseOrCallback = require('./helpers/promiseOrCallback');
|
|
@@ -15,6 +15,8 @@ const utils = require('./utils');
|
|
|
15
15
|
const read = Query.prototype.read;
|
|
16
16
|
const readConcern = Query.prototype.readConcern;
|
|
17
17
|
|
|
18
|
+
const validRedactStringValues = new Set(['$$DESCEND', '$$PRUNE', '$$KEEP']);
|
|
19
|
+
|
|
18
20
|
/**
|
|
19
21
|
* Aggregate constructor used for building aggregation pipelines. Do not
|
|
20
22
|
* instantiate this class directly, use [Model.aggregate()](/docs/api.html#model_Model.aggregate) instead.
|
|
@@ -672,8 +674,6 @@ Aggregate.prototype.readConcern = function(level) {
|
|
|
672
674
|
* @api public
|
|
673
675
|
*/
|
|
674
676
|
|
|
675
|
-
const validRedactStringValues = new Set(['$$DESCEND', '$$PRUNE', '$$KEEP']);
|
|
676
|
-
|
|
677
677
|
Aggregate.prototype.redact = function(expression, thenExpr, elseExpr) {
|
|
678
678
|
if (arguments.length === 3) {
|
|
679
679
|
if ((typeof thenExpr === 'string' && !validRedactStringValues.has(thenExpr)) ||
|
|
@@ -973,6 +973,7 @@ Aggregate.prototype.exec = function(callback) {
|
|
|
973
973
|
const collection = this._model.collection;
|
|
974
974
|
|
|
975
975
|
applyGlobalMaxTimeMS(this.options, model);
|
|
976
|
+
applyGlobalDiskUse(this.options, model);
|
|
976
977
|
|
|
977
978
|
if (this.options && this.options.cursor) {
|
|
978
979
|
return new AggregationCursor(this);
|
package/lib/collection.js
CHANGED
|
@@ -23,13 +23,6 @@ function Collection(name, conn, opts) {
|
|
|
23
23
|
if (opts === void 0) {
|
|
24
24
|
opts = {};
|
|
25
25
|
}
|
|
26
|
-
if (opts.capped === void 0) {
|
|
27
|
-
opts.capped = {};
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
if (typeof opts.capped === 'number') {
|
|
31
|
-
opts.capped = { size: opts.capped };
|
|
32
|
-
}
|
|
33
26
|
|
|
34
27
|
this.opts = opts;
|
|
35
28
|
this.name = name;
|
package/lib/connection.js
CHANGED
|
@@ -1357,7 +1357,8 @@ Connection.prototype.optionsProvideAuthenticationData = function(options) {
|
|
|
1357
1357
|
* that this connection uses to talk to MongoDB.
|
|
1358
1358
|
*
|
|
1359
1359
|
* #### Example:
|
|
1360
|
-
* const conn = await mongoose.createConnection('mongodb://localhost:27017/test')
|
|
1360
|
+
* const conn = await mongoose.createConnection('mongodb://localhost:27017/test').
|
|
1361
|
+
* asPromise();
|
|
1361
1362
|
*
|
|
1362
1363
|
* conn.getClient(); // MongoClient { ... }
|
|
1363
1364
|
*
|
|
@@ -16,6 +16,7 @@ class ChangeStream extends EventEmitter {
|
|
|
16
16
|
|
|
17
17
|
this.driverChangeStream = null;
|
|
18
18
|
this.closed = false;
|
|
19
|
+
this.bindedEvents = false;
|
|
19
20
|
this.pipeline = pipeline;
|
|
20
21
|
this.options = options;
|
|
21
22
|
|
|
@@ -27,21 +28,60 @@ class ChangeStream extends EventEmitter {
|
|
|
27
28
|
}
|
|
28
29
|
|
|
29
30
|
this.driverChangeStream = driverChangeStream;
|
|
30
|
-
this._bindEvents();
|
|
31
31
|
this.emit('ready');
|
|
32
32
|
});
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
_bindEvents() {
|
|
36
|
+
if (this.bindedEvents) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
this.bindedEvents = true;
|
|
41
|
+
|
|
42
|
+
if (this.driverChangeStream == null) {
|
|
43
|
+
this.once('ready', () => {
|
|
44
|
+
this.driverChangeStream.on('close', () => {
|
|
45
|
+
this.closed = true;
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
['close', 'change', 'end', 'error'].forEach(ev => {
|
|
49
|
+
this.driverChangeStream.on(ev, data => this.emit(ev, data));
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
|
|
36
56
|
this.driverChangeStream.on('close', () => {
|
|
37
57
|
this.closed = true;
|
|
38
58
|
});
|
|
39
59
|
|
|
40
60
|
['close', 'change', 'end', 'error'].forEach(ev => {
|
|
41
|
-
this.driverChangeStream.on(ev, data =>
|
|
61
|
+
this.driverChangeStream.on(ev, data => {
|
|
62
|
+
this.emit(ev, data);
|
|
63
|
+
});
|
|
42
64
|
});
|
|
43
65
|
}
|
|
44
66
|
|
|
67
|
+
hasNext(cb) {
|
|
68
|
+
return this.driverChangeStream.hasNext(cb);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
next(cb) {
|
|
72
|
+
return this.driverChangeStream.next(cb);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
on(event, handler) {
|
|
76
|
+
this._bindEvents();
|
|
77
|
+
return super.on(event, handler);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
once(event, handler) {
|
|
81
|
+
this._bindEvents();
|
|
82
|
+
return super.once(event, handler);
|
|
83
|
+
}
|
|
84
|
+
|
|
45
85
|
_queue(cb) {
|
|
46
86
|
this.once('ready', () => cb());
|
|
47
87
|
}
|
|
@@ -225,6 +225,8 @@ QueryCursor.prototype.next = function(callback) {
|
|
|
225
225
|
* @param {Function} fn
|
|
226
226
|
* @param {Object} [options]
|
|
227
227
|
* @param {Number} [options.parallel] the number of promises to execute in parallel. Defaults to 1.
|
|
228
|
+
* @param {Number} [options.batchSize] if set, will call `fn()` with arrays of documents with length at most `batchSize`
|
|
229
|
+
* @param {Boolean} [options.continueOnError=false] if true, `eachAsync()` iterates through all docs even if `fn` throws an error. If false, `eachAsync()` throws an error immediately if the given function `fn()` throws an error.
|
|
228
230
|
* @param {Function} [callback] executed when all docs have been processed
|
|
229
231
|
* @return {Promise}
|
|
230
232
|
* @api public
|
package/lib/document.js
CHANGED
|
@@ -1048,7 +1048,6 @@ Document.prototype.$set = function $set(path, val, type, options) {
|
|
|
1048
1048
|
const merge = options.merge;
|
|
1049
1049
|
const adhoc = type && type !== true;
|
|
1050
1050
|
const constructing = type === true;
|
|
1051
|
-
const typeKey = this.$__schema.options.typeKey;
|
|
1052
1051
|
let adhocs;
|
|
1053
1052
|
let keys;
|
|
1054
1053
|
let i = 0;
|
|
@@ -1150,14 +1149,15 @@ Document.prototype.$set = function $set(path, val, type, options) {
|
|
|
1150
1149
|
}
|
|
1151
1150
|
}
|
|
1152
1151
|
|
|
1153
|
-
// Ensure all properties are in correct order
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1152
|
+
// Ensure all properties are in correct order
|
|
1153
|
+
const orderedDoc = {};
|
|
1154
|
+
const orderedKeys = Object.keys(this.$__schema.tree);
|
|
1155
|
+
for (let i = 0, len = orderedKeys.length; i < len; ++i) {
|
|
1156
|
+
(key = orderedKeys[i]) &&
|
|
1157
|
+
(this._doc.hasOwnProperty(key)) &&
|
|
1158
|
+
(orderedDoc[key] = undefined);
|
|
1160
1159
|
}
|
|
1160
|
+
this._doc = Object.assign(orderedDoc, this._doc);
|
|
1161
1161
|
|
|
1162
1162
|
return this;
|
|
1163
1163
|
}
|
|
@@ -1381,6 +1381,7 @@ Document.prototype.$set = function $set(path, val, type, options) {
|
|
|
1381
1381
|
}
|
|
1382
1382
|
|
|
1383
1383
|
let popOpts;
|
|
1384
|
+
const typeKey = this.$__schema.options.typeKey;
|
|
1384
1385
|
if (schema.options &&
|
|
1385
1386
|
Array.isArray(schema.options[typeKey]) &&
|
|
1386
1387
|
schema.options[typeKey].length &&
|
|
@@ -1400,7 +1401,7 @@ Document.prototype.$set = function $set(path, val, type, options) {
|
|
|
1400
1401
|
// later in `$__set()` because we don't take `_doc` when we iterate through
|
|
1401
1402
|
// a single nested doc. That's to make sure we get the correct context.
|
|
1402
1403
|
// Otherwise we would double-call the setter, see gh-7196.
|
|
1403
|
-
val = schema.applySetters(val, this, false, priorVal);
|
|
1404
|
+
val = schema.applySetters(val, this, false, priorVal, options);
|
|
1404
1405
|
}
|
|
1405
1406
|
|
|
1406
1407
|
if (Array.isArray(val) &&
|
|
@@ -1454,14 +1455,18 @@ Document.prototype.$set = function $set(path, val, type, options) {
|
|
|
1454
1455
|
}
|
|
1455
1456
|
|
|
1456
1457
|
if (shouldSet) {
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
if (
|
|
1464
|
-
|
|
1458
|
+
let savedState = null;
|
|
1459
|
+
let savedStatePath = null;
|
|
1460
|
+
if (!constructing) {
|
|
1461
|
+
const doc = this.$isSubdocument ? this.ownerDocument() : this;
|
|
1462
|
+
savedState = doc.$__.savedState;
|
|
1463
|
+
savedStatePath = this.$isSubdocument ? this.$__.fullPath + '.' + path : path;
|
|
1464
|
+
if (savedState != null) {
|
|
1465
|
+
const firstDot = savedStatePath.indexOf('.');
|
|
1466
|
+
const topLevelPath = firstDot === -1 ? savedStatePath : savedStatePath.slice(0, firstDot);
|
|
1467
|
+
if (!savedState.hasOwnProperty(topLevelPath)) {
|
|
1468
|
+
savedState[topLevelPath] = utils.clone(doc.$__getValue(topLevelPath));
|
|
1469
|
+
}
|
|
1465
1470
|
}
|
|
1466
1471
|
}
|
|
1467
1472
|
|
|
@@ -1618,7 +1623,6 @@ Document.prototype.$__set = function(pathToMark, path, options, constructing, pa
|
|
|
1618
1623
|
|
|
1619
1624
|
const shouldModify = this.$__shouldModify(pathToMark, path, options, constructing, parts,
|
|
1620
1625
|
schema, val, priorVal);
|
|
1621
|
-
const _this = this;
|
|
1622
1626
|
|
|
1623
1627
|
if (shouldModify) {
|
|
1624
1628
|
this.markModified(pathToMark);
|
|
@@ -1634,14 +1638,6 @@ Document.prototype.$__set = function(pathToMark, path, options, constructing, pa
|
|
|
1634
1638
|
item && item.__parentArray && (item.__parentArray = val);
|
|
1635
1639
|
});
|
|
1636
1640
|
}
|
|
1637
|
-
|
|
1638
|
-
// Small hack for gh-1638: if we're overwriting the entire array, ignore
|
|
1639
|
-
// paths that were modified before the array overwrite
|
|
1640
|
-
this.$__.activePaths.forEach(function(modifiedPath) {
|
|
1641
|
-
if (modifiedPath.startsWith(path + '.')) {
|
|
1642
|
-
_this.$__.activePaths.ignore(modifiedPath);
|
|
1643
|
-
}
|
|
1644
|
-
});
|
|
1645
1641
|
}
|
|
1646
1642
|
} else if (Array.isArray(val) && Array.isArray(priorVal) && utils.isMongooseArray(val) && utils.isMongooseArray(priorVal)) {
|
|
1647
1643
|
val[arrayAtomicsSymbol] = priorVal[arrayAtomicsSymbol];
|
package/lib/error/cast.js
CHANGED
|
@@ -23,7 +23,7 @@ class CastError extends MongooseError {
|
|
|
23
23
|
const stringValue = getStringValue(value);
|
|
24
24
|
const valueType = getValueType(value);
|
|
25
25
|
const messageFormat = getMessageFormat(schemaType);
|
|
26
|
-
const msg = formatMessage(null, type, stringValue, path, messageFormat, valueType);
|
|
26
|
+
const msg = formatMessage(null, type, stringValue, path, messageFormat, valueType, reason);
|
|
27
27
|
super(msg);
|
|
28
28
|
this.init(type, value, path, reason, schemaType);
|
|
29
29
|
} else {
|
|
@@ -122,7 +122,7 @@ function getMessageFormat(schemaType) {
|
|
|
122
122
|
* ignore
|
|
123
123
|
*/
|
|
124
124
|
|
|
125
|
-
function formatMessage(model, kind, stringValue, path, messageFormat, valueType) {
|
|
125
|
+
function formatMessage(model, kind, stringValue, path, messageFormat, valueType, reason) {
|
|
126
126
|
if (messageFormat != null) {
|
|
127
127
|
let ret = messageFormat.
|
|
128
128
|
replace('{KIND}', kind).
|
|
@@ -140,6 +140,12 @@ function formatMessage(model, kind, stringValue, path, messageFormat, valueType)
|
|
|
140
140
|
if (model != null) {
|
|
141
141
|
ret += ' for model "' + model.modelName + '"';
|
|
142
142
|
}
|
|
143
|
+
if (reason != null &&
|
|
144
|
+
typeof reason.constructor === 'function' &&
|
|
145
|
+
reason.constructor.name !== 'AssertionError' &&
|
|
146
|
+
reason.constructor.name !== 'Error') {
|
|
147
|
+
ret += ' because of "' + reason.constructor.name + '"';
|
|
148
|
+
}
|
|
143
149
|
return ret;
|
|
144
150
|
}
|
|
145
151
|
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Module dependencies.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
'use strict';
|
|
6
|
+
|
|
7
|
+
const MongooseError = require('./');
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* If `eachAsync()` is called with `continueOnError: true`, there can be
|
|
12
|
+
* multiple errors. This error class contains an `errors` property, which
|
|
13
|
+
* contains an array of all errors that occurred in `eachAsync()`.
|
|
14
|
+
*
|
|
15
|
+
* @api private
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
class EachAsyncMultiError extends MongooseError {
|
|
19
|
+
/**
|
|
20
|
+
* @param {String} connectionString
|
|
21
|
+
*/
|
|
22
|
+
constructor(errors) {
|
|
23
|
+
let preview = errors.map(e => e.message).join(', ');
|
|
24
|
+
if (preview.length > 50) {
|
|
25
|
+
preview = preview.slice(0, 50) + '...';
|
|
26
|
+
}
|
|
27
|
+
super(`eachAsync() finished with ${errors.length} errors: ${preview}`);
|
|
28
|
+
|
|
29
|
+
this.errors = errors;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
Object.defineProperty(EachAsyncMultiError.prototype, 'name', {
|
|
34
|
+
value: 'EachAsyncMultiError'
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
/*!
|
|
38
|
+
* exports
|
|
39
|
+
*/
|
|
40
|
+
|
|
41
|
+
module.exports = EachAsyncMultiError;
|
package/lib/helpers/common.js
CHANGED
|
@@ -80,14 +80,6 @@ function modifiedPaths(update, path, result) {
|
|
|
80
80
|
|
|
81
81
|
const _path = path + key;
|
|
82
82
|
result[_path] = true;
|
|
83
|
-
if (_path.indexOf('.') !== -1) {
|
|
84
|
-
const sp = _path.split('.');
|
|
85
|
-
let cur = sp[0];
|
|
86
|
-
for (let i = 1; i < sp.length; ++i) {
|
|
87
|
-
result[cur] = true;
|
|
88
|
-
cur += '.' + sp[i];
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
83
|
if (!Buffer.isBuffer(val) && isMongooseObject(val)) {
|
|
92
84
|
val = val.toObject({ transform: false, virtuals: false });
|
|
93
85
|
}
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* Module dependencies.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
+
const EachAsyncMultiError = require('../../error/eachAsyncMultiError');
|
|
7
8
|
const immediate = require('../immediate');
|
|
8
9
|
const promiseOrCallback = require('../promiseOrCallback');
|
|
9
10
|
|
|
@@ -24,10 +25,11 @@ const promiseOrCallback = require('../promiseOrCallback');
|
|
|
24
25
|
module.exports = function eachAsync(next, fn, options, callback) {
|
|
25
26
|
const parallel = options.parallel || 1;
|
|
26
27
|
const batchSize = options.batchSize;
|
|
28
|
+
const continueOnError = options.continueOnError;
|
|
29
|
+
const aggregatedErrors = [];
|
|
27
30
|
const enqueue = asyncQueue();
|
|
28
31
|
|
|
29
32
|
return promiseOrCallback(callback, cb => {
|
|
30
|
-
|
|
31
33
|
if (batchSize != null) {
|
|
32
34
|
if (typeof batchSize !== 'number') {
|
|
33
35
|
throw new TypeError('batchSize must be a number');
|
|
@@ -62,14 +64,22 @@ module.exports = function eachAsync(next, fn, options, callback) {
|
|
|
62
64
|
return done();
|
|
63
65
|
}
|
|
64
66
|
if (err != null) {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
67
|
+
if (continueOnError) {
|
|
68
|
+
aggregatedErrors.push(err);
|
|
69
|
+
} else {
|
|
70
|
+
error = err;
|
|
71
|
+
finalCallback(err);
|
|
72
|
+
return done();
|
|
73
|
+
}
|
|
68
74
|
}
|
|
69
75
|
if (doc == null) {
|
|
70
76
|
drained = true;
|
|
71
77
|
if (handleResultsInProgress <= 0) {
|
|
72
|
-
|
|
78
|
+
const finalErr = continueOnError ?
|
|
79
|
+
createEachAsyncMultiError(aggregatedErrors) :
|
|
80
|
+
error;
|
|
81
|
+
|
|
82
|
+
finalCallback(finalErr);
|
|
73
83
|
} else if (batchSize && documentsBatch.length) {
|
|
74
84
|
handleNextResult(documentsBatch, currentDocumentIndex++, handleNextResultCallBack);
|
|
75
85
|
}
|
|
@@ -102,11 +112,18 @@ module.exports = function eachAsync(next, fn, options, callback) {
|
|
|
102
112
|
--handleResultsInProgress;
|
|
103
113
|
}
|
|
104
114
|
if (err != null) {
|
|
105
|
-
|
|
106
|
-
|
|
115
|
+
if (continueOnError) {
|
|
116
|
+
aggregatedErrors.push(err);
|
|
117
|
+
} else {
|
|
118
|
+
error = err;
|
|
119
|
+
return finalCallback(err);
|
|
120
|
+
}
|
|
107
121
|
}
|
|
108
122
|
if (drained && handleResultsInProgress <= 0) {
|
|
109
|
-
|
|
123
|
+
const finalErr = continueOnError ?
|
|
124
|
+
createEachAsyncMultiError(aggregatedErrors) :
|
|
125
|
+
error;
|
|
126
|
+
return finalCallback(finalErr);
|
|
110
127
|
}
|
|
111
128
|
|
|
112
129
|
immediate(() => enqueue(fetch));
|
|
@@ -118,11 +135,18 @@ module.exports = function eachAsync(next, fn, options, callback) {
|
|
|
118
135
|
}
|
|
119
136
|
|
|
120
137
|
function handleNextResult(doc, i, callback) {
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
138
|
+
let maybePromise;
|
|
139
|
+
try {
|
|
140
|
+
maybePromise = fn(doc, i);
|
|
141
|
+
} catch (err) {
|
|
142
|
+
return callback(err);
|
|
143
|
+
}
|
|
144
|
+
if (maybePromise && typeof maybePromise.then === 'function') {
|
|
145
|
+
maybePromise.then(
|
|
124
146
|
function() { callback(null); },
|
|
125
|
-
function(error) {
|
|
147
|
+
function(error) {
|
|
148
|
+
callback(error || new Error('`eachAsync()` promise rejected without error'));
|
|
149
|
+
});
|
|
126
150
|
} else {
|
|
127
151
|
callback(null);
|
|
128
152
|
}
|
|
@@ -158,3 +182,11 @@ function asyncQueue() {
|
|
|
158
182
|
}
|
|
159
183
|
}
|
|
160
184
|
}
|
|
185
|
+
|
|
186
|
+
function createEachAsyncMultiError(aggregatedErrors) {
|
|
187
|
+
if (aggregatedErrors.length === 0) {
|
|
188
|
+
return null;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
return new EachAsyncMultiError(aggregatedErrors);
|
|
192
|
+
}
|
package/lib/helpers/immediate.js
CHANGED
|
@@ -7,7 +7,9 @@
|
|
|
7
7
|
|
|
8
8
|
'use strict';
|
|
9
9
|
|
|
10
|
-
const nextTick = process.nextTick
|
|
10
|
+
const nextTick = typeof process !== 'undefined' && typeof process.nextTick === 'function' ?
|
|
11
|
+
process.nextTick.bind(process) :
|
|
12
|
+
cb => setTimeout(cb, 0); // Fallback for browser build
|
|
11
13
|
|
|
12
14
|
module.exports = function immediate(cb) {
|
|
13
15
|
return nextTick(cb);
|
|
@@ -1,10 +1,22 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
let asyncFunctionPrototype = null;
|
|
4
|
+
// try/catch for Babel compatibility, because Babel preset-env requires
|
|
5
|
+
// regenerator-runtime for async/await and we don't want to include that
|
|
6
|
+
// for a simple check.
|
|
7
|
+
try {
|
|
8
|
+
asyncFunctionPrototype = Object.getPrototypeOf(async function() {});
|
|
9
|
+
} catch (err) {}
|
|
4
10
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
+
if (asyncFunctionPrototype == null) {
|
|
12
|
+
module.exports = function isAsyncFunction() {
|
|
13
|
+
return false;
|
|
14
|
+
};
|
|
15
|
+
} else {
|
|
16
|
+
module.exports = function isAsyncFunction(v) {
|
|
17
|
+
return (
|
|
18
|
+
typeof v === 'function' &&
|
|
19
|
+
Object.getPrototypeOf(v) === asyncFunctionPrototype
|
|
20
|
+
);
|
|
21
|
+
};
|
|
22
|
+
}
|
|
@@ -17,7 +17,6 @@ const CUSTOMIZABLE_DISCRIMINATOR_OPTIONS = {
|
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
19
|
module.exports = function discriminator(model, name, schema, tiedValue, applyPlugins) {
|
|
20
|
-
|
|
21
20
|
if (!(schema && schema.instanceOfSchema)) {
|
|
22
21
|
throw new Error('You must pass a valid discriminator Schema');
|
|
23
22
|
}
|
|
@@ -109,7 +108,7 @@ module.exports = function discriminator(model, name, schema, tiedValue, applyPlu
|
|
|
109
108
|
|
|
110
109
|
utils.merge(schema, baseSchema, {
|
|
111
110
|
isDiscriminatorSchemaMerge: true,
|
|
112
|
-
omit: { discriminators: true, base: true },
|
|
111
|
+
omit: { discriminators: true, base: true, _applyDiscriminators: true },
|
|
113
112
|
omitNested: conflictingPaths.reduce((cur, path) => {
|
|
114
113
|
cur['tree.' + path] = true;
|
|
115
114
|
return cur;
|
|
@@ -141,7 +140,6 @@ module.exports = function discriminator(model, name, schema, tiedValue, applyPlu
|
|
|
141
140
|
obj[key][schema.options.typeKey] = existingPath ? existingPath.options[schema.options.typeKey] : String;
|
|
142
141
|
schema.add(obj);
|
|
143
142
|
|
|
144
|
-
|
|
145
143
|
schema.discriminatorMapping = { key: key, value: value, isRoot: false };
|
|
146
144
|
|
|
147
145
|
if (baseSchema.options.collection) {
|
|
@@ -76,17 +76,20 @@ module.exports = function getModelsMapForPopulate(model, docs, options) {
|
|
|
76
76
|
let schemaOptions = null;
|
|
77
77
|
let modelNamesInOrder = null;
|
|
78
78
|
|
|
79
|
-
if (schema != null && schema.instance === 'Embedded'
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
79
|
+
if (schema != null && schema.instance === 'Embedded') {
|
|
80
|
+
if (schema.options.ref) {
|
|
81
|
+
const data = {
|
|
82
|
+
localField: options.path + '._id',
|
|
83
|
+
foreignField: '_id',
|
|
84
|
+
justOne: true
|
|
85
|
+
};
|
|
86
|
+
const res = _getModelNames(doc, schema, modelNameFromQuery, model);
|
|
86
87
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
88
|
+
const unpopulatedValue = mpath.get(options.path, doc);
|
|
89
|
+
const id = mpath.get('_id', unpopulatedValue);
|
|
90
|
+
addModelNamesToMap(model, map, available, res.modelNames, options, data, id, doc, schemaOptions, unpopulatedValue);
|
|
91
|
+
}
|
|
92
|
+
// No-op if no `ref` set. See gh-11538
|
|
90
93
|
continue;
|
|
91
94
|
}
|
|
92
95
|
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const utils = require('../../utils');
|
|
4
|
+
|
|
5
|
+
function applyGlobalMaxTimeMS(options, model) {
|
|
6
|
+
applyGlobalOption(options, model, 'maxTimeMS');
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
function applyGlobalDiskUse(options, model) {
|
|
10
|
+
applyGlobalOption(options, model, 'allowDiskUse');
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
module.exports = {
|
|
14
|
+
applyGlobalMaxTimeMS,
|
|
15
|
+
applyGlobalDiskUse
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
function applyGlobalOption(options, model, optionName) {
|
|
20
|
+
if (utils.hasUserDefinedProperty(options, optionName)) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (utils.hasUserDefinedProperty(model.db.options, optionName)) {
|
|
25
|
+
options[optionName] = model.db.options[optionName];
|
|
26
|
+
} else if (utils.hasUserDefinedProperty(model.base.options, optionName)) {
|
|
27
|
+
options[optionName] = model.base.options[optionName];
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -19,13 +19,16 @@ module.exports = function(schematype) {
|
|
|
19
19
|
};
|
|
20
20
|
|
|
21
21
|
function createImmutableSetter(path, immutable) {
|
|
22
|
-
return function immutableSetter(v) {
|
|
22
|
+
return function immutableSetter(v, _priorVal, _doc, options) {
|
|
23
23
|
if (this == null || this.$__ == null) {
|
|
24
24
|
return v;
|
|
25
25
|
}
|
|
26
26
|
if (this.isNew) {
|
|
27
27
|
return v;
|
|
28
28
|
}
|
|
29
|
+
if (options && options.overwriteImmutable) {
|
|
30
|
+
return v;
|
|
31
|
+
}
|
|
29
32
|
|
|
30
33
|
const _immutable = typeof immutable === 'function' ?
|
|
31
34
|
immutable.call(this, this) :
|
|
@@ -48,8 +48,8 @@ module.exports = function setupTimestamps(schema, timestamps) {
|
|
|
48
48
|
currentTime() :
|
|
49
49
|
this.ownerDocument().constructor.base.now();
|
|
50
50
|
|
|
51
|
-
if (!skipCreatedAt && this.isNew && createdAt && !this.$__getValue(createdAt) && this.$__isSelected(createdAt)) {
|
|
52
|
-
this.$set(createdAt, defaultTimestamp);
|
|
51
|
+
if (!skipCreatedAt && (this.isNew || this.$isSubdocument) && createdAt && !this.$__getValue(createdAt) && this.$__isSelected(createdAt)) {
|
|
52
|
+
this.$set(createdAt, defaultTimestamp, undefined, { overwriteImmutable: true });
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
if (!skipUpdatedAt && updatedAt && (this.isNew || this.$isModified())) {
|
package/lib/index.js
CHANGED
|
@@ -179,7 +179,9 @@ Mongoose.prototype.driver = driver;
|
|
|
179
179
|
Mongoose.prototype.set = function(key, value) {
|
|
180
180
|
const _mongoose = this instanceof Mongoose ? this : mongoose;
|
|
181
181
|
|
|
182
|
-
if (VALID_OPTIONS.indexOf(key) === -1)
|
|
182
|
+
if (VALID_OPTIONS.indexOf(key) === -1) {
|
|
183
|
+
throw new Error(`\`${key}\` is an invalid option.`);
|
|
184
|
+
}
|
|
183
185
|
|
|
184
186
|
if (arguments.length === 1) {
|
|
185
187
|
return _mongoose.options[key];
|
|
@@ -265,7 +267,7 @@ Mongoose.prototype.get = Mongoose.prototype.set;
|
|
|
265
267
|
* @param {Number} [options.connectTimeoutMS=30000] How long the MongoDB driver will wait before killing a socket due to inactivity _during initial connection_. Defaults to 30000. This option is passed transparently to [Node.js' `socket#setTimeout()` function](https://nodejs.org/api/net.html#net_socket_settimeout_timeout_callback).
|
|
266
268
|
* @param {Number} [options.socketTimeoutMS=30000] 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. This is set to `30000` by default, you should set this to 2-3x your longest running operation if you expect some of your database operations to run longer than 20 seconds. 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.
|
|
267
269
|
* @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.
|
|
268
|
-
* @return {Connection} the created Connection object. Connections are thenable, so you can do `await mongoose.createConnection()
|
|
270
|
+
* @return {Connection} the created Connection object. Connections are not thenable, so you can't do `await mongoose.createConnection()`. To await use mongoose.createConnection(uri).asPromise() instead.
|
|
269
271
|
* @api public
|
|
270
272
|
*/
|
|
271
273
|
|
|
@@ -467,6 +469,7 @@ Mongoose.prototype.pluralize = function(fn) {
|
|
|
467
469
|
*/
|
|
468
470
|
|
|
469
471
|
Mongoose.prototype.model = function(name, schema, collection, options) {
|
|
472
|
+
|
|
470
473
|
const _mongoose = this instanceof Mongoose ? this : mongoose;
|
|
471
474
|
|
|
472
475
|
if (typeof schema === 'string') {
|
|
@@ -519,7 +522,6 @@ Mongoose.prototype.model = function(name, schema, collection, options) {
|
|
|
519
522
|
}
|
|
520
523
|
|
|
521
524
|
const model = _mongoose._model(name, schema, collection, options);
|
|
522
|
-
|
|
523
525
|
_mongoose.connection.models[name] = model;
|
|
524
526
|
_mongoose.models[name] = model;
|
|
525
527
|
|
|
@@ -561,12 +563,17 @@ Mongoose.prototype._model = function(name, schema, collection, options) {
|
|
|
561
563
|
|
|
562
564
|
const connection = options.connection || _mongoose.connection;
|
|
563
565
|
model = _mongoose.Model.compile(model || name, schema, collection, connection, _mongoose);
|
|
564
|
-
|
|
565
566
|
// Errors handled internally, so safe to ignore error
|
|
566
567
|
model.init(function $modelInitNoop() {});
|
|
567
568
|
|
|
568
569
|
connection.emit('model', model);
|
|
569
570
|
|
|
571
|
+
if (schema._applyDiscriminators != null) {
|
|
572
|
+
for (const disc of Object.keys(schema._applyDiscriminators)) {
|
|
573
|
+
model.discriminator(disc, schema._applyDiscriminators[disc]);
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
|
|
570
577
|
return model;
|
|
571
578
|
};
|
|
572
579
|
|