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
|
@@ -50,9 +50,9 @@ function SchemaSubdocument(schema, path, options, parentSchema) {
|
|
|
50
50
|
|
|
51
51
|
schema = handleIdOption(schema, options);
|
|
52
52
|
|
|
53
|
-
this.
|
|
54
|
-
this.
|
|
55
|
-
this.
|
|
53
|
+
this.Constructor = _createConstructor(schema, null, options);
|
|
54
|
+
this.Constructor.path = path;
|
|
55
|
+
this.Constructor.prototype.$basePath = path;
|
|
56
56
|
this.schema = schema;
|
|
57
57
|
this.$isSingleNested = true;
|
|
58
58
|
this.base = schema.base;
|
|
@@ -181,13 +181,13 @@ SchemaSubdocument.prototype.cast = function(val, doc, init, priorVal, options) {
|
|
|
181
181
|
return val;
|
|
182
182
|
}
|
|
183
183
|
|
|
184
|
-
if (val != null && (typeof val !== 'object' || Array.isArray(val))) {
|
|
184
|
+
if (!init && val != null && (typeof val !== 'object' || Array.isArray(val))) {
|
|
185
185
|
throw new ObjectExpectedError(this.path, val);
|
|
186
186
|
}
|
|
187
187
|
|
|
188
188
|
const discriminatorKeyPath = this.schema.path(this.schema.options.discriminatorKey);
|
|
189
189
|
const defaultDiscriminatorValue = discriminatorKeyPath == null ? null : discriminatorKeyPath.getDefault(doc);
|
|
190
|
-
const Constructor = getConstructor(this.
|
|
190
|
+
const Constructor = getConstructor(this.Constructor, val, defaultDiscriminatorValue);
|
|
191
191
|
|
|
192
192
|
let subdoc;
|
|
193
193
|
|
|
@@ -202,7 +202,7 @@ SchemaSubdocument.prototype.cast = function(val, doc, init, priorVal, options) {
|
|
|
202
202
|
return obj;
|
|
203
203
|
}, null);
|
|
204
204
|
if (init) {
|
|
205
|
-
subdoc = new Constructor(void 0, selected, doc,
|
|
205
|
+
subdoc = new Constructor(void 0, selected, doc, { defaults: false });
|
|
206
206
|
delete subdoc.$__.defaults;
|
|
207
207
|
// Don't pass `path` to $init - it's only for the subdocument itself, not its fields.
|
|
208
208
|
// For change tracking, subdocuments use relative paths internally.
|
|
@@ -217,10 +217,10 @@ SchemaSubdocument.prototype.cast = function(val, doc, init, priorVal, options) {
|
|
|
217
217
|
} else {
|
|
218
218
|
options = Object.assign({}, options, { priorDoc: priorVal });
|
|
219
219
|
if (Object.keys(val).length === 0) {
|
|
220
|
-
return new Constructor({}, selected, doc,
|
|
220
|
+
return new Constructor({}, selected, doc, options);
|
|
221
221
|
}
|
|
222
222
|
|
|
223
|
-
return new Constructor(val, selected, doc,
|
|
223
|
+
return new Constructor(val, selected, doc, options);
|
|
224
224
|
}
|
|
225
225
|
|
|
226
226
|
return subdoc;
|
|
@@ -247,7 +247,7 @@ SchemaSubdocument.prototype.castForQuery = function($conditional, val, context,
|
|
|
247
247
|
return val;
|
|
248
248
|
}
|
|
249
249
|
|
|
250
|
-
const Constructor = getConstructor(this.
|
|
250
|
+
const Constructor = getConstructor(this.Constructor, val);
|
|
251
251
|
if (val instanceof Constructor) {
|
|
252
252
|
return val;
|
|
253
253
|
}
|
|
@@ -275,11 +275,11 @@ SchemaSubdocument.prototype.castForQuery = function($conditional, val, context,
|
|
|
275
275
|
/**
|
|
276
276
|
* Async validation on this single nested doc.
|
|
277
277
|
*
|
|
278
|
-
* @api
|
|
278
|
+
* @api public
|
|
279
279
|
*/
|
|
280
280
|
|
|
281
|
-
SchemaSubdocument.prototype.doValidate = function(value,
|
|
282
|
-
const Constructor = getConstructor(this.
|
|
281
|
+
SchemaSubdocument.prototype.doValidate = async function doValidate(value, scope, options) {
|
|
282
|
+
const Constructor = getConstructor(this.Constructor, value);
|
|
283
283
|
|
|
284
284
|
if (value && !(value instanceof Constructor)) {
|
|
285
285
|
value = new Constructor(value, null, (scope != null && scope.$__ != null) ? scope : null);
|
|
@@ -287,21 +287,15 @@ SchemaSubdocument.prototype.doValidate = function(value, fn, scope, options) {
|
|
|
287
287
|
|
|
288
288
|
if (options && options.skipSchemaValidators) {
|
|
289
289
|
if (!value) {
|
|
290
|
-
return
|
|
290
|
+
return;
|
|
291
291
|
}
|
|
292
|
-
return value.validate()
|
|
292
|
+
return value.validate();
|
|
293
293
|
}
|
|
294
294
|
|
|
295
|
-
SchemaType.prototype.doValidate.call(this, value,
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
if (!value) {
|
|
300
|
-
return fn(null);
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
value.validate().then(() => fn(null), err => fn(err));
|
|
304
|
-
}, scope, options);
|
|
295
|
+
await SchemaType.prototype.doValidate.call(this, value, scope, options);
|
|
296
|
+
if (value != null) {
|
|
297
|
+
await value.validate();
|
|
298
|
+
}
|
|
305
299
|
};
|
|
306
300
|
|
|
307
301
|
/**
|
|
@@ -355,11 +349,11 @@ SchemaSubdocument.prototype.discriminator = function(name, schema, options) {
|
|
|
355
349
|
schema = schema.clone();
|
|
356
350
|
}
|
|
357
351
|
|
|
358
|
-
schema = discriminator(this.
|
|
352
|
+
schema = discriminator(this.Constructor, name, schema, value, null, null, options.overwriteExisting);
|
|
359
353
|
|
|
360
|
-
this.
|
|
354
|
+
this.Constructor.discriminators[name] = _createConstructor(schema, this.Constructor);
|
|
361
355
|
|
|
362
|
-
return this.
|
|
356
|
+
return this.Constructor.discriminators[name];
|
|
363
357
|
};
|
|
364
358
|
|
|
365
359
|
/*!
|
|
@@ -423,7 +417,7 @@ SchemaSubdocument.prototype.clone = function() {
|
|
|
423
417
|
if (this.requiredValidator !== undefined) {
|
|
424
418
|
schematype.requiredValidator = this.requiredValidator;
|
|
425
419
|
}
|
|
426
|
-
schematype.
|
|
420
|
+
schematype.Constructor.discriminators = Object.assign({}, this.Constructor.discriminators);
|
|
427
421
|
schematype._appliedDiscriminators = this._appliedDiscriminators;
|
|
428
422
|
return schematype;
|
|
429
423
|
};
|
package/lib/schema/uuid.js
CHANGED
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
|
|
5
5
|
'use strict';
|
|
6
6
|
|
|
7
|
-
const MongooseBuffer = require('../types/buffer');
|
|
8
7
|
const SchemaType = require('../schemaType');
|
|
9
8
|
const CastError = SchemaType.CastError;
|
|
10
9
|
const castUUID = require('../cast/uuid');
|
|
@@ -13,7 +12,6 @@ const utils = require('../utils');
|
|
|
13
12
|
const handleBitwiseOperator = require('./operators/bitwise');
|
|
14
13
|
|
|
15
14
|
const UUID_FORMAT = castUUID.UUID_FORMAT;
|
|
16
|
-
const Binary = MongooseBuffer.Binary;
|
|
17
15
|
|
|
18
16
|
/**
|
|
19
17
|
* Convert binary to a uuid string
|
|
@@ -45,21 +43,6 @@ function binaryToString(uuidBin) {
|
|
|
45
43
|
|
|
46
44
|
function SchemaUUID(key, options, _schemaOptions, parentSchema) {
|
|
47
45
|
SchemaType.call(this, key, options, 'UUID', parentSchema);
|
|
48
|
-
this.getters.push(function(value) {
|
|
49
|
-
// For populated
|
|
50
|
-
if (value != null && value.$__ != null) {
|
|
51
|
-
return value;
|
|
52
|
-
}
|
|
53
|
-
if (Buffer.isBuffer(value)) {
|
|
54
|
-
return binaryToString(value);
|
|
55
|
-
} else if (value instanceof Binary) {
|
|
56
|
-
return binaryToString(value.buffer);
|
|
57
|
-
} else if (utils.isPOJO(value) && value.type === 'Buffer' && Array.isArray(value.data)) {
|
|
58
|
-
// Cloned buffers look like `{ type: 'Buffer', data: [5, 224, ...] }`
|
|
59
|
-
return binaryToString(Buffer.from(value.data));
|
|
60
|
-
}
|
|
61
|
-
return value;
|
|
62
|
-
});
|
|
63
46
|
}
|
|
64
47
|
|
|
65
48
|
/**
|
|
@@ -251,11 +234,7 @@ const $conditionalHandlers = {
|
|
|
251
234
|
$bitsAllSet: handleBitwiseOperator,
|
|
252
235
|
$bitsAnySet: handleBitwiseOperator,
|
|
253
236
|
$all: handleArray,
|
|
254
|
-
$gt: handleSingle,
|
|
255
|
-
$gte: handleSingle,
|
|
256
237
|
$in: handleArray,
|
|
257
|
-
$lt: handleSingle,
|
|
258
|
-
$lte: handleSingle,
|
|
259
238
|
$ne: handleSingle,
|
|
260
239
|
$nin: handleArray
|
|
261
240
|
};
|
package/lib/schema.js
CHANGED
|
@@ -23,6 +23,7 @@ const merge = require('./helpers/schema/merge');
|
|
|
23
23
|
const mpath = require('mpath');
|
|
24
24
|
const setPopulatedVirtualValue = require('./helpers/populate/setPopulatedVirtualValue');
|
|
25
25
|
const setupTimestamps = require('./helpers/timestamps/setupTimestamps');
|
|
26
|
+
const symbols = require('./schema/symbols');
|
|
26
27
|
const utils = require('./utils');
|
|
27
28
|
const validateRef = require('./helpers/populate/validateRef');
|
|
28
29
|
|
|
@@ -31,7 +32,7 @@ const hasNumericSubpathRegex = /\.\d+(\.|$)/;
|
|
|
31
32
|
let MongooseTypes;
|
|
32
33
|
|
|
33
34
|
const queryHooks = require('./constants').queryMiddlewareFunctions;
|
|
34
|
-
const documentHooks = require('./
|
|
35
|
+
const documentHooks = require('./constants').documentMiddlewareFunctions;
|
|
35
36
|
const hookNames = queryHooks.concat(documentHooks).
|
|
36
37
|
reduce((s, hook) => s.add(hook), new Set());
|
|
37
38
|
|
|
@@ -372,6 +373,29 @@ Schema.prototype.paths;
|
|
|
372
373
|
|
|
373
374
|
Schema.prototype.tree;
|
|
374
375
|
|
|
376
|
+
/**
|
|
377
|
+
* Creates a new schema with the given definition and options. Equivalent to `new Schema(definition, options)`.
|
|
378
|
+
*
|
|
379
|
+
* `Schema.create()` is primarily useful for automatic schema type inference in TypeScript.
|
|
380
|
+
*
|
|
381
|
+
* #### Example:
|
|
382
|
+
*
|
|
383
|
+
* const schema = Schema.create({ name: String }, { toObject: { virtuals: true } });
|
|
384
|
+
* // Equivalent:
|
|
385
|
+
* const schema2 = new Schema({ name: String }, { toObject: { virtuals: true } });
|
|
386
|
+
*
|
|
387
|
+
* @param {Object} definition
|
|
388
|
+
* @param {Object} [options]
|
|
389
|
+
* @return {Schema} the new schema
|
|
390
|
+
* @api public
|
|
391
|
+
* @memberOf Schema
|
|
392
|
+
* @static
|
|
393
|
+
*/
|
|
394
|
+
|
|
395
|
+
Schema.create = function create(definition, options) {
|
|
396
|
+
return new Schema(definition, options);
|
|
397
|
+
};
|
|
398
|
+
|
|
375
399
|
/**
|
|
376
400
|
* Returns a deep copy of the schema
|
|
377
401
|
*
|
|
@@ -660,6 +684,33 @@ Schema.prototype.discriminator = function(name, schema, options) {
|
|
|
660
684
|
return this;
|
|
661
685
|
};
|
|
662
686
|
|
|
687
|
+
/*!
|
|
688
|
+
* Get the document middleware for this schema, filtering out any hooks that are specific to queries.
|
|
689
|
+
*/
|
|
690
|
+
Schema.prototype._getDocumentMiddleware = function _getDocumentMiddleware() {
|
|
691
|
+
return this.s.hooks.
|
|
692
|
+
filter(hook => {
|
|
693
|
+
if (hook.name === 'updateOne' || hook.name === 'deleteOne') {
|
|
694
|
+
return !!hook['document'];
|
|
695
|
+
}
|
|
696
|
+
if (hook.name === 'remove' || hook.name === 'init') {
|
|
697
|
+
return hook['document'] == null || !!hook['document'];
|
|
698
|
+
}
|
|
699
|
+
if (hook.query != null || hook.document != null) {
|
|
700
|
+
return hook.document !== false;
|
|
701
|
+
}
|
|
702
|
+
return true;
|
|
703
|
+
}).
|
|
704
|
+
filter(hook => {
|
|
705
|
+
// If user has overwritten the method, don't apply built-in middleware
|
|
706
|
+
if (this.methods[hook.name]) {
|
|
707
|
+
return !hook.fn[symbols.builtInMiddleware];
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
return true;
|
|
711
|
+
});
|
|
712
|
+
};
|
|
713
|
+
|
|
663
714
|
/*!
|
|
664
715
|
* Get this schema's default toObject/toJSON options, including Mongoose global
|
|
665
716
|
* options.
|
|
@@ -1300,7 +1351,7 @@ Schema.prototype.path = function(path, obj) {
|
|
|
1300
1351
|
if (schemaType.$__schemaType.$isSingleNested) {
|
|
1301
1352
|
this.childSchemas.push({
|
|
1302
1353
|
schema: schemaType.$__schemaType.schema,
|
|
1303
|
-
model: schemaType.$__schemaType.
|
|
1354
|
+
model: schemaType.$__schemaType.Constructor,
|
|
1304
1355
|
path: path
|
|
1305
1356
|
});
|
|
1306
1357
|
}
|
|
@@ -1329,10 +1380,10 @@ Schema.prototype.path = function(path, obj) {
|
|
|
1329
1380
|
value: this.base
|
|
1330
1381
|
});
|
|
1331
1382
|
|
|
1332
|
-
schemaType.
|
|
1383
|
+
schemaType.Constructor.base = this.base;
|
|
1333
1384
|
this.childSchemas.push({
|
|
1334
1385
|
schema: schemaType.schema,
|
|
1335
|
-
model: schemaType.
|
|
1386
|
+
model: schemaType.Constructor,
|
|
1336
1387
|
path: path
|
|
1337
1388
|
});
|
|
1338
1389
|
} else if (schemaType.$isMongooseDocumentArray) {
|
|
@@ -1343,15 +1394,15 @@ Schema.prototype.path = function(path, obj) {
|
|
|
1343
1394
|
value: this.base
|
|
1344
1395
|
});
|
|
1345
1396
|
|
|
1346
|
-
schemaType.
|
|
1397
|
+
schemaType.Constructor.base = this.base;
|
|
1347
1398
|
this.childSchemas.push({
|
|
1348
1399
|
schema: schemaType.schema,
|
|
1349
|
-
model: schemaType.
|
|
1400
|
+
model: schemaType.Constructor,
|
|
1350
1401
|
path: path
|
|
1351
1402
|
});
|
|
1352
1403
|
}
|
|
1353
1404
|
|
|
1354
|
-
if (schemaType.$isMongooseArray && schemaType
|
|
1405
|
+
if (schemaType.$isMongooseArray && !schemaType.$isMongooseDocumentArray) {
|
|
1355
1406
|
let arrayPath = path;
|
|
1356
1407
|
let _schemaType = schemaType;
|
|
1357
1408
|
|
|
@@ -1359,16 +1410,9 @@ Schema.prototype.path = function(path, obj) {
|
|
|
1359
1410
|
while (_schemaType.$isMongooseArray) {
|
|
1360
1411
|
arrayPath = arrayPath + '.$';
|
|
1361
1412
|
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
_schemaType.$embeddedSchemaType._arrayParentPath = path;
|
|
1366
|
-
_schemaType = _schemaType.$embeddedSchemaType;
|
|
1367
|
-
} else {
|
|
1368
|
-
_schemaType.caster._arrayPath = arrayPath;
|
|
1369
|
-
_schemaType.caster._arrayParentPath = path;
|
|
1370
|
-
_schemaType = _schemaType.caster;
|
|
1371
|
-
}
|
|
1413
|
+
_schemaType.embeddedSchemaType._arrayPath = arrayPath;
|
|
1414
|
+
_schemaType.embeddedSchemaType._arrayParentPath = path;
|
|
1415
|
+
_schemaType = _schemaType.embeddedSchemaType;
|
|
1372
1416
|
|
|
1373
1417
|
this.subpaths[arrayPath] = _schemaType;
|
|
1374
1418
|
}
|
|
@@ -1420,13 +1464,13 @@ Schema.prototype._gatherChildSchemas = function _gatherChildSchemas() {
|
|
|
1420
1464
|
if (schematype.$isMongooseDocumentArray || schematype.$isSingleNested) {
|
|
1421
1465
|
childSchemas.push({
|
|
1422
1466
|
schema: schematype.schema,
|
|
1423
|
-
model: schematype.
|
|
1467
|
+
model: schematype.Constructor,
|
|
1424
1468
|
path: path
|
|
1425
1469
|
});
|
|
1426
1470
|
} else if (schematype.$isSchemaMap && schematype.$__schemaType.$isSingleNested) {
|
|
1427
1471
|
childSchemas.push({
|
|
1428
1472
|
schema: schematype.$__schemaType.schema,
|
|
1429
|
-
model: schematype.$__schemaType.
|
|
1473
|
+
model: schematype.$__schemaType.Constructor,
|
|
1430
1474
|
path: path
|
|
1431
1475
|
});
|
|
1432
1476
|
}
|
|
@@ -1945,10 +1989,10 @@ function getPositionalPathType(self, path, cleanPath) {
|
|
|
1945
1989
|
|
|
1946
1990
|
if (i === last && val && !/\D/.test(subpath)) {
|
|
1947
1991
|
if (val.$isMongooseDocumentArray) {
|
|
1948
|
-
val = val
|
|
1992
|
+
val = val.embeddedSchemaType;
|
|
1949
1993
|
} else if (val instanceof MongooseTypes.Array) {
|
|
1950
1994
|
// StringSchema, NumberSchema, etc
|
|
1951
|
-
val = val.
|
|
1995
|
+
val = val.embeddedSchemaType;
|
|
1952
1996
|
} else {
|
|
1953
1997
|
val = undefined;
|
|
1954
1998
|
}
|
|
@@ -1959,7 +2003,7 @@ function getPositionalPathType(self, path, cleanPath) {
|
|
|
1959
2003
|
if (!/\D/.test(subpath)) {
|
|
1960
2004
|
// Nested array
|
|
1961
2005
|
if (val instanceof MongooseTypes.Array && i !== last) {
|
|
1962
|
-
val = val.
|
|
2006
|
+
val = val.embeddedSchemaType;
|
|
1963
2007
|
}
|
|
1964
2008
|
continue;
|
|
1965
2009
|
}
|
|
@@ -2022,23 +2066,21 @@ Schema.prototype.queue = function(name, args) {
|
|
|
2022
2066
|
*
|
|
2023
2067
|
* const toySchema = new Schema({ name: String, created: Date });
|
|
2024
2068
|
*
|
|
2025
|
-
* toySchema.pre('save', function(
|
|
2069
|
+
* toySchema.pre('save', function() {
|
|
2026
2070
|
* if (!this.created) this.created = new Date;
|
|
2027
|
-
* next();
|
|
2028
2071
|
* });
|
|
2029
2072
|
*
|
|
2030
|
-
* toySchema.pre('validate', function(
|
|
2073
|
+
* toySchema.pre('validate', function() {
|
|
2031
2074
|
* if (this.name !== 'Woody') this.name = 'Woody';
|
|
2032
|
-
* next();
|
|
2033
2075
|
* });
|
|
2034
2076
|
*
|
|
2035
2077
|
* // Equivalent to calling `pre()` on `find`, `findOne`, `findOneAndUpdate`.
|
|
2036
|
-
* toySchema.pre(/^find/, function(
|
|
2078
|
+
* toySchema.pre(/^find/, function() {
|
|
2037
2079
|
* console.log(this.getFilter());
|
|
2038
2080
|
* });
|
|
2039
2081
|
*
|
|
2040
2082
|
* // Equivalent to calling `pre()` on `updateOne`, `findOneAndUpdate`.
|
|
2041
|
-
* toySchema.pre(['updateOne', 'findOneAndUpdate'], function(
|
|
2083
|
+
* toySchema.pre(['updateOne', 'findOneAndUpdate'], function() {
|
|
2042
2084
|
* console.log(this.getFilter());
|
|
2043
2085
|
* });
|
|
2044
2086
|
*
|
|
@@ -2455,8 +2497,8 @@ Object.defineProperty(Schema, 'indexTypes', {
|
|
|
2455
2497
|
* registeredAt: { type: Date, index: true }
|
|
2456
2498
|
* });
|
|
2457
2499
|
*
|
|
2458
|
-
* // [ [ { email: 1 }, { unique: true
|
|
2459
|
-
* // [ { registeredAt: 1 }, {
|
|
2500
|
+
* // [ [ { email: 1 }, { unique: true } ],
|
|
2501
|
+
* // [ { registeredAt: 1 }, {} ] ]
|
|
2460
2502
|
* userSchema.indexes();
|
|
2461
2503
|
*
|
|
2462
2504
|
* [Plugins](https://mongoosejs.com/docs/plugins.html) can use the return value of this function to modify a schema's indexes.
|
|
@@ -2854,11 +2896,11 @@ Schema.prototype._getSchema = function(path) {
|
|
|
2854
2896
|
if (foundschema) {
|
|
2855
2897
|
resultPath.push(trypath);
|
|
2856
2898
|
|
|
2857
|
-
if (foundschema.
|
|
2899
|
+
if (foundschema.embeddedSchemaType || foundschema.Constructor) {
|
|
2858
2900
|
// array of Mixed?
|
|
2859
|
-
if (foundschema.
|
|
2860
|
-
foundschema.
|
|
2861
|
-
return foundschema.
|
|
2901
|
+
if (foundschema.embeddedSchemaType instanceof MongooseTypes.Mixed) {
|
|
2902
|
+
foundschema.embeddedSchemaType.$fullPath = resultPath.join('.');
|
|
2903
|
+
return foundschema.embeddedSchemaType;
|
|
2862
2904
|
}
|
|
2863
2905
|
|
|
2864
2906
|
// Now that we found the array, we need to check if there
|
|
@@ -2868,8 +2910,8 @@ Schema.prototype._getSchema = function(path) {
|
|
|
2868
2910
|
// If there is no foundschema.schema we are dealing with
|
|
2869
2911
|
// a path like array.$
|
|
2870
2912
|
if (p !== parts.length) {
|
|
2871
|
-
if (p + 1 === parts.length && foundschema
|
|
2872
|
-
return foundschema
|
|
2913
|
+
if (p + 1 === parts.length && foundschema.embeddedSchemaType && (parts[p] === '$' || isArrayFilter(parts[p]))) {
|
|
2914
|
+
return foundschema.embeddedSchemaType;
|
|
2873
2915
|
}
|
|
2874
2916
|
|
|
2875
2917
|
if (foundschema.schema) {
|
|
@@ -2877,7 +2919,7 @@ Schema.prototype._getSchema = function(path) {
|
|
|
2877
2919
|
if (parts[p] === '$' || isArrayFilter(parts[p])) {
|
|
2878
2920
|
if (p + 1 === parts.length) {
|
|
2879
2921
|
// comments.$
|
|
2880
|
-
return foundschema
|
|
2922
|
+
return foundschema.embeddedSchemaType;
|
|
2881
2923
|
}
|
|
2882
2924
|
// comments.$.comments.$.title
|
|
2883
2925
|
ret = search(parts.slice(p + 1), foundschema.schema);
|
|
@@ -2957,9 +2999,9 @@ Schema.prototype._getPathType = function(path) {
|
|
|
2957
2999
|
trypath = parts.slice(0, p).join('.');
|
|
2958
3000
|
foundschema = schema.path(trypath);
|
|
2959
3001
|
if (foundschema) {
|
|
2960
|
-
if (foundschema.
|
|
3002
|
+
if (foundschema.embeddedSchemaType || foundschema.Constructor) {
|
|
2961
3003
|
// array of Mixed?
|
|
2962
|
-
if (foundschema.
|
|
3004
|
+
if (foundschema.embeddedSchemaType instanceof MongooseTypes.Mixed) {
|
|
2963
3005
|
return { schema: foundschema, pathType: 'mixed' };
|
|
2964
3006
|
}
|
|
2965
3007
|
|
package/lib/schemaType.js
CHANGED
|
@@ -12,7 +12,6 @@ const clone = require('./helpers/clone');
|
|
|
12
12
|
const handleImmutable = require('./helpers/schematype/handleImmutable');
|
|
13
13
|
const isAsyncFunction = require('./helpers/isAsyncFunction');
|
|
14
14
|
const isSimpleValidator = require('./helpers/isSimpleValidator');
|
|
15
|
-
const immediate = require('./helpers/immediate');
|
|
16
15
|
const schemaTypeSymbol = require('./helpers/symbols').schemaTypeSymbol;
|
|
17
16
|
const utils = require('./utils');
|
|
18
17
|
const validatorErrorSymbol = require('./helpers/symbols').validatorErrorSymbol;
|
|
@@ -445,13 +444,6 @@ SchemaType.prototype.default = function(val) {
|
|
|
445
444
|
* s.path('my.date').index({ expires: 60 });
|
|
446
445
|
* s.path('my.path').index({ unique: true, sparse: true });
|
|
447
446
|
*
|
|
448
|
-
* #### Note:
|
|
449
|
-
*
|
|
450
|
-
* _Indexes are created [in the background](https://www.mongodb.com/docs/manual/core/index-creation/#index-creation-background)
|
|
451
|
-
* by default. If `background` is set to `false`, MongoDB will not execute any
|
|
452
|
-
* read/write operations you send until the index build.
|
|
453
|
-
* Specify `background: false` to override Mongoose's default._
|
|
454
|
-
*
|
|
455
447
|
* @param {Object|Boolean|String|Number} options
|
|
456
448
|
* @return {SchemaType} this
|
|
457
449
|
* @api public
|
|
@@ -1341,7 +1333,6 @@ SchemaType.prototype.select = function select(val) {
|
|
|
1341
1333
|
* Performs a validation of `value` using the validators declared for this SchemaType.
|
|
1342
1334
|
*
|
|
1343
1335
|
* @param {Any} value
|
|
1344
|
-
* @param {Function} callback
|
|
1345
1336
|
* @param {Object} scope
|
|
1346
1337
|
* @param {Object} [options]
|
|
1347
1338
|
* @param {String} [options.path]
|
|
@@ -1349,28 +1340,20 @@ SchemaType.prototype.select = function select(val) {
|
|
|
1349
1340
|
* @api public
|
|
1350
1341
|
*/
|
|
1351
1342
|
|
|
1352
|
-
SchemaType.prototype.doValidate = function(value,
|
|
1343
|
+
SchemaType.prototype.doValidate = async function doValidate(value, scope, options) {
|
|
1353
1344
|
let err = false;
|
|
1354
1345
|
const path = this.path;
|
|
1355
|
-
if (typeof fn !== 'function') {
|
|
1356
|
-
throw new TypeError(`Must pass callback function to doValidate(), got ${typeof fn}`);
|
|
1357
|
-
}
|
|
1358
1346
|
|
|
1359
1347
|
// Avoid non-object `validators`
|
|
1360
1348
|
const validators = this.validators.
|
|
1361
1349
|
filter(v => typeof v === 'object' && v !== null);
|
|
1362
1350
|
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
if (!count) {
|
|
1366
|
-
return fn(null);
|
|
1351
|
+
if (!validators.length) {
|
|
1352
|
+
return;
|
|
1367
1353
|
}
|
|
1368
1354
|
|
|
1355
|
+
const promises = [];
|
|
1369
1356
|
for (let i = 0, len = validators.length; i < len; ++i) {
|
|
1370
|
-
if (err) {
|
|
1371
|
-
break;
|
|
1372
|
-
}
|
|
1373
|
-
|
|
1374
1357
|
const v = validators[i];
|
|
1375
1358
|
const validator = v.validator;
|
|
1376
1359
|
let ok;
|
|
@@ -1386,17 +1369,19 @@ SchemaType.prototype.doValidate = function(value, fn, scope, options) {
|
|
|
1386
1369
|
}
|
|
1387
1370
|
}
|
|
1388
1371
|
|
|
1389
|
-
if (validator
|
|
1390
|
-
validate(validator.test(value), validatorProperties, scope);
|
|
1372
|
+
if (value === undefined && validator !== this.requiredValidator) {
|
|
1391
1373
|
continue;
|
|
1392
1374
|
}
|
|
1393
|
-
|
|
1394
|
-
|
|
1375
|
+
if (validator instanceof RegExp) {
|
|
1376
|
+
ok = validator.test(value);
|
|
1377
|
+
if (ok === false) {
|
|
1378
|
+
const ErrorConstructor = validatorProperties.ErrorConstructor || ValidatorError;
|
|
1379
|
+
err = new ErrorConstructor(validatorProperties, scope);
|
|
1380
|
+
err[validatorErrorSymbol] = true;
|
|
1381
|
+
throw err;
|
|
1382
|
+
}
|
|
1395
1383
|
continue;
|
|
1396
|
-
}
|
|
1397
|
-
|
|
1398
|
-
if (value === undefined && validator !== this.requiredValidator) {
|
|
1399
|
-
validate(true, validatorProperties, scope);
|
|
1384
|
+
} else if (typeof validator !== 'function') {
|
|
1400
1385
|
continue;
|
|
1401
1386
|
}
|
|
1402
1387
|
|
|
@@ -1415,38 +1400,35 @@ SchemaType.prototype.doValidate = function(value, fn, scope, options) {
|
|
|
1415
1400
|
}
|
|
1416
1401
|
|
|
1417
1402
|
if (ok != null && typeof ok.then === 'function') {
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
});
|
|
1440
|
-
}
|
|
1441
|
-
} else {
|
|
1403
|
+
promises.push(
|
|
1404
|
+
ok.then(
|
|
1405
|
+
function(ok) {
|
|
1406
|
+
if (ok === false) {
|
|
1407
|
+
const ErrorConstructor = validatorProperties.ErrorConstructor || ValidatorError;
|
|
1408
|
+
err = new ErrorConstructor(validatorProperties, scope);
|
|
1409
|
+
err[validatorErrorSymbol] = true;
|
|
1410
|
+
throw err;
|
|
1411
|
+
}
|
|
1412
|
+
},
|
|
1413
|
+
function(error) {
|
|
1414
|
+
validatorProperties.reason = error;
|
|
1415
|
+
validatorProperties.message = error.message;
|
|
1416
|
+
ok = false;
|
|
1417
|
+
const ErrorConstructor = validatorProperties.ErrorConstructor || ValidatorError;
|
|
1418
|
+
err = new ErrorConstructor(validatorProperties, scope);
|
|
1419
|
+
err[validatorErrorSymbol] = true;
|
|
1420
|
+
throw err;
|
|
1421
|
+
})
|
|
1422
|
+
);
|
|
1423
|
+
} else if (ok !== undefined && !ok) {
|
|
1442
1424
|
const ErrorConstructor = validatorProperties.ErrorConstructor || ValidatorError;
|
|
1443
1425
|
err = new ErrorConstructor(validatorProperties, scope);
|
|
1444
1426
|
err[validatorErrorSymbol] = true;
|
|
1445
|
-
|
|
1446
|
-
fn(err);
|
|
1447
|
-
});
|
|
1427
|
+
throw err;
|
|
1448
1428
|
}
|
|
1449
1429
|
}
|
|
1430
|
+
|
|
1431
|
+
await Promise.all(promises);
|
|
1450
1432
|
};
|
|
1451
1433
|
|
|
1452
1434
|
|
|
@@ -1811,7 +1793,7 @@ SchemaType.prototype.clone = function() {
|
|
|
1811
1793
|
*/
|
|
1812
1794
|
|
|
1813
1795
|
SchemaType.prototype.getEmbeddedSchemaType = function getEmbeddedSchemaType() {
|
|
1814
|
-
return this
|
|
1796
|
+
return this.embeddedSchemaType;
|
|
1815
1797
|
};
|
|
1816
1798
|
|
|
1817
1799
|
/*!
|
package/lib/types/array/index.js
CHANGED
|
@@ -88,8 +88,8 @@ function MongooseArray(values, path, doc, schematype) {
|
|
|
88
88
|
if (schematype && schematype.virtuals && schematype.virtuals.hasOwnProperty(prop)) {
|
|
89
89
|
return schematype.virtuals[prop].applyGetters(undefined, target);
|
|
90
90
|
}
|
|
91
|
-
if (typeof prop === 'string' && numberRE.test(prop) && schematype
|
|
92
|
-
return schematype
|
|
91
|
+
if (typeof prop === 'string' && numberRE.test(prop) && schematype?.embeddedSchemaType != null) {
|
|
92
|
+
return schematype.embeddedSchemaType.applyGetters(__array[prop], doc);
|
|
93
93
|
}
|
|
94
94
|
|
|
95
95
|
return __array[prop];
|
|
@@ -251,10 +251,10 @@ const methods = {
|
|
|
251
251
|
if (!isDisc) {
|
|
252
252
|
value = new Model(value);
|
|
253
253
|
}
|
|
254
|
-
return this[arraySchemaSymbol].
|
|
254
|
+
return this[arraySchemaSymbol].embeddedSchemaType.applySetters(value, parent, true);
|
|
255
255
|
}
|
|
256
256
|
|
|
257
|
-
return this[arraySchemaSymbol].
|
|
257
|
+
return this[arraySchemaSymbol].embeddedSchemaType.applySetters(value, parent, false);
|
|
258
258
|
},
|
|
259
259
|
|
|
260
260
|
/**
|
|
@@ -1007,7 +1007,7 @@ function _minimizePath(obj, parts, i) {
|
|
|
1007
1007
|
function _checkManualPopulation(arr, docs) {
|
|
1008
1008
|
const ref = arr == null ?
|
|
1009
1009
|
null :
|
|
1010
|
-
arr[arraySchemaSymbol]
|
|
1010
|
+
arr[arraySchemaSymbol]?.embeddedSchemaType?.options?.ref || null;
|
|
1011
1011
|
if (arr.length === 0 &&
|
|
1012
1012
|
docs.length !== 0) {
|
|
1013
1013
|
if (_isAllSubdocs(docs, ref)) {
|
|
@@ -1025,7 +1025,7 @@ function _checkManualPopulation(arr, docs) {
|
|
|
1025
1025
|
function _depopulateIfNecessary(arr, docs) {
|
|
1026
1026
|
const ref = arr == null ?
|
|
1027
1027
|
null :
|
|
1028
|
-
arr[arraySchemaSymbol]
|
|
1028
|
+
arr[arraySchemaSymbol]?.embeddedSchemaType?.options?.ref || null;
|
|
1029
1029
|
const parentDoc = arr[arrayParentSymbol];
|
|
1030
1030
|
const path = arr[arrayPathSymbol];
|
|
1031
1031
|
if (!ref || !parentDoc.populated(path)) {
|
|
@@ -41,7 +41,7 @@ function ArraySubdocument(obj, parentArr, skipId, fields, index) {
|
|
|
41
41
|
options = { isNew: true };
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
Subdocument.call(this, obj, fields, this[documentArrayParent],
|
|
44
|
+
Subdocument.call(this, obj, fields, this[documentArrayParent], options);
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
/*!
|