@lionweb/validation 0.7.0-beta.1 → 0.7.0-beta.11

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.
Files changed (59) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/dist/issues/ValidationIssue.d.ts +3 -3
  3. package/dist/issues/ValidationIssue.d.ts.map +1 -1
  4. package/dist/issues/ValidationIssue.js +1 -1
  5. package/dist/issues/ValidationIssue.js.map +1 -1
  6. package/dist/languages/LanguageUtils.d.ts.map +1 -1
  7. package/dist/languages/LionWebLanguageWrapper.d.ts.map +1 -1
  8. package/dist/runners/Utils.js +2 -2
  9. package/dist/runners/Utils.js.map +1 -1
  10. package/dist/validators/LionWebChunkDefinitions.d.ts +4 -4
  11. package/dist/validators/LionWebChunkDefinitions.d.ts.map +1 -1
  12. package/dist/validators/LionWebChunkDefinitions.js +80 -90
  13. package/dist/validators/LionWebChunkDefinitions.js.map +1 -1
  14. package/dist/validators/LionWebLanguageReferenceValidator.d.ts +1 -1
  15. package/dist/validators/LionWebLanguageReferenceValidator.d.ts.map +1 -1
  16. package/dist/validators/LionWebLanguageReferenceValidator.js +3 -3
  17. package/dist/validators/LionWebLanguageReferenceValidator.js.map +1 -1
  18. package/dist/validators/LionWebSyntaxValidator.js +2 -2
  19. package/dist/validators/LionWebValidator.js +1 -1
  20. package/dist/validators/LionWebValidator.js.map +1 -1
  21. package/dist/validators/ValidationFunctions.d.ts +1 -1
  22. package/dist/validators/ValidationFunctions.d.ts.map +1 -1
  23. package/dist/validators/ValidationFunctions.js +5 -12
  24. package/dist/validators/ValidationFunctions.js.map +1 -1
  25. package/dist/validators/generic/SyntaxValidator.d.ts +7 -7
  26. package/dist/validators/generic/SyntaxValidator.d.ts.map +1 -1
  27. package/dist/validators/generic/SyntaxValidator.js +28 -33
  28. package/dist/validators/generic/SyntaxValidator.js.map +1 -1
  29. package/dist/validators/generic/index.d.ts +1 -1
  30. package/dist/validators/generic/index.d.ts.map +1 -1
  31. package/dist/validators/generic/index.js +1 -1
  32. package/dist/validators/generic/index.js.map +1 -1
  33. package/dist/validators/generic/schema/DefinitionSchema.d.ts +23 -0
  34. package/dist/validators/generic/schema/DefinitionSchema.d.ts.map +1 -0
  35. package/dist/validators/generic/schema/DefinitionSchema.js +43 -0
  36. package/dist/validators/generic/schema/DefinitionSchema.js.map +1 -0
  37. package/dist/validators/generic/{ValidationTypes.d.ts → schema/ValidationTypes.d.ts} +45 -12
  38. package/dist/validators/generic/schema/ValidationTypes.d.ts.map +1 -0
  39. package/dist/validators/generic/{ValidationTypes.js → schema/ValidationTypes.js} +18 -21
  40. package/dist/validators/generic/schema/ValidationTypes.js.map +1 -0
  41. package/dist/validators/generic/schema/index.d.ts +3 -0
  42. package/dist/validators/generic/schema/index.d.ts.map +1 -0
  43. package/dist/validators/generic/schema/index.js +3 -0
  44. package/dist/validators/generic/schema/index.js.map +1 -0
  45. package/package.json +5 -5
  46. package/src/issues/ValidationIssue.ts +4 -4
  47. package/src/runners/Utils.ts +2 -2
  48. package/src/validators/LionWebChunkDefinitions.ts +80 -90
  49. package/src/validators/LionWebLanguageReferenceValidator.ts +3 -3
  50. package/src/validators/LionWebSyntaxValidator.ts +2 -2
  51. package/src/validators/LionWebValidator.ts +1 -1
  52. package/src/validators/ValidationFunctions.ts +6 -13
  53. package/src/validators/generic/SyntaxValidator.ts +81 -87
  54. package/src/validators/generic/index.ts +1 -1
  55. package/src/validators/generic/schema/DefinitionSchema.ts +52 -0
  56. package/src/validators/generic/{ValidationTypes.ts → schema/ValidationTypes.ts} +65 -35
  57. package/src/validators/generic/schema/index.ts +2 -0
  58. package/dist/validators/generic/ValidationTypes.d.ts.map +0 -1
  59. package/dist/validators/generic/ValidationTypes.js.map +0 -1
