-
Notifications
You must be signed in to change notification settings - Fork 32
Expand file tree
/
Copy pathifthenelse.ts
More file actions
121 lines (114 loc) · 4.71 KB
/
ifthenelse.ts
File metadata and controls
121 lines (114 loc) · 4.71 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
import { mergeSchema } from "../utils/mergeSchema";
import { Keyword, JsonSchemaReducerParams, JsonSchemaValidatorParams, ValidationAnnotation } from "../Keyword";
import { isBooleanSchema, isJsonSchema, SchemaNode } from "../types";
import { validateNode } from "../validateNode";
import { collectValidationErrors } from "src/utils/collectValidationErrors";
export const ifKeyword: Keyword = {
id: "if-then-else",
keyword: "if",
parse: parseIfThenElse,
addReduce: (node: SchemaNode) => node.if != null && (node.then != null || node.else != null),
reduce: reduceIf,
addValidate: (node) => node.if != null,
validate: validateIfThenElse
};
export function parseIfThenElse(node: SchemaNode) {
const { schema, evaluationPath } = node;
const errors: ValidationAnnotation[] = [];
if (schema.if != null) {
if (isJsonSchema(schema.if) || isBooleanSchema(schema.if)) {
node.if = node.compileSchema(schema.if, `${evaluationPath}/if`);
collectValidationErrors(errors, node.if);
} else {
errors.push(
node.createError("schema-error", {
pointer: `${node.schemaLocation}/if`,
schema: node.schema,
value: schema.if,
message: `Keyword 'if' must be valid JSON Schema - received '${typeof schema.if}'`
})
);
}
}
if (schema.then != null) {
if (isJsonSchema(schema.then) || isBooleanSchema(schema.then)) {
node.then = node.compileSchema(schema.then, `${evaluationPath}/then`);
collectValidationErrors(errors, node.then);
} else {
errors.push(
node.createError("schema-error", {
pointer: `${node.schemaLocation}/then`,
schema: node.schema,
value: schema.then,
message: `Keyword 'then' must be valid JSON Schema - received '${typeof schema.then}'`
})
);
}
}
if (schema.else != null) {
if (isJsonSchema(schema.else) || isBooleanSchema(schema.else)) {
node.else = node.compileSchema(schema.else, `${evaluationPath}/else`);
collectValidationErrors(errors, node.else);
} else {
errors.push(
node.createError("schema-error", {
pointer: `${node.schemaLocation}/else`,
schema: node.schema,
value: schema.else,
message: `Keyword 'else' must be valid JSON Schema - received '${typeof schema.else}'`
})
);
}
}
return errors;
}
function reduceIf({ node, data, pointer, path }: JsonSchemaReducerParams) {
// @todo issue with mergeNode (node.if == null)
if (data === undefined || node.if == null) {
return undefined;
}
if (validateNode(node.if, data, pointer, [...(path ?? [])]).length === 0) {
if (node.then) {
// reduce creates a new node
const { node: schemaNode } = node.then.reduceNode(data);
if (schemaNode) {
const nestedDynamicId = schemaNode.dynamicId?.replace(node.dynamicId, "").replace(/^#/, "") ?? "";
const dynamicId = nestedDynamicId === "" ? `(then)` : nestedDynamicId;
const schema = mergeSchema(node.then.schema, schemaNode.schema, "if", "then", "else");
return node.compileSchema(
schema,
node.then.evaluationPath,
node.schemaLocation,
`${node.schemaLocation}${dynamicId}`
);
}
}
} else if (node.else) {
const { node: schemaNode } = node.else.reduceNode(data);
if (schemaNode) {
const nestedDynamicId = schemaNode.dynamicId?.replace(node.dynamicId, "") ?? "";
const dynamicId = nestedDynamicId === "" ? `(else)` : nestedDynamicId;
const schema = mergeSchema(node.else.schema, schemaNode.schema, "if", "then", "else");
return node.compileSchema(
schema,
node.else.evaluationPath,
node.schemaLocation,
`${node.schemaLocation}${dynamicId}`
);
}
}
return undefined;
}
function validateIfThenElse({ node, data, pointer, path }: JsonSchemaValidatorParams) {
// @todo issue with mergeNode
if (node.if == null) {
return;
}
if (validateNode(node.if, data, pointer, [...(path ?? [])]).length === 0) {
if (node.then) {
return validateNode(node.then, data, pointer, path);
}
} else if (node.else) {
return validateNode(node.else, data, pointer, path);
}
}