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,140 +1,118 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { ValidationError, isObject } from "../utils";
|
|
1
|
+
import { isCompiledSchema, isObject } from "../utils";
|
|
3
2
|
|
|
4
|
-
|
|
3
|
+
import { KeywordFunction } from "../index";
|
|
4
|
+
|
|
5
|
+
export const ObjectKeywords: Record<string, KeywordFunction | false> = {
|
|
5
6
|
// Object
|
|
6
|
-
required(schema, data,
|
|
7
|
+
required(schema, data, defineError) {
|
|
7
8
|
if (!isObject(data)) {
|
|
8
|
-
return
|
|
9
|
-
valid: true,
|
|
10
|
-
errors: [],
|
|
11
|
-
data
|
|
12
|
-
};
|
|
9
|
+
return;
|
|
13
10
|
}
|
|
14
11
|
|
|
15
|
-
const errors = [];
|
|
16
12
|
for (let i = 0; i < schema.required.length; i++) {
|
|
17
13
|
const key = schema.required[i];
|
|
18
14
|
if (!data.hasOwnProperty(key)) {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
code: "MISSING_REQUIRED_PROPERTY"
|
|
24
|
-
})
|
|
25
|
-
);
|
|
15
|
+
return defineError("Required property is missing", {
|
|
16
|
+
item: key,
|
|
17
|
+
data: data[key]
|
|
18
|
+
});
|
|
26
19
|
}
|
|
27
20
|
}
|
|
28
21
|
|
|
29
|
-
return
|
|
22
|
+
return;
|
|
30
23
|
},
|
|
31
24
|
|
|
32
|
-
properties(schema, data,
|
|
25
|
+
properties(schema, data, defineError) {
|
|
33
26
|
if (!isObject(data)) {
|
|
34
|
-
return
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const errors = [];
|
|
38
|
-
let finalData = { ...data };
|
|
39
|
-
for (let key in schema.properties) {
|
|
40
|
-
if (!data.hasOwnProperty(key) || typeof data[key] === "undefined") {
|
|
41
|
-
if (
|
|
42
|
-
isObject(schema.properties[key]) &&
|
|
43
|
-
"default" in schema.properties[key]
|
|
44
|
-
) {
|
|
45
|
-
finalData[key] = schema.properties[key].default;
|
|
46
|
-
}
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
47
29
|
|
|
30
|
+
for (const key of Object.keys(schema.properties)) {
|
|
31
|
+
if (!data.hasOwnProperty(key)) {
|
|
32
|
+
const schemaProp = schema.properties[key];
|
|
33
|
+
if (isObject(schemaProp) && "default" in schemaProp) {
|
|
34
|
+
data[key] = schemaProp.default;
|
|
35
|
+
}
|
|
48
36
|
continue;
|
|
49
37
|
}
|
|
50
38
|
|
|
51
39
|
if (typeof schema.properties[key] === "boolean") {
|
|
52
40
|
if (schema.properties[key] === false) {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
code: "PROPERTY_NOT_ALLOWED"
|
|
58
|
-
})
|
|
59
|
-
);
|
|
41
|
+
return defineError("Property is not allowed", {
|
|
42
|
+
item: key,
|
|
43
|
+
data: data[key]
|
|
44
|
+
});
|
|
60
45
|
}
|
|
61
46
|
continue;
|
|
62
47
|
}
|
|
63
48
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
49
|
+
if ("$validate" in schema.properties[key]) {
|
|
50
|
+
const error = schema.properties[key].$validate(data[key]);
|
|
51
|
+
if (error) {
|
|
52
|
+
return defineError("Property is invalid", {
|
|
53
|
+
item: key,
|
|
54
|
+
cause: error,
|
|
55
|
+
data: data[key]
|
|
56
|
+
});
|
|
57
|
+
}
|
|
67
58
|
}
|
|
59
|
+
}
|
|
68
60
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
finalData[key],
|
|
72
|
-
`${pointer}/${key}`,
|
|
73
|
-
schemaShieldInstance
|
|
74
|
-
);
|
|
61
|
+
return;
|
|
62
|
+
},
|
|
75
63
|
|
|
76
|
-
|
|
64
|
+
values(schema, data, defineError) {
|
|
65
|
+
if (!isObject(data) || !isCompiledSchema(schema.values)) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
77
68
|
|
|
78
|
-
|
|
79
|
-
|
|
69
|
+
const keys = Object.keys(data);
|
|
70
|
+
for (const key of keys) {
|
|
71
|
+
const error = schema.values.$validate(data[key]);
|
|
72
|
+
if (error) {
|
|
73
|
+
return defineError("Property is invalid", {
|
|
74
|
+
item: key,
|
|
75
|
+
cause: error,
|
|
76
|
+
data: data[key]
|
|
77
|
+
});
|
|
80
78
|
}
|
|
81
79
|
}
|
|
82
80
|
|
|
83
|
-
return
|
|
81
|
+
return;
|
|
84
82
|
},
|
|
85
83
|
|
|
86
|
-
maxProperties(schema, data,
|
|
84
|
+
maxProperties(schema, data, defineError) {
|
|
87
85
|
if (!isObject(data) || Object.keys(data).length <= schema.maxProperties) {
|
|
88
|
-
return
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
return {
|
|
92
|
-
valid: false,
|
|
93
|
-
errors: [
|
|
94
|
-
new ValidationError("Object has too many properties", {
|
|
95
|
-
pointer,
|
|
96
|
-
value: data,
|
|
97
|
-
code: "OBJECT_TOO_MANY_PROPERTIES"
|
|
98
|
-
})
|
|
99
|
-
],
|
|
100
|
-
data
|
|
101
|
-
};
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return defineError("Too many properties", { data });
|
|
102
90
|
},
|
|
103
91
|
|
|
104
|
-
minProperties(schema, data,
|
|
92
|
+
minProperties(schema, data, defineError) {
|
|
105
93
|
if (!isObject(data) || Object.keys(data).length >= schema.minProperties) {
|
|
106
|
-
return
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
return {
|
|
110
|
-
valid: false,
|
|
111
|
-
errors: [
|
|
112
|
-
new ValidationError("Object has too few properties", {
|
|
113
|
-
pointer,
|
|
114
|
-
value: data,
|
|
115
|
-
code: "OBJECT_TOO_FEW_PROPERTIES"
|
|
116
|
-
})
|
|
117
|
-
],
|
|
118
|
-
data
|
|
119
|
-
};
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return defineError("Too few properties", { data });
|
|
120
98
|
},
|
|
121
99
|
|
|
122
|
-
additionalProperties(schema, data,
|
|
100
|
+
additionalProperties(schema, data, defineError) {
|
|
123
101
|
if (!isObject(data)) {
|
|
124
|
-
return
|
|
102
|
+
return;
|
|
125
103
|
}
|
|
126
104
|
|
|
127
|
-
const
|
|
128
|
-
|
|
129
|
-
for (
|
|
105
|
+
const keys = Object.keys(data);
|
|
106
|
+
const isCompiled = isCompiledSchema(schema.additionalProperties);
|
|
107
|
+
for (const key of keys) {
|
|
130
108
|
if (schema.properties && schema.properties.hasOwnProperty(key)) {
|
|
131
109
|
continue;
|
|
132
110
|
}
|
|
133
111
|
|
|
134
112
|
if (schema.patternProperties) {
|
|
135
113
|
let match = false;
|
|
136
|
-
for (
|
|
137
|
-
if (new RegExp(pattern).test(key)) {
|
|
114
|
+
for (const pattern in schema.patternProperties) {
|
|
115
|
+
if (new RegExp(pattern, "u").test(key)) {
|
|
138
116
|
match = true;
|
|
139
117
|
break;
|
|
140
118
|
}
|
|
@@ -145,86 +123,163 @@ export const ObjectKeywords: Record<string, ValidatorFunction> = {
|
|
|
145
123
|
}
|
|
146
124
|
|
|
147
125
|
if (schema.additionalProperties === false) {
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
code: "ADDITIONAL_PROPERTY_NOT_ALLOWED"
|
|
153
|
-
})
|
|
154
|
-
);
|
|
155
|
-
continue;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
const { validator } = schema.additionalProperties as CompiledSchema;
|
|
159
|
-
if (!validator) {
|
|
160
|
-
continue;
|
|
126
|
+
return defineError("Additional properties are not allowed", {
|
|
127
|
+
item: key,
|
|
128
|
+
data: data[key]
|
|
129
|
+
});
|
|
161
130
|
}
|
|
162
131
|
|
|
163
|
-
|
|
164
|
-
schema.additionalProperties
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
if (!validatorResult.valid) {
|
|
173
|
-
errors.push(...validatorResult.errors);
|
|
132
|
+
if (isCompiled) {
|
|
133
|
+
const error = schema.additionalProperties.$validate(data[key]);
|
|
134
|
+
if (error) {
|
|
135
|
+
return defineError("Additional properties are invalid", {
|
|
136
|
+
item: key,
|
|
137
|
+
cause: error,
|
|
138
|
+
data: data[key]
|
|
139
|
+
});
|
|
140
|
+
}
|
|
174
141
|
}
|
|
175
142
|
}
|
|
176
143
|
|
|
177
|
-
return
|
|
144
|
+
return;
|
|
178
145
|
},
|
|
179
146
|
|
|
180
|
-
patternProperties(schema, data,
|
|
147
|
+
patternProperties(schema, data, defineError) {
|
|
181
148
|
if (!isObject(data)) {
|
|
182
|
-
return
|
|
149
|
+
return;
|
|
183
150
|
}
|
|
184
151
|
|
|
185
|
-
const
|
|
186
|
-
|
|
187
|
-
|
|
152
|
+
const patterns = Object.keys(schema.patternProperties);
|
|
153
|
+
for (const pattern of patterns) {
|
|
154
|
+
const regex = new RegExp(pattern, "u");
|
|
188
155
|
if (typeof schema.patternProperties[pattern] === "boolean") {
|
|
189
156
|
if (schema.patternProperties[pattern] === false) {
|
|
190
|
-
for (
|
|
191
|
-
if (
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
code: "PROPERTY_NOT_ALLOWED"
|
|
197
|
-
})
|
|
198
|
-
);
|
|
157
|
+
for (const key in data) {
|
|
158
|
+
if (regex.test(key)) {
|
|
159
|
+
return defineError("Property is not allowed", {
|
|
160
|
+
item: key,
|
|
161
|
+
data: data[key]
|
|
162
|
+
});
|
|
199
163
|
}
|
|
200
164
|
}
|
|
201
165
|
}
|
|
202
166
|
continue;
|
|
203
167
|
}
|
|
204
168
|
|
|
205
|
-
const
|
|
206
|
-
|
|
207
|
-
|
|
169
|
+
const keys = Object.keys(data);
|
|
170
|
+
for (const key of keys) {
|
|
171
|
+
if (regex.test(key)) {
|
|
172
|
+
if ("$validate" in schema.patternProperties[pattern]) {
|
|
173
|
+
const error = schema.patternProperties[pattern].$validate(
|
|
174
|
+
data[key]
|
|
175
|
+
);
|
|
176
|
+
if (error) {
|
|
177
|
+
return defineError("Property is invalid", {
|
|
178
|
+
item: key,
|
|
179
|
+
cause: error,
|
|
180
|
+
data: data[key]
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
208
185
|
}
|
|
186
|
+
}
|
|
209
187
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
const validatorResult = validator(
|
|
213
|
-
schema.patternProperties[pattern],
|
|
214
|
-
finalData[key],
|
|
215
|
-
`${pointer}/${key}`,
|
|
216
|
-
schemaShieldInstance
|
|
217
|
-
);
|
|
188
|
+
return;
|
|
189
|
+
},
|
|
218
190
|
|
|
219
|
-
|
|
191
|
+
propertyNames(schema, data, defineError) {
|
|
192
|
+
if (!isObject(data)) {
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
if (typeof schema.propertyNames === "boolean") {
|
|
196
|
+
if (schema.propertyNames === false && Object.keys(data).length > 0) {
|
|
197
|
+
return defineError("Properties are not allowed", { data });
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
if (isCompiledSchema(schema.propertyNames)) {
|
|
201
|
+
for (let key in data) {
|
|
202
|
+
const error = schema.propertyNames.$validate(key);
|
|
203
|
+
if (error) {
|
|
204
|
+
return defineError("Property name is invalid", {
|
|
205
|
+
item: key,
|
|
206
|
+
cause: error,
|
|
207
|
+
data: data[key]
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
return;
|
|
214
|
+
},
|
|
215
|
+
|
|
216
|
+
dependencies(schema, data, defineError) {
|
|
217
|
+
if (!isObject(data)) {
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
for (const key in schema.dependencies) {
|
|
222
|
+
if (key in data === false) {
|
|
223
|
+
continue;
|
|
224
|
+
}
|
|
220
225
|
|
|
221
|
-
|
|
222
|
-
|
|
226
|
+
const dependency = schema.dependencies[key];
|
|
227
|
+
if (Array.isArray(dependency)) {
|
|
228
|
+
for (let i = 0; i < dependency.length; i++) {
|
|
229
|
+
if (!(dependency[i] in data)) {
|
|
230
|
+
return defineError("Dependency is not satisfied", {
|
|
231
|
+
item: i,
|
|
232
|
+
data: dependency[i]
|
|
233
|
+
});
|
|
223
234
|
}
|
|
224
235
|
}
|
|
236
|
+
continue;
|
|
237
|
+
}
|
|
238
|
+
if (typeof dependency === "boolean") {
|
|
239
|
+
if (dependency) {
|
|
240
|
+
continue;
|
|
241
|
+
}
|
|
242
|
+
return defineError("Dependency is not satisfied", { data: dependency });
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
if (typeof dependency === "string") {
|
|
246
|
+
if (dependency in data) {
|
|
247
|
+
continue;
|
|
248
|
+
}
|
|
249
|
+
return defineError("Dependency is not satisfied", { data: dependency });
|
|
250
|
+
}
|
|
251
|
+
const error = dependency.$validate(data);
|
|
252
|
+
if (error) {
|
|
253
|
+
return defineError("Dependency is not satisfied", {
|
|
254
|
+
cause: error,
|
|
255
|
+
data
|
|
256
|
+
});
|
|
225
257
|
}
|
|
226
258
|
}
|
|
227
259
|
|
|
228
|
-
return
|
|
229
|
-
}
|
|
260
|
+
return;
|
|
261
|
+
},
|
|
262
|
+
|
|
263
|
+
// Required by other keywords but not used as a function itself
|
|
264
|
+
then: false,
|
|
265
|
+
else: false,
|
|
266
|
+
default: false,
|
|
267
|
+
|
|
268
|
+
// Not implemented yet
|
|
269
|
+
$ref: false,
|
|
270
|
+
definitions: false,
|
|
271
|
+
$id: false,
|
|
272
|
+
$schema: false,
|
|
273
|
+
|
|
274
|
+
// Metadata keywords (not used as a function)
|
|
275
|
+
title: false,
|
|
276
|
+
description: false,
|
|
277
|
+
$comment: false,
|
|
278
|
+
examples: false,
|
|
279
|
+
contentMediaType: false,
|
|
280
|
+
contentEncoding: false,
|
|
281
|
+
|
|
282
|
+
// Not supported Open API keywords
|
|
283
|
+
discriminator: false,
|
|
284
|
+
nullable: false
|
|
230
285
|
};
|