json-schema-library 5.2.1 → 6.1.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 (115) hide show
  1. package/.prettierignore +1 -0
  2. package/.prettierrc +7 -0
  3. package/README.md +9 -8
  4. package/dist/index.d.ts +13 -44
  5. package/dist/jsonSchemaLibrary.js +1 -1
  6. package/dist/lib/addValidator.d.ts +2 -1
  7. package/dist/lib/compile/index.d.ts +11 -0
  8. package/dist/lib/config/strings.d.ts +1 -39
  9. package/dist/lib/cores/CoreInterface.d.ts +28 -9
  10. package/dist/lib/cores/Draft04.d.ts +2 -2
  11. package/dist/lib/cores/Draft06.d.ts +15 -0
  12. package/dist/lib/cores/Draft07.d.ts +15 -0
  13. package/dist/lib/cores/JsonEditor.d.ts +2 -2
  14. package/dist/lib/draft06/addSchema.d.ts +7 -0
  15. package/dist/lib/draft06/compile/index.d.ts +15 -0
  16. package/dist/lib/draft06/validation/keyword.d.ts +3 -0
  17. package/dist/lib/draft06/validation/type.d.ts +17 -0
  18. package/dist/lib/draft06/validation/typeKeywordMapping.d.ts +13 -0
  19. package/dist/lib/getChildSchemaSelection.d.ts +7 -5
  20. package/dist/lib/getSchema.d.ts +1 -1
  21. package/dist/lib/getTemplate.d.ts +5 -1
  22. package/dist/lib/getTypeOf.d.ts +2 -1
  23. package/dist/lib/schema/getTypeId.d.ts +1 -1
  24. package/dist/lib/step.d.ts +4 -4
  25. package/dist/lib/types.d.ts +10 -2
  26. package/dist/lib/utils/filter.d.ts +0 -1
  27. package/dist/lib/utils/merge.d.ts +3 -0
  28. package/dist/lib/validate.d.ts +1 -1
  29. package/dist/lib/validation/format.d.ts +6 -0
  30. package/dist/lib/validation/keyword.d.ts +2 -27
  31. package/dist/lib/validation/type.d.ts +3 -10
  32. package/dist/lib/validation/typeKeywordMapping.d.ts +4 -4
  33. package/dist/module/index.js +13 -6
  34. package/dist/module/lib/addValidator.js +3 -4
  35. package/dist/module/lib/compile/getRef.js +1 -1
  36. package/dist/module/lib/compile/index.js +11 -0
  37. package/dist/module/lib/config/strings.js +15 -2
  38. package/dist/module/lib/cores/CoreInterface.js +22 -0
  39. package/dist/module/lib/cores/Draft06.js +61 -0
  40. package/dist/module/lib/cores/Draft07.js +61 -0
  41. package/dist/module/lib/createSchemaOf.js +1 -1
  42. package/dist/module/lib/draft06/addSchema.js +11 -0
  43. package/dist/module/lib/draft06/compile/index.js +65 -0
  44. package/dist/module/lib/draft06/validation/keyword.js +156 -0
  45. package/dist/module/lib/draft06/validation/type.js +30 -0
  46. package/dist/module/lib/draft06/validation/typeKeywordMapping.js +15 -0
  47. package/dist/module/lib/each.js +1 -1
  48. package/dist/module/lib/eachSchema.js +3 -3
  49. package/dist/module/lib/getChildSchemaSelection.js +7 -6
  50. package/dist/module/lib/getSchema.js +2 -1
  51. package/dist/module/lib/getTemplate.js +57 -23
  52. package/dist/module/lib/resolveAllOf.js +3 -4
  53. package/dist/module/lib/resolveOneOf.fuzzy.js +13 -3
  54. package/dist/module/lib/resolveOneOf.strict.js +11 -2
  55. package/dist/module/lib/resolveRef.strict.js +8 -0
  56. package/dist/module/lib/schema/getTypeDefs.js +12 -1
  57. package/dist/module/lib/schema/getTypeId.js +1 -1
  58. package/dist/module/lib/step.js +62 -11
  59. package/dist/module/lib/types.js +7 -1
  60. package/dist/module/lib/utils/filter.js +3 -5
  61. package/dist/module/lib/utils/merge.js +3 -0
  62. package/dist/module/lib/validate.js +33 -8
  63. package/dist/module/lib/validateAsync.js +7 -7
  64. package/dist/module/lib/validation/errors.js +15 -2
  65. package/dist/module/lib/validation/format.js +105 -4
  66. package/dist/module/lib/validation/keyword.js +77 -30
  67. package/dist/module/lib/validation/type.js +2 -1
  68. package/dist/module/remotes/draft06.json +155 -0
  69. package/dist/module/remotes/draft07.json +172 -0
  70. package/dist/module/remotes/index.js +0 -1
  71. package/dist/remotes/index.d.ts +0 -1
  72. package/index.ts +14 -5
  73. package/lib/addValidator.ts +5 -5
  74. package/lib/compile/getRef.ts +1 -1
  75. package/lib/compile/index.ts +11 -1
  76. package/lib/config/strings.ts +17 -3
  77. package/lib/cores/CoreInterface.ts +37 -10
  78. package/lib/cores/Draft04.ts +2 -4
  79. package/lib/cores/Draft06.ts +76 -0
  80. package/lib/cores/Draft07.ts +75 -0
  81. package/lib/cores/JsonEditor.ts +2 -4
  82. package/lib/createSchemaOf.ts +1 -3
  83. package/lib/draft06/addSchema.ts +14 -0
  84. package/lib/draft06/compile/index.ts +68 -0
  85. package/lib/draft06/validation/keyword.ts +177 -0
  86. package/lib/draft06/validation/type.ts +43 -0
  87. package/lib/draft06/validation/typeKeywordMapping.ts +15 -0
  88. package/lib/each.ts +8 -3
  89. package/lib/eachSchema.ts +3 -3
  90. package/lib/getChildSchemaSelection.ts +14 -7
  91. package/lib/getSchema.ts +15 -7
  92. package/lib/getTemplate.ts +148 -38
  93. package/lib/getTypeOf.ts +2 -1
  94. package/lib/resolveAllOf.ts +9 -5
  95. package/lib/resolveOneOf.fuzzy.ts +25 -8
  96. package/lib/resolveOneOf.strict.ts +17 -4
  97. package/lib/resolveRef.strict.ts +9 -0
  98. package/lib/schema/getTypeDefs.ts +14 -1
  99. package/lib/schema/getTypeId.ts +2 -2
  100. package/lib/step.ts +103 -22
  101. package/lib/types.ts +21 -4
  102. package/lib/utils/filter.ts +4 -6
  103. package/lib/utils/merge.ts +4 -0
  104. package/lib/validate.ts +45 -15
  105. package/lib/validateAsync.ts +13 -12
  106. package/lib/validation/errors.ts +15 -2
  107. package/lib/validation/format.ts +113 -4
  108. package/lib/validation/keyword.ts +147 -78
  109. package/lib/validation/type.ts +5 -1
  110. package/package.json +73 -63
  111. package/remotes/draft06.json +155 -0
  112. package/remotes/draft07.json +172 -0
  113. package/remotes/draft2019-09.json +86 -0
  114. package/remotes/index.ts +0 -2
  115. package/tsconfig.json +2 -9
