@abedmurrar/objection 4.0.0-alpha.0 → 4.0.0-beta.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 +103 -67
- package/lib/index.mjs +6 -0
- package/lib/initialize.js +6 -9
- package/lib/model/AjvValidator.js +235 -282
- package/lib/model/Model.js +653 -823
- package/lib/model/ModifierNotFoundError.js +5 -7
- package/lib/model/NotFoundError.js +14 -18
- package/lib/model/RelationDoesNotExistError.js +6 -9
- package/lib/model/ValidationError.js +33 -41
- package/lib/model/Validator.js +15 -21
- package/lib/model/getModel.js +1 -3
- package/lib/model/graph/ModelGraph.js +44 -64
- package/lib/model/graph/ModelGraphBuilder.js +164 -217
- package/lib/model/graph/ModelGraphEdge.js +31 -43
- package/lib/model/graph/ModelGraphNode.js +192 -231
- package/lib/model/inheritModel.js +9 -18
- package/lib/model/modelBindKnex.js +48 -62
- package/lib/model/modelClone.js +79 -98
- package/lib/model/modelColPropMap.js +16 -26
- package/lib/model/modelConcurrency.js +24 -0
- package/lib/model/modelId.js +44 -49
- package/lib/model/modelJsonAttributes.js +56 -76
- package/lib/model/modelParseRelations.js +68 -67
- package/lib/model/modelQueryProps.js +76 -107
- package/lib/model/modelSet.js +92 -112
- package/lib/model/modelTableMetadata.js +60 -72
- package/lib/model/modelToJson.js +120 -150
- package/lib/model/modelUtils.js +30 -37
- package/lib/model/modelValidate.js +34 -42
- package/lib/model/modelValues.js +78 -91
- package/lib/model/modelVisitor.js +22 -29
- package/lib/objection.js +42 -67
- package/lib/queryBuilder/FunctionBuilder.js +231 -279
- package/lib/queryBuilder/InternalOptions.js +19 -24
- package/lib/queryBuilder/JoinBuilder.js +116 -149
- package/lib/queryBuilder/QueryBuilder.js +1009 -1271
- package/lib/queryBuilder/QueryBuilderBase.js +647 -865
- package/lib/queryBuilder/QueryBuilderContext.js +14 -21
- package/lib/queryBuilder/QueryBuilderContextBase.js +20 -29
- package/lib/queryBuilder/QueryBuilderOperationSupport.js +462 -536
- package/lib/queryBuilder/QueryBuilderUserContext.js +19 -25
- package/lib/queryBuilder/RawBuilder.js +58 -73
- package/lib/queryBuilder/ReferenceBuilder.js +232 -270
- package/lib/queryBuilder/RelationExpression.js +322 -380
- package/lib/queryBuilder/StaticHookArguments.js +94 -106
- package/lib/queryBuilder/ValueBuilder.js +100 -112
- package/lib/queryBuilder/expressions.js +86 -116
- package/lib/queryBuilder/functions/mysql.js +642 -697
- package/lib/queryBuilder/graph/GraphAction.js +44 -59
- package/lib/queryBuilder/graph/GraphData.js +7 -9
- package/lib/queryBuilder/graph/GraphFetcher.js +115 -151
- package/lib/queryBuilder/graph/GraphNodeDbExistence.js +114 -152
- package/lib/queryBuilder/graph/GraphOperation.js +16 -22
- package/lib/queryBuilder/graph/GraphOptions.js +143 -185
- package/lib/queryBuilder/graph/GraphUpsert.js +167 -241
- package/lib/queryBuilder/graph/delete/GraphDelete.js +8 -13
- package/lib/queryBuilder/graph/delete/GraphDeleteAction.js +44 -62
- package/lib/queryBuilder/graph/insert/GraphInsert.js +99 -128
- package/lib/queryBuilder/graph/insert/GraphInsertAction.js +151 -193
- package/lib/queryBuilder/graph/insert/JoinRowGraphInsertAction.js +57 -79
- package/lib/queryBuilder/graph/patch/GraphPatch.js +8 -13
- package/lib/queryBuilder/graph/patch/GraphPatchAction.js +181 -234
- package/lib/queryBuilder/graph/recursiveUpsert/GraphRecursiveUpsert.js +16 -21
- package/lib/queryBuilder/graph/recursiveUpsert/GraphRecursiveUpsertAction.js +80 -110
- package/lib/queryBuilder/join/JoinResultColumn.js +14 -18
- package/lib/queryBuilder/join/JoinResultParser.js +88 -101
- package/lib/queryBuilder/join/RelationJoiner.js +205 -288
- package/lib/queryBuilder/join/TableNode.js +117 -144
- package/lib/queryBuilder/join/TableTree.js +60 -76
- package/lib/queryBuilder/join/utils.js +10 -16
- package/lib/queryBuilder/operations/DelegateOperation.js +93 -133
- package/lib/queryBuilder/operations/DeleteOperation.js +33 -37
- package/lib/queryBuilder/operations/FindByIdOperation.js +20 -28
- package/lib/queryBuilder/operations/FindByIdsOperation.js +17 -23
- package/lib/queryBuilder/operations/FindOperation.js +114 -131
- package/lib/queryBuilder/operations/FirstOperation.js +14 -19
- package/lib/queryBuilder/operations/FromOperation.js +69 -88
- package/lib/queryBuilder/operations/InsertAndFetchOperation.js +28 -39
- package/lib/queryBuilder/operations/InsertGraphAndFetchOperation.js +25 -35
- package/lib/queryBuilder/operations/InsertGraphOperation.js +77 -98
- package/lib/queryBuilder/operations/InsertOperation.js +132 -165
- package/lib/queryBuilder/operations/InstanceDeleteOperation.js +27 -36
- package/lib/queryBuilder/operations/InstanceFindOperation.js +9 -13
- package/lib/queryBuilder/operations/InstanceInsertOperation.js +13 -17
- package/lib/queryBuilder/operations/InstanceUpdateOperation.js +32 -46
- package/lib/queryBuilder/operations/JoinRelatedOperation.js +66 -86
- package/lib/queryBuilder/operations/KnexOperation.js +4 -7
- package/lib/queryBuilder/operations/MergeOperation.js +32 -45
- package/lib/queryBuilder/operations/ObjectionToKnexConvertingOperation.js +131 -150
- package/lib/queryBuilder/operations/OnBuildKnexOperation.js +17 -23
- package/lib/queryBuilder/operations/OnBuildOperation.js +17 -23
- package/lib/queryBuilder/operations/OnErrorOperation.js +17 -23
- package/lib/queryBuilder/operations/QueryBuilderOperation.js +231 -270
- package/lib/queryBuilder/operations/RangeOperation.js +30 -40
- package/lib/queryBuilder/operations/RelateOperation.js +14 -21
- package/lib/queryBuilder/operations/ReturningOperation.js +12 -18
- package/lib/queryBuilder/operations/RunAfterOperation.js +17 -23
- package/lib/queryBuilder/operations/RunBeforeOperation.js +17 -23
- package/lib/queryBuilder/operations/UnrelateOperation.js +12 -17
- package/lib/queryBuilder/operations/UpdateAndFetchOperation.js +48 -65
- package/lib/queryBuilder/operations/UpdateOperation.js +104 -129
- package/lib/queryBuilder/operations/UpsertGraphAndFetchOperation.js +25 -35
- package/lib/queryBuilder/operations/UpsertGraphOperation.js +36 -55
- package/lib/queryBuilder/operations/WhereCompositeOperation.js +30 -39
- package/lib/queryBuilder/operations/WhereInOperation.js +34 -36
- package/lib/queryBuilder/operations/eager/EagerOperation.js +37 -52
- package/lib/queryBuilder/operations/eager/JoinEagerOperation.js +34 -44
- package/lib/queryBuilder/operations/eager/NaiveEagerOperation.js +4 -7
- package/lib/queryBuilder/operations/eager/WhereInEagerOperation.js +193 -251
- package/lib/queryBuilder/operations/jsonApi/WhereJsonHasOperation.js +18 -25
- package/lib/queryBuilder/operations/jsonApi/WhereJsonNotObjectOperation.js +25 -41
- package/lib/queryBuilder/operations/jsonApi/WhereJsonOperation.js +19 -20
- package/lib/queryBuilder/operations/jsonApi/WhereJsonOverlapsOperation.js +23 -21
- package/lib/queryBuilder/operations/jsonApi/mysqlJsonApi.js +106 -118
- package/lib/queryBuilder/operations/jsonApi/postgresJsonApi.js +79 -108
- package/lib/queryBuilder/operations/select/SelectOperation.js +37 -53
- package/lib/queryBuilder/operations/select/Selection.js +94 -105
- package/lib/queryBuilder/operations/whereInComposite/WhereInCompositeMsSqlOperation.js +68 -101
- package/lib/queryBuilder/operations/whereInComposite/WhereInCompositeOperation.js +65 -75
- package/lib/queryBuilder/operations/whereInComposite/WhereInCompositeSqliteOperation.js +75 -84
- package/lib/queryBuilder/parsers/jsonFieldExpressionParser.js +760 -859
- package/lib/queryBuilder/parsers/relationExpressionParser.js +840 -952
- package/lib/queryBuilder/transformations/CompositeQueryTransformation.js +10 -15
- package/lib/queryBuilder/transformations/QueryTransformation.js +4 -6
- package/lib/queryBuilder/transformations/WrapMysqlModifySubqueryTransformation.js +35 -49
- package/lib/queryBuilder/transformations/index.js +3 -9
- package/lib/queryBuilder/whereScopes.js +158 -186
- package/lib/relations/Relation.js +279 -363
- package/lib/relations/RelationDeleteOperation.js +16 -22
- package/lib/relations/RelationFindOperation.js +100 -133
- package/lib/relations/RelationInsertOperation.js +19 -27
- package/lib/relations/RelationOwner.js +167 -204
- package/lib/relations/RelationProperty.js +177 -217
- package/lib/relations/RelationUpdateOperation.js +16 -23
- package/lib/relations/belongsToOne/BelongsToOneDeleteOperation.js +11 -16
- package/lib/relations/belongsToOne/BelongsToOneInsertOperation.js +24 -35
- package/lib/relations/belongsToOne/BelongsToOneRelateOperation.js +30 -41
- package/lib/relations/belongsToOne/BelongsToOneRelation.js +33 -41
- package/lib/relations/belongsToOne/BelongsToOneUnrelateOperation.js +38 -53
- package/lib/relations/hasMany/HasManyInsertOperation.js +35 -51
- package/lib/relations/hasMany/HasManyRelateOperation.js +38 -54
- package/lib/relations/hasMany/HasManyRelation.js +30 -38
- package/lib/relations/hasMany/HasManyUnrelateOperation.js +19 -26
- package/lib/relations/hasOne/HasOneRelation.js +4 -7
- package/lib/relations/hasOneThrough/HasOneThroughRelation.js +4 -7
- package/lib/relations/manyToMany/ManyToManyModifyMixin.js +67 -90
- package/lib/relations/manyToMany/ManyToManyRelation.js +349 -451
- package/lib/relations/manyToMany/ManyToManySqliteModifyMixin.js +19 -26
- package/lib/relations/manyToMany/delete/ManyToManyDeleteOperation.js +3 -5
- package/lib/relations/manyToMany/delete/ManyToManyDeleteOperationBase.js +14 -20
- package/lib/relations/manyToMany/delete/ManyToManyDeleteSqliteOperation.js +3 -7
- package/lib/relations/manyToMany/find/ManyToManyFindOperation.js +71 -94
- package/lib/relations/manyToMany/insert/ManyToManyInsertOperation.js +31 -43
- package/lib/relations/manyToMany/relate/ManyToManyRelateOperation.js +50 -67
- package/lib/relations/manyToMany/unrelate/ManyToManyUnrelateOperation.js +4 -7
- package/lib/relations/manyToMany/unrelate/ManyToManyUnrelateOperationBase.js +20 -27
- package/lib/relations/manyToMany/unrelate/ManyToManyUnrelateSqliteOperation.js +5 -10
- package/lib/relations/manyToMany/update/ManyToManyUpdateOperation.js +3 -5
- package/lib/relations/manyToMany/update/ManyToManyUpdateOperationBase.js +55 -72
- package/lib/relations/manyToMany/update/ManyToManyUpdateSqliteOperation.js +3 -7
- package/lib/transaction.js +53 -83
- package/lib/utils/assert.js +15 -21
- package/lib/utils/buildUtils.js +17 -19
- package/lib/utils/classUtils.js +7 -11
- package/lib/utils/cloneDeep.js +365 -0
- package/lib/utils/createModifier.js +36 -41
- package/lib/utils/deprecate.js +8 -12
- package/lib/utils/identifierMapping.js +153 -192
- package/lib/utils/internalPropUtils.js +4 -8
- package/lib/utils/knexUtils.js +61 -56
- package/lib/utils/mixin.js +16 -23
- package/lib/utils/mysqlJsonPath.js +55 -40
- package/lib/utils/normalizeIds.js +110 -127
- package/lib/utils/objectUtils.js +236 -338
- package/lib/utils/parseFieldExpression.js +66 -44
- package/lib/utils/postgresJsonPath.js +48 -62
- package/lib/utils/promiseUtils/after.js +10 -13
- package/lib/utils/promiseUtils/afterReturn.js +10 -13
- package/lib/utils/promiseUtils/index.js +15 -17
- package/lib/utils/promiseUtils/isPromise.js +6 -9
- package/lib/utils/promiseUtils/map.js +75 -89
- package/lib/utils/promiseUtils/mapAfterAllReturn.js +17 -23
- package/lib/utils/promiseUtils/try.js +15 -18
- package/lib/utils/resolveModel.js +91 -94
- package/lib/utils/tmpColumnUtils.js +4 -13
- package/package.json +50 -23
- package/typings/objection/index.d.mts +362 -0
- package/typings/objection/index.d.ts +36 -9
- package/lib/.eslintrc.json +0 -8
- package/lib/queryBuilder/parsers/jsonFieldExpressionParser.pegjs +0 -97
- package/lib/queryBuilder/parsers/relationExpressionParser.pegjs +0 -141
- package/lib/utils/clone.js +0 -2329
|
@@ -1,325 +1,278 @@
|
|
|
1
1
|
'use strict';
|
|
2
|
-
|
|
3
2
|
const Ajv = require('ajv');
|
|
4
3
|
const addFormats = require('ajv-formats');
|
|
5
4
|
const { Validator } = require('./Validator');
|
|
6
5
|
const { ValidationErrorType } = require('../model/ValidationError');
|
|
7
|
-
const { isObject,
|
|
8
|
-
|
|
6
|
+
const { isObject, cloneDeep: cloneDeepValue, omit } = require('../utils/objectUtils');
|
|
9
7
|
class AjvValidator extends Validator {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
if (conf.onCreateAjv) {
|
|
40
|
-
conf.onCreateAjv(ajv);
|
|
41
|
-
}
|
|
42
|
-
// Only add Ajv formats if they weren't added in user-space already
|
|
43
|
-
if (!ajv.formats['date-time']) {
|
|
44
|
-
addFormats(ajv);
|
|
45
|
-
}
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
setupAjv(self.ajv);
|
|
49
|
-
setupAjv(self.ajvNoDefaults);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
beforeValidate({ json, model, options, ctx }) {
|
|
53
|
-
ctx.jsonSchema = model.constructor.getJsonSchema();
|
|
54
|
-
|
|
55
|
-
// Objection model's have a `$beforeValidate` hook that is allowed to modify the schema.
|
|
56
|
-
// We need to clone the schema in case the function modifies it. We only do this in the
|
|
57
|
-
// rare case that the given model has implemented the hook.
|
|
58
|
-
if (model.$beforeValidate !== model.$objectionModelClass.prototype.$beforeValidate) {
|
|
59
|
-
ctx.jsonSchema = cloneDeep(ctx.jsonSchema);
|
|
60
|
-
const ret = model.$beforeValidate(ctx.jsonSchema, json, options);
|
|
61
|
-
|
|
62
|
-
if (ret !== undefined) {
|
|
63
|
-
ctx.jsonSchema = ret;
|
|
64
|
-
}
|
|
8
|
+
static init(self, conf) {
|
|
9
|
+
super.init(self, conf);
|
|
10
|
+
self.ajvOptions = Object.assign({}, conf.options, {
|
|
11
|
+
allErrors: true,
|
|
12
|
+
});
|
|
13
|
+
// Create a normal Ajv instance.
|
|
14
|
+
self.ajv = new Ajv(Object.assign({
|
|
15
|
+
useDefaults: true,
|
|
16
|
+
}, self.ajvOptions));
|
|
17
|
+
// Create an instance that doesn't set default values. We need this one
|
|
18
|
+
// to validate `patch` objects (objects that have a subset of properties).
|
|
19
|
+
self.ajvNoDefaults = new Ajv(Object.assign({}, self.ajvOptions, {
|
|
20
|
+
useDefaults: false,
|
|
21
|
+
}));
|
|
22
|
+
// Caches for the compiled validator functions: by the serialized schema,
|
|
23
|
+
// and by the schema object for the schemas of model classes.
|
|
24
|
+
self.cache = new Map();
|
|
25
|
+
self.schemaCache = new WeakMap();
|
|
26
|
+
const setupAjv = (ajv) => {
|
|
27
|
+
if (conf.onCreateAjv) {
|
|
28
|
+
conf.onCreateAjv(ajv);
|
|
29
|
+
}
|
|
30
|
+
// Only add Ajv formats if they weren't added in user-space already
|
|
31
|
+
if (!ajv.formats['date-time']) {
|
|
32
|
+
addFormats(ajv);
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
setupAjv(self.ajv);
|
|
36
|
+
setupAjv(self.ajvNoDefaults);
|
|
65
37
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
38
|
+
beforeValidate({ json, model, options, ctx }) {
|
|
39
|
+
ctx.jsonSchema = model.constructor.getJsonSchema();
|
|
40
|
+
// Objection model's have a `$beforeValidate` hook that is allowed to modify the schema.
|
|
41
|
+
// We need to clone the schema in case the function modifies it. We only do this in the
|
|
42
|
+
// rare case that the given model has implemented the hook.
|
|
43
|
+
if (model.$beforeValidate !== model.$objectionModelClass.prototype.$beforeValidate) {
|
|
44
|
+
ctx.jsonSchema = cloneDeep(ctx.jsonSchema);
|
|
45
|
+
const ret = model.$beforeValidate(ctx.jsonSchema, json, options);
|
|
46
|
+
if (ret !== undefined) {
|
|
47
|
+
ctx.jsonSchema = ret;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
71
50
|
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
51
|
+
validate({ json, model, options, ctx }) {
|
|
52
|
+
if (!ctx.jsonSchema) {
|
|
53
|
+
return json;
|
|
54
|
+
}
|
|
55
|
+
const modelClass = model.constructor;
|
|
56
|
+
const validator = this.getValidator(modelClass, ctx.jsonSchema, !!options.patch);
|
|
57
|
+
// We need to clone the input json if we are about to set default values.
|
|
58
|
+
if (!options.mutable && !options.patch && setsDefaultValues(ctx.jsonSchema)) {
|
|
59
|
+
json = cloneDeep(json);
|
|
60
|
+
}
|
|
61
|
+
validator.call(model, json);
|
|
62
|
+
const error = parseValidationError(validator.errors, modelClass, options, this.ajvOptions);
|
|
63
|
+
if (error) {
|
|
64
|
+
throw error;
|
|
65
|
+
}
|
|
66
|
+
return json;
|
|
79
67
|
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
68
|
+
getValidator(modelClass, jsonSchema, isPatchObject) {
|
|
69
|
+
// Use the Ajv custom serializer if provided.
|
|
70
|
+
const createCacheKey = this.ajvOptions.serialize || JSON.stringify;
|
|
71
|
+
// The compiled validators are cached by the serialized schema. In the
|
|
72
|
+
// common case where jsonSchema is the model class's own schema, they are
|
|
73
|
+
// also cached by the schema object, so the costly createCacheKey function
|
|
74
|
+
// runs once per schema object. Classes bound to a knex instance share their
|
|
75
|
+
// validator with the class they are bound from, and a bound class can have
|
|
76
|
+
// a schema of its own, so the cache isn't keyed by the class name.
|
|
77
|
+
const isClassSchema = jsonSchema === modelClass.getJsonSchema() && isObject(jsonSchema);
|
|
78
|
+
let validators = isClassSchema ? this.schemaCache.get(jsonSchema) : undefined;
|
|
79
|
+
let validator = null;
|
|
80
|
+
if (!validators) {
|
|
81
|
+
const cacheKey = createCacheKey(jsonSchema);
|
|
82
|
+
validators = this.cache.get(cacheKey);
|
|
83
|
+
if (!validators) {
|
|
84
|
+
validators = {
|
|
85
|
+
// Validator created for the schema object without `required` properties
|
|
86
|
+
// using the Ajv instance that doesn't set default values.
|
|
87
|
+
patchValidator: null,
|
|
88
|
+
// Validator created for the unmodified schema.
|
|
89
|
+
normalValidator: null,
|
|
90
|
+
};
|
|
91
|
+
this.cache.set(cacheKey, validators);
|
|
92
|
+
}
|
|
93
|
+
if (isClassSchema) {
|
|
94
|
+
this.schemaCache.set(jsonSchema, validators);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
if (isPatchObject) {
|
|
98
|
+
validator = validators.patchValidator;
|
|
99
|
+
if (!validator) {
|
|
100
|
+
validator = this.compilePatchValidator(jsonSchema);
|
|
101
|
+
validators.patchValidator = validator;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
validator = validators.normalValidator;
|
|
106
|
+
if (!validator) {
|
|
107
|
+
validator = this.compileNormalValidator(jsonSchema);
|
|
108
|
+
validators.normalValidator = validator;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return validator;
|
|
86
112
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
getValidator(modelClass, jsonSchema, isPatchObject) {
|
|
92
|
-
// Use the Ajv custom serializer if provided.
|
|
93
|
-
const createCacheKey = this.ajvOptions.serialize || JSON.stringify;
|
|
94
|
-
|
|
95
|
-
// Optimization for the common case where jsonSchema is never modified.
|
|
96
|
-
// In that case we don't need to call the costly createCacheKey function.
|
|
97
|
-
const cacheKey =
|
|
98
|
-
jsonSchema === modelClass.getJsonSchema()
|
|
99
|
-
? modelClass.uniqueTag()
|
|
100
|
-
: createCacheKey(jsonSchema);
|
|
101
|
-
|
|
102
|
-
let validators = this.cache.get(cacheKey);
|
|
103
|
-
let validator = null;
|
|
104
|
-
|
|
105
|
-
if (!validators) {
|
|
106
|
-
validators = {
|
|
107
|
-
// Validator created for the schema object without `required` properties
|
|
108
|
-
// using the Ajv instance that doesn't set default values.
|
|
109
|
-
patchValidator: null,
|
|
110
|
-
|
|
111
|
-
// Validator created for the unmodified schema.
|
|
112
|
-
normalValidator: null,
|
|
113
|
-
};
|
|
114
|
-
|
|
115
|
-
this.cache.set(cacheKey, validators);
|
|
113
|
+
compilePatchValidator(jsonSchema) {
|
|
114
|
+
jsonSchema = jsonSchemaWithoutRequired(jsonSchema);
|
|
115
|
+
// We need to use the ajv instance that doesn't set the default values.
|
|
116
|
+
return this.ajvNoDefaults.compile(jsonSchema);
|
|
116
117
|
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
validator = validators.patchValidator;
|
|
120
|
-
|
|
121
|
-
if (!validator) {
|
|
122
|
-
validator = this.compilePatchValidator(jsonSchema);
|
|
123
|
-
validators.patchValidator = validator;
|
|
124
|
-
}
|
|
125
|
-
} else {
|
|
126
|
-
validator = validators.normalValidator;
|
|
127
|
-
|
|
128
|
-
if (!validator) {
|
|
129
|
-
validator = this.compileNormalValidator(jsonSchema);
|
|
130
|
-
validators.normalValidator = validator;
|
|
131
|
-
}
|
|
118
|
+
compileNormalValidator(jsonSchema) {
|
|
119
|
+
return this.ajv.compile(jsonSchema);
|
|
132
120
|
}
|
|
133
|
-
|
|
134
|
-
return validator;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
compilePatchValidator(jsonSchema) {
|
|
138
|
-
jsonSchema = jsonSchemaWithoutRequired(jsonSchema);
|
|
139
|
-
// We need to use the ajv instance that doesn't set the default values.
|
|
140
|
-
return this.ajvNoDefaults.compile(jsonSchema);
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
compileNormalValidator(jsonSchema) {
|
|
144
|
-
return this.ajv.compile(jsonSchema);
|
|
145
|
-
}
|
|
146
121
|
}
|
|
147
|
-
|
|
148
122
|
function parseValidationError(errors, modelClass, options, ajvOptions) {
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
let relationNames = modelClass.getRelationNames();
|
|
154
|
-
let errorHash = {};
|
|
155
|
-
let numErrors = 0;
|
|
156
|
-
|
|
157
|
-
for (const error of errors) {
|
|
158
|
-
// If additionalProperties = false, relations can pop up as additionalProperty
|
|
159
|
-
// errors. Skip those.
|
|
160
|
-
if (
|
|
161
|
-
error.params &&
|
|
162
|
-
error.params.additionalProperty &&
|
|
163
|
-
relationNames.includes(error.params.additionalProperty)
|
|
164
|
-
) {
|
|
165
|
-
continue;
|
|
123
|
+
if (!errors) {
|
|
124
|
+
return null;
|
|
166
125
|
}
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
126
|
+
const relationNames = modelClass.getRelationNames();
|
|
127
|
+
const errorHash = {};
|
|
128
|
+
let numErrors = 0;
|
|
129
|
+
for (const error of errors) {
|
|
130
|
+
// If additionalProperties = false, relations can pop up as additionalProperty
|
|
131
|
+
// errors. Skip those.
|
|
132
|
+
if (error.params &&
|
|
133
|
+
error.params.additionalProperty &&
|
|
134
|
+
relationNames.includes(error.params.additionalProperty)) {
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
let path = error.instancePath.replace(/\//g, '.');
|
|
138
|
+
if (error.params) {
|
|
139
|
+
if (error.params.missingProperty) {
|
|
140
|
+
path += `.${error.params.missingProperty}`;
|
|
141
|
+
}
|
|
142
|
+
else if (error.params.additionalProperty) {
|
|
143
|
+
path += `.${error.params.additionalProperty}`;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
const key = `${options.dataPath || ''}${path}`.substring(1);
|
|
147
|
+
// More than one error can occur for the same key in Ajv, merge them in the array:
|
|
148
|
+
const array = errorHash[key] || (errorHash[key] = []);
|
|
149
|
+
// Prepare error object
|
|
150
|
+
const errorObj = {
|
|
151
|
+
message: error.message,
|
|
152
|
+
keyword: error.keyword,
|
|
153
|
+
params: error.params,
|
|
154
|
+
};
|
|
155
|
+
// Add data if verbose enabled
|
|
156
|
+
if (ajvOptions.verbose) {
|
|
157
|
+
errorObj.data = error.data;
|
|
158
|
+
}
|
|
159
|
+
// Use unshift instead of push so that the last error ends up at [0],
|
|
160
|
+
// preserving previous behavior where only the last error was stored.
|
|
161
|
+
array.unshift(errorObj);
|
|
162
|
+
++numErrors;
|
|
176
163
|
}
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
// More than one error can occur for the same key in Ajv, merge them in the array:
|
|
181
|
-
const array = errorHash[key] || (errorHash[key] = []);
|
|
182
|
-
|
|
183
|
-
// Prepare error object
|
|
184
|
-
const errorObj = {
|
|
185
|
-
message: error.message,
|
|
186
|
-
keyword: error.keyword,
|
|
187
|
-
params: error.params,
|
|
188
|
-
};
|
|
189
|
-
|
|
190
|
-
// Add data if verbose enabled
|
|
191
|
-
if (ajvOptions.verbose) {
|
|
192
|
-
errorObj.data = error.data;
|
|
164
|
+
if (numErrors === 0) {
|
|
165
|
+
return null;
|
|
193
166
|
}
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
++numErrors;
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
if (numErrors === 0) {
|
|
203
|
-
return null;
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
return modelClass.createValidationError({
|
|
207
|
-
type: ValidationErrorType.ModelValidation,
|
|
208
|
-
data: errorHash,
|
|
209
|
-
});
|
|
167
|
+
return modelClass.createValidationError({
|
|
168
|
+
type: ValidationErrorType.ModelValidation,
|
|
169
|
+
data: errorHash,
|
|
170
|
+
});
|
|
210
171
|
}
|
|
211
|
-
|
|
212
172
|
function cloneDeep(obj) {
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
173
|
+
if (isObject(obj) && obj.$isObjectionModel) {
|
|
174
|
+
return obj.$clone();
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
return cloneDeepValue(obj);
|
|
178
|
+
}
|
|
218
179
|
}
|
|
219
|
-
|
|
180
|
+
// Whether a schema has default values is checked for every validated model,
|
|
181
|
+
// so the answer is cached per schema object.
|
|
182
|
+
const setsDefaultValuesCache = new WeakMap();
|
|
220
183
|
function setsDefaultValues(jsonSchema) {
|
|
221
|
-
|
|
184
|
+
if (!isObject(jsonSchema)) {
|
|
185
|
+
return jsonSchema && jsonSchema.properties && hasDefaults(jsonSchema.properties);
|
|
186
|
+
}
|
|
187
|
+
let result = setsDefaultValuesCache.get(jsonSchema);
|
|
188
|
+
if (result === undefined) {
|
|
189
|
+
result = !!(jsonSchema.properties && hasDefaults(jsonSchema.properties));
|
|
190
|
+
setsDefaultValuesCache.set(jsonSchema, result);
|
|
191
|
+
}
|
|
192
|
+
return result;
|
|
222
193
|
}
|
|
223
|
-
|
|
224
194
|
function hasDefaults(obj) {
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
195
|
+
if (Array.isArray(obj)) {
|
|
196
|
+
return arrayHasDefaults(obj);
|
|
197
|
+
}
|
|
198
|
+
else {
|
|
199
|
+
return objectHasDefaults(obj);
|
|
200
|
+
}
|
|
230
201
|
}
|
|
231
|
-
|
|
232
202
|
function arrayHasDefaults(arr) {
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
203
|
+
for (let i = 0, l = arr.length; i < l; ++i) {
|
|
204
|
+
const val = arr[i];
|
|
205
|
+
if (isObject(val) && hasDefaults(val)) {
|
|
206
|
+
return true;
|
|
207
|
+
}
|
|
238
208
|
}
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
return false;
|
|
209
|
+
return false;
|
|
242
210
|
}
|
|
243
|
-
|
|
244
211
|
function objectHasDefaults(obj) {
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
}
|
|
212
|
+
const keys = Object.keys(obj);
|
|
213
|
+
for (let i = 0, l = keys.length; i < l; ++i) {
|
|
214
|
+
const key = keys[i];
|
|
215
|
+
if (key === 'default') {
|
|
216
|
+
return true;
|
|
217
|
+
}
|
|
218
|
+
else {
|
|
219
|
+
const val = obj[key];
|
|
220
|
+
if (isObject(val) && hasDefaults(val)) {
|
|
221
|
+
return true;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
258
224
|
}
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
return false;
|
|
225
|
+
return false;
|
|
262
226
|
}
|
|
263
|
-
|
|
264
227
|
function jsonSchemaWithoutRequired(jsonSchema) {
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
definitions: Object.assign(
|
|
272
|
-
...Object.keys(jsonSchema.definitions).map((prop) => ({
|
|
273
|
-
[prop]: jsonSchemaWithoutRequired(jsonSchema.definitions[prop]),
|
|
274
|
-
})),
|
|
275
|
-
),
|
|
228
|
+
const subSchemaProps = ['anyOf', 'oneOf', 'allOf', 'not', 'then', 'else', 'properties'];
|
|
229
|
+
return Object.assign(omit(jsonSchema, ['required', ...subSchemaProps]), ...subSchemaProps.map((prop) => subSchemaWithoutRequired(jsonSchema, prop)), jsonSchema && jsonSchema.definitions && Object.keys(jsonSchema.definitions).length > 0
|
|
230
|
+
? {
|
|
231
|
+
definitions: Object.assign(...Object.keys(jsonSchema.definitions).map((prop) => ({
|
|
232
|
+
[prop]: jsonSchemaWithoutRequired(jsonSchema.definitions[prop]),
|
|
233
|
+
}))),
|
|
276
234
|
}
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
: {},
|
|
281
|
-
);
|
|
235
|
+
: {}, jsonSchema.discriminator && jsonSchema.discriminator.propertyName
|
|
236
|
+
? { required: [jsonSchema.discriminator.propertyName] }
|
|
237
|
+
: {});
|
|
282
238
|
}
|
|
283
|
-
|
|
284
239
|
function subSchemaWithoutRequired(jsonSchema, prop) {
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
240
|
+
if (jsonSchema[prop]) {
|
|
241
|
+
if (Array.isArray(jsonSchema[prop])) {
|
|
242
|
+
const schemaArray = jsonSchemaArrayWithoutRequired(jsonSchema[prop]);
|
|
243
|
+
if (schemaArray.length !== 0) {
|
|
244
|
+
return {
|
|
245
|
+
[prop]: schemaArray,
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
else {
|
|
249
|
+
return {};
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
else if (jsonSchema.type === 'object' && prop === 'properties') {
|
|
253
|
+
return {
|
|
254
|
+
[prop]: Object.fromEntries(Object.entries(jsonSchema[prop]).map(([key, schema]) => [
|
|
255
|
+
key,
|
|
256
|
+
jsonSchemaWithoutRequired(schema),
|
|
257
|
+
])),
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
else {
|
|
261
|
+
return {
|
|
262
|
+
[prop]: jsonSchemaWithoutRequired(jsonSchema[prop]),
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
else {
|
|
294
267
|
return {};
|
|
295
|
-
}
|
|
296
|
-
} else if (jsonSchema.type === 'object' && prop === 'properties') {
|
|
297
|
-
return {
|
|
298
|
-
[prop]: Object.fromEntries(
|
|
299
|
-
Object.entries(jsonSchema[prop]).map(([key, schema]) => [
|
|
300
|
-
key,
|
|
301
|
-
jsonSchemaWithoutRequired(schema),
|
|
302
|
-
]),
|
|
303
|
-
),
|
|
304
|
-
};
|
|
305
|
-
} else {
|
|
306
|
-
return {
|
|
307
|
-
[prop]: jsonSchemaWithoutRequired(jsonSchema[prop]),
|
|
308
|
-
};
|
|
309
268
|
}
|
|
310
|
-
} else {
|
|
311
|
-
return {};
|
|
312
|
-
}
|
|
313
269
|
}
|
|
314
|
-
|
|
315
270
|
function jsonSchemaArrayWithoutRequired(jsonSchemaArray) {
|
|
316
|
-
|
|
271
|
+
return jsonSchemaArray.map(jsonSchemaWithoutRequired).filter(isNotEmptyObject);
|
|
317
272
|
}
|
|
318
|
-
|
|
319
273
|
function isNotEmptyObject(obj) {
|
|
320
|
-
|
|
274
|
+
return Object.keys(obj).length !== 0;
|
|
321
275
|
}
|
|
322
|
-
|
|
323
276
|
module.exports = {
|
|
324
|
-
|
|
277
|
+
AjvValidator,
|
|
325
278
|
};
|