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,6 +4,7 @@ import getTypeOf from "./getTypeOf";
4
4
  import merge from "./utils/merge";
5
5
  import copy from "./utils/copy";
6
6
  import settings from "./config/settings";
7
+ import { isJSONError } from "./types";
7
8
  const defaultOptions = {
8
9
  addOptionalProps: true
9
10
  };
@@ -17,7 +18,7 @@ function shouldResolveRef(schema, pointer) {
17
18
  if ($ref == null) {
18
19
  return true;
19
20
  }
20
- const value = (cache[pointer] == null || cache[pointer][$ref] == null) ? 0 : cache[pointer][$ref];
21
+ const value = cache[pointer] == null || cache[pointer][$ref] == null ? 0 : cache[pointer][$ref];
21
22
  return value < settings.GET_TEMPLATE_RECURSION_LIMIT;
22
23
  }
23
24
  function resolveRef(core, schema, pointer) {
@@ -118,13 +119,16 @@ function getTemplate(core, data, _schema, pointer, opts) {
118
119
  return undefined;
119
120
  }
120
121
  pointer = schema.pointer;
122
+ if (schema === null || schema === void 0 ? void 0 : schema.const) {
123
+ return schema.const;
124
+ }
121
125
  if (schema.oneOf) {
122
126
  // find correct schema for data
123
127
  const resolvedSchema = resolveOneOfFuzzy(core, data, schema);
124
- if (data == null && resolvedSchema.type === "error") {
128
+ if (data == null && isJSONError(resolvedSchema)) {
125
129
  schema = schema.oneOf[0];
126
130
  }
127
- else if (resolvedSchema.type === "error") {
131
+ else if (isJSONError(resolvedSchema.type)) {
128
132
  // @todo - check: do not return schema, but either input-data or undefined (clearing wrong data)
129
133
  return data;
130
134
  }
@@ -132,6 +136,9 @@ function getTemplate(core, data, _schema, pointer, opts) {
132
136
  schema = resolvedSchema;
133
137
  }
134
138
  }
139
+ // @todo Array.isArray(schema.type)
140
+ // -> hasDefault? return
141
+ // if not -> pick first type
135
142
  if (!isJSONSchema(schema) || schema.type == null) {
136
143
  return undefined;
137
144
  }
@@ -139,23 +146,25 @@ function getTemplate(core, data, _schema, pointer, opts) {
139
146
  if (data != null && getTypeOf(data) !== schema.type) {
140
147
  data = convertValue(schema.type, data);
141
148
  }
142
- if (TYPE[schema.type] == null) { // eslint-disable-line no-use-before-define
149
+ if (TYPE[schema.type] == null) {
150
+ // eslint-disable-line no-use-before-define
143
151
  throw new Error(`Unsupported type '${schema.type} in ${JSON.stringify(schema)}'`);
144
152
  }
145
153
  const templateData = TYPE[schema.type](core, schema, data, pointer, opts); // eslint-disable-line no-use-before-define
146
154
  return templateData;
147
155
  }
148
156
  const TYPE = {
149
- "string": (core, schema, data) => getDefault(schema, data, ""),
150
- "number": (core, schema, data) => getDefault(schema, data, 0),
151
- "integer": (core, schema, data) => getDefault(schema, data, 0),
152
- "boolean": (core, schema, data) => getDefault(schema, data, false),
153
- "object": (core, schema, data, pointer, opts) => {
157
+ null: (core, schema, data) => getDefault(schema, data, null),
158
+ string: (core, schema, data) => getDefault(schema, data, ""),
159
+ number: (core, schema, data) => getDefault(schema, data, 0),
160
+ integer: (core, schema, data) => getDefault(schema, data, 0),
161
+ boolean: (core, schema, data) => getDefault(schema, data, false),
162
+ object: (core, schema, data, pointer, opts) => {
154
163
  const template = schema.default === undefined ? {} : schema.default;
155
164
  const d = {}; // do not assign data here, to keep ordering from json-schema
156
165
  if (schema.properties) {
157
- Object.keys(schema.properties).forEach(key => {
158
- const value = (data == null || data[key] == null) ? template[key] : data[key];
166
+ Object.keys(schema.properties).forEach((key) => {
167
+ const value = data == null || data[key] == null ? template[key] : data[key];
159
168
  const isRequired = Array.isArray(schema.required) && schema.required.includes(key);
160
169
  // Omit adding a property if it is not required or optional props should be added
161
170
  if (value != null || isRequired || opts.addOptionalProps) {
@@ -163,18 +172,33 @@ const TYPE = {
163
172
  }
164
173
  });
165
174
  }
175
+ if (schema.dependencies) {
176
+ Object.keys(schema.dependencies).forEach((key) => {
177
+ const dependency = schema.dependencies[key];
178
+ if (getTypeOf(dependency) !== "object") {
179
+ return;
180
+ }
181
+ if (d[key] === undefined) {
182
+ return;
183
+ }
184
+ const result = getTemplate(core, data, { ...dependency, type: "object" }, `${pointer}/dependencies/${key}`, opts);
185
+ if (result && !isJSONError(result)) {
186
+ Object.assign(d, result);
187
+ }
188
+ });
189
+ }
166
190
  if (data) {
167
191
  // merge any missing data (additionals) to resulting object
168
- Object.keys(data).forEach(key => (d[key] == null && (d[key] = data[key])));
192
+ Object.keys(data).forEach((key) => d[key] == null && (d[key] = data[key]));
169
193
  }
170
194
  // returns object, which is ordered by json-schema
171
195
  return d;
172
196
  },
173
197
  // build array type of items, ignores additionalItems
174
- "array": (core, schema, data, pointer, opts) => {
198
+ array: (core, schema, data, pointer, opts) => {
175
199
  const template = schema.default === undefined ? [] : schema.default;
176
- const d = data || [];
177
200
  schema.minItems = schema.minItems || 0;
201
+ const d = data || [];
178
202
  // items are undefined
179
203
  if (schema.items == null) {
180
204
  return d;
@@ -232,6 +256,9 @@ function getDefault(schema, templateValue, initValue) {
232
256
  if (templateValue != null) {
233
257
  return templateValue;
234
258
  }
259
+ else if (schema.const) {
260
+ return schema.const;
261
+ }
235
262
  else if (schema.default === undefined && Array.isArray(schema.enum)) {
236
263
  return schema.enum[0];
237
264
  }
@@ -241,6 +268,6 @@ function getDefault(schema, templateValue, initValue) {
241
268
  return schema.default;
242
269
  }
243
270
  export default (core, data, schema = core.rootSchema, opts = defaultOptions) => {
244
- cache = { "mi": ".." };
271
+ cache = { mi: {} };
245
272
  return getTemplate(core, data, schema, "#", opts);
246
273
  };
@@ -0,0 +1,16 @@
1
+ import merge from "../utils/merge";
2
+ import resolveOneOf from "../resolveOneOf.fuzzy";
3
+ import resolveRef from "../resolveRef.merge";
4
+ import { Draft } from "../draft";
5
+ import { draft07Config } from "../draft07";
6
+ const draftJsonEditorConfig = {
7
+ ...draft07Config,
8
+ resolveOneOf,
9
+ resolveRef
10
+ };
11
+ class JsonEditor extends Draft {
12
+ constructor(schema, config = {}) {
13
+ super(merge(draftJsonEditorConfig, config), schema);
14
+ }
15
+ }
16
+ export { JsonEditor, draftJsonEditorConfig };
@@ -1,13 +1,12 @@
1
1
  import copy from "./utils/copy";
2
2
  import merge from "./utils/merge";
3
- import errors from "./validation/errors";
4
3
  export default function resolveAllOf(core, data, schema = core.rootSchema, pointer = "#") {
5
4
  let mergedSchema = copy(schema);
6
5
  for (let i = 0; i < schema.allOf.length; i += 1) {
7
6
  const allOfSchema = core.resolveRef(schema.allOf[i]);
8
- if (core.isValid(data, allOfSchema, pointer) === false) {
9
- return errors.allOfError({ value: data, pointer, allOf: JSON.stringify(schema.allOf) });
10
- }
7
+ // if (core.isValid(data, allOfSchema, pointer) === false) {
8
+ // return errors.allOfError({ value: data, pointer, allOf: JSON.stringify(schema.allOf) });
9
+ // }
11
10
  mergedSchema = merge(mergedSchema, allOfSchema);
12
11
  }
13
12
  delete mergedSchema.allOf;
@@ -2,6 +2,7 @@ import { errorOrPromise } from "./utils/filter";
2
2
  import flattenArray from "./utils/flattenArray";
3
3
  import getTypeOf from "./getTypeOf";
4
4
  import settings from "./config/settings";
5
+ import { isJSONError } from "./types";
5
6
  const { DECLARATOR_ONEOF } = settings;
6
7
  /**
7
8
  * Returns a ranking for the data and given schema
@@ -52,7 +53,7 @@ export default function resolveOneOf(core, data, schema = core.rootSchema, point
52
53
  for (let i = 0; i < schema.oneOf.length; i += 1) {
53
54
  const one = core.resolveRef(schema.oneOf[i]);
54
55
  const oneOfPropertySchema = core.step(oneOfProperty, one, data, pointer);
55
- if (oneOfPropertySchema && oneOfPropertySchema.type === "error") {
56
+ if (isJSONError(oneOfPropertySchema)) {
56
57
  return oneOfPropertySchema;
57
58
  }
58
59
  let result = flattenArray(core.validate(oneOfValue, oneOfPropertySchema, pointer));
@@ -64,7 +65,12 @@ export default function resolveOneOf(core, data, schema = core.rootSchema, point
64
65
  return one; // return resolved schema
65
66
  }
66
67
  }
67
- return core.errors.oneOfPropertyError({ property: oneOfProperty, value: oneOfValue, pointer, errors });
68
+ return core.errors.oneOfPropertyError({
69
+ property: oneOfProperty,
70
+ value: oneOfValue,
71
+ pointer,
72
+ errors
73
+ });
68
74
  }
69
75
  // keyword: oneOf
70
76
  const matches = [];
@@ -90,7 +96,11 @@ export default function resolveOneOf(core, data, schema = core.rootSchema, point
90
96
  }
91
97
  }
92
98
  if (schemaOfItem === undefined) {
93
- return core.errors.oneOfError({ value: JSON.stringify(data), pointer, oneOf: schema.oneOf });
99
+ return core.errors.oneOfError({
100
+ value: JSON.stringify(data),
101
+ pointer,
102
+ oneOf: schema.oneOf
103
+ });
94
104
  }
95
105
  return schemaOfItem;
96
106
  }
@@ -1,5 +1,8 @@
1
1
  import { errorOrPromise } from "./utils/filter";
2
2
  import flattenArray from "./utils/flattenArray";
3
+ import settings from "./config/settings";
4
+ import { isJSONError } from "./types";
5
+ const { DECLARATOR_ONEOF } = settings;
3
6
  /**
4
7
  * Selects and returns a oneOf schema for the given data
5
8
  *
@@ -10,6 +13,41 @@ import flattenArray from "./utils/flattenArray";
10
13
  * @return oneOf schema or an error
11
14
  */
12
15
  export default function resolveOneOf(core, data, schema = core.rootSchema, pointer = "#") {
16
+ // !keyword: oneOfProperty
17
+ // an additional <DECLARATOR_ONEOF> (default `oneOfProperty`) on the schema will exactly determine the
18
+ // oneOf value (if set in data)
19
+ // @fixme
20
+ // abort if no data is given an DECLARATOR_ONEOF is set (used by getChildSchemaSelection)
21
+ // this case (data != null) should not be necessary
22
+ if (data != null && schema[DECLARATOR_ONEOF]) {
23
+ const errors = [];
24
+ const oneOfProperty = schema[DECLARATOR_ONEOF];
25
+ const oneOfValue = data[schema[DECLARATOR_ONEOF]];
26
+ if (oneOfValue === undefined) {
27
+ return core.errors.missingOneOfPropertyError({ property: oneOfProperty, pointer });
28
+ }
29
+ for (let i = 0; i < schema.oneOf.length; i += 1) {
30
+ const one = core.resolveRef(schema.oneOf[i]);
31
+ const oneOfPropertySchema = core.step(oneOfProperty, one, data, pointer);
32
+ if (isJSONError(oneOfPropertySchema)) {
33
+ return oneOfPropertySchema;
34
+ }
35
+ let result = flattenArray(core.validate(oneOfValue, oneOfPropertySchema, pointer));
36
+ result = result.filter(errorOrPromise);
37
+ if (result.length > 0) {
38
+ errors.push(...result);
39
+ }
40
+ else {
41
+ return one; // return resolved schema
42
+ }
43
+ }
44
+ return core.errors.oneOfPropertyError({
45
+ property: oneOfProperty,
46
+ value: oneOfValue,
47
+ pointer,
48
+ errors
49
+ });
50
+ }
13
51
  const matches = [];
14
52
  const errors = [];
15
53
  for (let i = 0; i < schema.oneOf.length; i += 1) {
@@ -27,7 +65,16 @@ export default function resolveOneOf(core, data, schema = core.rootSchema, point
27
65
  return matches[0];
28
66
  }
29
67
  if (matches.length > 1) {
30
- return core.errors.multipleOneOfError({ value: data, pointer, matches });
68
+ return core.errors.multipleOneOfError({
69
+ value: data,
70
+ pointer,
71
+ matches
72
+ });
31
73
  }
32
- return core.errors.oneOfError({ value: JSON.stringify(data), pointer, oneOf: schema.oneOf, errors });
74
+ return core.errors.oneOfError({
75
+ value: JSON.stringify(data),
76
+ pointer,
77
+ oneOf: schema.oneOf,
78
+ errors
79
+ });
33
80
  }
@@ -2,6 +2,14 @@ export default function resolveRef(schema, rootSchema) {
2
2
  if (schema == null || schema.$ref == null) {
3
3
  return schema;
4
4
  }
5
+ if (schema.getRoot) {
6
+ // we actually always need to resolve the schema like this, since returned subschemas
7
+ // must resolve relative from their schema
8
+ const resolvedSchema = schema.getRoot().getRef(schema);
9
+ // console.log(schema.$ref, "=>", resolvedSchema);
10
+ return resolvedSchema;
11
+ }
12
+ // tryout - this should never be called, except we missed something
5
13
  const resolvedSchema = rootSchema.getRef(schema);
6
14
  return resolvedSchema;
7
15
  }
@@ -2,7 +2,7 @@ import gp from "gson-pointer";
2
2
  import { get } from "gson-query";
3
3
  import getTypeId from "./getTypeId";
4
4
  import types from "./types";
5
- const isObject = value => Object.prototype.toString.call(value) === "[object Object]";
5
+ const isObject = (value) => Object.prototype.toString.call(value) === "[object Object]";
6
6
  /**
7
7
  * Returns a list of all (direct) type definitions from the given schema
8
8
  * @param schema
@@ -14,11 +14,22 @@ export default function getTypeDefs(schema) {
14
14
  if (id == null) {
15
15
  return defs;
16
16
  }
17
- const type = types[id];
17
+ let type;
18
+ if (Array.isArray(id)) {
19
+ // since types can also be declared as a set of types, merge the definitions
20
+ // maybe this will require a more sophisticated approach
21
+ type = {};
22
+ for (let i = 0, l = id.length; i < l; i += 1) {
23
+ Object.assign(type, types[id[i]]);
24
+ }
25
+ }
26
+ else {
27
+ type = types[id];
28
+ }
18
29
  if (type.definitions == null) {
19
30
  return defs;
20
31
  }
21
- type.definitions.forEach(query => {
32
+ type.definitions.forEach((query) => {
22
33
  get(schema, query, (value, key, parent, pointer) => {
23
34
  if (isObject(value) && getTypeId(value)) {
24
35
  defs.push({ pointer: gp.join(gp.split(pointer), false), def: value });
@@ -1,6 +1,7 @@
1
1
  import types from "./types";
2
- const isObject = value => Object.prototype.toString.call(value) === "[object Object]";
3
- const typeKeywords = Object.keys(types).filter(id => types[id].type === false);
2
+ const isObject = (value) => Object.prototype.toString.call(value) === "[object Object]";
3
+ const typeKeywords = Object.keys(types).filter((id) => types[id].type === false);
4
+ const hasOwnProperty = Object.prototype.hasOwnProperty;
4
5
  /**
5
6
  * @throws Error on multiple matches (invalid schema)
6
7
  *
@@ -15,10 +16,11 @@ export default function getTypeId(schema) {
15
16
  if (schema.enum) {
16
17
  return "enum";
17
18
  }
18
- if (types[schema.type]) {
19
+ // @ts-ignore
20
+ if (types[schema.type] || Array.isArray(schema.type)) {
19
21
  return schema.type;
20
22
  }
21
- const ids = typeKeywords.filter(type => schema[type]);
23
+ const ids = typeKeywords.filter((type) => schema[type]);
22
24
  if (ids.length === 1) {
23
25
  return ids[0];
24
26
  }
@@ -26,14 +28,16 @@ export default function getTypeId(schema) {
26
28
  // @expensive, guess type object
27
29
  for (let i = 0, l = types.object.keywords.length; i < l; i += 1) {
28
30
  const keyword = types.object.keywords[i];
29
- if (schema.hasOwnProperty(keyword)) { // eslint-disable-line
31
+ if (hasOwnProperty.call(schema, keyword)) {
32
+ // eslint-disable-line
30
33
  return "object";
31
34
  }
32
35
  }
33
36
  // @expensive, guess type array
34
37
  for (let i = 0, l = types.array.keywords.length; i < l; i += 1) {
35
38
  const keyword = types.array.keywords[i];
36
- if (schema.hasOwnProperty(keyword)) { // eslint-disable-line
39
+ if (hasOwnProperty.call(schema, keyword)) {
40
+ // eslint-disable-line
37
41
  return "array";
38
42
  }
39
43
  }
@@ -1,4 +1,4 @@
1
- export default {
1
+ const Types = {
2
2
  $ref: {
3
3
  type: false
4
4
  },
@@ -13,14 +13,22 @@ export default {
13
13
  array: {
14
14
  type: true,
15
15
  // ignore additionalItems:TypeDef, when items:TypeDef
16
- definitions: ["allOf/*", "anyOf/*", "oneOf/*", "not", "items", "items/*", "additionalItems"],
16
+ definitions: [
17
+ "allOf/*",
18
+ "anyOf/*",
19
+ "oneOf/*",
20
+ "not",
21
+ "items",
22
+ "items/*",
23
+ "additionalItems"
24
+ ],
17
25
  validationKeywords: ["minItems", "maxItems", "uniqueItems"],
18
26
  keywords: ["items", "additionalItems", "minItems", "maxItems", "uniqueItems"]
19
27
  },
20
- "boolean": {
28
+ boolean: {
21
29
  type: true
22
30
  },
23
- "enum": {
31
+ enum: {
24
32
  type: false
25
33
  },
26
34
  integer: {
@@ -37,7 +45,7 @@ export default {
37
45
  definitions: ["allOf/*", "anyOf/*", "oneOf/*", "not"],
38
46
  validationKeywords: ["minimum", "maximum", "multipleOf"]
39
47
  },
40
- "null": {
48
+ null: {
41
49
  type: true
42
50
  },
43
51
  object: {
@@ -45,11 +53,26 @@ export default {
45
53
  // patternProperties also validate properties
46
54
  // dependencies:(string, TypeDef) extend current TypeDef
47
55
  // additional Properties validate only remaining properties (after properties & pattern)
48
- definitions: ["allOf/*", "anyOf/*", "oneOf/*", "not",
49
- "properties/*", "additionalProperties", "patternProperties/*", "dependencies/*"],
56
+ definitions: [
57
+ "allOf/*",
58
+ "anyOf/*",
59
+ "oneOf/*",
60
+ "not",
61
+ "properties/*",
62
+ "additionalProperties",
63
+ "patternProperties/*",
64
+ "dependencies/*"
65
+ ],
50
66
  validationKeywords: ["minProperties", "maxProperties", "required"],
51
- keywords: ["properties", "additionalProperties", "patternProperties", "dependencies", "minProperties",
52
- "maxProperties", "required"]
67
+ keywords: [
68
+ "properties",
69
+ "additionalProperties",
70
+ "patternProperties",
71
+ "dependencies",
72
+ "minProperties",
73
+ "maxProperties",
74
+ "required"
75
+ ]
53
76
  },
54
77
  oneOf: {
55
78
  type: false,
@@ -61,3 +84,4 @@ export default {
61
84
  validationKeywords: ["minLength", "maxLength", "pattern"]
62
85
  }
63
86
  };
87
+ export default Types;
@@ -2,6 +2,7 @@ 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 { isJSONError } from "./types";
5
6
  const stepType = {
6
7
  array: (core, key, schema, data, pointer) => {
7
8
  const itemsType = getTypeOf(schema.items);
@@ -23,11 +24,27 @@ const stepType = {
23
24
  return core.resolveRef(schema.items);
24
25
  }
25
26
  if (itemsType === "array") {
27
+ // @draft >= 7 bool schema, items:[true, false]
28
+ if (schema.items[key] === true) {
29
+ return createSchemaOf(data[key]);
30
+ }
31
+ // @draft >= 7 bool schema, items:[true, false]
32
+ if (schema.items[key] === false) {
33
+ return errors.invalidDataError({
34
+ key,
35
+ value: data[key],
36
+ pointer
37
+ });
38
+ }
26
39
  if (schema.items[key]) {
27
40
  return core.resolveRef(schema.items[key]);
28
41
  }
29
42
  if (schema.additionalItems === false) {
30
- return errors.additionalItemsError({ key, value: data[key], pointer });
43
+ return errors.additionalItemsError({
44
+ key,
45
+ value: data[key],
46
+ pointer
47
+ });
31
48
  }
32
49
  if (schema.additionalItems === true || schema.additionalItems === undefined) {
33
50
  return createSchemaOf(data[key]);
@@ -50,21 +67,21 @@ const stepType = {
50
67
  const oneOfSchema = core.resolveOneOf(data, schema, pointer);
51
68
  // resolveOneOf does currently not apply merge with base schema
52
69
  schema = merge(schema, oneOfSchema);
53
- if (schema && schema.type === "error") {
70
+ if (isJSONError(schema)) {
54
71
  return schema;
55
72
  }
56
73
  }
57
74
  if (Array.isArray(schema.anyOf)) {
58
75
  // update current schema
59
76
  schema = core.resolveAnyOf(data, schema, pointer);
60
- if (schema && schema.type === "error") {
77
+ if (isJSONError(schema)) {
61
78
  return schema;
62
79
  }
63
80
  }
64
81
  if (Array.isArray(schema.allOf)) {
65
82
  // update current schema
66
83
  schema = core.resolveAllOf(data, schema, pointer);
67
- if (schema && schema.type === "error") {
84
+ if (isJSONError(schema)) {
68
85
  return schema;
69
86
  }
70
87
  }
@@ -73,7 +90,7 @@ const stepType = {
73
90
  if (schema.properties && schema.properties[key] !== undefined) {
74
91
  // @todo patternProperties also validate properties
75
92
  targetSchema = core.resolveRef(schema.properties[key]);
76
- if (targetSchema && targetSchema.type === "error") {
93
+ if (isJSONError(targetSchema)) {
77
94
  return targetSchema;
78
95
  }
79
96
  // check if there is a oneOf selection, which must be resolved
@@ -81,8 +98,10 @@ const stepType = {
81
98
  // @special case: this is a mix of a schema and optional definitions
82
99
  // we resolve the schema here and add the original schema to `oneOfSchema`
83
100
  let resolvedSchema = core.resolveOneOf(data[key], targetSchema, `${pointer}/${key}`);
101
+ const oneOfIndex = targetSchema.oneOf.findIndex((s) => s === resolvedSchema);
84
102
  resolvedSchema = JSON.parse(JSON.stringify(resolvedSchema));
85
103
  resolvedSchema.variableSchema = true;
104
+ resolvedSchema.oneOfIndex = oneOfIndex;
86
105
  resolvedSchema.oneOfSchema = targetSchema;
87
106
  return resolvedSchema;
88
107
  }
@@ -91,6 +110,20 @@ const stepType = {
91
110
  return targetSchema;
92
111
  }
93
112
  }
113
+ // @draft <= 07
114
+ const { dependencies } = schema;
115
+ if (getTypeOf(dependencies) === "object") {
116
+ const dependentProperties = Object.keys(dependencies).filter((propertyName) =>
117
+ // data[propertyName] !== undefined &&
118
+ getTypeOf(dependencies[propertyName]) === "object");
119
+ for (let i = 0, l = dependentProperties.length; i < l; i += 1) {
120
+ const dependentProperty = dependentProperties[i];
121
+ const schema = step(core, key, dependencies[dependentProperty], data);
122
+ if (!isJSONError(schema)) {
123
+ return schema;
124
+ }
125
+ }
126
+ }
94
127
  // find matching property key
95
128
  if (getTypeOf(schema.patternProperties) === "object") {
96
129
  let regex;
@@ -106,9 +139,14 @@ const stepType = {
106
139
  return schema.additionalProperties;
107
140
  }
108
141
  if (schema.additionalProperties === true) {
109
- return createSchemaOf(data);
142
+ return createSchemaOf(data[key]);
110
143
  }
111
- return errors.unknownPropertyError({ property: key, value: data, pointer });
144
+ return errors.unknownPropertyError({
145
+ property: key,
146
+ value: data,
147
+ // pointer: `${pointer}/${key}`,
148
+ pointer: `${pointer}`
149
+ });
112
150
  }
113
151
  };
114
152
  /**
@@ -118,17 +156,33 @@ const stepType = {
118
156
  * This helper determines the location of the property within the schema (additional properties, oneOf, ...) and
119
157
  * returns the correct schema.
120
158
  *
121
- * @param core - validator
122
- * @param key - property-name or array-index
123
- * @param schema - json schema of current data
159
+ * @param core - validator
160
+ * @param key - property-name or array-index
161
+ * @param schema - json schema of current data
124
162
  * @param data - parent of key
125
- * @param [pointer]
163
+ * @param [pointer] - pointer to schema and data (parent of key)
126
164
  * @return Schema or Error if failed resolving key
127
165
  */
128
166
  export default function step(core, key, schema, data, pointer = "#") {
167
+ // @draft >= 4 ?
168
+ if (Array.isArray(schema.type)) {
169
+ const dataType = getTypeOf(data);
170
+ if (schema.type.includes(dataType)) {
171
+ // @ts-ignore
172
+ return stepType[dataType](core, `${key}`, schema, data, pointer);
173
+ }
174
+ return core.errors.typeError({
175
+ value: data,
176
+ pointer,
177
+ expected: schema.type,
178
+ received: dataType
179
+ });
180
+ }
129
181
  const expectedType = schema.type || getTypeOf(data);
130
- if (stepType[expectedType]) {
131
- return stepType[expectedType](core, key, schema, data, pointer);
182
+ // @ts-ignore
183
+ const stepFunction = stepType[expectedType];
184
+ if (stepFunction) {
185
+ return stepFunction(core, `${key}`, schema, data, pointer);
132
186
  }
133
187
  return new Error(`Unsupported schema type ${schema.type} for key ${key}`);
134
188
  }
@@ -1 +1,7 @@
1
- export {};
1
+ /**
2
+ * ts type guard for json error
3
+ * @returns true if passed type is a JSONError
4
+ */
5
+ export function isJSONError(error) {
6
+ return (error === null || error === void 0 ? void 0 : error.type) === "error";
7
+ }
@@ -1,6 +1,6 @@
1
1
  import __ from "./__";
2
- function dashCase(str) {
3
- return str.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
2
+ function dashCase(text) {
3
+ return text.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
4
4
  }
5
5
  export function createError(name, data) {
6
6
  return {
@@ -13,11 +13,11 @@ export function createError(name, data) {
13
13
  }
14
14
  /**
15
15
  * Creates a custom Error-Constructor which instances may be identified by `customError instanceof Error`. Its messages
16
- * are defined by strings-object __@see config/strings.ts
16
+ * are defined by strings-object @see config/strings.ts
17
17
  *
18
18
  * @param name - id of error (camelcased)
19
19
  * @return error constructor function
20
20
  */
21
- export default function createCustomError(name) {
21
+ export function createCustomError(name) {
22
22
  return createError.bind(null, name);
23
23
  }
@@ -1,12 +1,10 @@
1
+ import { isJSONError } from "../types";
1
2
  export function isPromise(obj) {
2
3
  return obj instanceof Promise;
3
4
  }
4
- export function isError(obj) {
5
- return obj && obj.type === "error";
6
- }
7
5
  export function errorOrPromise(error) {
8
- return isError(error) || isPromise(error);
6
+ return isJSONError(error) || isPromise(error);
9
7
  }
10
8
  export function errorsOnly(error) {
11
- return isError(error);
9
+ return isJSONError(error);
12
10
  }