@@ -0,0 +1,61 @@
1
+ import CoreInterface from "./CoreInterface";
2
+ import step from "../step";
3
+ import validate from "../validate";
4
+ import resolveOneOf from "../resolveOneOf.strict";
5
+ import resolveRef from "../resolveRef.strict";
6
+ import getTemplate from "../getTemplate";
7
+ import getSchema from "../getSchema";
8
+ import each from "../each";
9
+ import compileSchema from "../draft06/compile";
10
+ import remotes from "../../remotes";
11
+ import draft06 from "../../remotes/draft06.json";
12
+ // @ts-ignore
13
+ remotes["http://json-schema.org/draft-06/schema"] = compileSchema(draft06);
14
+ import TYPE_KEYWORD_MAPPING from "../draft06/validation/typeKeywordMapping";
15
+ import KEYWORDS from "../draft06/validation/keyword";
16
+ import TYPES from "../draft06/validation/type";
17
+ import FORMATS from "../validation/format";
18
+ import ERRORS from "../validation/errors";
19
+ export default class Draft06Core extends CoreInterface {
20
+ constructor(schema) {
21
+ super(schema);
22
+ this.typeKeywords = JSON.parse(JSON.stringify(TYPE_KEYWORD_MAPPING));
23
+ this.validateKeyword = Object.assign({}, KEYWORDS);
24
+ this.validateType = Object.assign({}, TYPES);
25
+ this.validateFormat = Object.assign({}, FORMATS);
26
+ this.errors = Object.assign({}, ERRORS);
27
+ }
28
+ get rootSchema() {
29
+ return this.__rootSchema;
30
+ }
31
+ set rootSchema(rootSchema) {
32
+ if (rootSchema == null) {
33
+ return;
34
+ }
35
+ this.__rootSchema = compileSchema(rootSchema);
36
+ }
37
+ each(data, callback, schema = this.rootSchema, pointer = "#") {
38
+ each(this, data, callback, schema, pointer);
39
+ }
40
+ validate(data, schema = this.rootSchema, pointer = "#") {
41
+ return validate(this, data, schema, pointer);
42
+ }
43
+ isValid(data, schema = this.rootSchema, pointer = "#") {
44
+ return this.validate(data, schema, pointer).length === 0;
45
+ }
46
+ resolveOneOf(data, schema, pointer) {
47
+ return resolveOneOf(this, data, schema, pointer);
48
+ }
49
+ resolveRef(schema) {
50
+ return resolveRef(schema, this.rootSchema);
51
+ }
52
+ getSchema(pointer, data, schema = this.rootSchema) {
53
+ return getSchema(this, pointer, data, schema);
54
+ }
55
+ getTemplate(data, schema = this.rootSchema) {
56
+ return getTemplate(this, data, schema);
57
+ }
58
+ step(key, schema, data, pointer = "#") {
59
+ return step(this, key, schema, data, pointer);
60
+ }
61
+ }
@@ -0,0 +1,61 @@
1
+ import CoreInterface from "./CoreInterface";
2
+ import step from "../step";
3
+ import validate from "../validate";
4
+ import resolveOneOf from "../resolveOneOf.strict";
5
+ import resolveRef from "../resolveRef.strict";
6
+ import getTemplate from "../getTemplate";
7
+ import getSchema from "../getSchema";
8
+ import addSchema from "../addSchema";
9
+ import each from "../each";
10
+ import compileSchema from "../draft06/compile";
11
+ import draft07 from "../../remotes/draft07.json";
12
+ import TYPE_KEYWORD_MAPPING from "../draft06/validation/typeKeywordMapping";
13
+ import KEYWORDS from "../draft06/validation/keyword";
14
+ import TYPES from "../draft06/validation/type";
15
+ import FORMATS from "../validation/format";
16
+ import ERRORS from "../validation/errors";
17
+ import addValidator from "../addValidator";
18
+ addSchema("http://json-schema.org/draft-07/schema", draft07);
19
+ export default class Draft07Core extends CoreInterface {
20
+ constructor(schema) {
21
+ super(schema);
22
+ this.typeKeywords = JSON.parse(JSON.stringify(TYPE_KEYWORD_MAPPING));
23
+ Object.assign(this.validateKeyword, KEYWORDS);
24
+ Object.assign(this.validateType, TYPES);
25
+ Object.keys(FORMATS).forEach((id) => addValidator.format(this, id, FORMATS[id]));
26
+ Object.keys(ERRORS).forEach((id) => addValidator.error(this, id, ERRORS[id]));
27
+ }
28
+ get rootSchema() {
29
+ return this.__rootSchema;
30
+ }
31
+ set rootSchema(rootSchema) {
32
+ if (rootSchema == null) {
33
+ return;
34
+ }
35
+ this.__rootSchema = compileSchema(rootSchema);
36
+ }
37
+ each(data, callback, schema = this.rootSchema, pointer = "#") {
38
+ each(this, data, callback, schema, pointer);
39
+ }
40
+ validate(data, schema = this.rootSchema, pointer = "#") {
41
+ return validate(this, data, schema, pointer);
42
+ }
43
+ isValid(data, schema = this.rootSchema, pointer = "#") {
44
+ return this.validate(data, schema, pointer).length === 0;
45
+ }
46
+ resolveOneOf(data, schema, pointer) {
47
+ return resolveOneOf(this, data, schema, pointer);
48
+ }
49
+ resolveRef(schema) {
50
+ return resolveRef(schema, this.rootSchema);
51
+ }
52
+ getSchema(pointer, data, schema = this.rootSchema) {
53
+ return getSchema(this, pointer, data, schema);
54
+ }
55
+ getTemplate(data, schema = this.rootSchema) {
56
+ return getTemplate(this, data, schema);
57
+ }
58
+ step(key, schema, data, pointer = "#") {
59
+ return step(this, key, schema, data, pointer);
60
+ }
61
+ }
@@ -10,7 +10,7 @@ export default function createSchemaOf(data) {
10
10
  };
