mongoose 7.6.2 → 7.6.4
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 +4 -0
- package/lib/document.js +11 -1
- package/lib/helpers/model/castBulkWrite.js +21 -0
- package/lib/helpers/populate/getModelsMapForPopulate.js +2 -1
- package/lib/helpers/query/castUpdate.js +2 -1
- package/lib/helpers/update/decorateUpdateWithVersionKey.js +26 -0
- package/lib/model.js +3 -28
- package/lib/query.js +0 -1
- package/lib/schema/SubdocumentPath.js +6 -3
- package/lib/schema/array.js +2 -2
- package/lib/schema.js +3 -1
- package/lib/schematype.js +2 -0
- package/lib/utils.js +8 -5
- package/package.json +1 -1
- package/types/index.d.ts +1 -1
- package/types/validation.d.ts +1 -0
package/lib/connection.js
CHANGED
|
@@ -563,6 +563,10 @@ function _resetSessionDocuments(session) {
|
|
|
563
563
|
doc.$__.activePaths.states.modify = {};
|
|
564
564
|
}
|
|
565
565
|
for (const path of state.modifiedPaths) {
|
|
566
|
+
const currentState = doc.$__.activePaths.paths[path];
|
|
567
|
+
if (currentState != null) {
|
|
568
|
+
delete doc.$__.activePaths[currentState][path];
|
|
569
|
+
}
|
|
566
570
|
doc.$__.activePaths.paths[path] = 'modify';
|
|
567
571
|
doc.$__.activePaths.states.modify[path] = true;
|
|
568
572
|
}
|
package/lib/document.js
CHANGED
|
@@ -53,6 +53,7 @@ const scopeSymbol = require('./helpers/symbols').scopeSymbol;
|
|
|
53
53
|
const schemaMixedSymbol = require('./schema/symbols').schemaMixedSymbol;
|
|
54
54
|
const parentPaths = require('./helpers/path/parentPaths');
|
|
55
55
|
const getDeepestSubdocumentForPath = require('./helpers/document/getDeepestSubdocumentForPath');
|
|
56
|
+
const sessionNewDocuments = require('./helpers/symbols').sessionNewDocuments;
|
|
56
57
|
|
|
57
58
|
let DocumentArray;
|
|
58
59
|
let MongooseArray;
|
|
@@ -1474,7 +1475,16 @@ Document.prototype.$set = function $set(path, val, type, options) {
|
|
|
1474
1475
|
|
|
1475
1476
|
this.$__set(pathToMark, path, options, constructing, parts, schema, val, priorVal);
|
|
1476
1477
|
|
|
1477
|
-
|
|
1478
|
+
const isInTransaction = !!this.$__.session?.transaction;
|
|
1479
|
+
const isModifiedWithinTransaction = this.$__.session &&
|
|
1480
|
+
this.$__.session[sessionNewDocuments] &&
|
|
1481
|
+
this.$__.session[sessionNewDocuments].has(this) &&
|
|
1482
|
+
this.$__.session[sessionNewDocuments].get(this).modifiedPaths &&
|
|
1483
|
+
!this.$__.session[sessionNewDocuments].get(this).modifiedPaths.has(savedStatePath);
|
|
1484
|
+
if (savedState != null &&
|
|
1485
|
+
savedState.hasOwnProperty(savedStatePath) &&
|
|
1486
|
+
(!isInTransaction || isModifiedWithinTransaction) &&
|
|
1487
|
+
utils.deepEqual(val, savedState[savedStatePath])) {
|
|
1478
1488
|
this.unmarkModified(path);
|
|
1479
1489
|
}
|
|
1480
1490
|
}
|
|
@@ -6,6 +6,7 @@ const applyTimestampsToChildren = require('../update/applyTimestampsToChildren')
|
|
|
6
6
|
const applyTimestampsToUpdate = require('../update/applyTimestampsToUpdate');
|
|
7
7
|
const cast = require('../../cast');
|
|
8
8
|
const castUpdate = require('../query/castUpdate');
|
|
9
|
+
const decorateUpdateWithVersionKey = require('../update/decorateUpdateWithVersionKey');
|
|
9
10
|
const { inspect } = require('util');
|
|
10
11
|
const setDefaultsOnInsert = require('../setDefaultsOnInsert');
|
|
11
12
|
|
|
@@ -33,6 +34,10 @@ module.exports = function castBulkWrite(originalModel, op, options) {
|
|
|
33
34
|
if (options.session != null) {
|
|
34
35
|
doc.$session(options.session);
|
|
35
36
|
}
|
|
37
|
+
const versionKey = model?.schema?.options?.versionKey;
|
|
38
|
+
if (versionKey && doc[versionKey] == null) {
|
|
39
|
+
doc[versionKey] = 0;
|
|
40
|
+
}
|
|
36
41
|
op['insertOne']['document'] = doc;
|
|
37
42
|
|
|
38
43
|
if (options.skipValidation || op['insertOne'].skipValidation) {
|
|
@@ -81,6 +86,12 @@ module.exports = function castBulkWrite(originalModel, op, options) {
|
|
|
81
86
|
});
|
|
82
87
|
}
|
|
83
88
|
|
|
89
|
+
decorateUpdateWithVersionKey(
|
|
90
|
+
op['updateOne']['update'],
|
|
91
|
+
op['updateOne'],
|
|
92
|
+
model.schema.options.versionKey
|
|
93
|
+
);
|
|
94
|
+
|
|
84
95
|
op['updateOne']['filter'] = cast(model.schema, op['updateOne']['filter'], {
|
|
85
96
|
strict: strict,
|
|
86
97
|
upsert: op['updateOne'].upsert
|
|
@@ -133,6 +144,12 @@ module.exports = function castBulkWrite(originalModel, op, options) {
|
|
|
133
144
|
|
|
134
145
|
_addDiscriminatorToObject(schema, op['updateMany']['filter']);
|
|
135
146
|
|
|
147
|
+
decorateUpdateWithVersionKey(
|
|
148
|
+
op['updateMany']['update'],
|
|
149
|
+
op['updateMany'],
|
|
150
|
+
model.schema.options.versionKey
|
|
151
|
+
);
|
|
152
|
+
|
|
136
153
|
op['updateMany']['filter'] = cast(model.schema, op['updateMany']['filter'], {
|
|
137
154
|
strict: strict,
|
|
138
155
|
upsert: op['updateMany'].upsert
|
|
@@ -173,6 +190,10 @@ module.exports = function castBulkWrite(originalModel, op, options) {
|
|
|
173
190
|
if (options.session != null) {
|
|
174
191
|
doc.$session(options.session);
|
|
175
192
|
}
|
|
193
|
+
const versionKey = model?.schema?.options?.versionKey;
|
|
194
|
+
if (versionKey && doc[versionKey] == null) {
|
|
195
|
+
doc[versionKey] = 0;
|
|
196
|
+
}
|
|
176
197
|
op['replaceOne']['replacement'] = doc;
|
|
177
198
|
|
|
178
199
|
if (options.skipValidation || op['replaceOne'].skipValidation) {
|
|
@@ -45,7 +45,8 @@ module.exports = function getModelsMapForPopulate(model, docs, options) {
|
|
|
45
45
|
let allSchemaTypes = getSchemaTypes(model, modelSchema, null, options.path);
|
|
46
46
|
allSchemaTypes = Array.isArray(allSchemaTypes) ? allSchemaTypes : [allSchemaTypes].filter(v => v != null);
|
|
47
47
|
|
|
48
|
-
|
|
48
|
+
const isStrictPopulateDisabled = options.strictPopulate === false || options.options?.strictPopulate === false;
|
|
49
|
+
if (!isStrictPopulateDisabled && allSchemaTypes.length === 0 && options._localModel != null) {
|
|
49
50
|
return new StrictPopulate(options._fullPath || options.path);
|
|
50
51
|
}
|
|
51
52
|
|
|
@@ -126,7 +126,8 @@ module.exports = function castUpdate(schema, obj, options, context, filter) {
|
|
|
126
126
|
Object.keys(filter).length > 0) {
|
|
127
127
|
// Trick the driver into allowing empty upserts to work around
|
|
128
128
|
// https://github.com/mongodb/node-mongodb-native/pull/2490
|
|
129
|
-
|
|
129
|
+
// Shallow clone to avoid passing defaults in re: gh-13962
|
|
130
|
+
return { $setOnInsert: { ...filter } };
|
|
130
131
|
}
|
|
131
132
|
return ret;
|
|
132
133
|
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const modifiedPaths = require('./modifiedPaths');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Decorate the update with a version key, if necessary
|
|
7
|
+
* @api private
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
module.exports = function decorateUpdateWithVersionKey(update, options, versionKey) {
|
|
11
|
+
if (!versionKey || !(options && options.upsert || false)) {
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const updatedPaths = modifiedPaths(update);
|
|
16
|
+
if (!updatedPaths[versionKey]) {
|
|
17
|
+
if (options.overwrite) {
|
|
18
|
+
update[versionKey] = 0;
|
|
19
|
+
} else {
|
|
20
|
+
if (!update.$setOnInsert) {
|
|
21
|
+
update.$setOnInsert = {};
|
|
22
|
+
}
|
|
23
|
+
update.$setOnInsert[versionKey] = 0;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
};
|
package/lib/model.js
CHANGED
|
@@ -33,6 +33,7 @@ const assignVals = require('./helpers/populate/assignVals');
|
|
|
33
33
|
const castBulkWrite = require('./helpers/model/castBulkWrite');
|
|
34
34
|
const clone = require('./helpers/clone');
|
|
35
35
|
const createPopulateQueryFilter = require('./helpers/populate/createPopulateQueryFilter');
|
|
36
|
+
const decorateUpdateWithVersionKey = require('./helpers/update/decorateUpdateWithVersionKey');
|
|
36
37
|
const getDefaultBulkwriteResult = require('./helpers/getDefaultBulkwriteResult');
|
|
37
38
|
const getSchemaDiscriminatorByValue = require('./helpers/discriminator/getSchemaDiscriminatorByValue');
|
|
38
39
|
const discriminator = require('./helpers/model/discriminator');
|
|
@@ -54,7 +55,6 @@ const isPathExcluded = require('./helpers/projection/isPathExcluded');
|
|
|
54
55
|
const decorateDiscriminatorIndexOptions = require('./helpers/indexes/decorateDiscriminatorIndexOptions');
|
|
55
56
|
const isPathSelectedInclusive = require('./helpers/projection/isPathSelectedInclusive');
|
|
56
57
|
const leanPopulateMap = require('./helpers/populate/leanPopulateMap');
|
|
57
|
-
const modifiedPaths = require('./helpers/update/modifiedPaths');
|
|
58
58
|
const parallelLimit = require('./helpers/parallelLimit');
|
|
59
59
|
const parentPaths = require('./helpers/path/parentPaths');
|
|
60
60
|
const prepareDiscriminatorPipeline = require('./helpers/aggregate/prepareDiscriminatorPipeline');
|
|
@@ -2451,7 +2451,7 @@ Model.findOneAndUpdate = function(conditions, update, options) {
|
|
|
2451
2451
|
_isNested: true
|
|
2452
2452
|
});
|
|
2453
2453
|
|
|
2454
|
-
|
|
2454
|
+
decorateUpdateWithVersionKey(update, options, this.schema.options.versionKey);
|
|
2455
2455
|
|
|
2456
2456
|
const mq = new this.Query({}, {}, this, this.$__collection);
|
|
2457
2457
|
mq.select(fields);
|
|
@@ -2459,29 +2459,6 @@ Model.findOneAndUpdate = function(conditions, update, options) {
|
|
|
2459
2459
|
return mq.findOneAndUpdate(conditions, update, options);
|
|
2460
2460
|
};
|
|
2461
2461
|
|
|
2462
|
-
/**
|
|
2463
|
-
* Decorate the update with a version key, if necessary
|
|
2464
|
-
* @api private
|
|
2465
|
-
*/
|
|
2466
|
-
|
|
2467
|
-
function _decorateUpdateWithVersionKey(update, options, versionKey) {
|
|
2468
|
-
if (!versionKey || !(options && options.upsert || false)) {
|
|
2469
|
-
return;
|
|
2470
|
-
}
|
|
2471
|
-
|
|
2472
|
-
const updatedPaths = modifiedPaths(update);
|
|
2473
|
-
if (!updatedPaths[versionKey]) {
|
|
2474
|
-
if (options.overwrite) {
|
|
2475
|
-
update[versionKey] = 0;
|
|
2476
|
-
} else {
|
|
2477
|
-
if (!update.$setOnInsert) {
|
|
2478
|
-
update.$setOnInsert = {};
|
|
2479
|
-
}
|
|
2480
|
-
update.$setOnInsert[versionKey] = 0;
|
|
2481
|
-
}
|
|
2482
|
-
}
|
|
2483
|
-
}
|
|
2484
|
-
|
|
2485
2462
|
/**
|
|
2486
2463
|
* Issues a mongodb findOneAndUpdate command by a document's _id field.
|
|
2487
2464
|
* `findByIdAndUpdate(id, ...)` is equivalent to `findOneAndUpdate({ _id: id }, ...)`.
|
|
@@ -4022,7 +3999,7 @@ function _update(model, op, conditions, doc, options) {
|
|
|
4022
3999
|
model.schema &&
|
|
4023
4000
|
model.schema.options &&
|
|
4024
4001
|
model.schema.options.versionKey || null;
|
|
4025
|
-
|
|
4002
|
+
decorateUpdateWithVersionKey(doc, options, versionKey);
|
|
4026
4003
|
|
|
4027
4004
|
return mq[op](conditions, doc, options);
|
|
4028
4005
|
}
|
|
@@ -4286,9 +4263,7 @@ Model.populate = async function populate(docs, paths) {
|
|
|
4286
4263
|
if (typeof paths === 'function' || typeof arguments[2] === 'function') {
|
|
4287
4264
|
throw new MongooseError('Model.populate() no longer accepts a callback');
|
|
4288
4265
|
}
|
|
4289
|
-
|
|
4290
4266
|
const _this = this;
|
|
4291
|
-
|
|
4292
4267
|
// normalized paths
|
|
4293
4268
|
paths = utils.populate(paths);
|
|
4294
4269
|
// data that should persist across subPopulate calls
|
package/lib/query.js
CHANGED
|
@@ -2305,7 +2305,6 @@ Query.prototype._find = async function _find() {
|
|
|
2305
2305
|
_completeManyLean(_this.model.schema, docs, null, completeManyOptions) :
|
|
2306
2306
|
completeMany(_this.model, docs, fields, userProvidedFields, completeManyOptions);
|
|
2307
2307
|
}
|
|
2308
|
-
|
|
2309
2308
|
const pop = helpers.preparePopulationOptionsMQ(_this, mongooseOptions);
|
|
2310
2309
|
|
|
2311
2310
|
if (mongooseOptions.lean) {
|
|
@@ -56,7 +56,7 @@ function SubdocumentPath(schema, path, options) {
|
|
|
56
56
|
this.base = schema.base;
|
|
57
57
|
SchemaType.call(this, path, options, 'Embedded');
|
|
58
58
|
|
|
59
|
-
if (schema._applyDiscriminators != null) {
|
|
59
|
+
if (schema._applyDiscriminators != null && !options?._skipApplyDiscriminators) {
|
|
60
60
|
for (const disc of schema._applyDiscriminators.keys()) {
|
|
61
61
|
this.discriminator(disc, schema._applyDiscriminators.get(disc));
|
|
62
62
|
}
|
|
@@ -388,8 +388,11 @@ SubdocumentPath.prototype.toJSON = function toJSON() {
|
|
|
388
388
|
*/
|
|
389
389
|
|
|
390
390
|
SubdocumentPath.prototype.clone = function() {
|
|
391
|
-
const
|
|
392
|
-
|
|
391
|
+
const schematype = new this.constructor(
|
|
392
|
+
this.schema,
|
|
393
|
+
this.path,
|
|
394
|
+
{ ...this.options, _skipApplyDiscriminators: true }
|
|
395
|
+
);
|
|
393
396
|
schematype.validators = this.validators.slice();
|
|
394
397
|
if (this.requiredValidator !== undefined) {
|
|
395
398
|
schematype.requiredValidator = this.requiredValidator;
|
package/lib/schema/array.js
CHANGED
|
@@ -623,8 +623,8 @@ function cast$elemMatch(val, context) {
|
|
|
623
623
|
discriminators[val[discriminatorKey]] != null) {
|
|
624
624
|
return cast(discriminators[val[discriminatorKey]], val, null, this && this.$$context);
|
|
625
625
|
}
|
|
626
|
-
|
|
627
|
-
return cast(
|
|
626
|
+
const schema = this.casterConstructor.schema ?? context.schema;
|
|
627
|
+
return cast(schema, val, null, this && this.$$context);
|
|
628
628
|
}
|
|
629
629
|
|
|
630
630
|
const handle = SchemaArray.prototype.$conditionalHandlers = {};
|
package/lib/schema.js
CHANGED
|
@@ -412,7 +412,9 @@ Schema.prototype._clone = function _clone(Constructor) {
|
|
|
412
412
|
s.s.hooks = this.s.hooks.clone();
|
|
413
413
|
|
|
414
414
|
s.tree = clone(this.tree);
|
|
415
|
-
s.paths =
|
|
415
|
+
s.paths = Object.fromEntries(
|
|
416
|
+
Object.entries(this.paths).map(([key, value]) => ([key, value.clone()]))
|
|
417
|
+
);
|
|
416
418
|
s.nested = clone(this.nested);
|
|
417
419
|
s.subpaths = clone(this.subpaths);
|
|
418
420
|
for (const schemaType of Object.values(s.paths)) {
|
package/lib/schematype.js
CHANGED
|
@@ -1305,6 +1305,7 @@ SchemaType.prototype.doValidate = function(value, fn, scope, options) {
|
|
|
1305
1305
|
|
|
1306
1306
|
const validatorProperties = isSimpleValidator(v) ? Object.assign({}, v) : clone(v);
|
|
1307
1307
|
validatorProperties.path = options && options.path ? options.path : path;
|
|
1308
|
+
validatorProperties.fullPath = this.$fullPath;
|
|
1308
1309
|
validatorProperties.value = value;
|
|
1309
1310
|
|
|
1310
1311
|
if (validator instanceof RegExp) {
|
|
@@ -1426,6 +1427,7 @@ SchemaType.prototype.doValidateSync = function(value, scope, options) {
|
|
|
1426
1427
|
const validator = v.validator;
|
|
1427
1428
|
const validatorProperties = isSimpleValidator(v) ? Object.assign({}, v) : clone(v);
|
|
1428
1429
|
validatorProperties.path = options && options.path ? options.path : path;
|
|
1430
|
+
validatorProperties.fullPath = this.$fullPath;
|
|
1429
1431
|
validatorProperties.value = value;
|
|
1430
1432
|
let ok = false;
|
|
1431
1433
|
|
package/lib/utils.js
CHANGED
|
@@ -31,6 +31,9 @@ exports.isMongooseDocumentArray = isMongooseDocumentArray.isMongooseDocumentArra
|
|
|
31
31
|
exports.registerMongooseArray = isMongooseArray.registerMongooseArray;
|
|
32
32
|
exports.registerMongooseDocumentArray = isMongooseDocumentArray.registerMongooseDocumentArray;
|
|
33
33
|
|
|
34
|
+
const oneSpaceRE = /\s/;
|
|
35
|
+
const manySpaceRE = /\s+/;
|
|
36
|
+
|
|
34
37
|
/**
|
|
35
38
|
* Produces a collection name from model `name`. By default, just returns
|
|
36
39
|
* the model name
|
|
@@ -572,8 +575,8 @@ exports.populate = function populate(path, select, model, match, options, subPop
|
|
|
572
575
|
function makeSingles(arr) {
|
|
573
576
|
const ret = [];
|
|
574
577
|
arr.forEach(function(obj) {
|
|
575
|
-
if (
|
|
576
|
-
const paths = obj.path.split(
|
|
578
|
+
if (oneSpaceRE.test(obj.path)) {
|
|
579
|
+
const paths = obj.path.split(manySpaceRE);
|
|
577
580
|
paths.forEach(function(p) {
|
|
578
581
|
const copy = Object.assign({}, obj);
|
|
579
582
|
copy.path = p;
|
|
@@ -592,9 +595,9 @@ function _populateObj(obj) {
|
|
|
592
595
|
if (Array.isArray(obj.populate)) {
|
|
593
596
|
const ret = [];
|
|
594
597
|
obj.populate.forEach(function(obj) {
|
|
595
|
-
if (
|
|
598
|
+
if (oneSpaceRE.test(obj.path)) {
|
|
596
599
|
const copy = Object.assign({}, obj);
|
|
597
|
-
const paths = copy.path.split(
|
|
600
|
+
const paths = copy.path.split(manySpaceRE);
|
|
598
601
|
paths.forEach(function(p) {
|
|
599
602
|
copy.path = p;
|
|
600
603
|
ret.push(exports.populate(copy)[0]);
|
|
@@ -609,7 +612,7 @@ function _populateObj(obj) {
|
|
|
609
612
|
}
|
|
610
613
|
|
|
611
614
|
const ret = [];
|
|
612
|
-
const paths = obj.path.split(
|
|
615
|
+
const paths = oneSpaceRE.test(obj.path) ? obj.path.split(manySpaceRE) : [obj.path];
|
|
613
616
|
if (obj.options != null) {
|
|
614
617
|
obj.options = clone(obj.options);
|
|
615
618
|
}
|
package/package.json
CHANGED
package/types/index.d.ts
CHANGED
|
@@ -260,7 +260,7 @@ declare module 'mongoose' {
|
|
|
260
260
|
/** Returns a copy of this schema */
|
|
261
261
|
clone<T = this>(): T;
|
|
262
262
|
|
|
263
|
-
discriminator<DisSchema = Schema>(name: string, schema: DisSchema): this;
|
|
263
|
+
discriminator<DisSchema = Schema>(name: string | number, schema: DisSchema): this;
|
|
264
264
|
|
|
265
265
|
/** Returns a new schema that has the picked `paths` from this schema. */
|
|
266
266
|
pick<T = this>(paths: string[], options?: SchemaOptions): T;
|