json-schema-library 5.3.0 → 7.0.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.
Files changed (161) hide show
  1. package/.editorconfig +1 -0
  2. package/.prettierignore +1 -0
  3. package/.prettierrc +7 -0
  4. package/CHANGELOG.md +106 -0
  5. package/README.md +811 -199
  6. package/TASKS.md +3 -81
  7. package/dist/index.d.ts +29 -71
  8. package/dist/jsonSchemaLibrary.js +1 -1
  9. package/dist/lib/SchemaService.d.ts +6 -8
  10. package/dist/lib/{addSchema.d.ts → addRemoteSchema.d.ts} +2 -1
  11. package/dist/lib/addValidator.d.ts +3 -2
  12. package/dist/lib/compile/getRef.d.ts +2 -1
  13. package/dist/lib/compile/index.d.ts +15 -1
  14. package/dist/lib/compile/types.d.ts +5 -0
  15. package/dist/lib/config/strings.d.ts +1 -39
  16. package/dist/lib/draft/index.d.ts +132 -0
  17. package/dist/lib/draft04/index.d.ts +7 -0
  18. package/dist/lib/draft06/compile/index.d.ts +16 -0
  19. package/dist/lib/draft06/index.d.ts +7 -0
  20. package/dist/lib/draft06/validation/keyword.d.ts +3 -0
  21. package/dist/lib/draft06/validation/type.d.ts +10 -0
  22. package/dist/lib/draft06/validation/typeKeywordMapping.d.ts +13 -0
  23. package/dist/lib/draft07/index.d.ts +7 -0
  24. package/dist/lib/each.d.ts +3 -2
  25. package/dist/lib/eachSchema.d.ts +2 -4
  26. package/dist/lib/getChildSchemaSelection.d.ts +7 -5
  27. package/dist/lib/getSchema.d.ts +2 -2
  28. package/dist/lib/getTemplate.d.ts +1 -1
  29. package/dist/lib/getTypeOf.d.ts +2 -1
  30. package/dist/lib/isValid.d.ts +1 -1
  31. package/dist/lib/jsoneditor/index.d.ts +7 -0
  32. package/dist/lib/resolveAllOf.d.ts +1 -1
  33. package/dist/lib/resolveAnyOf.d.ts +1 -1
  34. package/dist/lib/resolveOneOf.fuzzy.d.ts +1 -1
  35. package/dist/lib/resolveOneOf.strict.d.ts +2 -2
  36. package/dist/lib/{resolveRef.withOverwrite.d.ts → resolveRef.merge.d.ts} +0 -0
  37. package/dist/lib/schema/getTypeDefs.d.ts +6 -4
  38. package/dist/lib/schema/getTypeId.d.ts +1 -1
  39. package/dist/lib/schema/types.d.ts +7 -57
  40. package/dist/lib/step.d.ts +5 -5
  41. package/dist/lib/types.d.ts +11 -3
  42. package/dist/lib/utils/createCustomError.d.ts +8 -11
  43. package/dist/lib/utils/filter.d.ts +4 -4
  44. package/dist/lib/utils/flattenArray.d.ts +1 -1
  45. package/dist/lib/utils/merge.d.ts +3 -0
  46. package/dist/lib/utils/punycode.ucs2decode.d.ts +1 -1
  47. package/dist/lib/validate.d.ts +2 -2
  48. package/dist/lib/validateAsync.d.ts +1 -1
  49. package/dist/lib/validation/errors.d.ts +1 -3
  50. package/dist/lib/validation/format.d.ts +4 -11
  51. package/dist/lib/validation/keyword.d.ts +2 -27
  52. package/dist/lib/validation/type.d.ts +3 -10
  53. package/dist/lib/validation/typeKeywordMapping.d.ts +4 -4
  54. package/dist/module/index.js +23 -32
  55. package/dist/module/lib/SchemaService.js +7 -4
  56. package/dist/module/lib/{addSchema.js → addRemoteSchema.js} +2 -4
  57. package/dist/module/lib/addValidator.js +3 -4
  58. package/dist/module/lib/compile/getRef.js +1 -1
  59. package/dist/module/lib/compile/index.js +43 -18
  60. package/dist/module/lib/compile/types.js +1 -0
  61. package/dist/module/lib/config/strings.js +15 -2
  62. package/dist/module/lib/createSchemaOf.js +1 -1
  63. package/dist/module/lib/draft/index.js +133 -0
  64. package/dist/module/lib/draft04/index.js +90 -0
  65. package/dist/module/lib/draft06/compile/index.js +77 -0
  66. package/dist/module/lib/draft06/index.js +96 -0
  67. package/dist/module/lib/draft06/validation/keyword.js +168 -0
  68. package/dist/module/lib/draft06/validation/type.js +31 -0
  69. package/dist/module/lib/draft06/validation/typeKeywordMapping.js +15 -0
  70. package/dist/module/lib/draft07/index.js +96 -0
  71. package/dist/module/lib/each.js +2 -2
  72. package/dist/module/lib/eachSchema.js +28 -19
  73. package/dist/module/lib/getChildSchemaSelection.js +7 -6
  74. package/dist/module/lib/getSchema.js +4 -2
  75. package/dist/module/lib/getTemplate.js +42 -15
  76. package/dist/module/lib/jsoneditor/index.js +16 -0
  77. package/dist/module/lib/resolveAllOf.js +3 -4
  78. package/dist/module/lib/resolveOneOf.fuzzy.js +13 -3
  79. package/dist/module/lib/resolveOneOf.strict.js +49 -2
  80. package/dist/module/lib/{resolveRef.withOverwrite.js → resolveRef.merge.js} +0 -0
  81. package/dist/module/lib/resolveRef.strict.js +8 -0
  82. package/dist/module/lib/schema/getTypeDefs.js +14 -3
  83. package/dist/module/lib/schema/getTypeId.js +10 -6
  84. package/dist/module/lib/schema/types.js +33 -9
  85. package/dist/module/lib/step.js +67 -13
  86. package/dist/module/lib/types.js +7 -1
  87. package/dist/module/lib/utils/createCustomError.js +4 -4
  88. package/dist/module/lib/utils/filter.js +3 -5
  89. package/dist/module/lib/utils/flattenArray.js +4 -3
  90. package/dist/module/lib/utils/merge.js +4 -0
  91. package/dist/module/lib/utils/punycode.ucs2decode.js +4 -3
  92. package/dist/module/lib/validate.js +34 -8
  93. package/dist/module/lib/validateAsync.js +7 -7
  94. package/dist/module/lib/validation/errors.js +16 -3
  95. package/dist/module/lib/validation/format.js +115 -8
  96. package/dist/module/lib/validation/keyword.js +79 -32
  97. package/dist/module/lib/validation/type.js +2 -1
  98. package/index.ts +46 -32
  99. package/lib/SchemaService.ts +18 -11
  100. package/lib/{addSchema.ts → addRemoteSchema.ts} +3 -5
  101. package/lib/addValidator.ts +15 -12
  102. package/lib/compile/getRef.ts +3 -4
  103. package/lib/compile/index.ts +65 -19
  104. package/lib/compile/types.ts +6 -0
  105. package/lib/config/strings.ts +17 -3
  106. package/lib/createSchemaOf.ts +1 -3
  107. package/lib/draft/index.ts +201 -0
  108. package/lib/draft04/index.ts +95 -0
  109. package/lib/draft06/compile/index.ts +104 -0
  110. package/lib/draft06/index.ts +101 -0
  111. package/lib/draft06/validation/keyword.ts +199 -0
  112. package/lib/draft06/validation/type.ts +47 -0
  113. package/lib/draft06/validation/typeKeywordMapping.ts +15 -0
  114. package/lib/draft07/index.ts +101 -0
  115. package/lib/each.ts +11 -4
  116. package/lib/eachSchema.ts +45 -32
  117. package/lib/getChildSchemaSelection.ts +14 -7
  118. package/lib/getSchema.ts +18 -9
  119. package/lib/getTemplate.ts +155 -42
  120. package/lib/getTypeOf.ts +2 -1
  121. package/lib/isValid.ts +7 -3
  122. package/lib/jsoneditor/index.ts +20 -0
  123. package/lib/resolveAllOf.ts +10 -6
  124. package/lib/resolveAnyOf.ts +7 -3
  125. package/lib/resolveOneOf.fuzzy.ts +26 -9
  126. package/lib/resolveOneOf.strict.ts +63 -5
  127. package/lib/{resolveRef.withOverwrite.ts → resolveRef.merge.ts} +0 -0
  128. package/lib/resolveRef.strict.ts +9 -0
  129. package/lib/schema/getTypeDefs.ts +19 -7
  130. package/lib/schema/getTypeId.ts +11 -8
  131. package/lib/schema/types.ts +41 -9
  132. package/lib/step.ts +109 -25
  133. package/lib/types.ts +23 -5
  134. package/lib/utils/createCustomError.ts +8 -13
  135. package/lib/utils/filter.ts +7 -9
  136. package/lib/utils/flattenArray.ts +5 -4
  137. package/lib/utils/merge.ts +5 -0
  138. package/lib/utils/punycode.ucs2decode.ts +6 -5
  139. package/lib/validate.ts +47 -16
  140. package/lib/validateAsync.ts +15 -14
  141. package/lib/validation/errors.ts +17 -6
  142. package/lib/validation/format.ts +147 -13
  143. package/lib/validation/keyword.ts +172 -103
  144. package/lib/validation/type.ts +5 -1
  145. package/package.json +75 -63
  146. package/{dist/module/remotes/draft04.json → remotes/draft06.json} +47 -42
  147. package/remotes/draft07.json +172 -0
  148. package/remotes/draft2019-09.json +86 -0
  149. package/tsconfig.json +3 -10
  150. package/dist/lib/cores/CoreInterface.d.ts +0 -23
  151. package/dist/lib/cores/Draft04.d.ts +0 -13
  152. package/dist/lib/cores/JsonEditor.d.ts +0 -13
  153. package/dist/module/lib/cores/CoreInterface.js +0 -51
  154. package/dist/module/lib/cores/Draft04.js +0 -52
  155. package/dist/module/lib/cores/JsonEditor.js +0 -51
  156. package/dist/module/remotes/index.js +0 -10
  157. package/dist/remotes/index.d.ts +0 -5
  158. package/lib/cores/CoreInterface.ts +0 -76
  159. package/lib/cores/Draft04.ts +0 -66
  160. package/lib/cores/JsonEditor.ts +0 -64
  161. package/remotes/index.ts +0 -11
