@lionweb/validation 0.7.0-beta.7 → 0.7.0-beta.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/runners/Utils.js +2 -2
- package/dist/runners/Utils.js.map +1 -1
- package/dist/validators/LionWebChunkDefinitions.d.ts +4 -4
- package/dist/validators/LionWebChunkDefinitions.d.ts.map +1 -1
- package/dist/validators/LionWebChunkDefinitions.js +80 -90
- package/dist/validators/LionWebChunkDefinitions.js.map +1 -1
- package/dist/validators/LionWebSyntaxValidator.js +2 -2
- package/dist/validators/LionWebValidator.js +1 -1
- package/dist/validators/LionWebValidator.js.map +1 -1
- package/dist/validators/ValidationFunctions.d.ts +1 -1
- package/dist/validators/ValidationFunctions.d.ts.map +1 -1
- package/dist/validators/ValidationFunctions.js +4 -4
- package/dist/validators/ValidationFunctions.js.map +1 -1
- package/dist/validators/generic/SyntaxValidator.d.ts +21 -7
- package/dist/validators/generic/SyntaxValidator.d.ts.map +1 -1
- package/dist/validators/generic/SyntaxValidator.js +78 -34
- package/dist/validators/generic/SyntaxValidator.js.map +1 -1
- package/dist/validators/generic/index.d.ts +1 -1
- package/dist/validators/generic/index.d.ts.map +1 -1
- package/dist/validators/generic/index.js +1 -1
- package/dist/validators/generic/index.js.map +1 -1
- package/dist/validators/generic/schema/DefinitionSchema.d.ts +26 -0
- package/dist/validators/generic/schema/DefinitionSchema.d.ts.map +1 -0
- package/dist/validators/generic/schema/DefinitionSchema.js +75 -0
- package/dist/validators/generic/schema/DefinitionSchema.js.map +1 -0
- package/dist/validators/generic/{ValidationTypes.d.ts → schema/ValidationTypes.d.ts} +45 -12
- package/dist/validators/generic/schema/ValidationTypes.d.ts.map +1 -0
- package/dist/validators/generic/{ValidationTypes.js → schema/ValidationTypes.js} +18 -21
- package/dist/validators/generic/schema/ValidationTypes.js.map +1 -0
- package/dist/validators/generic/schema/index.d.ts +3 -0
- package/dist/validators/generic/schema/index.d.ts.map +1 -0
- package/dist/validators/generic/schema/index.js +3 -0
- package/dist/validators/generic/schema/index.js.map +1 -0
- package/package.json +4 -4
- package/src/runners/Utils.ts +2 -2
- package/src/validators/LionWebChunkDefinitions.ts +80 -90
- package/src/validators/LionWebSyntaxValidator.ts +2 -2
- package/src/validators/LionWebValidator.ts +1 -1
- package/src/validators/ValidationFunctions.ts +5 -5
- package/src/validators/generic/SyntaxValidator.ts +134 -87
- package/src/validators/generic/index.ts +1 -1
- package/src/validators/generic/schema/DefinitionSchema.ts +84 -0
- package/src/validators/generic/{ValidationTypes.ts → schema/ValidationTypes.ts} +65 -35
- package/src/validators/generic/schema/index.ts +2 -0
- package/dist/validators/generic/ValidationTypes.d.ts.map +0 -1
- package/dist/validators/generic/ValidationTypes.js.map +0 -1
|
@@ -1,112 +1,102 @@
|
|
|
1
|
-
import { MAY_BE_NULL,
|
|
1
|
+
import { DefinitionSchema, MAY_BE_NULL, PropertyDef, PrimitiveDef } from "./generic/index.js"
|
|
2
2
|
import { validateId, validateKey, validateSerializationFormatVersion, validateVersion } from "./ValidationFunctions.js"
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* The structure below defines the structure of a LionWeb Chunk by defining all the properties.
|
|
6
6
|
* It can
|
|
7
|
-
* - be
|
|
8
|
-
* - used to generate all the types for a LionWebChunk.
|
|
7
|
+
* - be used by the SyntaxValidator to validate an object sat runtime.
|
|
8
|
+
* - used to generate all the TypeScript types for a LionWebChunk.
|
|
9
9
|
*/
|
|
10
|
-
export const
|
|
11
|
-
|
|
12
|
-
"
|
|
13
|
-
[
|
|
14
|
-
PropertyDef({
|
|
15
|
-
PropertyDef({
|
|
16
|
-
PropertyDef({
|
|
10
|
+
export const LionWebSchema: DefinitionSchema = new DefinitionSchema([], [
|
|
11
|
+
{
|
|
12
|
+
name: "LionWebJsonMetaPointer",
|
|
13
|
+
properties: [
|
|
14
|
+
PropertyDef({ name: "key", type: "LionWebKey" }),
|
|
15
|
+
PropertyDef({ name: "version", type: "LionWebVersion" }),
|
|
16
|
+
PropertyDef({ name: "language", type: "LionWebKey" })
|
|
17
17
|
]
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
"
|
|
21
|
-
[
|
|
22
|
-
PropertyDef({
|
|
23
|
-
PropertyDef({
|
|
24
|
-
PropertyDef({
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
name: "LionWebJsonMetaPointer",
|
|
21
|
+
properties: [
|
|
22
|
+
PropertyDef({ name: "key", type: "LionWebKey" }),
|
|
23
|
+
PropertyDef({ name: "version", type: "LionWebVersion" }),
|
|
24
|
+
PropertyDef({ name: "language", type: "LionWebKey" }),
|
|
25
25
|
]
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
"
|
|
29
|
-
[
|
|
30
|
-
PropertyDef({
|
|
31
|
-
PropertyDef({
|
|
32
|
-
PropertyDef({
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
name: "ResponseMessage",
|
|
29
|
+
properties: [
|
|
30
|
+
PropertyDef({ name: "kind", type: "JSstring" }),
|
|
31
|
+
PropertyDef({ name: "message", type: "JSstring" }),
|
|
32
|
+
PropertyDef({ name: "data", type: "JSobject", mayBeNull: true, isOptional: true })
|
|
33
33
|
]
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
"
|
|
37
|
-
[
|
|
38
|
-
PropertyDef({
|
|
39
|
-
PropertyDef({
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
name: "LionWebJsonChunk",
|
|
37
|
+
properties: [
|
|
38
|
+
PropertyDef({ name: "serializationFormatVersion", type: "LionWebSerializationFormatVersion" }),
|
|
39
|
+
PropertyDef({ name: "languages", type: "LionWebJsonUsedLanguage", isList: true }),
|
|
40
|
+
PropertyDef({ name: "nodes", type: "LionWebJsonNode", isList: true })
|
|
40
41
|
]
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
"
|
|
44
|
-
[
|
|
45
|
-
PropertyDef({
|
|
46
|
-
PropertyDef({
|
|
47
|
-
PropertyDef({ property: "properties", expectedType: "LionWebProperty", isList: true }),
|
|
48
|
-
PropertyDef({ property: "containments", expectedType: "LionWebContainment", isList: true }),
|
|
49
|
-
PropertyDef({ property: "references", expectedType: "LionWebReference", isList: true }),
|
|
50
|
-
PropertyDef({ property: "annotations", expectedType: "LionWebId", isList: true }),
|
|
51
|
-
PropertyDef({ property: "parent", expectedType: "LionWebId", mayBeNull: MAY_BE_NULL }),
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
name: "LionWebJsonUsedLanguage",
|
|
45
|
+
properties: [
|
|
46
|
+
PropertyDef({ name: "key", type: "LionWebKey" }),
|
|
47
|
+
PropertyDef({ name: "version", type: "LionWebVersion" })
|
|
52
48
|
]
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
"
|
|
56
|
-
[
|
|
57
|
-
PropertyDef({
|
|
58
|
-
PropertyDef({
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
name: "LionWebJsonNode",
|
|
52
|
+
properties: [
|
|
53
|
+
PropertyDef({ name: "id", type: "LionWebId" }),
|
|
54
|
+
PropertyDef({ name: "classifier", type: "LionWebJsonMetaPointer" }),
|
|
55
|
+
PropertyDef({ name: "properties", type: "LionWebJsonProperty", isList: true }),
|
|
56
|
+
PropertyDef({ name: "containments", type: "LionWebJsonContainment", isList: true }),
|
|
57
|
+
PropertyDef({ name: "references", type: "LionWebJsonReference", isList: true }),
|
|
58
|
+
PropertyDef({ name: "annotations", type: "LionWebId", isList: true }),
|
|
59
|
+
PropertyDef({ name: "parent", type: "LionWebId", mayBeNull: MAY_BE_NULL }),
|
|
59
60
|
]
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
"
|
|
63
|
-
[
|
|
64
|
-
PropertyDef({
|
|
65
|
-
PropertyDef({
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
name: "LionWebJsonProperty",
|
|
64
|
+
properties: [
|
|
65
|
+
PropertyDef({ name: "property", type: "LionWebJsonMetaPointer" }),
|
|
66
|
+
PropertyDef({ name: "value", type: "JSstring", mayBeNull: MAY_BE_NULL }),
|
|
66
67
|
]
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
"
|
|
70
|
-
[
|
|
71
|
-
PropertyDef({
|
|
72
|
-
PropertyDef({
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
name: "LionWebJsonContainment",
|
|
71
|
+
properties: [
|
|
72
|
+
PropertyDef({ name: "containment", type: "LionWebJsonMetaPointer" }),
|
|
73
|
+
PropertyDef({ name: "children", type: "LionWebId", isList: true }),
|
|
73
74
|
]
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
"
|
|
77
|
-
[
|
|
78
|
-
PropertyDef({
|
|
79
|
-
PropertyDef({
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
name: "LionWebJsonReference",
|
|
78
|
+
properties: [
|
|
79
|
+
PropertyDef({ name: "reference", type: "LionWebJsonMetaPointer"}),
|
|
80
|
+
PropertyDef({ name: "targets", type: "LionWebJsonReferenceTarget", isList: true}),
|
|
80
81
|
]
|
|
81
|
-
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
name: "LionWebJsonReferenceTarget",
|
|
85
|
+
properties: [
|
|
86
|
+
PropertyDef({ name: "resolveInfo", type: "JSstring", mayBeNull: MAY_BE_NULL }),
|
|
87
|
+
PropertyDef({ name: "reference", type: "LionWebId", mayBeNull: MAY_BE_NULL }),
|
|
88
|
+
]
|
|
89
|
+
},
|
|
82
90
|
/**
|
|
83
91
|
* Elements without properties are assumed to be JSON/JS primitive values, and tested using `typeof`
|
|
84
92
|
* and the (optional) validate function.
|
|
85
93
|
*/
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
PrimitiveDef({ primitiveType: "string", validate: validateKey }),
|
|
93
|
-
],
|
|
94
|
-
[
|
|
95
|
-
"LionWebVersion",
|
|
96
|
-
PrimitiveDef({ primitiveType: "string", validate: validateVersion }),
|
|
97
|
-
],
|
|
98
|
-
[
|
|
99
|
-
"LionWebSerializationFormatVersion",
|
|
100
|
-
PrimitiveDef({ primitiveType: "string", validate: validateSerializationFormatVersion }),
|
|
101
|
-
],
|
|
102
|
-
[
|
|
103
|
-
"string",
|
|
104
|
-
PrimitiveDef({ primitiveType: "string" }),
|
|
105
|
-
],
|
|
106
|
-
[
|
|
107
|
-
"object",
|
|
108
|
-
PrimitiveDef({ primitiveType: "object" }),
|
|
109
|
-
]
|
|
94
|
+
PrimitiveDef({ name: "LionWebId", primitiveType: "string", validate: validateId }),
|
|
95
|
+
PrimitiveDef({ name: "LionWebKey", primitiveType: "string", validate: validateKey }),
|
|
96
|
+
PrimitiveDef({ name: "LionWebVersion",primitiveType: "string", validate: validateVersion }),
|
|
97
|
+
PrimitiveDef({ name: "LionWebSerializationFormatVersion",primitiveType: "string", validate: validateSerializationFormatVersion }),
|
|
98
|
+
PrimitiveDef({ name: "JSstring", primitiveType: "string" }),
|
|
99
|
+
PrimitiveDef({ name: "JSobject",primitiveType: "object" }),
|
|
110
100
|
])
|
|
111
101
|
|
|
112
102
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { SyntaxValidator } from "./generic/SyntaxValidator.js"
|
|
2
2
|
import { ValidationResult } from "./generic/ValidationResult.js"
|
|
3
|
-
import {
|
|
3
|
+
import { LionWebSchema } from "./LionWebChunkDefinitions.js"
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* LionWebSyntaxValidator can check whether objects are structurally LionWeb objects.
|
|
@@ -8,7 +8,7 @@ import { expectedTypes } from "./LionWebChunkDefinitions.js"
|
|
|
8
8
|
export class LionWebSyntaxValidator extends SyntaxValidator {
|
|
9
9
|
|
|
10
10
|
constructor(validationResult: ValidationResult) {
|
|
11
|
-
super(validationResult,
|
|
11
|
+
super(validationResult, LionWebSchema)
|
|
12
12
|
}
|
|
13
13
|
}
|
|
14
14
|
|
|
@@ -34,7 +34,7 @@ export class LionWebValidator {
|
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
validateSyntax() {
|
|
37
|
-
this.syntaxValidator.validate(this.object, "
|
|
37
|
+
this.syntaxValidator.validate(this.object, "LionWebJsonChunk")
|
|
38
38
|
this.syntaxCorrect = !this.validationResult.hasErrors()
|
|
39
39
|
if (this.syntaxCorrect) {
|
|
40
40
|
this.chunk = new LionWebJsonChunkWrapper(this.object as LionWebJsonChunk)
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
Syntax_VersionFormat_Issue
|
|
13
13
|
} from "../issues/SyntaxIssues.js"
|
|
14
14
|
import { ValidationResult } from "./generic/ValidationResult.js"
|
|
15
|
-
import { PropertyDefinition } from "./generic/ValidationTypes.js"
|
|
15
|
+
import { PropertyDefinition } from "./generic/schema/ValidationTypes.js"
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
18
|
* Check whether `id` is a valid LionWeb id.
|
|
@@ -72,7 +72,7 @@ export function validateBoolean<String>(value: String, result: ValidationResult,
|
|
|
72
72
|
result.issue(
|
|
73
73
|
new Language_PropertyValue_Issue(
|
|
74
74
|
context,
|
|
75
|
-
propDef ? propDef.
|
|
75
|
+
propDef ? propDef.name : "unknown",
|
|
76
76
|
valueAsPrimitive,
|
|
77
77
|
"boolean " + JSON.stringify(value)
|
|
78
78
|
)
|
|
@@ -92,7 +92,7 @@ export function validateInteger<String>(value: String, result: ValidationResult,
|
|
|
92
92
|
const valueAsPrimitive = "" + value
|
|
93
93
|
const regexp = /^[+-]?(0|[1-9][0-9]*)$/
|
|
94
94
|
if (valueAsPrimitive === null || !regexp.test(valueAsPrimitive)) {
|
|
95
|
-
result.issue(new Language_PropertyValue_Issue(context, propDef ? propDef.
|
|
95
|
+
result.issue(new Language_PropertyValue_Issue(context, propDef ? propDef.name : "unknown", valueAsPrimitive, "integer"))
|
|
96
96
|
}
|
|
97
97
|
}
|
|
98
98
|
|
|
@@ -107,12 +107,12 @@ export function validateInteger<String>(value: String, result: ValidationResult,
|
|
|
107
107
|
export function validateJSON<String>(value: String, result: ValidationResult, context: JsonContext, propDef?: PropertyDefinition): void {
|
|
108
108
|
const valueAsPrimitive = "" + value
|
|
109
109
|
if (value === null) {
|
|
110
|
-
result.issue(new Syntax_PropertyNullIssue(context, propDef!.
|
|
110
|
+
result.issue(new Syntax_PropertyNullIssue(context, propDef!.name!))
|
|
111
111
|
}
|
|
112
112
|
try {
|
|
113
113
|
JSON.parse(valueAsPrimitive)
|
|
114
114
|
} catch (e) {
|
|
115
|
-
result.issue(new Language_PropertyValue_Issue(context, propDef ? propDef.
|
|
115
|
+
result.issue(new Language_PropertyValue_Issue(context, propDef ? propDef.name : "unknown", valueAsPrimitive, "JSON"))
|
|
116
116
|
}
|
|
117
117
|
}
|
|
118
118
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { JsonContext } from "@lionweb/json-utils"
|
|
2
2
|
import {
|
|
3
|
+
GenericIssue,
|
|
3
4
|
Syntax_ArrayContainsNull_Issue,
|
|
4
5
|
Syntax_PropertyMissingIssue,
|
|
5
6
|
Syntax_PropertyNullIssue,
|
|
@@ -9,40 +10,38 @@ import {
|
|
|
9
10
|
import { ValidationResult } from "./ValidationResult.js"
|
|
10
11
|
import {
|
|
11
12
|
isObjectDefinition,
|
|
12
|
-
isPrimitiveDefinition,
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
TypeDefinition,
|
|
16
|
-
UnknownObjectType
|
|
17
|
-
} from "./ValidationTypes.js"
|
|
13
|
+
isPrimitiveDefinition, ObjectDefinition, PrimitiveDefinition, DefinitionSchema,
|
|
14
|
+
UnknownObjectType, PropertyDefinition
|
|
15
|
+
} from "./schema/index.js"
|
|
18
16
|
|
|
19
17
|
/**
|
|
20
|
-
* Syntax Validator
|
|
21
|
-
* definitions given in `
|
|
18
|
+
* Syntax Validator checks whether objects are structurally conforming to the
|
|
19
|
+
* definitions given in `schema`.
|
|
22
20
|
*/
|
|
23
21
|
export class SyntaxValidator {
|
|
24
22
|
validationResult: ValidationResult
|
|
25
|
-
|
|
23
|
+
schema: DefinitionSchema
|
|
26
24
|
|
|
27
|
-
constructor(validationResult: ValidationResult,
|
|
25
|
+
constructor(validationResult: ValidationResult, schema: DefinitionSchema) {
|
|
28
26
|
this.validationResult = validationResult
|
|
29
|
-
this.
|
|
27
|
+
this.schema = schema
|
|
30
28
|
}
|
|
31
29
|
|
|
32
30
|
/**
|
|
33
31
|
* Check whether `obj` is a JSON object that conforms to the definition of `expectedType`.
|
|
34
|
-
* All errors found will be
|
|
32
|
+
* All errors found will be added to the `validationResult` object.
|
|
35
33
|
* @param obj The object to validate.
|
|
36
34
|
* @param expectedType The expected type of the object.
|
|
37
35
|
*/
|
|
38
36
|
validate(obj: unknown, expectedType: string) {
|
|
39
37
|
const object = obj as UnknownObjectType
|
|
40
|
-
const typeDef = this.
|
|
38
|
+
const typeDef = this.schema.getDefinition(expectedType)
|
|
39
|
+
|
|
41
40
|
if (typeDef === undefined) {
|
|
42
41
|
throw new Error(`SyntaxValidator.validate: cannot find definition for ${expectedType}`)
|
|
43
|
-
} else if (isObjectDefinition(typeDef)){
|
|
42
|
+
} else if (isObjectDefinition(typeDef)) {
|
|
44
43
|
this.validateObjectProperties(expectedType, typeDef, object, new JsonContext(null, ["$"]))
|
|
45
|
-
} else if(
|
|
44
|
+
} else if (isPrimitiveDefinition(typeDef)) {
|
|
46
45
|
this.validatePrimitiveValue("$", typeDef, object, new JsonContext(null, ["$"]))
|
|
47
46
|
}
|
|
48
47
|
}
|
|
@@ -50,7 +49,7 @@ export class SyntaxValidator {
|
|
|
50
49
|
/**
|
|
51
50
|
* Validate whether `object` is structured conform the properties in `propertyDef`
|
|
52
51
|
* @param originalProperty The property of which `object` it the value
|
|
53
|
-
* @param typeDef
|
|
52
|
+
* @param typeDef The property definitions that are being validated
|
|
54
53
|
* @param object The object being validated
|
|
55
54
|
* @param jsonContext The location in the JSON
|
|
56
55
|
* @private
|
|
@@ -59,99 +58,147 @@ export class SyntaxValidator {
|
|
|
59
58
|
if (typeDef === null || typeDef === undefined) {
|
|
60
59
|
return
|
|
61
60
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
61
|
+
if (typeof object !== "object") {
|
|
62
|
+
this.validationResult.issue(new Syntax_PropertyTypeIssue(jsonContext, originalProperty, "object", typeof object))
|
|
63
|
+
return
|
|
64
|
+
}
|
|
65
|
+
for (const propertyDef of typeDef.properties) {
|
|
66
|
+
const taggedUnion = this.schema.getTaggedUnionDefinition(propertyDef.type)
|
|
67
|
+
if (taggedUnion !== undefined) {
|
|
68
|
+
this.validateTaggedUnion(propertyDef, typeDef, object, jsonContext.concat(propertyDef.name))
|
|
69
|
+
continue
|
|
65
70
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
if (
|
|
71
|
-
|
|
72
|
-
this.validationResult.issue(new Syntax_PropertyMissingIssue(jsonContext, propertyDef.property))
|
|
73
|
-
}
|
|
74
|
-
continue
|
|
71
|
+
const expectedTypeDef = this.schema.getDefinition(propertyDef.type)
|
|
72
|
+
const validator = propertyDef.validate!
|
|
73
|
+
const propertyValue = object[propertyDef.name]
|
|
74
|
+
if (propertyValue === undefined) {
|
|
75
|
+
if (!propertyDef.isOptional) {
|
|
76
|
+
this.validationResult.issue(new Syntax_PropertyMissingIssue(jsonContext, propertyDef.name))
|
|
75
77
|
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
78
|
+
continue
|
|
79
|
+
}
|
|
80
|
+
if (!propertyDef.mayBeNull && propertyValue === null) {
|
|
81
|
+
this.validationResult.issue(new Syntax_PropertyNullIssue(jsonContext, propertyDef.name))
|
|
82
|
+
continue
|
|
83
|
+
}
|
|
84
|
+
if (propertyDef.mayBeNull && propertyValue === null) {
|
|
85
|
+
// Ok, stop checking, continue with next property def
|
|
86
|
+
continue
|
|
87
|
+
}
|
|
88
|
+
if (propertyDef.isList) {
|
|
89
|
+
// Check whether value is an array
|
|
90
|
+
if (!Array.isArray(propertyValue)) {
|
|
91
|
+
const newContext = jsonContext.concat(propertyDef.name)
|
|
92
|
+
this.validationResult.issue(new Syntax_PropertyTypeIssue(newContext, propertyDef.name, "array", typeof propertyValue))
|
|
93
|
+
return
|
|
83
94
|
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
this.validationResult.issue(new
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
const newContext = jsonContext.concat(propertyDef.property, index)
|
|
94
|
-
if (item === null) {
|
|
95
|
-
this.validationResult.issue(new Syntax_ArrayContainsNull_Issue(newContext, propertyDef.property, index))
|
|
96
|
-
} else {
|
|
97
|
-
if (expectedTypeDef !== undefined) {
|
|
98
|
-
if (isPrimitiveDefinition(expectedTypeDef)) {
|
|
99
|
-
// propertyValue should be a primitive as it has no property definitions
|
|
100
|
-
if (this.validatePrimitiveValue(propertyDef.property, expectedTypeDef, item, jsonContext)) {
|
|
101
|
-
validator.apply(null, [item, this.validationResult, newContext, propertyDef])
|
|
102
|
-
}
|
|
103
|
-
} else {
|
|
104
|
-
// propertyValue should be an object, validate its properties
|
|
105
|
-
this.validateObjectProperties(propertyDef.property, expectedTypeDef, item as UnknownObjectType, newContext)
|
|
95
|
+
// If an array, validate every item in the array
|
|
96
|
+
(propertyValue as UnknownObjectType[]).forEach((item, index) => {
|
|
97
|
+
const newContext = jsonContext.concat(propertyDef.name, index)
|
|
98
|
+
if (item === null) {
|
|
99
|
+
this.validationResult.issue(new Syntax_ArrayContainsNull_Issue(newContext, propertyDef.name, index))
|
|
100
|
+
} else {
|
|
101
|
+
if (expectedTypeDef !== undefined) {
|
|
102
|
+
if (isPrimitiveDefinition(expectedTypeDef)) {
|
|
103
|
+
if (this.validatePrimitiveValue(propertyDef.name, expectedTypeDef, item, jsonContext)) {
|
|
106
104
|
validator.apply(null, [item, this.validationResult, newContext, propertyDef])
|
|
107
105
|
}
|
|
108
106
|
} else {
|
|
109
|
-
|
|
107
|
+
// propertyValue should be an object, validate its properties
|
|
108
|
+
this.validateObjectProperties(propertyDef.name, expectedTypeDef, item as UnknownObjectType, newContext)
|
|
109
|
+
validator.apply(null, [item, this.validationResult, newContext, propertyDef])
|
|
110
110
|
}
|
|
111
|
+
} else {
|
|
112
|
+
throw new Error(`Expected type '${propertyDef.type} has neither property defs, nor a validator.`)
|
|
111
113
|
}
|
|
112
|
-
})
|
|
113
|
-
} else {
|
|
114
|
-
const newContext = jsonContext.concat(propertyDef.property)
|
|
115
|
-
if (Array.isArray(propertyValue)) {
|
|
116
|
-
this.validationResult.issue(new Syntax_PropertyTypeIssue(newContext, propertyDef.property, propertyDef.expectedType, "array"))
|
|
117
|
-
return
|
|
118
114
|
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
115
|
+
})
|
|
116
|
+
} else {
|
|
117
|
+
const newContext = jsonContext.concat(propertyDef.name)
|
|
118
|
+
if (Array.isArray(propertyValue)) {
|
|
119
|
+
this.validationResult.issue(new Syntax_PropertyTypeIssue(newContext, propertyDef.name, propertyDef.type, "array"))
|
|
120
|
+
return
|
|
121
|
+
}
|
|
122
|
+
// Single valued property, validate it
|
|
123
|
+
if (expectedTypeDef !== undefined) {
|
|
124
|
+
if (isPrimitiveDefinition(expectedTypeDef)) {
|
|
125
|
+
// propertyValue should be a primitive as it has no property definitions
|
|
126
|
+
if (this.validatePrimitiveValue(propertyDef.name, expectedTypeDef, propertyValue, jsonContext)) {
|
|
129
127
|
validator.apply(null, [propertyValue, this.validationResult, newContext, propertyDef])
|
|
130
|
-
} else {
|
|
131
|
-
throw new Error("EXPECTING ObjectDefinition or PrimitiveDefinition, but got something else")
|
|
132
128
|
}
|
|
129
|
+
} else if (isObjectDefinition(expectedTypeDef)) {
|
|
130
|
+
// propertyValue should be an object, validate its properties
|
|
131
|
+
this.validateObjectProperties(propertyDef.name, expectedTypeDef, propertyValue as UnknownObjectType, newContext)
|
|
132
|
+
validator.apply(null, [propertyValue, this.validationResult, newContext, propertyDef])
|
|
133
133
|
} else {
|
|
134
|
-
throw new Error(
|
|
134
|
+
throw new Error("EXPECTING ObjectDefinition or PrimitiveDefinition, but got something else")
|
|
135
135
|
}
|
|
136
|
+
} else {
|
|
137
|
+
throw new Error(
|
|
138
|
+
`Expected single type '${propertyDef.type}' for '${propertyDef.name}' at ${newContext.toString()} has neither property defs, nor a validator.`
|
|
139
|
+
)
|
|
136
140
|
}
|
|
137
141
|
}
|
|
138
|
-
|
|
142
|
+
}
|
|
143
|
+
this.checkStrayProperties(object, typeDef, jsonContext)
|
|
139
144
|
}
|
|
140
|
-
|
|
141
|
-
validatePrimitiveValue(propertyName: string, propDef: PrimitiveDefinition, object: unknown, jsonContext: JsonContext): boolean {
|
|
142
|
-
// if (!propDef.mayBeNull && (object === null || object === undefined)) {
|
|
143
|
-
// this.validationResult.issue(new Syntax_PropertyNullIssue(jsonContext, propDef.property))
|
|
144
|
-
// return false
|
|
145
|
-
// }
|
|
146
145
|
|
|
146
|
+
validatePrimitiveValue(propertyName: string, propDef: PrimitiveDefinition, object: unknown, jsonContext: JsonContext): boolean {
|
|
147
147
|
if (typeof object !== propDef.primitiveType) {
|
|
148
|
-
this.validationResult.issue(new Syntax_PropertyTypeIssue(jsonContext, propertyName, propDef.primitiveType,typeof object))
|
|
148
|
+
this.validationResult.issue(new Syntax_PropertyTypeIssue(jsonContext, propertyName, propDef.primitiveType, typeof object))
|
|
149
149
|
return false
|
|
150
150
|
}
|
|
151
151
|
propDef.validate!(object, this.validationResult, jsonContext)
|
|
152
152
|
return true
|
|
153
153
|
}
|
|
154
154
|
|
|
155
|
+
/**
|
|
156
|
+
*
|
|
157
|
+
* @param propertyDef the definition of the property that has the TaggedUnionType as its type
|
|
158
|
+
* @param typeDef The object definition containing the `propertyDef`
|
|
159
|
+
* @param object The object of type `typeDef` that should have the property described by `propertyDef`
|
|
160
|
+
* @param jsonContext
|
|
161
|
+
*/
|
|
162
|
+
validateTaggedUnion(
|
|
163
|
+
propertyDef: PropertyDefinition,
|
|
164
|
+
typeDef: ObjectDefinition,
|
|
165
|
+
object: UnknownObjectType,
|
|
166
|
+
jsonContext: JsonContext
|
|
167
|
+
): void {
|
|
168
|
+
// console.log(`validateTaggedUnion ${JSON.stringify(propertyDef)}, typedef ${typeDef.name} object: ${JSON.stringify(object, null, 3)}`)
|
|
169
|
+
const taggedObject = object[propertyDef.name]
|
|
170
|
+
if (propertyDef.isList) {
|
|
171
|
+
if (!Array.isArray(taggedObject)) {
|
|
172
|
+
this.validationResult.issue(new GenericIssue(jsonContext, `Property value '${propertyDef.name}' expects an array, found '${typeof taggedObject}'`))
|
|
173
|
+
} else {
|
|
174
|
+
taggedObject.forEach((taggedObjectSingle, index) => {
|
|
175
|
+
this.validateTaggedObject(taggedObjectSingle, jsonContext.concat(index))
|
|
176
|
+
})
|
|
177
|
+
}
|
|
178
|
+
} else {
|
|
179
|
+
if (!(typeof taggedObject === "object")) {
|
|
180
|
+
this.validationResult.issue(new GenericIssue(jsonContext, `Property value '${propertyDef.name}' expects an object, found '${typeof taggedObject}'`))
|
|
181
|
+
} else {
|
|
182
|
+
this.validateTaggedObject(taggedObject as UnknownObjectType, jsonContext)
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Validate a single tagged object
|
|
189
|
+
* @param taggedObject
|
|
190
|
+
* @param jsonContext
|
|
191
|
+
*/
|
|
192
|
+
validateTaggedObject(taggedObject: UnknownObjectType, jsonContext: JsonContext): void {
|
|
193
|
+
const actualTypeName = taggedObject["messageKind"] as string
|
|
194
|
+
const actualType = this.schema.getDefinition(actualTypeName)
|
|
195
|
+
if (actualType === undefined || !isObjectDefinition(actualType)) {
|
|
196
|
+
this.validationResult.issue(new GenericIssue(jsonContext, `Expected object type is ${typeof taggedObject}, should be object`))
|
|
197
|
+
} else {
|
|
198
|
+
this.validateObjectProperties(actualTypeName, actualType, taggedObject, jsonContext)
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
155
202
|
/**
|
|
156
203
|
* Check whether there are extra properties that should not be there.
|
|
157
204
|
* @param obj Object to be validated
|
|
@@ -160,8 +207,8 @@ export class SyntaxValidator {
|
|
|
160
207
|
*/
|
|
161
208
|
checkStrayProperties(obj: UnknownObjectType, def: ObjectDefinition, context: JsonContext) {
|
|
162
209
|
const own = Object.getOwnPropertyNames(obj)
|
|
163
|
-
const defined = def.map(pdef => pdef.
|
|
164
|
-
own.forEach(
|
|
210
|
+
const defined = def.properties.map(pdef => pdef.name)
|
|
211
|
+
own.forEach(ownProp => {
|
|
165
212
|
if (!defined.includes(ownProp)) {
|
|
166
213
|
this.validationResult.issue(new Syntax_PropertyUnknownIssue(context, ownProp))
|
|
167
214
|
}
|