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.
- package/.editorconfig +1 -0
- package/.prettierignore +1 -0
- package/.prettierrc +7 -0
- package/CHANGELOG.md +106 -0
- package/README.md +811 -199
- package/TASKS.md +3 -81
- package/dist/index.d.ts +29 -71
- package/dist/jsonSchemaLibrary.js +1 -1
- package/dist/lib/SchemaService.d.ts +6 -8
- package/dist/lib/{addSchema.d.ts → addRemoteSchema.d.ts} +2 -1
- package/dist/lib/addValidator.d.ts +3 -2
- package/dist/lib/compile/getRef.d.ts +2 -1
- package/dist/lib/compile/index.d.ts +15 -1
- package/dist/lib/compile/types.d.ts +5 -0
- package/dist/lib/config/strings.d.ts +1 -39
- package/dist/lib/draft/index.d.ts +132 -0
- package/dist/lib/draft04/index.d.ts +7 -0
- package/dist/lib/draft06/compile/index.d.ts +16 -0
- package/dist/lib/draft06/index.d.ts +7 -0
- package/dist/lib/draft06/validation/keyword.d.ts +3 -0
- package/dist/lib/draft06/validation/type.d.ts +10 -0
- package/dist/lib/draft06/validation/typeKeywordMapping.d.ts +13 -0
- package/dist/lib/draft07/index.d.ts +7 -0
- package/dist/lib/each.d.ts +3 -2
- package/dist/lib/eachSchema.d.ts +2 -4
- package/dist/lib/getChildSchemaSelection.d.ts +7 -5
- package/dist/lib/getSchema.d.ts +2 -2
- package/dist/lib/getTemplate.d.ts +1 -1
- package/dist/lib/getTypeOf.d.ts +2 -1
- package/dist/lib/isValid.d.ts +1 -1
- package/dist/lib/jsoneditor/index.d.ts +7 -0
- package/dist/lib/resolveAllOf.d.ts +1 -1
- package/dist/lib/resolveAnyOf.d.ts +1 -1
- package/dist/lib/resolveOneOf.fuzzy.d.ts +1 -1
- package/dist/lib/resolveOneOf.strict.d.ts +2 -2
- package/dist/lib/{resolveRef.withOverwrite.d.ts → resolveRef.merge.d.ts} +0 -0
- package/dist/lib/schema/getTypeDefs.d.ts +6 -4
- package/dist/lib/schema/getTypeId.d.ts +1 -1
- package/dist/lib/schema/types.d.ts +7 -57
- package/dist/lib/step.d.ts +5 -5
- package/dist/lib/types.d.ts +11 -3
- package/dist/lib/utils/createCustomError.d.ts +8 -11
- package/dist/lib/utils/filter.d.ts +4 -4
- package/dist/lib/utils/flattenArray.d.ts +1 -1
- package/dist/lib/utils/merge.d.ts +3 -0
- package/dist/lib/utils/punycode.ucs2decode.d.ts +1 -1
- package/dist/lib/validate.d.ts +2 -2
- package/dist/lib/validateAsync.d.ts +1 -1
- package/dist/lib/validation/errors.d.ts +1 -3
- package/dist/lib/validation/format.d.ts +4 -11
- package/dist/lib/validation/keyword.d.ts +2 -27
- package/dist/lib/validation/type.d.ts +3 -10
- package/dist/lib/validation/typeKeywordMapping.d.ts +4 -4
- package/dist/module/index.js +23 -32
- package/dist/module/lib/SchemaService.js +7 -4
- package/dist/module/lib/{addSchema.js → addRemoteSchema.js} +2 -4
- package/dist/module/lib/addValidator.js +3 -4
- package/dist/module/lib/compile/getRef.js +1 -1
- package/dist/module/lib/compile/index.js +43 -18
- package/dist/module/lib/compile/types.js +1 -0
- package/dist/module/lib/config/strings.js +15 -2
- package/dist/module/lib/createSchemaOf.js +1 -1
- package/dist/module/lib/draft/index.js +133 -0
- package/dist/module/lib/draft04/index.js +90 -0
- package/dist/module/lib/draft06/compile/index.js +77 -0
- package/dist/module/lib/draft06/index.js +96 -0
- package/dist/module/lib/draft06/validation/keyword.js +168 -0
- package/dist/module/lib/draft06/validation/type.js +31 -0
- package/dist/module/lib/draft06/validation/typeKeywordMapping.js +15 -0
- package/dist/module/lib/draft07/index.js +96 -0
- package/dist/module/lib/each.js +2 -2
- package/dist/module/lib/eachSchema.js +28 -19
- package/dist/module/lib/getChildSchemaSelection.js +7 -6
- package/dist/module/lib/getSchema.js +4 -2
- package/dist/module/lib/getTemplate.js +42 -15
- package/dist/module/lib/jsoneditor/index.js +16 -0
- package/dist/module/lib/resolveAllOf.js +3 -4
- package/dist/module/lib/resolveOneOf.fuzzy.js +13 -3
- package/dist/module/lib/resolveOneOf.strict.js +49 -2
- package/dist/module/lib/{resolveRef.withOverwrite.js → resolveRef.merge.js} +0 -0
- package/dist/module/lib/resolveRef.strict.js +8 -0
- package/dist/module/lib/schema/getTypeDefs.js +14 -3
- package/dist/module/lib/schema/getTypeId.js +10 -6
- package/dist/module/lib/schema/types.js +33 -9
- package/dist/module/lib/step.js +67 -13
- package/dist/module/lib/types.js +7 -1
- package/dist/module/lib/utils/createCustomError.js +4 -4
- package/dist/module/lib/utils/filter.js +3 -5
- package/dist/module/lib/utils/flattenArray.js +4 -3
- package/dist/module/lib/utils/merge.js +4 -0
- package/dist/module/lib/utils/punycode.ucs2decode.js +4 -3
- package/dist/module/lib/validate.js +34 -8
- package/dist/module/lib/validateAsync.js +7 -7
- package/dist/module/lib/validation/errors.js +16 -3
- package/dist/module/lib/validation/format.js +115 -8
- package/dist/module/lib/validation/keyword.js +79 -32
- package/dist/module/lib/validation/type.js +2 -1
- package/index.ts +46 -32
- package/lib/SchemaService.ts +18 -11
- package/lib/{addSchema.ts → addRemoteSchema.ts} +3 -5
- package/lib/addValidator.ts +15 -12
- package/lib/compile/getRef.ts +3 -4
- package/lib/compile/index.ts +65 -19
- package/lib/compile/types.ts +6 -0
- package/lib/config/strings.ts +17 -3
- package/lib/createSchemaOf.ts +1 -3
- package/lib/draft/index.ts +201 -0
- package/lib/draft04/index.ts +95 -0
- package/lib/draft06/compile/index.ts +104 -0
- package/lib/draft06/index.ts +101 -0
- package/lib/draft06/validation/keyword.ts +199 -0
- package/lib/draft06/validation/type.ts +47 -0
- package/lib/draft06/validation/typeKeywordMapping.ts +15 -0
- package/lib/draft07/index.ts +101 -0
- package/lib/each.ts +11 -4
- package/lib/eachSchema.ts +45 -32
- package/lib/getChildSchemaSelection.ts +14 -7
- package/lib/getSchema.ts +18 -9
- package/lib/getTemplate.ts +155 -42
- package/lib/getTypeOf.ts +2 -1
- package/lib/isValid.ts +7 -3
- package/lib/jsoneditor/index.ts +20 -0
- package/lib/resolveAllOf.ts +10 -6
- package/lib/resolveAnyOf.ts +7 -3
- package/lib/resolveOneOf.fuzzy.ts +26 -9
- package/lib/resolveOneOf.strict.ts +63 -5
- package/lib/{resolveRef.withOverwrite.ts → resolveRef.merge.ts} +0 -0
- package/lib/resolveRef.strict.ts +9 -0
- package/lib/schema/getTypeDefs.ts +19 -7
- package/lib/schema/getTypeId.ts +11 -8
- package/lib/schema/types.ts +41 -9
- package/lib/step.ts +109 -25
- package/lib/types.ts +23 -5
- package/lib/utils/createCustomError.ts +8 -13
- package/lib/utils/filter.ts +7 -9
- package/lib/utils/flattenArray.ts +5 -4
- package/lib/utils/merge.ts +5 -0
- package/lib/utils/punycode.ucs2decode.ts +6 -5
- package/lib/validate.ts +47 -16
- package/lib/validateAsync.ts +15 -14
- package/lib/validation/errors.ts +17 -6
- package/lib/validation/format.ts +147 -13
- package/lib/validation/keyword.ts +172 -103
- package/lib/validation/type.ts +5 -1
- package/package.json +75 -63
- package/{dist/module/remotes/draft04.json → remotes/draft06.json} +47 -42
- package/remotes/draft07.json +172 -0
- package/remotes/draft2019-09.json +86 -0
- package/tsconfig.json +3 -10
- package/dist/lib/cores/CoreInterface.d.ts +0 -23
- package/dist/lib/cores/Draft04.d.ts +0 -13
- package/dist/lib/cores/JsonEditor.d.ts +0 -13
- package/dist/module/lib/cores/CoreInterface.js +0 -51
- package/dist/module/lib/cores/Draft04.js +0 -52
- package/dist/module/lib/cores/JsonEditor.js +0 -51
- package/dist/module/remotes/index.js +0 -10
- package/dist/remotes/index.d.ts +0 -5
- package/lib/cores/CoreInterface.ts +0 -76
- package/lib/cores/Draft04.ts +0 -66
- package/lib/cores/JsonEditor.ts +0 -64
- 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
|
-
|
|
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):
|
|
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
|
-
|
|
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
|
}
|
package/lib/schema/getTypeId.ts
CHANGED
|
@@ -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
|
-
|
|
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 (
|
|
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 (
|
|
48
|
+
if (hasOwnProperty.call(schema, keyword)) {
|
|
49
|
+
// eslint-disable-line
|
|
47
50
|
return "array";
|
|
48
51
|
}
|
|
49
52
|
}
|
package/lib/schema/types.ts
CHANGED
|
@@ -1,4 +1,11 @@
|
|
|
1
|
-
export
|
|
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: [
|
|
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
|
-
|
|
35
|
+
boolean: {
|
|
21
36
|
type: true
|
|
22
37
|
},
|
|
23
|
-
|
|
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
|
-
|
|
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: [
|
|
49
|
-
"
|
|
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: [
|
|
52
|
-
"
|
|
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 "./
|
|
7
|
-
|
|
5
|
+
import { JSONSchema, JSONPointer, JSONError, isJSONError } from "./types";
|
|
6
|
+
import { Draft as Core } from "./draft";
|
|
8
7
|
|
|
9
8
|
const stepType = {
|
|
10
|
-
|
|
11
|
-
|
|
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({
|
|
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(
|
|
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: (
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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(
|
|
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({
|
|
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
|
|
153
|
-
* @param key
|
|
154
|
-
* @param schema
|
|
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(
|
|
160
|
-
|
|
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
|
-
|
|
163
|
-
|
|
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 "./
|
|
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"
|
|
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:
|
|
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
|
-
|
|
6
|
-
(
|
|
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
|
|
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
|
|
28
|
+
export function createCustomError(name: string): CreateError {
|
|
34
29
|
return createError.bind(null, name);
|
|
35
30
|
}
|
package/lib/utils/filter.ts
CHANGED
|
@@ -1,15 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
return obj instanceof Promise;
|
|
3
|
-
}
|
|
1
|
+
import { isJSONError, JSONError } from "../types";
|
|
4
2
|
|
|
5
|
-
export function
|
|
6
|
-
return obj
|
|
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
|
|
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
|
|
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 =
|
|
1
|
+
export default function flattenArray<T = unknown>(list: unknown[], result: T[] = []): T[] {
|
|
2
2
|
for (let i = 0; i < list.length; i += 1) {
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
const item = list[i];
|
|
4
|
+
if (Array.isArray(item)) {
|
|
5
|
+
flattenArray(item, result);
|
|
5
6
|
} else {
|
|
6
|
-
result.push(
|
|
7
|
+
result.push(item as T);
|
|
7
8
|
}
|
|
8
9
|
}
|
|
9
10
|
return result;
|
package/lib/utils/merge.ts
CHANGED
|
@@ -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):
|
|
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 >=
|
|
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 &
|
|
29
|
-
|
|
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
|
}
|