schema-shield 0.0.2 → 0.0.3
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/LICENSE +201 -0
- package/README.md +738 -6
- package/dist/formats.d.ts +2 -2
- package/dist/formats.d.ts.map +1 -1
- package/dist/index.d.ts +25 -28
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +891 -964
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/dist/index.mjs +904 -964
- package/dist/keywords/array-keywords.d.ts +2 -2
- package/dist/keywords/array-keywords.d.ts.map +1 -1
- package/dist/keywords/number-keywords.d.ts +2 -2
- package/dist/keywords/number-keywords.d.ts.map +1 -1
- package/dist/keywords/object-keywords.d.ts +2 -2
- package/dist/keywords/object-keywords.d.ts.map +1 -1
- package/dist/keywords/other-keywords.d.ts +2 -2
- package/dist/keywords/other-keywords.d.ts.map +1 -1
- package/dist/keywords/string-keywords.d.ts +2 -2
- package/dist/keywords/string-keywords.d.ts.map +1 -1
- package/dist/keywords.d.ts +2 -2
- package/dist/keywords.d.ts.map +1 -1
- package/dist/types.d.ts +2 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/utils.d.ts +23 -7
- package/dist/utils.d.ts.map +1 -1
- package/lib/formats.ts +80 -36
- package/lib/index.ts +175 -221
- package/lib/keywords/array-keywords.ts +137 -145
- package/lib/keywords/number-keywords.ts +78 -62
- package/lib/keywords/object-keywords.ts +199 -144
- package/lib/keywords/other-keywords.ts +137 -195
- package/lib/keywords/string-keywords.ts +25 -132
- package/lib/keywords.ts +2 -2
- package/lib/types.ts +37 -164
- package/lib/utils.ts +106 -28
- package/package.json +3 -2
|
@@ -1,204 +1,196 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { ValidationError, isObject } from "../utils";
|
|
1
|
+
import { isCompiledSchema, isObject } from "../utils";
|
|
3
2
|
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
import { KeywordFunction } from "../index";
|
|
4
|
+
|
|
5
|
+
export const ArrayKeywords: Record<string, KeywordFunction> = {
|
|
6
|
+
items(schema, data, defineError) {
|
|
6
7
|
if (!Array.isArray(data)) {
|
|
7
|
-
return
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const schemaItems = schema.items;
|
|
12
|
+
const dataLength = data.length;
|
|
13
|
+
|
|
14
|
+
if (typeof schemaItems === "boolean") {
|
|
15
|
+
if (schemaItems === false && dataLength > 0) {
|
|
16
|
+
return defineError("Array items are not allowed", { data });
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (Array.isArray(schemaItems)) {
|
|
23
|
+
const schemaItemsLength = schemaItems.length;
|
|
24
|
+
const itemsLength = Math.min(schemaItemsLength, dataLength);
|
|
25
|
+
for (let i = 0; i < itemsLength; i++) {
|
|
26
|
+
const schemaItem = schemaItems[i];
|
|
27
|
+
if (typeof schemaItem === "boolean") {
|
|
28
|
+
if (schemaItem === false && typeof data[i] !== "undefined") {
|
|
29
|
+
return defineError("Array item is not allowed", {
|
|
30
|
+
item: i,
|
|
31
|
+
data: data[i]
|
|
32
|
+
});
|
|
23
33
|
}
|
|
24
34
|
continue;
|
|
25
35
|
}
|
|
26
36
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
37
|
+
if (isCompiledSchema(schemaItem)) {
|
|
38
|
+
const error = schemaItem.$validate(data[i]);
|
|
39
|
+
if (error) {
|
|
40
|
+
return defineError("Array item is invalid", {
|
|
41
|
+
item: i,
|
|
42
|
+
cause: error,
|
|
43
|
+
data: data[i]
|
|
44
|
+
});
|
|
45
|
+
}
|
|
30
46
|
}
|
|
31
|
-
|
|
32
|
-
schema.items[i],
|
|
33
|
-
finalData[i],
|
|
34
|
-
`${pointer}/${i}`,
|
|
35
|
-
schemaShieldInstance
|
|
36
|
-
);
|
|
47
|
+
}
|
|
37
48
|
|
|
38
|
-
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
39
51
|
|
|
40
|
-
|
|
41
|
-
|
|
52
|
+
if (isCompiledSchema(schemaItems)) {
|
|
53
|
+
for (let i = 0; i < dataLength; i++) {
|
|
54
|
+
const error = schemaItems.$validate(data[i]);
|
|
55
|
+
if (error) {
|
|
56
|
+
return defineError("Array item is invalid", {
|
|
57
|
+
item: i,
|
|
58
|
+
cause: error,
|
|
59
|
+
data: data[i]
|
|
60
|
+
});
|
|
42
61
|
}
|
|
43
62
|
}
|
|
44
|
-
}
|
|
45
|
-
if (schema.items === false && data.length > 0) {
|
|
46
|
-
errors.push(
|
|
47
|
-
new ValidationError("Array is not allowed", {
|
|
48
|
-
pointer,
|
|
49
|
-
value: data,
|
|
50
|
-
code: "ARRAY_NOT_ALLOWED"
|
|
51
|
-
})
|
|
52
|
-
);
|
|
53
|
-
}
|
|
54
|
-
} else {
|
|
55
|
-
const { validator } = schema.items as CompiledSchema;
|
|
56
|
-
if (!validator) {
|
|
57
|
-
return { valid: true, errors: [], data };
|
|
58
|
-
}
|
|
63
|
+
}
|
|
59
64
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
schema.items,
|
|
63
|
-
finalData[i],
|
|
64
|
-
`${pointer}/${i}`,
|
|
65
|
-
schemaShieldInstance
|
|
66
|
-
);
|
|
65
|
+
return;
|
|
66
|
+
},
|
|
67
67
|
|
|
68
|
-
|
|
68
|
+
elements(schema, data, defineError) {
|
|
69
|
+
if (!Array.isArray(data) || !isCompiledSchema(schema.elements)) {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
69
72
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
+
for (let i = 0; i < data.length; i++) {
|
|
74
|
+
const error = schema.elements.$validate(data[i]);
|
|
75
|
+
if (error) {
|
|
76
|
+
return defineError("Array item is invalid", {
|
|
77
|
+
item: i,
|
|
78
|
+
cause: error,
|
|
79
|
+
data: data[i]
|
|
80
|
+
});
|
|
73
81
|
}
|
|
74
82
|
}
|
|
75
83
|
|
|
76
|
-
return
|
|
84
|
+
return;
|
|
77
85
|
},
|
|
78
86
|
|
|
79
|
-
minItems(schema, data,
|
|
87
|
+
minItems(schema, data, defineError) {
|
|
80
88
|
if (!Array.isArray(data) || data.length >= schema.minItems) {
|
|
81
|
-
return
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
return {
|
|
85
|
-
valid: false,
|
|
86
|
-
errors: [
|
|
87
|
-
new ValidationError("Array is too short", {
|
|
88
|
-
pointer,
|
|
89
|
-
value: data,
|
|
90
|
-
code: "ARRAY_TOO_SHORT"
|
|
91
|
-
})
|
|
92
|
-
],
|
|
93
|
-
data
|
|
94
|
-
};
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return defineError("Array is too short", { data });
|
|
95
93
|
},
|
|
96
94
|
|
|
97
|
-
maxItems(schema, data,
|
|
95
|
+
maxItems(schema, data, defineError) {
|
|
98
96
|
if (!Array.isArray(data) || data.length <= schema.maxItems) {
|
|
99
|
-
return
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
return {
|
|
103
|
-
valid: false,
|
|
104
|
-
errors: [
|
|
105
|
-
new ValidationError("Array is too long", {
|
|
106
|
-
pointer,
|
|
107
|
-
value: data,
|
|
108
|
-
code: "ARRAY_TOO_LONG"
|
|
109
|
-
})
|
|
110
|
-
],
|
|
111
|
-
data
|
|
112
|
-
};
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return defineError("Array is too long", { data });
|
|
113
101
|
},
|
|
114
102
|
|
|
115
|
-
additionalItems(schema, data,
|
|
103
|
+
additionalItems(schema, data, defineError) {
|
|
116
104
|
if (!Array.isArray(data) || !schema.items || !Array.isArray(schema.items)) {
|
|
117
|
-
return
|
|
105
|
+
return;
|
|
118
106
|
}
|
|
119
107
|
|
|
120
108
|
if (schema.additionalItems === false) {
|
|
121
109
|
if (data.length > schema.items.length) {
|
|
122
|
-
return {
|
|
123
|
-
valid: false,
|
|
124
|
-
errors: [
|
|
125
|
-
new ValidationError("Array has too many items", {
|
|
126
|
-
pointer,
|
|
127
|
-
value: data,
|
|
128
|
-
code: "ARRAY_TOO_MANY_ITEMS"
|
|
129
|
-
})
|
|
130
|
-
],
|
|
131
|
-
data
|
|
132
|
-
};
|
|
110
|
+
return defineError("Array is too long", { data });
|
|
133
111
|
}
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
134
114
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
`${pointer}/${i}`,
|
|
147
|
-
schemaShieldInstance
|
|
148
|
-
);
|
|
149
|
-
if (!validatorResult.valid) {
|
|
150
|
-
errors.push(...validatorResult.errors);
|
|
115
|
+
if (isObject(schema.additionalItems)) {
|
|
116
|
+
if (isCompiledSchema(schema.additionalItems)) {
|
|
117
|
+
for (let i = schema.items.length; i < data.length; i++) {
|
|
118
|
+
const error = schema.additionalItems.$validate(data[i]);
|
|
119
|
+
if (error) {
|
|
120
|
+
return defineError("Array item is invalid", {
|
|
121
|
+
item: i,
|
|
122
|
+
cause: error,
|
|
123
|
+
data: data[i]
|
|
124
|
+
});
|
|
125
|
+
}
|
|
151
126
|
}
|
|
152
|
-
|
|
127
|
+
return;
|
|
153
128
|
}
|
|
129
|
+
|
|
130
|
+
return;
|
|
154
131
|
}
|
|
155
132
|
|
|
156
|
-
return
|
|
133
|
+
return;
|
|
157
134
|
},
|
|
158
135
|
|
|
159
|
-
uniqueItems(schema, data,
|
|
136
|
+
uniqueItems(schema, data, defineError) {
|
|
160
137
|
if (!Array.isArray(data) || !schema.uniqueItems) {
|
|
161
|
-
return
|
|
138
|
+
return;
|
|
162
139
|
}
|
|
163
140
|
|
|
164
141
|
const unique = new Set();
|
|
165
142
|
|
|
166
143
|
for (const item of data) {
|
|
167
|
-
let itemStr
|
|
144
|
+
let itemStr;
|
|
168
145
|
|
|
169
146
|
// Change string to "string" to avoid false positives
|
|
170
147
|
if (typeof item === "string") {
|
|
171
|
-
itemStr = `
|
|
172
|
-
|
|
148
|
+
itemStr = `s:${item}`;
|
|
173
149
|
// Sort object keys to avoid false positives
|
|
174
150
|
} else if (isObject(item)) {
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
}
|
|
180
|
-
itemStr = JSON.stringify(sorted);
|
|
151
|
+
itemStr = `o:${JSON.stringify(
|
|
152
|
+
Object.fromEntries(
|
|
153
|
+
Object.entries(item).sort(([a], [b]) => a.localeCompare(b))
|
|
154
|
+
)
|
|
155
|
+
)}`;
|
|
181
156
|
} else if (Array.isArray(item)) {
|
|
182
157
|
itemStr = JSON.stringify(item);
|
|
158
|
+
} else {
|
|
159
|
+
itemStr = String(item);
|
|
183
160
|
}
|
|
184
161
|
|
|
185
162
|
if (unique.has(itemStr)) {
|
|
186
|
-
return {
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
163
|
+
return defineError("Array items are not unique", { data: item });
|
|
164
|
+
}
|
|
165
|
+
unique.add(itemStr);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
return;
|
|
169
|
+
},
|
|
170
|
+
|
|
171
|
+
contains(schema, data, defineError) {
|
|
172
|
+
if (!Array.isArray(data)) {
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
if (typeof schema.contains === "boolean") {
|
|
176
|
+
if (schema.contains) {
|
|
177
|
+
if (data.length === 0) {
|
|
178
|
+
return defineError("Array must contain at least one item", { data });
|
|
179
|
+
}
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
return defineError("Array must not contain any items", { data });
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
for (let i = 0; i < data.length; i++) {
|
|
187
|
+
const error = schema.contains.$validate(data[i]);
|
|
188
|
+
if (!error) {
|
|
189
|
+
return;
|
|
199
190
|
}
|
|
191
|
+
continue;
|
|
200
192
|
}
|
|
201
193
|
|
|
202
|
-
return
|
|
194
|
+
return defineError("Array must contain at least one item", { data });
|
|
203
195
|
}
|
|
204
196
|
};
|
|
@@ -1,79 +1,95 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { KeywordFunction } from "../index";
|
|
2
|
+
import { areCloseEnough } from "../utils";
|
|
3
3
|
|
|
4
|
-
export const NumberKeywords: Record<string,
|
|
5
|
-
minimum(schema, data,
|
|
4
|
+
export const NumberKeywords: Record<string, KeywordFunction> = {
|
|
5
|
+
minimum(schema, data, defineError, instance) {
|
|
6
6
|
if (typeof data !== "number") {
|
|
7
|
-
return
|
|
7
|
+
return;
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
pointer,
|
|
23
|
-
value: data,
|
|
24
|
-
code: "NUMBER_TOO_SMALL"
|
|
25
|
-
})
|
|
26
|
-
],
|
|
27
|
-
data
|
|
28
|
-
};
|
|
10
|
+
let min = schema.minimum;
|
|
11
|
+
if (typeof schema.exclusiveMinimum === "number") {
|
|
12
|
+
min = schema.exclusiveMinimum + 1e-15;
|
|
13
|
+
} else if (schema.exclusiveMinimum === true) {
|
|
14
|
+
min += 1e-15;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
if (data < min) {
|
|
18
|
+
return defineError("Value is less than the minimum", { data });
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return;
|
|
29
22
|
},
|
|
30
23
|
|
|
31
|
-
maximum(schema, data,
|
|
24
|
+
maximum(schema, data, defineError, instance) {
|
|
32
25
|
if (typeof data !== "number") {
|
|
33
|
-
return
|
|
26
|
+
return;
|
|
34
27
|
}
|
|
35
28
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
pointer,
|
|
49
|
-
value: data,
|
|
50
|
-
code: "NUMBER_TOO_LARGE"
|
|
51
|
-
})
|
|
52
|
-
],
|
|
53
|
-
data
|
|
54
|
-
};
|
|
29
|
+
let max = schema.maximum;
|
|
30
|
+
if (typeof schema.exclusiveMaximum === "number") {
|
|
31
|
+
max = schema.exclusiveMaximum - 1e-15;
|
|
32
|
+
} else if (schema.exclusiveMaximum === true) {
|
|
33
|
+
max -= 1e-15;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (data > max) {
|
|
37
|
+
return defineError("Value is greater than the maximum", { data });
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return;
|
|
55
41
|
},
|
|
56
42
|
|
|
57
|
-
multipleOf(schema, data,
|
|
43
|
+
multipleOf(schema, data, defineError, instance) {
|
|
58
44
|
if (typeof data !== "number") {
|
|
59
|
-
return
|
|
45
|
+
return;
|
|
60
46
|
}
|
|
61
47
|
|
|
62
48
|
const quotient = data / schema.multipleOf;
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
49
|
+
|
|
50
|
+
if (!isFinite(quotient)) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (!areCloseEnough(quotient, Math.round(quotient))) {
|
|
55
|
+
return defineError("Value is not a multiple of the multipleOf", { data });
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return;
|
|
59
|
+
},
|
|
60
|
+
|
|
61
|
+
exclusiveMinimum(schema, data, defineError, instance) {
|
|
62
|
+
if (
|
|
63
|
+
typeof data !== "number" ||
|
|
64
|
+
typeof schema.exclusiveMinimum !== "number" ||
|
|
65
|
+
"minimum" in schema
|
|
66
|
+
) {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (data <= schema.exclusiveMinimum + 1e-15) {
|
|
71
|
+
return defineError("Value is less than or equal to the exclusiveMinimum");
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return;
|
|
75
|
+
},
|
|
76
|
+
|
|
77
|
+
exclusiveMaximum(schema, data, defineError, instance) {
|
|
78
|
+
if (
|
|
79
|
+
typeof data !== "number" ||
|
|
80
|
+
typeof schema.exclusiveMaximum !== "number" ||
|
|
81
|
+
"maximum" in schema
|
|
82
|
+
) {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (data >= schema.exclusiveMaximum) {
|
|
87
|
+
return defineError(
|
|
88
|
+
"Value is greater than or equal to the exclusiveMaximum",
|
|
89
|
+
{ data }
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return;
|
|
78
94
|
}
|
|
79
95
|
};
|