@depup/mongoose 9.3.3-depup.0 → 9.8.0-depup.0
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/README.md +3 -9
- package/changes.json +3 -8
- package/eslint.config.mjs +4 -1
- package/lib/aggregate.js +54 -24
- package/lib/cast.js +1 -1
- package/lib/connection.js +20 -8
- package/lib/cursor/aggregationCursor.js +47 -16
- package/lib/cursor/queryCursor.js +23 -7
- package/lib/document.js +240 -105
- package/lib/drivers/node-mongodb-native/collection.js +47 -14
- package/lib/drivers/node-mongodb-native/connection.js +13 -0
- package/lib/error/cast.js +18 -9
- package/lib/error/divergentArray.js +1 -1
- package/lib/error/index.js +1 -1
- package/lib/error/messages.js +1 -0
- package/lib/helpers/clone.js +22 -5
- package/lib/helpers/document/applyDefaults.js +5 -0
- package/lib/helpers/populate/createPopulateQueryFilter.js +9 -1
- package/lib/helpers/populate/getModelsMapForPopulate.js +8 -6
- package/lib/helpers/populate/splitPopulateQuery.js +81 -0
- package/lib/helpers/query/castUpdate.js +4 -0
- package/lib/helpers/schema/getKeysInSchemaOrder.js +13 -16
- package/lib/helpers/update/applyTimestampsToUpdate.js +4 -2
- package/lib/model.js +159 -41
- package/lib/mongoose.js +3 -3
- package/lib/options/schemaTypeOptions.js +14 -0
- package/lib/plugins/saveSubdocs.js +16 -13
- package/lib/query.js +208 -102
- package/lib/queryHelpers.js +13 -12
- package/lib/schema/array.js +4 -6
- package/lib/schema/bigint.js +1 -3
- package/lib/schema/boolean.js +1 -3
- package/lib/schema/buffer.js +1 -3
- package/lib/schema/date.js +8 -8
- package/lib/schema/decimal128.js +1 -3
- package/lib/schema/documentArray.js +3 -5
- package/lib/schema/double.js +1 -3
- package/lib/schema/int32.js +1 -3
- package/lib/schema/map.js +1 -4
- package/lib/schema/number.js +2 -4
- package/lib/schema/objectId.js +7 -3
- package/lib/schema/string.js +20 -5
- package/lib/schema/subdocument.js +2 -4
- package/lib/schema/union.js +50 -0
- package/lib/schema/uuid.js +1 -3
- package/lib/schema.js +40 -14
- package/lib/schemaType.js +93 -12
- package/lib/standardSchema/convertErrorToIssues.js +20 -0
- package/lib/stateMachine.js +11 -6
- package/lib/tracing.js +38 -0
- package/lib/types/array/methods/index.js +4 -4
- package/lib/types/documentArray/methods/index.js +117 -3
- package/lib/types/subdocument.js +4 -2
- package/lib/utils.js +12 -2
- package/lib/validOptions.js +1 -0
- package/package.json +30 -33
- package/{tstyche.config.json → tstyche.json} +2 -1
- package/types/augmentations.d.ts +2 -2
- package/types/document.d.ts +61 -7
- package/types/expressions.d.ts +16 -0
- package/types/index.d.ts +25 -7
- package/types/inferhydrateddoctype.d.ts +1 -1
- package/types/inferrawdoctype.d.ts +6 -3
- package/types/inferschematype.d.ts +10 -2
- package/types/models.d.ts +30 -13
- package/types/mongooseoptions.d.ts +9 -1
- package/types/populate.d.ts +52 -0
- package/types/query.d.ts +39 -12
- package/types/schemaoptions.d.ts +5 -0
- package/types/schematypes.d.ts +10 -0
- package/types/tracing.d.ts +10 -0
- package/types/utility.d.ts +11 -2
- package/lib/helpers/createJSONSchemaTypeDefinition.js +0 -24
package/lib/queryHelpers.js
CHANGED
|
@@ -84,28 +84,29 @@ exports.createModel = function createModel(model, doc, fields, userProvidedField
|
|
|
84
84
|
discriminatorMapping.key :
|
|
85
85
|
null;
|
|
86
86
|
|
|
87
|
+
const _opts = {
|
|
88
|
+
skipId: true,
|
|
89
|
+
isNew: false,
|
|
90
|
+
willInit: true
|
|
91
|
+
};
|
|
92
|
+
if (options?.defaults != null) {
|
|
93
|
+
_opts.defaults = options.defaults;
|
|
94
|
+
}
|
|
95
|
+
if (options?.strict != null) {
|
|
96
|
+
_opts.strict = options.strict;
|
|
97
|
+
}
|
|
98
|
+
|
|
87
99
|
const value = doc[key];
|
|
88
100
|
if (key && value && model.discriminators) {
|
|
89
101
|
const discriminator = model.discriminators[value] || getDiscriminatorByValue(model.discriminators, value);
|
|
90
102
|
if (discriminator) {
|
|
91
103
|
const _fields = clone(userProvidedFields);
|
|
92
104
|
exports.applyPaths(_fields, discriminator.schema);
|
|
93
|
-
|
|
105
|
+
|
|
94
106
|
return new discriminator(undefined, _fields, _opts);
|
|
95
107
|
}
|
|
96
108
|
}
|
|
97
109
|
|
|
98
|
-
const _opts = {
|
|
99
|
-
skipId: true,
|
|
100
|
-
isNew: false,
|
|
101
|
-
willInit: true
|
|
102
|
-
};
|
|
103
|
-
if (options != null && 'defaults' in options) {
|
|
104
|
-
_opts.defaults = options.defaults;
|
|
105
|
-
}
|
|
106
|
-
if (options != null && 'strict' in options) {
|
|
107
|
-
_opts.strict = options.strict;
|
|
108
|
-
}
|
|
109
110
|
return new model(undefined, fields, _opts);
|
|
110
111
|
};
|
|
111
112
|
|
package/lib/schema/array.js
CHANGED
|
@@ -21,7 +21,6 @@ const isOperator = require('../helpers/query/isOperator');
|
|
|
21
21
|
const util = require('util');
|
|
22
22
|
const utils = require('../utils');
|
|
23
23
|
const castToNumber = require('./operators/helpers').castToNumber;
|
|
24
|
-
const createJSONSchemaTypeDefinition = require('../helpers/createJSONSchemaTypeDefinition');
|
|
25
24
|
const geospatial = require('./operators/geospatial');
|
|
26
25
|
const getDiscriminatorByValue = require('../helpers/discriminator/getDiscriminatorByValue');
|
|
27
26
|
|
|
@@ -511,9 +510,9 @@ SchemaArray.prototype._castForQuery = function(val, context) {
|
|
|
511
510
|
}
|
|
512
511
|
|
|
513
512
|
if (Array.isArray(val)) {
|
|
514
|
-
this.setters.
|
|
515
|
-
val =
|
|
516
|
-
}
|
|
513
|
+
for (let i = this.setters.length - 1; i >= 0; i--) {
|
|
514
|
+
val = this.setters[i].call(this, val, this);
|
|
515
|
+
}
|
|
517
516
|
val = val.map(function(v) {
|
|
518
517
|
if (utils.isObject(v) && v.$elemMatch) {
|
|
519
518
|
return v;
|
|
@@ -684,9 +683,8 @@ handle.$in = SchemaType.prototype.$conditionalHandlers.$in;
|
|
|
684
683
|
|
|
685
684
|
SchemaArray.prototype.toJSONSchema = function toJSONSchema(options) {
|
|
686
685
|
const embeddedSchemaType = this.getEmbeddedSchemaType();
|
|
687
|
-
const isRequired = this.options.required && typeof this.options.required !== 'function';
|
|
688
686
|
return {
|
|
689
|
-
...
|
|
687
|
+
...this._createJSONSchemaTypeDefinition('array', 'array', options),
|
|
690
688
|
items: embeddedSchemaType.toJSONSchema(options)
|
|
691
689
|
};
|
|
692
690
|
};
|
package/lib/schema/bigint.js
CHANGED
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
const CastError = require('../error/cast');
|
|
8
8
|
const SchemaType = require('../schemaType');
|
|
9
9
|
const castBigInt = require('../cast/bigint');
|
|
10
|
-
const createJSONSchemaTypeDefinition = require('../helpers/createJSONSchemaTypeDefinition');
|
|
11
10
|
|
|
12
11
|
/**
|
|
13
12
|
* BigInt SchemaType constructor.
|
|
@@ -267,8 +266,7 @@ SchemaBigInt.prototype._castNullish = function _castNullish(v) {
|
|
|
267
266
|
*/
|
|
268
267
|
|
|
269
268
|
SchemaBigInt.prototype.toJSONSchema = function toJSONSchema(options) {
|
|
270
|
-
|
|
271
|
-
return createJSONSchemaTypeDefinition('string', 'long', options?.useBsonType, isRequired);
|
|
269
|
+
return this._createJSONSchemaTypeDefinition('string', 'long', options);
|
|
272
270
|
};
|
|
273
271
|
|
|
274
272
|
SchemaBigInt.prototype.autoEncryptionType = function autoEncryptionType() {
|
package/lib/schema/boolean.js
CHANGED
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
const CastError = require('../error/cast');
|
|
8
8
|
const SchemaType = require('../schemaType');
|
|
9
9
|
const castBoolean = require('../cast/boolean');
|
|
10
|
-
const createJSONSchemaTypeDefinition = require('../helpers/createJSONSchemaTypeDefinition');
|
|
11
10
|
|
|
12
11
|
/**
|
|
13
12
|
* Boolean SchemaType constructor.
|
|
@@ -317,8 +316,7 @@ SchemaBoolean.prototype._castNullish = function _castNullish(v) {
|
|
|
317
316
|
*/
|
|
318
317
|
|
|
319
318
|
SchemaBoolean.prototype.toJSONSchema = function toJSONSchema(options) {
|
|
320
|
-
|
|
321
|
-
return createJSONSchemaTypeDefinition('boolean', 'bool', options?.useBsonType, isRequired);
|
|
319
|
+
return this._createJSONSchemaTypeDefinition('boolean', 'bool', options);
|
|
322
320
|
};
|
|
323
321
|
|
|
324
322
|
SchemaBoolean.prototype.autoEncryptionType = function autoEncryptionType() {
|
package/lib/schema/buffer.js
CHANGED
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
const MongooseBuffer = require('../types/buffer');
|
|
8
8
|
const SchemaBufferOptions = require('../options/schemaBufferOptions');
|
|
9
9
|
const SchemaType = require('../schemaType');
|
|
10
|
-
const createJSONSchemaTypeDefinition = require('../helpers/createJSONSchemaTypeDefinition');
|
|
11
10
|
const handleBitwiseOperator = require('./operators/bitwise');
|
|
12
11
|
const utils = require('../utils');
|
|
13
12
|
|
|
@@ -328,8 +327,7 @@ SchemaBuffer.prototype.castForQuery = function($conditional, val, context) {
|
|
|
328
327
|
*/
|
|
329
328
|
|
|
330
329
|
SchemaBuffer.prototype.toJSONSchema = function toJSONSchema(options) {
|
|
331
|
-
|
|
332
|
-
return createJSONSchemaTypeDefinition('string', 'binData', options?.useBsonType, isRequired);
|
|
330
|
+
return this._createJSONSchemaTypeDefinition('string', 'binData', options);
|
|
333
331
|
};
|
|
334
332
|
|
|
335
333
|
SchemaBuffer.prototype.autoEncryptionType = function autoEncryptionType() {
|
package/lib/schema/date.js
CHANGED
|
@@ -8,7 +8,6 @@ const MongooseError = require('../error/index');
|
|
|
8
8
|
const SchemaDateOptions = require('../options/schemaDateOptions');
|
|
9
9
|
const SchemaType = require('../schemaType');
|
|
10
10
|
const castDate = require('../cast/date');
|
|
11
|
-
const createJSONSchemaTypeDefinition = require('../helpers/createJSONSchemaTypeDefinition');
|
|
12
11
|
const getConstructorName = require('../helpers/getConstructorName');
|
|
13
12
|
const utils = require('../utils');
|
|
14
13
|
|
|
@@ -189,16 +188,18 @@ SchemaDate.prototype.expires = function(when) {
|
|
|
189
188
|
SchemaDate._checkRequired = v => v instanceof Date;
|
|
190
189
|
|
|
191
190
|
/**
|
|
192
|
-
* Override the function the required validator uses to check whether a
|
|
191
|
+
* Override the function the required validator uses to check whether a date
|
|
193
192
|
* passes the `required` check.
|
|
194
193
|
*
|
|
195
194
|
* #### Example:
|
|
196
195
|
*
|
|
197
|
-
* //
|
|
198
|
-
* mongoose.Schema.Types.
|
|
196
|
+
* // Disallow "invalid date"
|
|
197
|
+
* mongoose.Schema.Types.Date.checkRequired(v => v instanceof Date && !isNaN(v.valueOf()));
|
|
199
198
|
*
|
|
200
|
-
* const
|
|
201
|
-
*
|
|
199
|
+
* const schema = new mongoose.Schema({ myDate: { type: Date, required: true } });
|
|
200
|
+
* const M = mongoose.model('Test', schema);
|
|
201
|
+
* // returns a ValidationError due to date being invalid
|
|
202
|
+
* new M({ myDate: new Date('invalid') }).validateSync();
|
|
202
203
|
*
|
|
203
204
|
* @param {Function} fn
|
|
204
205
|
* @return {Function}
|
|
@@ -452,8 +453,7 @@ SchemaDate.prototype.castForQuery = function($conditional, val, context) {
|
|
|
452
453
|
*/
|
|
453
454
|
|
|
454
455
|
SchemaDate.prototype.toJSONSchema = function toJSONSchema(options) {
|
|
455
|
-
|
|
456
|
-
return createJSONSchemaTypeDefinition('string', 'date', options?.useBsonType, isRequired);
|
|
456
|
+
return this._createJSONSchemaTypeDefinition('string', 'date', options);
|
|
457
457
|
};
|
|
458
458
|
|
|
459
459
|
SchemaDate.prototype.autoEncryptionType = function autoEncryptionType() {
|
package/lib/schema/decimal128.js
CHANGED
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
const SchemaType = require('../schemaType');
|
|
8
8
|
const CastError = SchemaType.CastError;
|
|
9
9
|
const castDecimal128 = require('../cast/decimal128');
|
|
10
|
-
const createJSONSchemaTypeDefinition = require('../helpers/createJSONSchemaTypeDefinition');
|
|
11
10
|
const isBsonType = require('../helpers/isBsonType');
|
|
12
11
|
|
|
13
12
|
/**
|
|
@@ -248,8 +247,7 @@ Object.defineProperty(SchemaDecimal128.prototype, '$conditionalHandlers', {
|
|
|
248
247
|
*/
|
|
249
248
|
|
|
250
249
|
SchemaDecimal128.prototype.toJSONSchema = function toJSONSchema(options) {
|
|
251
|
-
|
|
252
|
-
return createJSONSchemaTypeDefinition('string', 'decimal', options?.useBsonType, isRequired);
|
|
250
|
+
return this._createJSONSchemaTypeDefinition('string', 'decimal', options);
|
|
253
251
|
};
|
|
254
252
|
|
|
255
253
|
SchemaDecimal128.prototype.autoEncryptionType = function autoEncryptionType() {
|
|
@@ -12,7 +12,6 @@ const SchemaDocumentArrayOptions =
|
|
|
12
12
|
require('../options/schemaDocumentArrayOptions');
|
|
13
13
|
const SchemaType = require('../schemaType');
|
|
14
14
|
const cast = require('../cast');
|
|
15
|
-
const createJSONSchemaTypeDefinition = require('../helpers/createJSONSchemaTypeDefinition');
|
|
16
15
|
const discriminator = require('../helpers/model/discriminator');
|
|
17
16
|
const handleIdOption = require('../helpers/schema/handleIdOption');
|
|
18
17
|
const handleSpreadDoc = require('../helpers/document/handleSpreadDoc');
|
|
@@ -315,7 +314,7 @@ SchemaDocumentArray.prototype.doValidateSync = function(array, scope, options) {
|
|
|
315
314
|
continue;
|
|
316
315
|
}
|
|
317
316
|
|
|
318
|
-
const subdocValidateError = doc
|
|
317
|
+
const subdocValidateError = doc.$__validateSync(options);
|
|
319
318
|
|
|
320
319
|
if (subdocValidateError && resultError == null) {
|
|
321
320
|
resultError = subdocValidateError;
|
|
@@ -651,10 +650,9 @@ function cast$elemMatch(val, context) {
|
|
|
651
650
|
*/
|
|
652
651
|
|
|
653
652
|
SchemaDocumentArray.prototype.toJSONSchema = function toJSONSchema(options) {
|
|
654
|
-
const itemsTypeDefinition =
|
|
655
|
-
const isRequired = this.options.required && typeof this.options.required !== 'function';
|
|
653
|
+
const itemsTypeDefinition = this._createJSONSchemaTypeDefinition('object', 'object', { ...options, _overrideRequired: false });
|
|
656
654
|
return {
|
|
657
|
-
...
|
|
655
|
+
...this._createJSONSchemaTypeDefinition('array', 'array', options),
|
|
658
656
|
items: { ...itemsTypeDefinition, ...this.schema.toJSONSchema(options) }
|
|
659
657
|
};
|
|
660
658
|
};
|
package/lib/schema/double.js
CHANGED
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
const CastError = require('../error/cast');
|
|
8
8
|
const SchemaType = require('../schemaType');
|
|
9
9
|
const castDouble = require('../cast/double');
|
|
10
|
-
const createJSONSchemaTypeDefinition = require('../helpers/createJSONSchemaTypeDefinition');
|
|
11
10
|
|
|
12
11
|
/**
|
|
13
12
|
* Double SchemaType constructor.
|
|
@@ -231,8 +230,7 @@ Object.defineProperty(SchemaDouble.prototype, '$conditionalHandlers', {
|
|
|
231
230
|
*/
|
|
232
231
|
|
|
233
232
|
SchemaDouble.prototype.toJSONSchema = function toJSONSchema(options) {
|
|
234
|
-
|
|
235
|
-
return createJSONSchemaTypeDefinition('number', 'double', options?.useBsonType, isRequired);
|
|
233
|
+
return this._createJSONSchemaTypeDefinition('number', 'double', options);
|
|
236
234
|
};
|
|
237
235
|
|
|
238
236
|
SchemaDouble.prototype.autoEncryptionType = function autoEncryptionType() {
|
package/lib/schema/int32.js
CHANGED
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
const CastError = require('../error/cast');
|
|
8
8
|
const SchemaType = require('../schemaType');
|
|
9
9
|
const castInt32 = require('../cast/int32');
|
|
10
|
-
const createJSONSchemaTypeDefinition = require('../helpers/createJSONSchemaTypeDefinition');
|
|
11
10
|
const handleBitwiseOperator = require('./operators/bitwise');
|
|
12
11
|
|
|
13
12
|
/**
|
|
@@ -273,8 +272,7 @@ SchemaInt32.prototype.castForQuery = function($conditional, val, context) {
|
|
|
273
272
|
*/
|
|
274
273
|
|
|
275
274
|
SchemaInt32.prototype.toJSONSchema = function toJSONSchema(options) {
|
|
276
|
-
|
|
277
|
-
return createJSONSchemaTypeDefinition('number', 'int', options?.useBsonType, isRequired);
|
|
275
|
+
return this._createJSONSchemaTypeDefinition('number', 'int', options);
|
|
278
276
|
};
|
|
279
277
|
|
|
280
278
|
SchemaInt32.prototype.autoEncryptionType = function autoEncryptionType() {
|
package/lib/schema/map.js
CHANGED
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
const MongooseMap = require('../types/map');
|
|
8
8
|
const SchemaMapOptions = require('../options/schemaMapOptions');
|
|
9
9
|
const SchemaType = require('../schemaType');
|
|
10
|
-
const createJSONSchemaTypeDefinition = require('../helpers/createJSONSchemaTypeDefinition');
|
|
11
10
|
const MongooseError = require('../error/mongooseError');
|
|
12
11
|
const Schema = require('../schema');
|
|
13
12
|
const utils = require('../utils');
|
|
@@ -125,11 +124,9 @@ class SchemaMap extends SchemaType {
|
|
|
125
124
|
*/
|
|
126
125
|
|
|
127
126
|
toJSONSchema(options) {
|
|
128
|
-
const useBsonType = options?.useBsonType;
|
|
129
127
|
const embeddedSchemaType = this.getEmbeddedSchemaType();
|
|
130
128
|
|
|
131
|
-
const
|
|
132
|
-
const result = createJSONSchemaTypeDefinition('object', 'object', useBsonType, isRequired);
|
|
129
|
+
const result = this._createJSONSchemaTypeDefinition('object', 'object', options);
|
|
133
130
|
result.additionalProperties = embeddedSchemaType.toJSONSchema(options);
|
|
134
131
|
|
|
135
132
|
return result;
|
package/lib/schema/number.js
CHANGED
|
@@ -8,7 +8,6 @@ const MongooseError = require('../error/index');
|
|
|
8
8
|
const SchemaNumberOptions = require('../options/schemaNumberOptions');
|
|
9
9
|
const SchemaType = require('../schemaType');
|
|
10
10
|
const castNumber = require('../cast/number');
|
|
11
|
-
const createJSONSchemaTypeDefinition = require('../helpers/createJSONSchemaTypeDefinition');
|
|
12
11
|
const handleBitwiseOperator = require('./operators/bitwise');
|
|
13
12
|
const utils = require('../utils');
|
|
14
13
|
|
|
@@ -473,7 +472,7 @@ SchemaNumber.prototype.castForQuery = function($conditional, val, context) {
|
|
|
473
472
|
if ($conditional != null) {
|
|
474
473
|
handler = this.$conditionalHandlers[$conditional];
|
|
475
474
|
if (!handler) {
|
|
476
|
-
throw new
|
|
475
|
+
throw new MongooseError('Can\'t use ' + $conditional + ' with Number.');
|
|
477
476
|
}
|
|
478
477
|
return handler.call(this, val, context);
|
|
479
478
|
}
|
|
@@ -499,8 +498,7 @@ SchemaNumber.prototype.castForQuery = function($conditional, val, context) {
|
|
|
499
498
|
*/
|
|
500
499
|
|
|
501
500
|
SchemaNumber.prototype.toJSONSchema = function toJSONSchema(options) {
|
|
502
|
-
|
|
503
|
-
return createJSONSchemaTypeDefinition('number', 'number', options?.useBsonType, isRequired);
|
|
501
|
+
return this._createJSONSchemaTypeDefinition('number', 'number', options);
|
|
504
502
|
};
|
|
505
503
|
|
|
506
504
|
/*!
|
package/lib/schema/objectId.js
CHANGED
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
const SchemaObjectIdOptions = require('../options/schemaObjectIdOptions');
|
|
8
8
|
const SchemaType = require('../schemaType');
|
|
9
9
|
const castObjectId = require('../cast/objectid');
|
|
10
|
-
const createJSONSchemaTypeDefinition = require('../helpers/createJSONSchemaTypeDefinition');
|
|
11
10
|
const getConstructorName = require('../helpers/getConstructorName');
|
|
12
11
|
const oid = require('../types/objectid');
|
|
13
12
|
const isBsonType = require('../helpers/isBsonType');
|
|
@@ -318,8 +317,13 @@ function resetId(v) {
|
|
|
318
317
|
*/
|
|
319
318
|
|
|
320
319
|
SchemaObjectId.prototype.toJSONSchema = function toJSONSchema(options) {
|
|
321
|
-
const
|
|
322
|
-
|
|
320
|
+
const jsonSchema = this._createJSONSchemaTypeDefinition('string', 'objectId', options);
|
|
321
|
+
// `bsonType: 'objectId'` already validates ObjectIds, so the regex is only useful
|
|
322
|
+
// for the portable `type: 'string'` representation (e.g. for ajv, zod, etc.)
|
|
323
|
+
if (!options?.useBsonType) {
|
|
324
|
+
jsonSchema.pattern = '^[A-Fa-f0-9]{24}$';
|
|
325
|
+
}
|
|
326
|
+
return jsonSchema;
|
|
323
327
|
};
|
|
324
328
|
|
|
325
329
|
SchemaObjectId.prototype.autoEncryptionType = function autoEncryptionType() {
|
package/lib/schema/string.js
CHANGED
|
@@ -8,7 +8,6 @@ const SchemaType = require('../schemaType');
|
|
|
8
8
|
const MongooseError = require('../error/index');
|
|
9
9
|
const SchemaStringOptions = require('../options/schemaStringOptions');
|
|
10
10
|
const castString = require('../cast/string');
|
|
11
|
-
const createJSONSchemaTypeDefinition = require('../helpers/createJSONSchemaTypeDefinition');
|
|
12
11
|
const utils = require('../utils');
|
|
13
12
|
const isBsonType = require('../helpers/isBsonType');
|
|
14
13
|
|
|
@@ -474,12 +473,14 @@ SchemaString.prototype.maxlength = function(value, message) {
|
|
|
474
473
|
|
|
475
474
|
if (value != null) {
|
|
476
475
|
let msg = message || MongooseError.messages.String.maxlength;
|
|
477
|
-
|
|
476
|
+
if (typeof msg !== 'function') {
|
|
477
|
+
msg = msg.replace(/{MAXLENGTH}/, value);
|
|
478
|
+
}
|
|
478
479
|
this.validators.push({
|
|
479
480
|
validator: this.maxlengthValidator = function(v) {
|
|
480
481
|
return v === null || v.length <= value;
|
|
481
482
|
},
|
|
482
|
-
message: msg,
|
|
483
|
+
message: formatMaxLengthValidatorMessage(msg),
|
|
483
484
|
type: 'maxlength',
|
|
484
485
|
maxlength: value
|
|
485
486
|
});
|
|
@@ -718,8 +719,7 @@ SchemaString.prototype.castForQuery = function($conditional, val, context) {
|
|
|
718
719
|
*/
|
|
719
720
|
|
|
720
721
|
SchemaString.prototype.toJSONSchema = function toJSONSchema(options) {
|
|
721
|
-
|
|
722
|
-
return createJSONSchemaTypeDefinition('string', 'string', options?.useBsonType, isRequired);
|
|
722
|
+
return this._createJSONSchemaTypeDefinition('string', 'string', options);
|
|
723
723
|
};
|
|
724
724
|
|
|
725
725
|
SchemaString.prototype.autoEncryptionType = function autoEncryptionType() {
|
|
@@ -731,3 +731,18 @@ SchemaString.prototype.autoEncryptionType = function autoEncryptionType() {
|
|
|
731
731
|
*/
|
|
732
732
|
|
|
733
733
|
module.exports = SchemaString;
|
|
734
|
+
|
|
735
|
+
function formatMaxLengthValidatorMessage(msg) {
|
|
736
|
+
return function(props, doc) {
|
|
737
|
+
if (typeof msg === 'function') {
|
|
738
|
+
return MongooseError.ValidatorError.prototype.formatMessage(msg, props, doc);
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
if (typeof msg === 'string' && typeof props.value === 'string' && props.value.length > 30) {
|
|
742
|
+
props = Object.assign({}, props, {
|
|
743
|
+
value: props.value.slice(0, 30) + '...'
|
|
744
|
+
});
|
|
745
|
+
}
|
|
746
|
+
return MongooseError.ValidatorError.prototype.formatMessage(msg, props, doc);
|
|
747
|
+
};
|
|
748
|
+
}
|
|
@@ -12,7 +12,6 @@ const SchemaType = require('../schemaType');
|
|
|
12
12
|
const applyDefaults = require('../helpers/document/applyDefaults');
|
|
13
13
|
const $exists = require('./operators/exists');
|
|
14
14
|
const castToNumber = require('./operators/helpers').castToNumber;
|
|
15
|
-
const createJSONSchemaTypeDefinition = require('../helpers/createJSONSchemaTypeDefinition');
|
|
16
15
|
const discriminator = require('../helpers/model/discriminator');
|
|
17
16
|
const geospatial = require('./operators/geospatial');
|
|
18
17
|
const getConstructor = require('../helpers/discriminator/getConstructor');
|
|
@@ -311,7 +310,7 @@ SchemaSubdocument.prototype.doValidateSync = function(value, scope, options) {
|
|
|
311
310
|
if (!value) {
|
|
312
311
|
return;
|
|
313
312
|
}
|
|
314
|
-
return value
|
|
313
|
+
return value.$__validateSync();
|
|
315
314
|
};
|
|
316
315
|
|
|
317
316
|
/**
|
|
@@ -428,9 +427,8 @@ SchemaSubdocument.prototype.clone = function() {
|
|
|
428
427
|
*/
|
|
429
428
|
|
|
430
429
|
SchemaSubdocument.prototype.toJSONSchema = function toJSONSchema(options) {
|
|
431
|
-
const isRequired = this.options.required && typeof this.options.required !== 'function';
|
|
432
430
|
return {
|
|
433
431
|
...this.schema.toJSONSchema(options),
|
|
434
|
-
...
|
|
432
|
+
...this._createJSONSchemaTypeDefinition('object', 'object', options)
|
|
435
433
|
};
|
|
436
434
|
};
|
package/lib/schema/union.js
CHANGED
|
@@ -28,6 +28,7 @@ class Union extends SchemaType {
|
|
|
28
28
|
throw new Error('Union schema type requires an array of types');
|
|
29
29
|
}
|
|
30
30
|
this.schemaTypes = options.of.map(obj => parentSchema.interpretAsType(key, obj, schemaOptions));
|
|
31
|
+
this.$isSchemaUnion = true;
|
|
31
32
|
}
|
|
32
33
|
|
|
33
34
|
cast(val, doc, init, prev, options) {
|
|
@@ -90,12 +91,61 @@ class Union extends SchemaType {
|
|
|
90
91
|
throw lastError;
|
|
91
92
|
}
|
|
92
93
|
|
|
94
|
+
async doValidate(value, scope, options) {
|
|
95
|
+
if (options && options.skipSchemaValidators) {
|
|
96
|
+
if (value != null && typeof value.validate === 'function') {
|
|
97
|
+
return value.validate();
|
|
98
|
+
}
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
await super.doValidate(value, scope, options);
|
|
103
|
+
if (value != null && typeof value.validate === 'function') {
|
|
104
|
+
await value.validate();
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
doValidateSync(value, scope, options) {
|
|
109
|
+
if (!options || !options.skipSchemaValidators) {
|
|
110
|
+
const schemaTypeError = super.doValidateSync(value, scope, options);
|
|
111
|
+
if (schemaTypeError) {
|
|
112
|
+
return schemaTypeError;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
if (value != null && typeof value.$__validateSync === 'function') {
|
|
116
|
+
return value.$__validateSync();
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
93
120
|
clone() {
|
|
94
121
|
const schematype = super.clone();
|
|
95
122
|
|
|
96
123
|
schematype.schemaTypes = this.schemaTypes.map(schemaType => schemaType.clone());
|
|
97
124
|
return schematype;
|
|
98
125
|
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Returns this schema type's representation in a JSON schema.
|
|
129
|
+
*
|
|
130
|
+
* @param {object} [options]
|
|
131
|
+
* @param {boolean} [options.useBsonType=false] If true, return a representation with `bsonType` for use with MongoDB's `$jsonSchema`.
|
|
132
|
+
* @returns {object} JSON schema properties
|
|
133
|
+
*/
|
|
134
|
+
toJSONSchema(options) {
|
|
135
|
+
const isRequired = this.options.required && typeof this.options.required !== 'function';
|
|
136
|
+
const childOptions = { ...options, _overrideRequired: true };
|
|
137
|
+
const jsonSchemas = this.schemaTypes.map(schemaType => schemaType.toJSONSchema(childOptions));
|
|
138
|
+
if (isRequired) {
|
|
139
|
+
return { anyOf: jsonSchemas };
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
return {
|
|
143
|
+
anyOf: [
|
|
144
|
+
options?.useBsonType ? { bsonType: 'null' } : { type: 'null' },
|
|
145
|
+
...jsonSchemas
|
|
146
|
+
]
|
|
147
|
+
};
|
|
148
|
+
}
|
|
99
149
|
}
|
|
100
150
|
|
|
101
151
|
/**
|
package/lib/schema/uuid.js
CHANGED
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
const SchemaType = require('../schemaType');
|
|
8
8
|
const CastError = SchemaType.CastError;
|
|
9
9
|
const castUUID = require('../cast/uuid');
|
|
10
|
-
const createJSONSchemaTypeDefinition = require('../helpers/createJSONSchemaTypeDefinition');
|
|
11
10
|
const utils = require('../utils');
|
|
12
11
|
const handleBitwiseOperator = require('./operators/bitwise');
|
|
13
12
|
|
|
@@ -290,8 +289,7 @@ SchemaUUID.prototype.castForQuery = function($conditional, val, context) {
|
|
|
290
289
|
*/
|
|
291
290
|
|
|
292
291
|
SchemaUUID.prototype.toJSONSchema = function toJSONSchema(options) {
|
|
293
|
-
|
|
294
|
-
return createJSONSchemaTypeDefinition('string', 'binData', options?.useBsonType, isRequired);
|
|
292
|
+
return this._createJSONSchemaTypeDefinition('string', 'binData', options);
|
|
295
293
|
};
|
|
296
294
|
|
|
297
295
|
SchemaUUID.prototype.autoEncryptionType = function autoEncryptionType() {
|
package/lib/schema.js
CHANGED
|
@@ -59,7 +59,7 @@ const numberRE = /^\d+$/;
|
|
|
59
59
|
* - [autoIndex](https://mongoosejs.com/docs/guide.html#autoIndex): bool - defaults to null (which means use the connection's autoIndex option)
|
|
60
60
|
* - [autoCreate](https://mongoosejs.com/docs/guide.html#autoCreate): bool - defaults to null (which means use the connection's autoCreate option)
|
|
61
61
|
* - [bufferCommands](https://mongoosejs.com/docs/guide.html#bufferCommands): bool - defaults to true
|
|
62
|
-
* - [bufferTimeoutMS](https://mongoosejs.com/docs/guide.html#bufferTimeoutMS): number - defaults to 10000 (10 seconds). If `bufferCommands` is enabled, the amount of time Mongoose will wait for connectivity to be
|
|
62
|
+
* - [bufferTimeoutMS](https://mongoosejs.com/docs/guide.html#bufferTimeoutMS): number - defaults to 10000 (10 seconds). If `bufferCommands` is enabled, the amount of time Mongoose will wait for connectivity to be established before erroring out.
|
|
63
63
|
* - [capped](https://mongoosejs.com/docs/guide.html#capped): bool | number | object - defaults to false
|
|
64
64
|
* - [collection](https://mongoosejs.com/docs/guide.html#collection): string - no default
|
|
65
65
|
* - [discriminatorKey](https://mongoosejs.com/docs/guide.html#discriminatorKey): string - defaults to `__t`
|
|
@@ -72,6 +72,7 @@ const numberRE = /^\d+$/;
|
|
|
72
72
|
* - [shardKey](https://mongoosejs.com/docs/guide.html#shardKey): object - defaults to `null`
|
|
73
73
|
* - [strict](https://mongoosejs.com/docs/guide.html#strict): bool - defaults to true
|
|
74
74
|
* - [strictQuery](https://mongoosejs.com/docs/guide.html#strictQuery): bool - defaults to false
|
|
75
|
+
* - [strictRead](https://mongoosejs.com/docs/guide.html#strictRead): bool or 'throw' - defaults to false. If set to `true`, fields not in the schema will be stripped when hydrating documents from MongoDB. If set to `'throw'`, an error will be thrown when a field not in the schema is encountered during document hydration.
|
|
75
76
|
* - [toJSON](https://mongoosejs.com/docs/guide.html#toJSON) - object - no default
|
|
76
77
|
* - [toObject](https://mongoosejs.com/docs/guide.html#toObject) - object - no default
|
|
77
78
|
* - [typeKey](https://mongoosejs.com/docs/guide.html#typeKey) - string - defaults to 'type'
|
|
@@ -606,10 +607,12 @@ Schema.prototype.defaultOptions = function(options) {
|
|
|
606
607
|
const baseOptions = this.base?.options || {};
|
|
607
608
|
const defaultStrict = baseOptions.strict ?? true;
|
|
608
609
|
const defaultStrictQuery = baseOptions.strictQuery ?? false;
|
|
610
|
+
const defaultStrictRead = baseOptions.strictRead ?? false;
|
|
609
611
|
const defaultId = baseOptions.id ?? true;
|
|
610
612
|
options = {
|
|
611
613
|
strict: defaultStrict,
|
|
612
614
|
strictQuery: defaultStrictQuery,
|
|
615
|
+
strictRead: defaultStrictRead,
|
|
613
616
|
bufferCommands: true,
|
|
614
617
|
capped: false, // { size, max, autoIndexId }
|
|
615
618
|
versionKey: '__v',
|
|
@@ -750,7 +753,7 @@ Schema.prototype.encryptionType = function encryptionType(encryptionType) {
|
|
|
750
753
|
return this.options.encryptionType;
|
|
751
754
|
}
|
|
752
755
|
if (!(typeof encryptionType === 'string' || encryptionType === null)) {
|
|
753
|
-
throw new MongooseError(
|
|
756
|
+
throw new MongooseError(`invalid \`encryptionType\`: ${encryptionType}`);
|
|
754
757
|
}
|
|
755
758
|
this.options.encryptionType = encryptionType;
|
|
756
759
|
};
|
|
@@ -1268,7 +1271,7 @@ reserved.collection = 1;
|
|
|
1268
1271
|
|
|
1269
1272
|
Schema.prototype.path = function(path, obj) {
|
|
1270
1273
|
if (obj === undefined) {
|
|
1271
|
-
if (this.paths
|
|
1274
|
+
if (Object.hasOwn(this.paths, path)) {
|
|
1272
1275
|
return this.paths[path];
|
|
1273
1276
|
}
|
|
1274
1277
|
// Convert to '.$' to check subpaths re: gh-6405
|
|
@@ -1296,9 +1299,15 @@ Schema.prototype.path = function(path, obj) {
|
|
|
1296
1299
|
: undefined;
|
|
1297
1300
|
}
|
|
1298
1301
|
|
|
1302
|
+
const subpaths = path.indexOf('.') === -1 ? [path] : path.split('.');
|
|
1303
|
+
const last = subpaths.pop();
|
|
1304
|
+
if (utils.specialProperties.has(last)) {
|
|
1305
|
+
throw new MongooseError('Cannot set special property `' + last + '` on a schema');
|
|
1306
|
+
}
|
|
1307
|
+
|
|
1299
1308
|
// some path names conflict with document methods
|
|
1300
|
-
const firstPieceOfPath =
|
|
1301
|
-
if (reserved
|
|
1309
|
+
const firstPieceOfPath = subpaths.length === 0 ? last : subpaths[0];
|
|
1310
|
+
if (Object.hasOwn(reserved, firstPieceOfPath) && !this.options.suppressReservedKeysWarning) {
|
|
1302
1311
|
const errorMessage = `\`${firstPieceOfPath}\` is a reserved schema pathname and may break some functionality. ` +
|
|
1303
1312
|
'You are allowed to use it, but use at your own risk. ' +
|
|
1304
1313
|
'To disable this warning pass `suppressReservedKeysWarning` as a schema option.';
|
|
@@ -1311,8 +1320,6 @@ Schema.prototype.path = function(path, obj) {
|
|
|
1311
1320
|
}
|
|
1312
1321
|
|
|
1313
1322
|
// update the tree
|
|
1314
|
-
const subpaths = path.split(/\./);
|
|
1315
|
-
const last = subpaths.pop();
|
|
1316
1323
|
let branch = this.tree;
|
|
1317
1324
|
let fullPath = '';
|
|
1318
1325
|
|
|
@@ -1536,7 +1543,7 @@ function getMapPath(schema, path) {
|
|
|
1536
1543
|
} else if (val.schema && path.startsWith(cleanPath + '.')) {
|
|
1537
1544
|
let remnant = path.slice(cleanPath.length + 1);
|
|
1538
1545
|
remnant = remnant.slice(remnant.indexOf('.') + 1);
|
|
1539
|
-
return val.schema.
|
|
1546
|
+
return val.schema.path(remnant);
|
|
1540
1547
|
} else if (val.$isSchemaMap && path.startsWith(cleanPath + '.')) {
|
|
1541
1548
|
let remnant = path.slice(cleanPath.length + 1);
|
|
1542
1549
|
remnant = remnant.slice(remnant.indexOf('.') + 1);
|
|
@@ -3026,7 +3033,7 @@ Schema.prototype._getPathType = function(path) {
|
|
|
3026
3033
|
};
|
|
3027
3034
|
}
|
|
3028
3035
|
return { schema: foundschema, pathType: 'real' };
|
|
3029
|
-
} else if (p === parts.length && schema.nested
|
|
3036
|
+
} else if (p === parts.length && Object.hasOwn(schema.nested, trypath)) {
|
|
3030
3037
|
return { schema: schema, pathType: 'nested' };
|
|
3031
3038
|
}
|
|
3032
3039
|
}
|
|
@@ -3089,8 +3096,27 @@ function isArrayFilter(piece) {
|
|
|
3089
3096
|
|
|
3090
3097
|
Schema.prototype._preCompile = function _preCompile() {
|
|
3091
3098
|
this.plugin(idGetter, { deduplicate: true });
|
|
3099
|
+
_precomputeOptimisticConcurrency(this);
|
|
3092
3100
|
};
|
|
3093
3101
|
|
|
3102
|
+
/*!
|
|
3103
|
+
* Build precomputed sets for optimisticConcurrency include/exclude,
|
|
3104
|
+
* expanding user-specified paths to include all schema subpaths so that
|
|
3105
|
+
* lookups at save time are a simple `Set.has()`.
|
|
3106
|
+
*/
|
|
3107
|
+
|
|
3108
|
+
function _precomputeOptimisticConcurrency(schema) {
|
|
3109
|
+
const opt = schema.options.optimisticConcurrency;
|
|
3110
|
+
if (!opt || opt === true) {
|
|
3111
|
+
return;
|
|
3112
|
+
}
|
|
3113
|
+
if (Array.isArray(opt)) {
|
|
3114
|
+
schema.options._optimisticConcurrencySet = new Set(opt);
|
|
3115
|
+
} else if (Array.isArray(opt.exclude)) {
|
|
3116
|
+
schema.options._optimisticConcurrencyExcludeSet = new Set(opt.exclude);
|
|
3117
|
+
}
|
|
3118
|
+
}
|
|
3119
|
+
|
|
3094
3120
|
/**
|
|
3095
3121
|
* Returns a JSON schema representation of this Schema.
|
|
3096
3122
|
*
|
|
@@ -3102,12 +3128,12 @@ Schema.prototype._preCompile = function _preCompile() {
|
|
|
3102
3128
|
* - `enum` for strings and numbers
|
|
3103
3129
|
*
|
|
3104
3130
|
* #### Example:
|
|
3105
|
-
*
|
|
3106
|
-
*
|
|
3107
|
-
*
|
|
3131
|
+
* const schema = new Schema({ name: String });
|
|
3132
|
+
* // { required: ['_id'], properties: { name: { type: ['string', 'null'] }, _id: { type: 'string' } } }
|
|
3133
|
+
* schema.toJSONSchema();
|
|
3108
3134
|
*
|
|
3109
|
-
*
|
|
3110
|
-
*
|
|
3135
|
+
* // { required: ['_id'], properties: { name: { bsonType: ['string', 'null'] }, _id: { bsonType: 'objectId' } } }
|
|
3136
|
+
* schema.toJSONSchema({ useBsonType: true });
|
|
3111
3137
|
*
|
|
3112
3138
|
* @param {object} [options]
|
|
3113
3139
|
* @param {boolean} [options.useBsonType=false] if true, specify each path's type using `bsonType` rather than `type` for MongoDB $jsonSchema support
|