@@ -1,112 +1,102 @@
1
- import { MAY_BE_NULL, PrimitiveDef, PropertyDef, TypeDefinition } from "./generic/ValidationTypes.js"
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 fed to the SyntaxValidator to validate an object sat runtime.
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 expectedTypes: Map<string, TypeDefinition> = new Map<string, TypeDefinition>([
11
- [
12
- "LionWebMetaPointer",
13
- [
14
- PropertyDef({ property: "key", expectedType: "LionWebKey" }),
15
- PropertyDef({ property: "version", expectedType: "LionWebVersion" }),
16
- PropertyDef({ property: "language", expectedType: "LionWebKey" })
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
- "ResponseMessage",
21
- [
22
- PropertyDef({ property: "kind", expectedType: "string" }),
23
- PropertyDef({ property: "message", expectedType: "string" }),
24
- PropertyDef({ property: "data", expectedType: "object", mayBeNull: true, isOptional: true })
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
- "LionWebChunk",
29
- [
30
- PropertyDef({ property: "serializationFormatVersion", expectedType: "LionWebSerializationFormatVersion" }),
31
- PropertyDef({ property: "languages", expectedType: "LionWebUsedLanguage", isList: true }),
32
- PropertyDef({ property: "nodes", expectedType: "LionWebNode", isList: true })
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
- "LionWebUsedLanguage",
37
- [
38
- PropertyDef({ property: "key", expectedType: "LionWebKey" }),
39
- PropertyDef({ property: "version", expectedType: "LionWebVersion" })
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
- "LionWebNode",
44
- [
45
- PropertyDef({ property: "id", expectedType: "LionWebId" }),
46
- PropertyDef({ property: "classifier", expectedType: "LionWebMetaPointer" }),
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
- "LionWebProperty",
56
- [
57
- PropertyDef({ property: "property", expectedType: "LionWebMetaPointer" }),
58
- PropertyDef({ property: "value", expectedType: "string", mayBeNull: MAY_BE_NULL }),
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
- "LionWebContainment",
63
- [
64
- PropertyDef({ property: "containment", expectedType: "LionWebMetaPointer" }),
65
- PropertyDef({ property: "children", expectedType: "LionWebId", isList: true }),
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
- "LionWebReference",
70
- [
71
- PropertyDef({ property: "reference", expectedType: "LionWebMetaPointer"}),
72
- PropertyDef({ property: "targets", expectedType: "LionWebReferenceTarget", isList: true}),
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
- "LionWebReferenceTarget",
77
- [
78
- PropertyDef({ property: "resolveInfo", expectedType: "string", mayBeNull: MAY_BE_NULL }),
79
- PropertyDef({ property: "reference", expectedType: "LionWebId", mayBeNull: MAY_BE_NULL }),
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
- "LionWebId",
88
- PrimitiveDef({ primitiveType: "string", validate: validateId }),
89
- ],
90
- [
91
- "LionWebKey",
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
 
@@ -66,7 +66,7 @@ export class LionWebLanguageReferenceValidator {
66
66
  })
67
67
  }
68
68
 
69
- private validateContainment(node: LionWebJsonNode, nodeConcept: LionWebJsonNode | undefined, containment: LionWebJsonContainment, context: JsonContext) {
69
+ private validateContainment(_node: LionWebJsonNode, nodeConcept: LionWebJsonNode | undefined, containment: LionWebJsonContainment, context: JsonContext) {
70
70
  const metaConcept = this.registry.getNodeByMetaPointer(containment.containment)
71
71
  if (metaConcept === null || metaConcept === undefined) {
72
72
  this.validationResult.issue(new Language_UnknownContainment_Issue(context, containment.containment))
@@ -85,7 +85,7 @@ export class LionWebLanguageReferenceValidator {
85
85
  // TODO check type of children
86
86
  }
87
87
 
88
- private validateReference(node: LionWebJsonNode, nodeConcept: LionWebJsonNode | undefined, ref: LionWebJsonReference, context: JsonContext) {
88
+ private validateReference(_node: LionWebJsonNode, nodeConcept: LionWebJsonNode | undefined, ref: LionWebJsonReference, context: JsonContext) {
89
89
  const referenceDefinition = this.registry.getNodeByMetaPointer(ref.reference)
90
90
  if (referenceDefinition === null || referenceDefinition === undefined) {
91
91
  this.validationResult.issue(new Language_UnknownReference_Issue(context, ref.reference))
@@ -113,7 +113,7 @@ export class LionWebLanguageReferenceValidator {
113
113
  * Checks wwhether the value of `prop1` is correct in relation with its property definition in the referred language.
114
114
  * @param prop
115
115
  */
116
- validateProperty(node: LionWebJsonNode, nodeConcept: LionWebJsonNode | undefined, prop: LionWebJsonProperty, context: JsonContext): void {
116
+ validateProperty(_node: LionWebJsonNode, nodeConcept: LionWebJsonNode | undefined, prop: LionWebJsonProperty, context: JsonContext): void {
117
117
  if (prop.value === null) {
118
118
  return
119
119
  }
@@ -1,6 +1,6 @@
1
1
  import { SyntaxValidator } from "./generic/SyntaxValidator.js"
2
2
  import { ValidationResult } from "./generic/ValidationResult.js"
3
- import { expectedTypes } from "./LionWebChunkDefinitions.js"
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, expectedTypes)
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, "LionWebChunk")
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.
@@ -20,7 +20,6 @@ import { PropertyDefinition } from "./generic/ValidationTypes.js"
20
20
  * @param result Any validation issues found will be put into this object.
21
21
  * @param context The context for the error message in errors.
22
22
  */
23
- // eslint-disable-next-line @typescript-eslint/ban-types
24
23
  export function validateId<String>(value: String, result: ValidationResult, context: JsonContext): void {
25
24
  const idString: string = "" + value
26
25
  const regexp = /^[a-zA-Z0-9_-][a-zA-Z0-9_-]*$/
@@ -35,7 +34,6 @@ export function validateId<String>(value: String, result: ValidationResult, cont
35
34
  * @param result Any validation issues found will be put into this object.
36
35
  * @param context The context for the error message in errors.
37
36
  */
38
- // eslint-disable-next-line @typescript-eslint/ban-types
39
37
  export function validateKey<String>(value: String, result: ValidationResult, context: JsonContext): void {
40
38
  const keyString: string = "" + value
41
39
  const regexp = /^[a-zA-Z0-9_-][a-zA-Z0-9_-]*$/
@@ -50,7 +48,6 @@ export function validateKey<String>(value: String, result: ValidationResult, con
50
48
  * @param result Any validation issues found will be put into this object.
51
49
  * @param context The location in the overall JSON.
52
50
  */
53
- // eslint-disable-next-line @typescript-eslint/ban-types
54
51
  export function validateVersion<String>(value: String, result: ValidationResult, context: JsonContext): void {
55
52
  const versionString: string = "" + value
56
53
  if (versionString.length === 0) {
@@ -65,14 +62,13 @@ export function validateVersion<String>(value: String, result: ValidationResult,
65
62
  * @param context The location in the overall JSON.
66
63
  * @param propDef The PropertyDefinition for this value
67
64
  */
68
- // eslint-disable-next-line @typescript-eslint/ban-types
69
65
  export function validateBoolean<String>(value: String, result: ValidationResult, context: JsonContext, propDef?: PropertyDefinition): void {
70
66
  const valueAsPrimitive = "" + value
71
67
  if (valueAsPrimitive !== "true" && valueAsPrimitive !== "false") {
72
68
  result.issue(
73
69
  new Language_PropertyValue_Issue(
74
70
  context,
75
- propDef ? propDef.property : "unknown",
71
+ propDef ? propDef.name : "unknown",
76
72
  valueAsPrimitive,
77
73
  "boolean " + JSON.stringify(value)
78
74
  )
@@ -87,12 +83,11 @@ export function validateBoolean<String>(value: String, result: ValidationResult,
87
83
  * @param context The location in the overall JSON.
88
84
  * @param propDef The PropertyDefinition for this value
89
85
  */
90
- // eslint-disable-next-line @typescript-eslint/ban-types
91
86
  export function validateInteger<String>(value: String, result: ValidationResult, context: JsonContext, propDef?: PropertyDefinition): void {
92
87
  const valueAsPrimitive = "" + value
93
88
  const regexp = /^[+-]?(0|[1-9][0-9]*)$/
94
89
  if (valueAsPrimitive === null || !regexp.test(valueAsPrimitive)) {
95
- result.issue(new Language_PropertyValue_Issue(context, propDef ? propDef.property : "unknown", valueAsPrimitive, "integer"))
90
+ result.issue(new Language_PropertyValue_Issue(context, propDef ? propDef.name : "unknown", valueAsPrimitive, "integer"))
96
91
  }
97
92
  }
98
93
 
@@ -103,16 +98,15 @@ export function validateInteger<String>(value: String, result: ValidationResult,
103
98
  * @param context The location in the overall JSON.
104
99
  * @param propDef The PropertyDefinition for this value
105
100
  */
106
- // eslint-disable-next-line @typescript-eslint/ban-types
107
101
  export function validateJSON<String>(value: String, result: ValidationResult, context: JsonContext, propDef?: PropertyDefinition): void {
108
102
  const valueAsPrimitive = "" + value
109
103
  if (value === null) {
110
- result.issue(new Syntax_PropertyNullIssue(context, propDef!.property!))
104
+ result.issue(new Syntax_PropertyNullIssue(context, propDef!.name!))
111
105
  }
112
106
  try {
113
107
  JSON.parse(valueAsPrimitive)
114
- } catch (e) {
115
- result.issue(new Language_PropertyValue_Issue(context, propDef ? propDef.property : "unknown", valueAsPrimitive, "JSON"))
108
+ } catch (_) {
109
+ result.issue(new Language_PropertyValue_Issue(context, propDef ? propDef.name : "unknown", valueAsPrimitive, "JSON"))
116
110
  }
117
111
  }
118
112
 
@@ -122,7 +116,6 @@ export function validateJSON<String>(value: String, result: ValidationResult, co
122
116
  * @param result
123
117
  * @param context
124
118
  */
125
- // eslint-disable-next-line @typescript-eslint/ban-types
126
119
  export function validateSerializationFormatVersion<String>(value: String, result: ValidationResult, context: JsonContext): void {
127
120
  if (typeof value !== "string") {
128
121
  result.issue(new Syntax_SerializationFormatVersion_Issue(context, JSON.stringify(value)))
@@ -9,40 +9,38 @@ import {
9
9
  import { ValidationResult } from "./ValidationResult.js"
10
10
  import {
11
11
  isObjectDefinition,
12
- isPrimitiveDefinition,
13
- ObjectDefinition,
14
- PrimitiveDefinition,
15
- TypeDefinition,
12
+ isPrimitiveDefinition, ObjectDefinition, PrimitiveDefinition, DefinitionSchema,
16
13
  UnknownObjectType
17
- } from "./ValidationTypes.js"
14
+ } from "./schema/index.js"
18
15
 
19
16
  /**
20
- * Syntax Validator can check whether objects are structurally conforming to the
21
- * definitions given in `typeDefinitions`.
17
+ * Syntax Validator checks whether objects are structurally conforming to the
18
+ * definitions given in `schema`.
22
19
  */
23
20
  export class SyntaxValidator {
24
21
  validationResult: ValidationResult
25
- typeDefinitions: Map<string, TypeDefinition>
22
+ schema: DefinitionSchema
26
23
 
27
- constructor(validationResult: ValidationResult, expectedTypes: Map<string, TypeDefinition>) {
24
+ constructor(validationResult: ValidationResult, schema: DefinitionSchema) {
28
25
  this.validationResult = validationResult
29
- this.typeDefinitions = expectedTypes
26
+ this.schema = schema
30
27
  }
31
28
 
32
29
  /**
33
30
  * Check whether `obj` is a JSON object that conforms to the definition of `expectedType`.
34
- * All errors found will be pushed into the `errors` array, if its length is not 0, the check has failed.
31
+ * All errors found will be added to the `validationResult` object.
35
32
  * @param obj The object to validate.
36
33
  * @param expectedType The expected type of the object.
37
34
  */
38
35
  validate(obj: unknown, expectedType: string) {
39
36
  const object = obj as UnknownObjectType
40
- const typeDef = this.typeDefinitions.get(expectedType)
37
+ const typeDef = this.schema.getDefinition(expectedType)
38
+
41
39
  if (typeDef === undefined) {
42
40
  throw new Error(`SyntaxValidator.validate: cannot find definition for ${expectedType}`)
43
- } else if (isObjectDefinition(typeDef)){
41
+ } else if (isObjectDefinition(typeDef)) {
44
42
  this.validateObjectProperties(expectedType, typeDef, object, new JsonContext(null, ["$"]))
45
- } else if( isPrimitiveDefinition(typeDef)) {
43
+ } else if (isPrimitiveDefinition(typeDef)) {
46
44
  this.validatePrimitiveValue("$", typeDef, object, new JsonContext(null, ["$"]))
47
45
  }
48
46
  }
@@ -50,7 +48,7 @@ export class SyntaxValidator {
50
48
  /**
51
49
  * Validate whether `object` is structured conform the properties in `propertyDef`
52
50
  * @param originalProperty The property of which `object` it the value
53
- * @param typeDef The property definitions that are being validated
51
+ * @param typeDef The property definitions that are being validated
54
52
  * @param object The object being validated
55
53
  * @param jsonContext The location in the JSON
56
54
  * @private
@@ -59,93 +57,89 @@ export class SyntaxValidator {
59
57
  if (typeDef === null || typeDef === undefined) {
60
58
  return
61
59
  }
62
- if ((typeof object) !== "object") {
63
- this.validationResult.issue(new Syntax_PropertyTypeIssue(jsonContext, originalProperty, "object", typeof object))
64
- return
65
- }
66
- for (const propertyDef of typeDef) {
67
- const expectedTypeDef = this.typeDefinitions.get(propertyDef.expectedType)
68
- const validator = propertyDef.validate!
69
- const propertyValue = object[propertyDef.property]
70
- if (propertyValue === undefined) {
71
- if (!propertyDef.isOptional) {
72
- this.validationResult.issue(new Syntax_PropertyMissingIssue(jsonContext, propertyDef.property))
73
- }
74
- continue
75
- }
76
- if (!propertyDef.mayBeNull && propertyValue === null) {
77
- this.validationResult.issue(new Syntax_PropertyNullIssue(jsonContext, propertyDef.property))
78
- continue
60
+ if (typeof object !== "object") {
61
+ this.validationResult.issue(new Syntax_PropertyTypeIssue(jsonContext, originalProperty, "object", typeof object))
62
+ return
63
+ }
64
+ for (const propertyDef of typeDef.properties) {
65
+ const expectedTypeDef = this.schema.getDefinition(propertyDef.type)
66
+ const validator = propertyDef.validate!
67
+ const propertyValue = object[propertyDef.name]
68
+ if (propertyValue === undefined) {
69
+ if (!propertyDef.isOptional) {
70
+ this.validationResult.issue(new Syntax_PropertyMissingIssue(jsonContext, propertyDef.name))
79
71
  }
80
- if (propertyDef.mayBeNull && propertyValue === null) {
81
- // Ok, stop checking, continue with next property def
82
- continue
72
+ continue
73
+ }
74
+ if (!propertyDef.mayBeNull && propertyValue === null) {
75
+ this.validationResult.issue(new Syntax_PropertyNullIssue(jsonContext, propertyDef.name))
76
+ continue
77
+ }
78
+ if (propertyDef.mayBeNull && propertyValue === null) {
79
+ // Ok, stop checking, continue with next property def
80
+ continue
81
+ }
82
+ if (propertyDef.isList) {
83
+ // Check whether value is an array
84
+ if (!Array.isArray(propertyValue)) {
85
+ const newContext = jsonContext.concat(propertyDef.name)
86
+ this.validationResult.issue(new Syntax_PropertyTypeIssue(newContext, propertyDef.name, "array", typeof propertyValue))
87
+ return
83
88
  }
84
- if (propertyDef.isList) {
85
- // Check whether value is an array
86
- if (!Array.isArray(propertyValue)) {
87
- const newContext = jsonContext.concat(propertyDef.property)
88
- this.validationResult.issue(new Syntax_PropertyTypeIssue(newContext, propertyDef.property, "array", typeof propertyValue))
89
- return
90
- }
91
- // If an array, validate every item in the array
92
- (propertyValue as UnknownObjectType[]).forEach((item, index) => {
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)
89
+ // If an array, validate every item in the array
90
+ (propertyValue as UnknownObjectType[]).forEach((item, index) => {
91
+ const newContext = jsonContext.concat(propertyDef.name, index)
92
+ if (item === null) {
93
+ this.validationResult.issue(new Syntax_ArrayContainsNull_Issue(newContext, propertyDef.name, index))
94
+ } else {
95
+ if (expectedTypeDef !== undefined) {
96
+ if (isPrimitiveDefinition(expectedTypeDef)) {
97
+ if (this.validatePrimitiveValue(propertyDef.name, expectedTypeDef, item, jsonContext)) {
106
98
  validator.apply(null, [item, this.validationResult, newContext, propertyDef])
107
99
  }
108
100
  } else {
109
- throw new Error(`Expected type '${propertyDef.expectedType} has neither property defs, nor a validator.`)
101
+ // propertyValue should be an object, validate its properties
102
+ this.validateObjectProperties(propertyDef.name, expectedTypeDef, item as UnknownObjectType, newContext)
103
+ validator.apply(null, [item, this.validationResult, newContext, propertyDef])
110
104
  }
105
+ } else {
106
+ throw new Error(`Expected type '${propertyDef.type} has neither property defs, nor a validator.`)
111
107
  }
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
108
  }
119
- // Single valued property, validate it
120
- if (expectedTypeDef !== undefined) {
121
- if (isPrimitiveDefinition(expectedTypeDef)) {
122
- // propertyValue should be a primitive as it has no property definitions
123
- if (this.validatePrimitiveValue(propertyDef.property, expectedTypeDef, propertyValue, jsonContext)) {
124
- validator.apply(null, [propertyValue, this.validationResult, newContext, propertyDef])
125
- }
126
- } else if (isObjectDefinition(expectedTypeDef)) {
127
- // propertyValue should be an object, validate its properties
128
- this.validateObjectProperties(propertyDef.property, expectedTypeDef, propertyValue as UnknownObjectType, newContext)
109
+ })
110
+ } else {
111
+ const newContext = jsonContext.concat(propertyDef.name)
112
+ if (Array.isArray(propertyValue)) {
113
+ this.validationResult.issue(new Syntax_PropertyTypeIssue(newContext, propertyDef.name, propertyDef.type, "array"))
114
+ return
115
+ }
116
+ // Single valued property, validate it
117
+ if (expectedTypeDef !== undefined) {
118
+ if (isPrimitiveDefinition(expectedTypeDef)) {
119
+ // propertyValue should be a primitive as it has no property definitions
120
+ if (this.validatePrimitiveValue(propertyDef.name, expectedTypeDef, propertyValue, jsonContext)) {
129
121
  validator.apply(null, [propertyValue, this.validationResult, newContext, propertyDef])
130
- } else {
131
- throw new Error("EXPECTING ObjectDefinition or PrimitiveDefinition, but got something else")
132
122
  }
123
+ } else if (isObjectDefinition(expectedTypeDef)) {
124
+ // propertyValue should be an object, validate its properties
125
+ this.validateObjectProperties(propertyDef.name, expectedTypeDef, propertyValue as UnknownObjectType, newContext)
126
+ validator.apply(null, [propertyValue, this.validationResult, newContext, propertyDef])
133
127
  } else {
134
- throw new Error(`Expected single type '${propertyDef.expectedType}' for '${propertyDef.property}' at ${newContext.toString()} has neither property defs, nor a validator.`)
128
+ throw new Error("EXPECTING ObjectDefinition or PrimitiveDefinition, but got something else")
135
129
  }
130
+ } else {
131
+ throw new Error(
132
+ `Expected single type '${propertyDef.type}' for '${propertyDef.name}' at ${newContext.toString()} has neither property defs, nor a validator.`
133
+ )
136
134
  }
137
135
  }
138
- this.checkStrayProperties(object, typeDef, jsonContext)
136
+ }
137
+ this.checkStrayProperties(object, typeDef, jsonContext)
139
138
  }
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
139
 
140
+ validatePrimitiveValue(propertyName: string, propDef: PrimitiveDefinition, object: unknown, jsonContext: JsonContext): boolean {
147
141
  if (typeof object !== propDef.primitiveType) {
148
- this.validationResult.issue(new Syntax_PropertyTypeIssue(jsonContext, propertyName, propDef.primitiveType,typeof object))
142
+ this.validationResult.issue(new Syntax_PropertyTypeIssue(jsonContext, propertyName, propDef.primitiveType, typeof object))
149
143
  return false
150
144
  }
151
145
  propDef.validate!(object, this.validationResult, jsonContext)
@@ -160,8 +154,8 @@ export class SyntaxValidator {
160
154
  */
161
155
  checkStrayProperties(obj: UnknownObjectType, def: ObjectDefinition, context: JsonContext) {
162
156
  const own = Object.getOwnPropertyNames(obj)
163
- const defined = def.map(pdef => pdef.property)
164
- own.forEach((ownProp) => {
157
+ const defined = def.properties.map(pdef => pdef.name)
158
+ own.forEach(ownProp => {
165
159
  if (!defined.includes(ownProp)) {
166
160
  this.validationResult.issue(new Syntax_PropertyUnknownIssue(context, ownProp))
167
161
  }
@@ -1,3 +1,3 @@
1
- export * from "./ValidationTypes.js"
1
+ export * from "./schema/index.js"
2
2
  export * from "./ValidationResult.js"
3
3
  export * from "./SyntaxValidator.js"
@@ -0,0 +1,52 @@
1
+ import { Definition, PrimitiveDefinition, TaggedUnionDefinition } from "./ValidationTypes.js"
2
+
3
+ /**
4
+ * A collection of object and primitive definitions describing JSON objects.
5
+ * Used to
6
+ * - validate an incoming JSON object
7
+ * - generate the corresponding TypeScript type definitions
8
+ * - generate handlers for the JSOn objects (in @lionweb/server)
9
+ */
10
+ export class DefinitionSchema {
11
+ unionDefinition: TaggedUnionDefinition | undefined
12
+ /**
13
+ * Mapping from extenden object type name to list of extending Object Definitions
14
+ */
15
+ definitionsMap: Map<string, Definition> = new Map<string, Definition>()
16
+
17
+ constructor(definitions: Definition[], taggedUnion?: TaggedUnionDefinition) {
18
+ this.add(definitions)
19
+ this.unionDefinition = taggedUnion
20
+ }
21
+
22
+ getDefinition(name: string): Definition | undefined {
23
+ return this.definitionsMap.get(name)
24
+ }
25
+
26
+ add(definitions :Definition[] | Definition) {
27
+ if (!Array.isArray(definitions)) {
28
+ definitions = [definitions]
29
+ }
30
+ for(const def of definitions) {
31
+ this.definitionsMap.set(def.name, def)
32
+ }
33
+ }
34
+
35
+ isTagProperty(propertyName: string): boolean {
36
+ return this.unionDefinition?.unionProperty === propertyName
37
+ }
38
+
39
+ definitions(): Definition[] {
40
+ return Array.from(this.definitionsMap.values())
41
+ }
42
+
43
+ isUnionDiscriminator(propDef: PrimitiveDefinition): boolean {
44
+ return this.unionDefinition?.unionDiscriminator === propDef.name
45
+ }
46
+
47
+ joinDefinitions(...schema: DefinitionSchema[]): void {
48
+ schema.forEach(sch => {
49
+ this.add(sch.definitions())
50
+ })
51
+ }
52
+ }