11
11
  if (schema.type === "object") {
12
12
  schema.properties = {};
13
- Object.keys(data).forEach(key => (schema.properties[key] = createSchemaOf(data[key])));
13
+ Object.keys(data).forEach((key) => (schema.properties[key] = createSchemaOf(data[key])));
14
14
  }
15
15
  if (schema.type === "array" && data.length === 1) {
16
16
  schema.items = createSchemaOf(data[0]);
@@ -0,0 +1,11 @@
1
+ import remotes from "../../remotes";
2
+ import compileSchema from "./compile";
3
+ /**
4
+ * register a json-schema to be referenced from another json-schema
5
+ * @param url base-url of json-schema (aka id)
6
+ * @param schema
7
+ */
8
+ export default function addSchema(url, schema) {
9
+ schema.id = schema.id || url;
10
+ remotes[url] = compileSchema(schema);
11
+ }
@@ -0,0 +1,65 @@
1
+ /* eslint max-statements-per-line: ["error", { "max": 2 }] */
2
+ import eachSchema from "../../eachSchema";
3
+ import remotes from "../../../remotes";
4
+ import joinScope from "../../compile/joinScope";
5
+ import getRef from "../../compile/getRef";
6
+ const COMPILED = "__compiled";
7
+ const COMPILED_REF = "__ref";
8
+ const GET_REF = "getRef";
9
+ const GET_ROOT = "getRoot";
10
+ const suffixes = /(#|\/)+$/g;
11
+ /**
12
+ * @draft starting with _draft 06_ keyword `id` has been renamed to `$id`
13
+ *
14
+ * compiles the input root schema for $ref resolution and returns it again
15
+ * @attention this modifies input schema but maintains object-structure
16
+ *
17
+ * for a compiled json-schema you can call getRef on any contained schema (location of type).
18
+ * this resolves a $ref target to a valid schema (for a valid $ref)
19
+ *
20
+ * @param rootSchema root json-schema ($id, defs, ... ) to compile
21
+ * @param [force] = false force compile json-schema
22
+ * @return compiled json-schema
23
+ */
24
+ export default function compile(rootSchema, force = false) {
25
+ // @ts-ignore
26
+ if (rootSchema === true || rootSchema === false) {
27
+ return rootSchema;
28
+ }
29
+ if (rootSchema[COMPILED] !== undefined) {
30
+ return rootSchema;
31
+ } // eslint-disable-line
32
+ const context = { ids: {}, remotes: Object.assign({}, remotes) };
33
+ const rootSchemaAsString = JSON.stringify(rootSchema);
34
+ rootSchema = JSON.parse(rootSchemaAsString);
35
+ Object.defineProperty(rootSchema, COMPILED, { enumerable: false, value: true });
36
+ Object.defineProperty(rootSchema, GET_REF, { enumerable: false, value: getRef.bind(null, context, rootSchema) });
37
+ if (force === false && rootSchemaAsString.includes("$ref") === false) {
38
+ // bail early, when no $refs are defined
39
+ return rootSchema;
40
+ }
41
+ const scopes = {};
42
+ const getRoot = () => rootSchema;
43
+ eachSchema(rootSchema, (schema, pointer) => {
44
+ if (schema.$id) {
45
+ context.ids[schema.$id.replace(suffixes, "")] = pointer;
46
+ }
47
+ // build up scopes and add them to $ref-resolution map
48
+ pointer = `#${pointer}`.replace(/##+/, "#");
49
+ const previousPointer = pointer.replace(/\/[^/]+$/, "");
50
+ const parentPointer = pointer.replace(/\/[^/]+\/[^/]+$/, "");
51
+ const previousScope = scopes[previousPointer] || scopes[parentPointer];
52
+ const scope = joinScope(previousScope, schema.$id);
53
+ scopes[pointer] = scope;
54
+ if (context.ids[scope] == null) {
55
+ context.ids[scope] = pointer;
56
+ }
57
+ if (schema.$ref) {
58
+ Object.defineProperty(schema, COMPILED_REF, { enumerable: false, value: joinScope(scope, schema.$ref) });
59
+ // @todo currently not used:
60
+ Object.defineProperty(schema, GET_ROOT, { enumerable: false, value: getRoot });
61
+ // console.log("compiled ref", scope, schema.$ref, "=>", joinScope(scope, schema.$ref));
62
+ }
63
+ });
64
+ return rootSchema;
65
+ }
@@ -0,0 +1,156 @@
1
+ import Keywords from "../../validation/keyword";
2
+ import getTypeOf from "../../getTypeOf";
3
+ const KeywordValidation = {
4
+ ...Keywords,
5
+ // @draft >= 6
6
+ contains: (core, schema, value, pointer) => {
7
+ if (schema.contains === false) {
8
+ return core.errors.containsArrayError({ pointer, value });
9
+ }
10
+ if (schema.contains === true) {
11
+ if (Array.isArray(value) && value.length === 0) {
12
+ return core.errors.containsAnyError({ pointer });
13
+ }
14
+ return undefined;
15
+ }
16
+ if (getTypeOf(schema.contains) !== "object") {
17
+ // ignore invalid schema
18
+ return undefined;
19
+ }
20
+ for (let i = 0; i < value.length; i += 1) {
21
+ if (core.isValid(value[i], schema.contains)) {
22
+ return undefined;
23
+ }
24
+ }
25
+ return core.errors.containsError({ pointer, schema: JSON.stringify(schema.contains) });
26
+ },
27
+ exclusiveMaximum: (core, schema, value, pointer) => {
28
+ if (isNaN(schema.exclusiveMaximum)) {
29
+ return undefined;
30
+ }
31
+ if (schema.exclusiveMaximum <= value) {
32
+ return core.errors.maximumError({ maximum: schema.exclusiveMaximum, length: value, pointer });
33
+ }
34
+ return undefined;
35
+ },
36
+ exclusiveMinimum: (core, schema, value, pointer) => {
37
+ if (isNaN(schema.exclusiveMinimum)) {
38
+ return undefined;
39
+ }
40
+ if (schema.exclusiveMinimum >= value) {
41
+ return core.errors.minimumError({ minimum: schema.exclusiveMinimum, length: value, pointer });
42
+ }
43
+ return undefined;
44
+ },
45
+ if: (core, schema, value, pointer) => {
46
+ if (schema.if == null) {
47
+ return undefined;
48
+ }
49
+ const ifErrors = core.validate(value, schema.if, pointer);
50
+ // console.log("if Errors", value, ifErrors);
51
+ if (ifErrors.length === 0 && schema.then) {
52
+ return core.validate(value, schema.then, pointer);
53
+ }
54
+ if (ifErrors.length !== 0 && schema.else) {
55
+ return core.validate(value, schema.else, pointer);
56
+ }
57
+ },
58
+ maximum: (core, schema, value, pointer) => {
59
+ if (isNaN(schema.maximum)) {
60
+ return undefined;
61
+ }
62
+ if (schema.maximum && schema.maximum < value) {
63
+ return core.errors.maximumError({ maximum: schema.maximum, length: value, pointer });
64
+ }
65
+ return undefined;
66
+ },
67
+ minimum: (core, schema, value, pointer) => {
68
+ if (isNaN(schema.minimum)) {
69
+ return undefined;
70
+ }
71
+ if (schema.minimum > value) {
72
+ return core.errors.minimumError({ minimum: schema.minimum, length: value, pointer });
73
+ }
74
+ return undefined;
75
+ },
76
+ patternProperties: (core, schema, value, pointer) => {
77
+ const properties = schema.properties || {};
78
+ const pp = schema.patternProperties;
79
+ if (getTypeOf(pp) !== "object") {
80
+ return undefined;
81
+ }
82
+ const errors = [];
83
+ const keys = Object.keys(value);
84
+ const patterns = Object.keys(pp).map(expr => ({
85
+ regex: new RegExp(expr),
86
+ patternSchema: pp[expr]
87
+ }));
88
+ keys.forEach(key => {
89
+ let patternFound = false;
90
+ for (let i = 0, l = patterns.length; i < l; i += 1) {
91
+ if (patterns[i].regex.test(key)) {
92
+ patternFound = true;
93
+ // for a boolean schema `false`, always invalidate
94
+ if (patterns[i].patternSchema === false) {
95
+ errors.push(core.errors.patternPropertiesError({
96
+ key, pointer, patterns: Object.keys(pp).join(",")
97
+ }));
98
+ return;
99
+ }
100
+ const valErrors = core.validate(value[key], patterns[i].patternSchema, `${pointer}/${key}`);
101
+ if (valErrors && valErrors.length > 0) {
102
+ errors.push(...valErrors);
103
+ }
104
+ }
105
+ }
106
+ if (properties[key]) {
107
+ return;
108
+ }
109
+ if (patternFound === false && schema.additionalProperties === false) {
110
+ // this is an arrangement with additionalProperties
111
+ errors.push(core.errors.patternPropertiesError({
112
+ key, pointer, patterns: Object.keys(pp).join(",")
113
+ }));
114
+ }
115
+ });
116
+ return errors;
117
+ },
118
+ // @draft >= 6
119
+ propertyNames: (core, schema, value, pointer) => {
120
+ // bool schema
121
+ if (schema.propertyNames === false) {
122
+ // empty objects are valid
123
+ if (Object.keys(value).length === 0) {
124
+ return undefined;
125
+ }
126
+ return core.errors.invalidPropertyNameError({
127
+ property: Object.keys(value),
128
+ pointer,
129
+ value
130
+ });
131
+ }
132
+ if (schema.propertyNames === true) {
133
+ return undefined;
134
+ }
135
+ if (getTypeOf(schema.propertyNames) !== "object") {
136
+ // ignore invalid schema
137
+ return undefined;
138
+ }
139
+ const errors = [];
140
+ const properties = Object.keys(value);
141
+ const propertySchema = { ...schema.propertyNames, type: "string" };
142
+ properties.forEach(prop => {
143
+ const validationResult = core.validate(prop, propertySchema, `${pointer}/${prop}`);
144
+ if (validationResult.length > 0) {
145
+ errors.push(core.errors.invalidPropertyNameError({
146
+ property: prop,
147
+ pointer,
148
+ validationError: validationResult[0],
149
+ value: value[prop]
150
+ }));
151
+ }
152
+ });
153
+ return errors;
154
+ }
155
+ };
156
+ export default KeywordValidation;
@@ -0,0 +1,30 @@
1
+ /**
2
+ * @todo: type is also a keyword, as is properties, items, etc
3
+ *
4
+ * An instance has one of six primitive types (http://json-schema.org/latest/json-schema-core.html#rfc.section.4.2)
5
+ * or seven in case of ajv https://github.com/epoberezkin/ajv/blob/master/KEYWORDS.md#type
6
+ * 1 null, 2 boolean, 3 object, 4 array, 5 number, 6 string (7 integer)
7
+ */
8
+ export default {
9
+ array: (core, schema, value, pointer) => core.typeKeywords.array
10
+ .filter(key => schema && schema[key] != null)
11
+ .map(key => core.validateKeyword[key](core, schema, value, pointer)),
12
+ object: (core, schema, value, pointer) => core.typeKeywords.object
13
+ .filter(key => schema && schema[key] != null)
14
+ .map(key => core.validateKeyword[key](core, schema, value, pointer)),
15
+ string: (core, schema, value, pointer) => core.typeKeywords.string
16
+ .filter(key => schema && schema[key] != null)
17
+ .map(key => core.validateKeyword[key](core, schema, value, pointer)),
18
+ integer: (core, schema, value, pointer) => core.typeKeywords.number
19
+ .filter(key => schema && schema[key] != null)
20
+ .map(key => core.validateKeyword[key](core, schema, value, pointer)),
21
+ number: (core, schema, value, pointer) => core.typeKeywords.number
22
+ .filter(key => schema && schema[key] != null)
23
+ .map(key => core.validateKeyword[key](core, schema, value, pointer)),
24
+ "boolean": (core, schema, value, pointer) => core.typeKeywords.boolean
25
+ .filter(key => schema && schema[key] != null)
26
+ .map(key => core.validateKeyword[key](core, schema, value, pointer)),
27
+ "null": (core, schema, value, pointer) => core.typeKeywords.null
28
+ .filter(key => schema && schema[key] != null)
29
+ .map(key => core.validateKeyword[key](core, schema, value, pointer))
30
+ };
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Mapping, used in type validation to iterate over type-specific keywords to validate
3
+ * - overview https://epoberezkin.github.io/ajv/keywords.html
4
+ */
5
+ export default {
6
+ array: ["enum", "contains", "items", "minItems", "maxItems", "uniqueItems", "not", "if"],
7
+ boolean: ["enum", "not"],
8
+ object: [
9
+ "additionalProperties", "dependencies", "enum", "format", "minProperties", "maxProperties",
10
+ "patternProperties", "properties", "propertyNames", "required", "not", "oneOf", "allOf", "anyOf", "if"
11
+ ],
12
+ string: ["enum", "format", "maxLength", "minLength", "pattern", "not", "oneOf", "allOf", "anyOf", "if"],
13
+ number: ["enum", "exclusiveMaximum", "exclusiveMinimum", "format", "maximum", "minimum", "multipleOf", "not", "oneOf", "allOf", "anyOf", "if"],
14
+ null: ["enum", "format", "not", "oneOf", "allOf", "anyOf"]
15
+ };
@@ -12,7 +12,7 @@ export default function each(core, data, callback, schema = core.rootSchema, poi
12
12
  callback(schema, data, pointer);
13
13
  const dataType = getTypeOf(data);
14
14
  if (dataType === "object") {
15
- Object.keys(data).forEach(key => {
15
+ Object.keys(data).forEach((key) => {
16
16
  const nextSchema = core.step(key, schema, data, pointer); // not save
17
17
  const next = data[key]; // save
18
18
  core.each(next, callback, nextSchema, `${pointer}/${key}`);
@@ -12,11 +12,11 @@ function nextTypeDefs(schema, pointer) {
12
12
  function eachDefinition(walk, schema, pointer) {
13
13
  Object.keys(schema.definitions)
14
14
  .forEach(defId => {
15
- if (!isObject(schema.definitions[defId])) {
16
- console.log(`Invalid schema in ${pointer}/definitions/${defId}`);
15
+ if (schema.definitions[defId] === false || isObject(schema.definitions[defId])) {
16
+ walk.nextTypeDefs(schema.definitions[defId], gp.join(pointer, "definitions", defId, false));
17
17
  return;
18
18
  }
19
- walk.nextTypeDefs(schema.definitions[defId], gp.join(pointer, "definitions", defId, false));
19
+ console.log(`Invalid schema in ${pointer}/definitions/${defId}`);
20
20
  });
21
21
  }
22
22
  export default function eachSchema(schema, callback, pointer = "#") {
@@ -1,18 +1,19 @@
1
+ import { isJSONError } from "./types";
1
2
  /**
2
3
  * Returns a list of possible child-schemas for the given property key. In case of a oneOf selection, multiple schemas
3
4
  * could be added at the given property (e.g. item-index), thus an array of options is returned. In all other cases
4
5
  * a list with a single item will be returned
5
6
  *
6
- * @param {Core} core - core to use
7
- * @param {String} property - parent schema of following property
8
- * @param {Object} [schema] - parent schema of following property
9
- * @return {Object}
7
+ * @param core - core to use
8
+ * @param property - parent schema of following property
9
+ * @param [schema] - parent schema of following property
10
+ * @return
10
11
  */
11
12
  export default function getChildSchemaSelection(core, property, schema = core.rootSchema) {
12
13
  const result = core.step(property, schema, {}, "#");
13
- if (result.type === "error") {
14
+ if (isJSONError(result)) {
14
15
  if (result.code === "one-of-error") {
15
- return result.data.oneOf.map(item => core.resolveRef(item));
16
+ return result.data.oneOf.map((item) => core.resolveRef(item));
16
17
  }
17
18
  return result;
18
19
  }
@@ -1,4 +1,5 @@
1
1
  import gp from "gson-pointer";
2
+ import { isJSONError } from "./types";
2
3
  const emptyObject = {};
3
4
  /**
4
5
  * Returns the json-schema of a data-json-pointer.
@@ -23,7 +24,7 @@ function _get(core, schema, frags, pointer, data = emptyObject) {
23
24
  }
24
25
  const key = frags.shift(); // step key
25
26
  schema = core.step(key, schema, data, pointer); // step schema
26
- if (schema && schema.type === "error") {
27
+ if (isJSONError(schema)) {
27
28
  return schema;
28
29
  }
29
30
  data = data[key]; // step data
@@ -4,6 +4,10 @@ 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";
8
+ const defaultOptions = {
9
+ addOptionalProps: true
10
+ };
7
11
  let cache;
8
12
  function shouldResolveRef(schema, pointer) {
9
13
  // ensure we refactored consistently
@@ -14,7 +18,7 @@ function shouldResolveRef(schema, pointer) {
14
18
  if ($ref == null) {
15
19
  return true;
16
20
  }
17
- 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];
18
22
  return value < settings.GET_TEMPLATE_RECURSION_LIMIT;
19
23
  }
20
24
  function resolveRef(core, schema, pointer) {
@@ -102,7 +106,7 @@ const isJSONSchema = (template) => template && typeof template === "object";
102
106
  * @param [schema] - json schema, defaults to rootSchema
103
107
  * @return created template data
104
108
  */
105
- function getTemplate(core, data, _schema, pointer) {
109
+ function getTemplate(core, data, _schema, pointer, opts) {
106
110
  if (_schema == null) {
107
111
  throw new Error(`getTemplate: missing schema for data: ${JSON.stringify(data)}`);
108
112
  }
@@ -115,13 +119,16 @@ function getTemplate(core, data, _schema, pointer) {
115
119
  return undefined;
116
120
  }
117
121
  pointer = schema.pointer;
122
+ if (schema === null || schema === void 0 ? void 0 : schema.const) {
123
+ return schema.const;
124
+ }
118
125
  if (schema.oneOf) {
119
126
  // find correct schema for data
120
127
  const resolvedSchema = resolveOneOfFuzzy(core, data, schema);
121
- if (data == null && resolvedSchema.type === "error") {
128
+ if (data == null && isJSONError(resolvedSchema)) {
122
129
  schema = schema.oneOf[0];
123
130
  }
124
- else if (resolvedSchema.type === "error") {
131
+ else if (isJSONError(resolvedSchema.type)) {
125
132
  // @todo - check: do not return schema, but either input-data or undefined (clearing wrong data)
126
133
  return data;
127
134
  }
@@ -129,6 +136,9 @@ function getTemplate(core, data, _schema, pointer) {
129
136
  schema = resolvedSchema;
130
137
  }
131
138
  }
139
+ // @todo Array.isArray(schema.type)
140
+ // -> hasDefault? return
141
+ // if not -> pick first type
132
142
  if (!isJSONSchema(schema) || schema.type == null) {
133
143
  return undefined;
134
144
  }
@@ -136,35 +146,56 @@ function getTemplate(core, data, _schema, pointer) {
136
146
  if (data != null && getTypeOf(data) !== schema.type) {
137
147
  data = convertValue(schema.type, data);
138
148
  }
139
- 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
140
151
  throw new Error(`Unsupported type '${schema.type} in ${JSON.stringify(schema)}'`);
141
152
  }
142
- const templateData = TYPE[schema.type](core, schema, data, pointer); // eslint-disable-line no-use-before-define
153
+ const templateData = TYPE[schema.type](core, schema, data, pointer, opts); // eslint-disable-line no-use-before-define
143
154
  return templateData;
144
155
  }
145
156
  const TYPE = {
146
- "string": (core, schema, data) => getDefault(schema, data, ""),
147
- "number": (core, schema, data) => getDefault(schema, data, 0),
148
- "integer": (core, schema, data) => getDefault(schema, data, 0),
149
- "boolean": (core, schema, data) => getDefault(schema, data, false),
150
- "object": (core, schema, data, pointer) => {
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) => {
151
163
  const template = schema.default === undefined ? {} : schema.default;
152
164
  const d = {}; // do not assign data here, to keep ordering from json-schema
153
165
  if (schema.properties) {
154
- Object.keys(schema.properties).forEach(key => {
155
- const value = (data == null || data[key] == null) ? template[key] : data[key];
156
- d[key] = getTemplate(core, value, schema.properties[key], `${pointer}/properties/${key}`);
166
+ Object.keys(schema.properties).forEach((key) => {
167
+ const value = data == null || data[key] == null ? template[key] : data[key];
168
+ const isRequired = Array.isArray(schema.required) && schema.required.includes(key);
169
+ // Omit adding a property if it is not required or optional props should be added
170
+ if (value != null || isRequired || opts.addOptionalProps) {
171
+ d[key] = getTemplate(core, value, schema.properties[key], `${pointer}/properties/${key}`, opts);
172
+ }
173
+ });
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
+ }
157
188
  });
158
189
  }
159
190
  if (data) {
160
191
  // merge any missing data (additionals) to resulting object
161
- 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]));
162
193
  }
163
194
  // returns object, which is ordered by json-schema
164
195
  return d;
165
196
  },
166
197
  // build array type of items, ignores additionalItems
167
- "array": (core, schema, data, pointer) => {
198
+ array: (core, schema, data, pointer, opts) => {
168
199
  const template = schema.default === undefined ? [] : schema.default;
169
200
  const d = data || [];
170
201
  schema.minItems = schema.minItems || 0;
@@ -175,7 +206,7 @@ const TYPE = {
175
206
  // build defined set of items
176
207
  if (Array.isArray(schema.items)) {
177
208
  for (let i = 0, l = Math.min(schema.minItems, schema.items.length); i < l; i += 1) {
178
- d[i] = getTemplate(core, d[i] == null ? template[i] : d[i], schema.items[i], `${pointer}/items/${i}`);
209
+ d[i] = getTemplate(core, d[i] == null ? template[i] : d[i], schema.items[i], `${pointer}/items/${i}`, opts);
179
210
  }
180
211
  return d;
181
212
  }
@@ -193,7 +224,7 @@ const TYPE = {
193
224
  if (templateSchema.oneOf && d.length === 0) {
194
225
  const oneOfSchema = templateSchema.oneOf[0];
195
226
  for (let i = 0; i < schema.minItems; i += 1) {
196
- d[i] = getTemplate(core, d[i] == null ? template[i] : d[i], oneOfSchema, `${pointer}/oneOf/0`);
227
+ d[i] = getTemplate(core, d[i] == null ? template[i] : d[i], oneOfSchema, `${pointer}/oneOf/0`, opts);
197
228
  }
198
229
  return d;
199
230
  }
@@ -203,7 +234,7 @@ const TYPE = {
203
234
  const value = d[i] == null ? template[i] : d[i];
204
235
  const one = resolveOneOfFuzzy(core, value, templateSchema);
205
236
  if (one) {
206
- d[i] = getTemplate(core, value, one, `${pointer}/oneOf/${i}`);
237
+ d[i] = getTemplate(core, value, one, `${pointer}/oneOf/${i}`, opts);
207
238
  }
208
239
  else {
209
240
  d[i] = value;
@@ -214,7 +245,7 @@ const TYPE = {
214
245
  // build items-definition
215
246
  if (templateSchema.type) {
216
247
  for (let i = 0, l = Math.max(schema.minItems, d.length); i < l; i += 1) {
217
- d[i] = getTemplate(core, d[i] == null ? template[i] : d[i], templateSchema, `${pointer}/items`);
248
+ d[i] = getTemplate(core, d[i] == null ? template[i] : d[i], templateSchema, `${pointer}/items`, opts);
218
249
  }
219
250
  return d;
220
251
  }
@@ -225,6 +256,9 @@ function getDefault(schema, templateValue, initValue) {
225
256
  if (templateValue != null) {
226
257
  return templateValue;
227
258
  }
259
+ else if (schema.const) {
260
+ return schema.const;
261
+ }
228
262
  else if (schema.default === undefined && Array.isArray(schema.enum)) {
229
263
  return schema.enum[0];
230
264
  }
@@ -233,7 +267,7 @@ function getDefault(schema, templateValue, initValue) {
233
267
  }
234
268
  return schema.default;
235
269
  }
236
- export default (core, data, schema = core.rootSchema) => {
237
- cache = { "mi": ".." };
238
- return getTemplate(core, data, schema, "#");
270
+ export default (core, data, schema = core.rootSchema, opts = defaultOptions) => {
271
+ cache = { mi: ".." };
272
+ return getTemplate(core, data, schema, "#", opts);
239
273
  };