@@ -4,28 +4,40 @@ import getTypeId from "./getTypeId";
4
4
  import types from "./types";
5
5
  import { JSONSchema, JSONPointer } from "../types";
6
6
 
7
+ const isObject = (value: unknown) => Object.prototype.toString.call(value) === "[object Object]";
7
8
 
8
- const isObject = value => Object.prototype.toString.call(value) === "[object Object]";
9
-
9
+ type TypeDef = { pointer: JSONPointer; def: unknown };
10
10
 
11
11
  /**
12
12
  * Returns a list of all (direct) type definitions from the given schema
13
13
  * @param schema
14
14
  * @return list of type definition, given as { pointer, def }
15
15
  */
16
- export default function getTypeDefs(schema: JSONSchema): Array<{ pointer: JSONPointer, def: any }> {
17
- const defs = [];
16
+ export default function getTypeDefs(schema: JSONSchema): TypeDef[] {
17
+ const defs: TypeDef[] = [];
18
18
  const id = getTypeId(schema);
19
19
  if (id == null) {
20
20
  return defs;
21
21
  }
22
- const type = types[id];
22
+
23
+ let type;
24
+ if (Array.isArray(id)) {
25
+ // since types can also be declared as a set of types, merge the definitions
26
+ // maybe this will require a more sophisticated approach
27
+ type = {};
28
+ for (let i = 0, l = id.length; i < l; i += 1) {
29
+ Object.assign(type, types[id[i]]);
30
+ }
31
+ } else {
32
+ type = types[id];
33
+ }
34
+
23
35
  if (type.definitions == null) {
24
36
  return defs;
25
37
  }
26
38
 
27
- type.definitions.forEach(query => {
28
- get(schema, query, (value, key, parent, pointer) => {
39
+ type.definitions.forEach((query: string) => {
40
+ get(schema, query, (value: unknown, key, parent, pointer) => {
29
41
  if (isObject(value) && getTypeId(value)) {
30
42
  defs.push({ pointer: gp.join(gp.split(pointer), false), def: value });
31
43
  }
@@ -1,9 +1,9 @@
1
1
  import types from "./types";
2
2
  import { JSONSchema } from "../types";
3
3
 
4
- const isObject = value => Object.prototype.toString.call(value) === "[object Object]";
5
- const typeKeywords = Object.keys(types).filter(id => types[id].type === false);
6
-
4
+ const isObject = (value: unknown) => Object.prototype.toString.call(value) === "[object Object]";
5
+ const typeKeywords = Object.keys(types).filter((id) => types[id].type === false);
6
+ const hasOwnProperty = Object.prototype.hasOwnProperty;
7
7
 
8
8
  /**
9
9
  * @throws Error on multiple matches (invalid schema)
@@ -12,7 +12,7 @@ const typeKeywords = Object.keys(types).filter(id => types[id].type === false);
12
12
  * @param schema
13
13
  * @return type id, if found
14
14
  */
15
- export default function getTypeId(schema: JSONSchema): string|undefined {
15
+ export default function getTypeId(schema: JSONSchema): string | string[] | undefined {
16
16
  if (isObject(schema) === false) {
17
17
  return undefined;
18
18
  }
@@ -21,11 +21,12 @@ export default function getTypeId(schema: JSONSchema): string|undefined {
21
21
  return "enum";
22
22
  }
23
23
 
24
- if (types[schema.type]) {
24
+ // @ts-ignore
25
+ if (types[schema.type] || Array.isArray(schema.type)) {
25
26
  return schema.type;
26
27
  }
27
28
 
28
- const ids = typeKeywords.filter(type => schema[type]);
29
+ const ids = typeKeywords.filter((type) => schema[type]);
29
30
 
30
31
  if (ids.length === 1) {
31
32
  return ids[0];
@@ -35,7 +36,8 @@ export default function getTypeId(schema: JSONSchema): string|undefined {
35
36
  // @expensive, guess type object
36
37
  for (let i = 0, l = types.object.keywords.length; i < l; i += 1) {
37
38
  const keyword = types.object.keywords[i];
38
- if (schema.hasOwnProperty(keyword)) { // eslint-disable-line
39
+ if (hasOwnProperty.call(schema, keyword)) {
40
+ // eslint-disable-line
39
41
  return "object";
40
42
  }
41
43
  }
@@ -43,7 +45,8 @@ export default function getTypeId(schema: JSONSchema): string|undefined {
43
45
  // @expensive, guess type array
44
46
  for (let i = 0, l = types.array.keywords.length; i < l; i += 1) {
45
47
  const keyword = types.array.keywords[i];
46
- if (schema.hasOwnProperty(keyword)) { // eslint-disable-line
48
+ if (hasOwnProperty.call(schema, keyword)) {
49
+ // eslint-disable-line
47
50
  return "array";
48
51
  }
49
52
  }
@@ -1,4 +1,11 @@
1
- export default {
1
+ export type Type = {
2
+ type: boolean;
3
+ definitions?: string[];
4
+ validationKeywords?: string[];
5
+ keywords?: string[];
6
+ };
7
+
8
+ const Types: Record<string, Type> = {
2
9
  $ref: {
3
10
  type: false
4
11
  },
@@ -13,14 +20,22 @@ export default {
13
20
  array: {
14
21
  type: true,
15
22
  // ignore additionalItems:TypeDef, when items:TypeDef
16
- definitions: ["allOf/*", "anyOf/*", "oneOf/*", "not", "items", "items/*", "additionalItems"],
23
+ definitions: [
24
+ "allOf/*",
25
+ "anyOf/*",
26
+ "oneOf/*",
27
+ "not",
28
+ "items",
29
+ "items/*",
30
+ "additionalItems"
31
+ ],
17
32
  validationKeywords: ["minItems", "maxItems", "uniqueItems"],
18
33
  keywords: ["items", "additionalItems", "minItems", "maxItems", "uniqueItems"]
19
34
  },
20
- "boolean": {
35
+ boolean: {
21
36
  type: true
22
37
  },
23
- "enum": {
38
+ enum: {
24
39
  type: false
25
40
  },
26
41
  integer: {
@@ -37,7 +52,7 @@ export default {
37
52
  definitions: ["allOf/*", "anyOf/*", "oneOf/*", "not"],
38
53
  validationKeywords: ["minimum", "maximum", "multipleOf"]
39
54
  },
40
- "null": {
55
+ null: {
41
56
  type: true
42
57
  },
43
58
  object: {
@@ -45,11 +60,26 @@ export default {
45
60
  // patternProperties also validate properties
46
61
  // dependencies:(string, TypeDef) extend current TypeDef
47
62
  // additional Properties validate only remaining properties (after properties & pattern)
48
- definitions: ["allOf/*", "anyOf/*", "oneOf/*", "not",
49
- "properties/*", "additionalProperties", "patternProperties/*", "dependencies/*"],
63
+ definitions: [
64
+ "allOf/*",
65
+ "anyOf/*",
66
+ "oneOf/*",
67
+ "not",
68
+ "properties/*",
69
+ "additionalProperties",
70
+ "patternProperties/*",
71
+ "dependencies/*"
72
+ ],
50
73
  validationKeywords: ["minProperties", "maxProperties", "required"],
51
- keywords: ["properties", "additionalProperties", "patternProperties", "dependencies", "minProperties",
52
- "maxProperties", "required"]
74
+ keywords: [
75
+ "properties",
76
+ "additionalProperties",
77
+ "patternProperties",
78
+ "dependencies",
79
+ "minProperties",
80
+ "maxProperties",
81
+ "required"
82
+ ]
53
83
  },
54
84
  oneOf: {
55
85
  type: false,
@@ -61,3 +91,5 @@ export default {
61
91
  validationKeywords: ["minLength", "maxLength", "pattern"]
62
92
  }
63
93
  };
94
+
95
+ export default Types;
package/lib/step.ts CHANGED
@@ -2,13 +2,17 @@ import getTypeOf from "./getTypeOf";
2
2
  import createSchemaOf from "./createSchemaOf";
3
3
  import errors from "./validation/errors";
4
4
  import merge from "./utils/merge";
5
- import { JSONSchema, JSONPointer, JSONError } from "./types";
6
- import Core from "./cores/CoreInterface";
7
-
5
+ import { JSONSchema, JSONPointer, JSONError, isJSONError } from "./types";
6
+ import { Draft as Core } from "./draft";
8
7
 
9
8
  const stepType = {
10
-
11
- array: (core: Core, key: string|number, schema: JSONSchema, data: any, pointer: JSONPointer): JSONSchema|JSONError => {
9
+ array: (
10
+ core: Core,
11
+ key: string,
12
+ schema: JSONSchema,
13
+ data: any,
14
+ pointer: JSONPointer
15
+ ): JSONSchema | JSONError => {
12
16
  const itemsType = getTypeOf(schema.items);
13
17
 
14
18
  if (itemsType === "object") {
@@ -33,12 +37,29 @@ const stepType = {
33
37
  }
34
38
 
35
39
  if (itemsType === "array") {
40
+ // @draft >= 7 bool schema, items:[true, false]
41
+ if (schema.items[key] === true) {
42
+ return createSchemaOf(data[key]);
43
+ }
44
+ // @draft >= 7 bool schema, items:[true, false]
45
+ if (schema.items[key] === false) {
46
+ return errors.invalidDataError({
47
+ key,
48
+ value: data[key],
49
+ pointer
50
+ });
51
+ }
52
+
36
53
  if (schema.items[key]) {
37
54
  return core.resolveRef(schema.items[key]);
38
55
  }
39
56
 
40
57
  if (schema.additionalItems === false) {
41
- return errors.additionalItemsError({ key, value: data[key], pointer });
58
+ return errors.additionalItemsError({
59
+ key,
60
+ value: data[key],
61
+ pointer
62
+ });
42
63
  }
43
64
 
44
65
  if (schema.additionalItems === true || schema.additionalItems === undefined) {
@@ -49,7 +70,13 @@ const stepType = {
49
70
  return schema.additionalItems;
50
71
  }
51
72
 
52
- throw new Error(`Invalid schema ${JSON.stringify(schema, null, 4)} for ${JSON.stringify(data, null, 4)}`);
73
+ throw new Error(
74
+ `Invalid schema ${JSON.stringify(schema, null, 4)} for ${JSON.stringify(
75
+ data,
76
+ null,
77
+ 4
78
+ )}`
79
+ );
53
80
  }
54
81
 
55
82
  if (schema.additionalItems !== false && data[key]) {
@@ -61,14 +88,19 @@ const stepType = {
61
88
  return new Error(`Invalid array schema for ${key} at ${pointer}`) as JSONError;
62
89
  },
63
90
 
64
- object: (core: Core, key: string|number, schema: JSONSchema, data: any, pointer: JSONPointer): JSONSchema|JSONError => {
65
-
91
+ object: (
92
+ core: Core,
93
+ key: string,
94
+ schema: JSONSchema,
95
+ data: any,
96
+ pointer: JSONPointer
97
+ ): JSONSchema | JSONError => {
66
98
  if (Array.isArray(schema.oneOf)) {
67
99
  // update current schema
68
100
  const oneOfSchema = core.resolveOneOf(data, schema, pointer);
69
101
  // resolveOneOf does currently not apply merge with base schema
70
102
  schema = merge(schema, oneOfSchema);
71
- if (schema && schema.type === "error") {
103
+ if (isJSONError(schema)) {
72
104
  return schema;
73
105
  }
74
106
  }
@@ -76,7 +108,7 @@ const stepType = {
76
108
  if (Array.isArray(schema.anyOf)) {
77
109
  // update current schema
78
110
  schema = core.resolveAnyOf(data, schema, pointer);
79
- if (schema && schema.type === "error") {
111
+ if (isJSONError(schema)) {
80
112
  return schema;
81
113
  }
82
114
  }
@@ -84,7 +116,7 @@ const stepType = {
84
116
  if (Array.isArray(schema.allOf)) {
85
117
  // update current schema
86
118
  schema = core.resolveAllOf(data, schema, pointer);
87
- if (schema && schema.type === "error") {
119
+ if (isJSONError(schema)) {
88
120
  return schema;
89
121
  }
90
122
  }
@@ -96,7 +128,7 @@ const stepType = {
96
128
  // @todo patternProperties also validate properties
97
129
 
98
130
  targetSchema = core.resolveRef(schema.properties[key]);
99
- if (targetSchema && targetSchema.type === "error") {
131
+ if (isJSONError(targetSchema)) {
100
132
  return targetSchema;
101
133
  }
102
134
 
@@ -104,9 +136,17 @@ const stepType = {
104
136
  if (targetSchema && Array.isArray(targetSchema.oneOf)) {
105
137
  // @special case: this is a mix of a schema and optional definitions
106
138
  // we resolve the schema here and add the original schema to `oneOfSchema`
107
- let resolvedSchema = core.resolveOneOf(data[key], targetSchema, `${pointer}/${key}`);
139
+ let resolvedSchema = core.resolveOneOf(
140
+ data[key],
141
+ targetSchema,
142
+ `${pointer}/${key}`
143
+ );
144
+
145
+ const oneOfIndex = targetSchema.oneOf.findIndex((s) => s === resolvedSchema);
146
+
108
147
  resolvedSchema = JSON.parse(JSON.stringify(resolvedSchema));
109
148
  resolvedSchema.variableSchema = true;
149
+ resolvedSchema.oneOfIndex = oneOfIndex;
110
150
  resolvedSchema.oneOfSchema = targetSchema;
111
151
  return resolvedSchema;
112
152
  }
@@ -117,6 +157,24 @@ const stepType = {
117
157
  }
118
158
  }
119
159
 
160
+ // @draft <= 07
161
+ const { dependencies } = schema;
162
+ if (getTypeOf(dependencies) === "object") {
163
+ const dependentProperties = Object.keys(dependencies).filter(
164
+ (propertyName) =>
165
+ // data[propertyName] !== undefined &&
166
+ getTypeOf(dependencies[propertyName]) === "object"
167
+ );
168
+
169
+ for (let i = 0, l = dependentProperties.length; i < l; i += 1) {
170
+ const dependentProperty = dependentProperties[i];
171
+ const schema = step(core, key, dependencies[dependentProperty], data);
172
+ if (!isJSONError(schema)) {
173
+ return schema;
174
+ }
175
+ }
176
+ }
177
+
120
178
  // find matching property key
121
179
  if (getTypeOf(schema.patternProperties) === "object") {
122
180
  let regex;
@@ -134,14 +192,18 @@ const stepType = {
134
192
  }
135
193
 
136
194
  if (schema.additionalProperties === true) {
137
- return createSchemaOf(data);
195
+ return createSchemaOf(data[key]);
138
196
  }
139
197
 
140
- return errors.unknownPropertyError({ property: key, value: data, pointer });
198
+ return errors.unknownPropertyError({
199
+ property: key,
200
+ value: data,
201
+ // pointer: `${pointer}/${key}`,
202
+ pointer: `${pointer}`
203
+ });
141
204
  }
142
205
  };
143
206
 
144
-
145
207
  /**
146
208
  * Returns the json-schema of the given object property or array item.
147
209
  * e.g. it steps by one key into the data
@@ -149,18 +211,40 @@ const stepType = {
149
211
  * This helper determines the location of the property within the schema (additional properties, oneOf, ...) and
150
212
  * returns the correct schema.
151
213
  *
152
- * @param core - validator
153
- * @param key - property-name or array-index
154
- * @param schema - json schema of current data
214
+ * @param core - validator
215
+ * @param key - property-name or array-index
216
+ * @param schema - json schema of current data
155
217
  * @param data - parent of key
156
- * @param [pointer]
218
+ * @param [pointer] - pointer to schema and data (parent of key)
157
219
  * @return Schema or Error if failed resolving key
158
220
  */
159
- export default function step(core: Core, key: string|number, schema: JSONSchema, data?: any, pointer: JSONPointer = "#"):
160
- JSONSchema|JSONError {
221
+ export default function step(
222
+ core: Core,
223
+ key: string | number,
224
+ schema: JSONSchema,
225
+ data?: any,
226
+ pointer: JSONPointer = "#"
227
+ ): JSONSchema | JSONError {
228
+ // @draft >= 4 ?
229
+ if (Array.isArray(schema.type)) {
230
+ const dataType = getTypeOf(data);
231
+ if (schema.type.includes(dataType)) {
232
+ // @ts-ignore
233
+ return stepType[dataType](core, `${key}`, schema, data, pointer);
234
+ }
235
+ return core.errors.typeError({
236
+ value: data,
237
+ pointer,
238
+ expected: schema.type,
239
+ received: dataType
240
+ });
241
+ }
242
+
161
243
  const expectedType = schema.type || getTypeOf(data);
162
- if (stepType[expectedType]) {
163
- return stepType[expectedType](core, key, schema, data, pointer);
244
+ // @ts-ignore
245
+ const stepFunction = stepType[expectedType];
246
+ if (stepFunction) {
247
+ return stepFunction(core, `${key}`, schema, data, pointer);
164
248
  }
165
249
  return new Error(`Unsupported schema type ${schema.type} for key ${key}`) as JSONError;
166
250
  }
package/lib/types.ts CHANGED
@@ -1,19 +1,37 @@
1
- import Core from "./cores/CoreInterface";
1
+ import { Draft as Core } from "./draft";
2
2
 
3
-
4
- export type JSONSchema = { [p:string]: any };
3
+ export type JSONSchema = { [p: string]: any };
5
4
 
6
5
  export type JSONPointer = string;
7
6
 
8
7
  export type JSONError = {
9
- type: "error"|"string";
8
+ type: "error";
10
9
  name: string;
11
10
  code: string;
12
11
  message: string;
13
12
  data?: { [p: string]: any };
14
13
  [p: string]: any;
14
+ };
15
+
16
+ /**
17
+ * ts type guard for json error
18
+ * @returns true if passed type is a JSONError
19
+ */
20
+ export function isJSONError(error: any): error is JSONError {
21
+ return error?.type === "error";
15
22
  }
16
23
 
17
24
  export interface JSONValidator {
18
- (core: Core, schema: JSONSchema, value: any, pointer: JSONPointer): void|undefined|JSONError|Array<JSONError>;
25
+ (core: Core, schema: JSONSchema, value: unknown, pointer: JSONPointer):
26
+ | void
27
+ | undefined
28
+ | JSONError
29
+ | JSONError[]
30
+ | JSONError[][];
31
+ }
32
+
33
+ export interface JSONTypeValidator {
34
+ (core: Core, schema: JSONSchema, value: unknown, pointer: JSONPointer): Array<
35
+ void | undefined | JSONError | JSONError[] | JSONError[][]
36
+ >;
19
37
  }
@@ -1,18 +1,14 @@
1
1
  import __ from "./__";
2
- import { JSONError } from "../types";
2
+ import { JSONError, JSONPointer } from "../types";
3
3
 
4
+ export type ErrorData = { pointer: JSONPointer } & Record<string, unknown>;
5
+ export type CreateError = (data: ErrorData) => JSONError;
4
6
 
5
- export interface CreateError {
6
- (data?: { [p : string]: any }): JSONError
7
+ function dashCase(text: string): string {
8
+ return text.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
7
9
  }
8
10
 
9
-
10
- function dashCase(str: string): string {
11
- return str.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
12
- }
13
-
14
-
15
- export function createError(name: string, data?: { [p : string]: any }): JSONError {
11
+ export function createError(name: string, data: ErrorData): JSONError {
16
12
  return {
17
13
  type: "error",
18
14
  name,
@@ -22,14 +18,13 @@ export function createError(name: string, data?: { [p : string]: any }): JSONErr
22
18
  };
23
19
  }
24
20
 
25
-
26
21
  /**
27
22
  * Creates a custom Error-Constructor which instances may be identified by `customError instanceof Error`. Its messages
28
- * are defined by strings-object __@see config/strings.ts
23
+ * are defined by strings-object @see config/strings.ts
29
24
  *
30
25
  * @param name - id of error (camelcased)
31
26
  * @return error constructor function
32
27
  */
33
- export default function createCustomError(name: string): CreateError {
28
+ export function createCustomError(name: string): CreateError {
34
29
  return createError.bind(null, name);
35
30
  }
@@ -1,15 +1,13 @@
1
- export function isPromise(obj) {
2
- return obj instanceof Promise;
3
- }
1
+ import { isJSONError, JSONError } from "../types";
4
2
 
5
- export function isError(obj) {
6
- return obj && obj.type === "error";
3
+ export function isPromise(obj: unknown): obj is Promise<unknown> {
4
+ return obj instanceof Promise;
7
5
  }
8
6
 
9
- export function errorOrPromise(error) {
10
- return isError(error) || isPromise(error);
7
+ export function errorOrPromise(error: unknown): error is JSONError | Promise<unknown> {
8
+ return isJSONError(error) || isPromise(error);
11
9
  }
12
10
 
13
- export function errorsOnly(error) {
14
- return isError(error);
11
+ export function errorsOnly(error: unknown): error is JSONError {
12
+ return isJSONError(error);
15
13
  }
@@ -1,9 +1,10 @@
1
- export default function flattenArray<T = any>(list: Array<any>, result = []): Array<T> {
1
+ export default function flattenArray<T = unknown>(list: unknown[], result: T[] = []): T[] {
2
2
  for (let i = 0; i < list.length; i += 1) {
3
- if (Array.isArray(list[i])) {
4
- flattenArray(list[i], result);
3
+ const item = list[i];
4
+ if (Array.isArray(item)) {
5
+ flattenArray(item, result);
5
6
  } else {
6
- result.push(list[i]);
7
+ result.push(item as T);
7
8
  }
8
9
  }
9
10
  return result;
@@ -1,3 +1,8 @@
1
1
  import deepmerge from "deepmerge";
2
+ // @ts-ignore
2
3
  const overwriteMerge = (destinationArray, sourceArray) => sourceArray;
4
+
5
+ /**
6
+ * returns a new json-schema, where properties are combined and arrays are replaced
7
+ */
3
8
  export default <T, K>(a: T, b: K): T & K => deepmerge(a, b, { arrayMerge: overwriteMerge });
@@ -15,18 +15,19 @@
15
15
  * @param string The Unicode input string (UCS-2).
16
16
  * @returns The new array of code points.
17
17
  */
18
- export default function ucs2decode(string: string): Array<string> {
18
+ export default function ucs2decode(string: string): string[] {
19
19
  const output = [];
20
20
  let counter = 0;
21
21
  const length = string.length;
22
22
  while (counter < length) {
23
23
  const value = string.charCodeAt(counter++);
24
- if (value >= 0xD800 && value <= 0xDBFF && counter < length) {
24
+ if (value >= 0xd800 && value <= 0xdbff && counter < length) {
25
25
  // It's a high surrogate, and there is a next character.
26
26
  const extra = string.charCodeAt(counter++);
27
27
  // eslint-disable-next-line eqeqeq
28
- if ((extra & 0xFC00) == 0xDC00) { // Low surrogate.
29
- output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000);
28
+ if ((extra & 0xfc00) == 0xdc00) {
29
+ // Low surrogate.
30
+ output.push(((value & 0x3ff) << 10) + (extra & 0x3ff) + 0x10000);
30
31
  } else {
31
32
  // It's an unmatched surrogate; only append this code unit, in case the
32
33
  // next code unit is the high surrogate of a surrogate pair.
@@ -37,5 +38,5 @@ export default function ucs2decode(string: string): Array<string> {
37
38
  output.push(value);
38
39
  }
39
40
  }
40
- return output;
41
+ return output as unknown as string[];
41
42
  }