z-schema 7.0.0 → 7.0.6
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/README.md +7 -11
- package/bin/z-schema +0 -0
- package/cjs/index.d.ts +192 -117
- package/cjs/index.js +949 -998
- package/{src/FormatValidators.ts → dist/format-validators.js} +97 -65
- package/dist/index.js +1 -1
- package/dist/json-schema.js +40 -0
- package/dist/{JsonValidation.js → json-validation.js} +75 -69
- package/dist/{Report.js → report.js} +35 -45
- package/dist/schema-cache.js +109 -0
- package/dist/schema-compiler.js +255 -0
- package/dist/{SchemaValidation.js → schema-validator.js} +153 -149
- package/dist/types/{Errors.d.ts → errors.d.ts} +2 -0
- package/dist/types/format-validators.d.ts +10 -0
- package/dist/types/index.d.ts +10 -1
- package/dist/types/json-schema.d.ts +50 -0
- package/dist/types/json-validation.d.ts +7 -0
- package/dist/types/{Report.d.ts → report.d.ts} +22 -23
- package/dist/types/schema-cache.d.ts +17 -0
- package/dist/types/schema-compiler.d.ts +16 -0
- package/dist/types/schema-validator.d.ts +10 -0
- package/dist/types/utils/array.d.ts +2 -0
- package/dist/types/utils/clone.d.ts +2 -0
- package/dist/types/utils/json.d.ts +7 -0
- package/dist/types/utils/symbols.d.ts +2 -0
- package/dist/types/utils/unicode.d.ts +14 -0
- package/dist/types/utils/uri.d.ts +4 -0
- package/dist/types/utils/what-is.d.ts +3 -0
- package/dist/types/z-schema.d.ts +75 -0
- package/dist/utils/array.js +27 -0
- package/dist/utils/clone.js +61 -0
- package/dist/utils/json.js +59 -0
- package/dist/utils/symbols.js +2 -0
- package/dist/utils/unicode.js +45 -0
- package/dist/utils/uri.js +15 -0
- package/dist/utils/what-is.js +29 -0
- package/dist/{ZSchema.js → z-schema.js} +66 -77
- package/package.json +8 -4
- package/src/{Errors.ts → errors.ts} +4 -0
- package/src/format-validators.ts +191 -0
- package/src/index.ts +12 -1
- package/src/json-schema.ts +97 -0
- package/src/{JsonValidation.ts → json-validation.ts} +137 -127
- package/src/{Report.ts → report.ts} +60 -70
- package/src/schema-cache.ts +122 -0
- package/src/schema-compiler.ts +300 -0
- package/src/{SchemaValidation.ts → schema-validator.ts} +213 -215
- package/src/utils/array.ts +29 -0
- package/src/utils/clone.ts +63 -0
- package/src/utils/json.ts +74 -0
- package/src/utils/symbols.ts +3 -0
- package/src/utils/unicode.ts +43 -0
- package/src/utils/uri.ts +18 -0
- package/src/utils/what-is.ts +46 -0
- package/src/{ZSchema.ts → z-schema.ts} +108 -113
- package/umd/ZSchema.js +949 -998
- package/umd/ZSchema.min.js +1 -1
- package/dist/FormatValidators.js +0 -136
- package/dist/SchemaCache.js +0 -173
- package/dist/SchemaCompilation.js +0 -259
- package/dist/Utils.js +0 -266
- package/dist/types/FormatValidators.d.ts +0 -12
- package/dist/types/JsonValidation.d.ts +0 -37
- package/dist/types/SchemaCache.d.ts +0 -26
- package/dist/types/SchemaCompilation.d.ts +0 -1
- package/dist/types/SchemaValidation.d.ts +0 -6
- package/dist/types/Utils.d.ts +0 -64
- package/dist/types/ZSchema.d.ts +0 -97
- package/src/SchemaCache.ts +0 -189
- package/src/SchemaCompilation.ts +0 -293
- package/src/Utils.ts +0 -286
- /package/dist/{Errors.js → errors.js} +0 -0
- /package/dist/schemas/{hyper-schema.json → draft-04-hyper-schema.json} +0 -0
- /package/dist/schemas/{schema.json → draft-04-schema.json} +0 -0
- /package/src/schemas/{hyper-schema.json → draft-04-hyper-schema.json} +0 -0
- /package/src/schemas/{schema.json → draft-04-schema.json} +0 -0
package/cjs/index.js
CHANGED
|
@@ -997,38 +997,8 @@ const Errors = {
|
|
|
997
997
|
REMOTE_NOT_VALID: "Remote reference didn't compile successfully: {0}",
|
|
998
998
|
};
|
|
999
999
|
|
|
1000
|
-
const
|
|
1001
|
-
|
|
1002
|
-
/**
|
|
1003
|
-
* @param {object} obj
|
|
1004
|
-
*
|
|
1005
|
-
* @returns {string[]}
|
|
1006
|
-
*/
|
|
1007
|
-
function sortedKeys(obj) {
|
|
1008
|
-
return Object.keys(obj).sort();
|
|
1009
|
-
}
|
|
1010
|
-
/**
|
|
1011
|
-
*
|
|
1012
|
-
* @param {string} uri
|
|
1013
|
-
*
|
|
1014
|
-
* @returns {boolean}
|
|
1015
|
-
*/
|
|
1016
|
-
function isAbsoluteUri(uri) {
|
|
1017
|
-
return /^https?:\/\//.test(uri);
|
|
1018
|
-
}
|
|
1019
|
-
/**
|
|
1020
|
-
*
|
|
1021
|
-
* @param {string} uri
|
|
1022
|
-
*
|
|
1023
|
-
* @returns {boolean}
|
|
1024
|
-
*/
|
|
1025
|
-
function isRelativeUri(uri) {
|
|
1026
|
-
// relative URIs that end with a hash sign, issue #56
|
|
1027
|
-
return /.+#/.test(uri);
|
|
1028
|
-
}
|
|
1029
|
-
function whatIs(what) {
|
|
1030
|
-
const to = typeof what;
|
|
1031
|
-
if (to === 'object') {
|
|
1000
|
+
const whatIs = (what) => {
|
|
1001
|
+
if (typeof what === 'object') {
|
|
1032
1002
|
if (what === null) {
|
|
1033
1003
|
return 'null';
|
|
1034
1004
|
}
|
|
@@ -1037,7 +1007,7 @@ function whatIs(what) {
|
|
|
1037
1007
|
}
|
|
1038
1008
|
return 'object'; // typeof what === 'object' && what === Object(what) && !Array.isArray(what);
|
|
1039
1009
|
}
|
|
1040
|
-
if (
|
|
1010
|
+
if (typeof what === 'number') {
|
|
1041
1011
|
if (Number.isFinite(what)) {
|
|
1042
1012
|
if (what % 1 === 0) {
|
|
1043
1013
|
return 'integer';
|
|
@@ -1051,242 +1021,45 @@ function whatIs(what) {
|
|
|
1051
1021
|
}
|
|
1052
1022
|
return 'unknown-number';
|
|
1053
1023
|
}
|
|
1054
|
-
return
|
|
1055
|
-
}
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
* @param {*} json1
|
|
1059
|
-
* @param {*} json2
|
|
1060
|
-
* @param {*} [options]
|
|
1061
|
-
*
|
|
1062
|
-
* @returns {boolean}
|
|
1063
|
-
*/
|
|
1064
|
-
function areEqual(json1, json2, options) {
|
|
1065
|
-
options = options || {};
|
|
1066
|
-
const caseInsensitiveComparison = options.caseInsensitiveComparison || false;
|
|
1067
|
-
// http://json-schema.org/latest/json-schema-core.html#rfc.section.3.6
|
|
1068
|
-
// Two JSON values are said to be equal if and only if:
|
|
1069
|
-
// both are nulls; or
|
|
1070
|
-
// both are booleans, and have the same value; or
|
|
1071
|
-
// both are strings, and have the same value; or
|
|
1072
|
-
// both are numbers, and have the same mathematical value; or
|
|
1073
|
-
if (json1 === json2) {
|
|
1074
|
-
return true;
|
|
1075
|
-
}
|
|
1076
|
-
if (caseInsensitiveComparison === true &&
|
|
1077
|
-
typeof json1 === 'string' &&
|
|
1078
|
-
typeof json2 === 'string' &&
|
|
1079
|
-
json1.toUpperCase() === json2.toUpperCase()) {
|
|
1080
|
-
return true;
|
|
1081
|
-
}
|
|
1082
|
-
let i, len;
|
|
1083
|
-
// both are arrays, and:
|
|
1084
|
-
if (Array.isArray(json1) && Array.isArray(json2)) {
|
|
1085
|
-
// have the same number of items; and
|
|
1086
|
-
if (json1.length !== json2.length) {
|
|
1087
|
-
return false;
|
|
1088
|
-
}
|
|
1089
|
-
// items at the same index are equal according to this definition; or
|
|
1090
|
-
len = json1.length;
|
|
1091
|
-
for (i = 0; i < len; i++) {
|
|
1092
|
-
if (!areEqual(json1[i], json2[i], { caseInsensitiveComparison: caseInsensitiveComparison })) {
|
|
1093
|
-
return false;
|
|
1094
|
-
}
|
|
1095
|
-
}
|
|
1096
|
-
return true;
|
|
1097
|
-
}
|
|
1098
|
-
// both are objects, and:
|
|
1099
|
-
if (whatIs(json1) === 'object' && whatIs(json2) === 'object') {
|
|
1100
|
-
// have the same set of property names; and
|
|
1101
|
-
const keys1 = sortedKeys(json1);
|
|
1102
|
-
const keys2 = sortedKeys(json2);
|
|
1103
|
-
if (!areEqual(keys1, keys2, { caseInsensitiveComparison: caseInsensitiveComparison })) {
|
|
1104
|
-
return false;
|
|
1105
|
-
}
|
|
1106
|
-
// values for a same property name are equal according to this definition.
|
|
1107
|
-
len = keys1.length;
|
|
1108
|
-
for (i = 0; i < len; i++) {
|
|
1109
|
-
if (!areEqual(json1[keys1[i]], json2[keys1[i]], { caseInsensitiveComparison: caseInsensitiveComparison })) {
|
|
1110
|
-
return false;
|
|
1111
|
-
}
|
|
1112
|
-
}
|
|
1113
|
-
return true;
|
|
1114
|
-
}
|
|
1115
|
-
return false;
|
|
1116
|
-
}
|
|
1117
|
-
/**
|
|
1118
|
-
*
|
|
1119
|
-
* @param {*[]} arr
|
|
1120
|
-
* @param {number[]} [indexes]
|
|
1121
|
-
*
|
|
1122
|
-
* @returns {boolean}
|
|
1123
|
-
*/
|
|
1124
|
-
function isUniqueArray(arr, indexes) {
|
|
1125
|
-
let i;
|
|
1126
|
-
let j;
|
|
1127
|
-
const l = arr.length;
|
|
1128
|
-
for (i = 0; i < l; i++) {
|
|
1129
|
-
for (j = i + 1; j < l; j++) {
|
|
1130
|
-
if (areEqual(arr[i], arr[j])) {
|
|
1131
|
-
if (indexes) {
|
|
1132
|
-
indexes.push(i, j);
|
|
1133
|
-
}
|
|
1134
|
-
return false;
|
|
1135
|
-
}
|
|
1136
|
-
}
|
|
1137
|
-
}
|
|
1138
|
-
return true;
|
|
1139
|
-
}
|
|
1140
|
-
/**
|
|
1141
|
-
*
|
|
1142
|
-
* @param {*} bigSet
|
|
1143
|
-
* @param {*} subSet
|
|
1144
|
-
*
|
|
1145
|
-
* @returns {*[]}
|
|
1146
|
-
*/
|
|
1147
|
-
function difference(bigSet, subSet) {
|
|
1148
|
-
const arr = [];
|
|
1149
|
-
let idx = bigSet.length;
|
|
1150
|
-
while (idx--) {
|
|
1151
|
-
if (subSet.indexOf(bigSet[idx]) === -1) {
|
|
1152
|
-
arr.push(bigSet[idx]);
|
|
1153
|
-
}
|
|
1154
|
-
}
|
|
1155
|
-
return arr;
|
|
1024
|
+
return typeof what; // undefined, boolean, string, function
|
|
1025
|
+
};
|
|
1026
|
+
function isObject(value) {
|
|
1027
|
+
return whatIs(value) === 'object';
|
|
1156
1028
|
}
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
if (Array.isArray(src)) {
|
|
1167
|
-
res = [];
|
|
1168
|
-
idx = src.length;
|
|
1169
|
-
while (idx--) {
|
|
1170
|
-
res[idx] = src[idx];
|
|
1171
|
-
}
|
|
1172
|
-
}
|
|
1173
|
-
else {
|
|
1174
|
-
res = {};
|
|
1175
|
-
const keys = Object.keys(src);
|
|
1176
|
-
idx = keys.length;
|
|
1177
|
-
while (idx--) {
|
|
1178
|
-
const key = keys[idx];
|
|
1179
|
-
res[key] = src[key];
|
|
1180
|
-
}
|
|
1181
|
-
}
|
|
1029
|
+
|
|
1030
|
+
const jsonSymbol = Symbol.for('z-schema/json');
|
|
1031
|
+
const schemaSymbol = Symbol.for('z-schema/schema');
|
|
1032
|
+
|
|
1033
|
+
const getQueryPath = (uri) => {
|
|
1034
|
+
const io = uri.indexOf('#');
|
|
1035
|
+
const res = io === -1 ? undefined : uri.slice(io + 1);
|
|
1036
|
+
// WARN: do not slice slash, #/ means take root and go down from it
|
|
1037
|
+
// if (res && res[0] === "/") { res = res.slice(1); }
|
|
1182
1038
|
return res;
|
|
1183
|
-
}
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
let res;
|
|
1193
|
-
let idx;
|
|
1194
|
-
const cidx = visited.get(src);
|
|
1195
|
-
if (cidx !== undefined) {
|
|
1196
|
-
return cloned[cidx];
|
|
1197
|
-
}
|
|
1198
|
-
visited.set(src, vidx++);
|
|
1199
|
-
if (Array.isArray(src)) {
|
|
1200
|
-
res = [];
|
|
1201
|
-
cloned.push(res);
|
|
1202
|
-
idx = src.length;
|
|
1203
|
-
while (idx--) {
|
|
1204
|
-
res[idx] = cloneDeepInner(src[idx]);
|
|
1205
|
-
}
|
|
1206
|
-
}
|
|
1207
|
-
else {
|
|
1208
|
-
res = {};
|
|
1209
|
-
cloned.push(res);
|
|
1210
|
-
const keys = Object.keys(src);
|
|
1211
|
-
idx = keys.length;
|
|
1212
|
-
while (idx--) {
|
|
1213
|
-
const key = keys[idx];
|
|
1214
|
-
res[key] = cloneDeepInner(src[key]);
|
|
1215
|
-
}
|
|
1216
|
-
}
|
|
1217
|
-
return res;
|
|
1218
|
-
}
|
|
1219
|
-
return cloneDeepInner(src);
|
|
1220
|
-
}
|
|
1221
|
-
/*
|
|
1222
|
-
following function comes from punycode.js library
|
|
1223
|
-
see: https://github.com/bestiejs/punycode.js
|
|
1224
|
-
*/
|
|
1225
|
-
/**
|
|
1226
|
-
* Creates an array containing the numeric code points of each Unicode
|
|
1227
|
-
* character in the string. While JavaScript uses UCS-2 internally,
|
|
1228
|
-
* this function will convert a pair of surrogate halves (each of which
|
|
1229
|
-
* UCS-2 exposes as separate characters) into a single code point,
|
|
1230
|
-
* matching UTF-16.
|
|
1231
|
-
* @see `punycode.ucs2.encode`
|
|
1232
|
-
* @see <https://mathiasbynens.be/notes/javascript-encoding>
|
|
1233
|
-
* @memberOf punycode.ucs2
|
|
1234
|
-
* @name decode
|
|
1235
|
-
* @param {String} string The Unicode input string (UCS-2).
|
|
1236
|
-
* @returns {Array} The new array of code points.
|
|
1237
|
-
*/
|
|
1238
|
-
function ucs2decode(string) {
|
|
1239
|
-
const output = [];
|
|
1240
|
-
let counter = 0;
|
|
1241
|
-
const length = string.length;
|
|
1242
|
-
let value;
|
|
1243
|
-
let extra;
|
|
1244
|
-
while (counter < length) {
|
|
1245
|
-
value = string.charCodeAt(counter++);
|
|
1246
|
-
if (value >= 0xd800 && value <= 0xdbff && counter < length) {
|
|
1247
|
-
// high surrogate, and there is a next character
|
|
1248
|
-
extra = string.charCodeAt(counter++);
|
|
1249
|
-
if ((extra & 0xfc00) == 0xdc00) {
|
|
1250
|
-
// low surrogate
|
|
1251
|
-
output.push(((value & 0x3ff) << 10) + (extra & 0x3ff) + 0x10000);
|
|
1252
|
-
}
|
|
1253
|
-
else {
|
|
1254
|
-
// unmatched surrogate; only append this code unit, in case the next
|
|
1255
|
-
// code unit is the high surrogate of a surrogate pair
|
|
1256
|
-
output.push(value);
|
|
1257
|
-
counter--;
|
|
1258
|
-
}
|
|
1259
|
-
}
|
|
1260
|
-
else {
|
|
1261
|
-
output.push(value);
|
|
1262
|
-
}
|
|
1263
|
-
}
|
|
1264
|
-
return output;
|
|
1265
|
-
}
|
|
1039
|
+
};
|
|
1040
|
+
const getRemotePath = (uri) => {
|
|
1041
|
+
const io = uri.indexOf('#');
|
|
1042
|
+
return io === -1 ? uri : uri.slice(0, io);
|
|
1043
|
+
};
|
|
1044
|
+
const isAbsoluteUri = (uri) => /^https?:\/\//.test(uri);
|
|
1045
|
+
const isRelativeUri = (uri) =>
|
|
1046
|
+
// relative URIs that end with a hash sign, issue #56
|
|
1047
|
+
/.+#/.test(uri);
|
|
1266
1048
|
|
|
1267
1049
|
class Report {
|
|
1268
|
-
|
|
1050
|
+
asyncTasks = [];
|
|
1051
|
+
commonErrorMessage;
|
|
1052
|
+
errors = [];
|
|
1053
|
+
json;
|
|
1054
|
+
path = [];
|
|
1055
|
+
rootSchema;
|
|
1269
1056
|
parentReport;
|
|
1270
1057
|
options;
|
|
1271
1058
|
reportOptions;
|
|
1272
|
-
path;
|
|
1273
|
-
asyncTasks;
|
|
1274
|
-
rootSchema;
|
|
1275
|
-
commonErrorMessage;
|
|
1276
|
-
json;
|
|
1277
1059
|
constructor(parentOrOptions, reportOptions) {
|
|
1278
1060
|
this.parentReport = parentOrOptions instanceof Report ? parentOrOptions : undefined;
|
|
1279
1061
|
this.options = parentOrOptions instanceof Report ? parentOrOptions.options : parentOrOptions || {};
|
|
1280
1062
|
this.reportOptions = reportOptions || {};
|
|
1281
|
-
this.errors = [];
|
|
1282
|
-
/**
|
|
1283
|
-
* @type {string[]}
|
|
1284
|
-
*/
|
|
1285
|
-
this.path = [];
|
|
1286
|
-
this.asyncTasks = [];
|
|
1287
|
-
this.rootSchema = undefined;
|
|
1288
|
-
this.commonErrorMessage = undefined;
|
|
1289
|
-
this.json = undefined;
|
|
1290
1063
|
}
|
|
1291
1064
|
isValid() {
|
|
1292
1065
|
if (this.asyncTasks.length > 0) {
|
|
@@ -1317,17 +1090,15 @@ class Report {
|
|
|
1317
1090
|
callback(err, valid);
|
|
1318
1091
|
}, 0);
|
|
1319
1092
|
};
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
};
|
|
1330
|
-
}
|
|
1093
|
+
const respond = (asyncTaskResultProcessFn) => (asyncTaskResult) => {
|
|
1094
|
+
if (timedOut) {
|
|
1095
|
+
return;
|
|
1096
|
+
}
|
|
1097
|
+
asyncTaskResultProcessFn(asyncTaskResult);
|
|
1098
|
+
if (--tasksCount === 0) {
|
|
1099
|
+
finish();
|
|
1100
|
+
}
|
|
1101
|
+
};
|
|
1331
1102
|
// finish if tasks are completed or there are any errors and breaking on first error was requested
|
|
1332
1103
|
if (tasksCount === 0 || (this.errors.length > 0 && this.options.breakOnFirstError)) {
|
|
1333
1104
|
finish();
|
|
@@ -1347,9 +1118,6 @@ class Report {
|
|
|
1347
1118
|
}, validationTimeout);
|
|
1348
1119
|
}
|
|
1349
1120
|
getPath(returnPathAsString) {
|
|
1350
|
-
/**
|
|
1351
|
-
* @type {string[]|string}
|
|
1352
|
-
*/
|
|
1353
1121
|
let path = [];
|
|
1354
1122
|
if (this.parentReport) {
|
|
1355
1123
|
path = path.concat(this.parentReport.path);
|
|
@@ -1372,7 +1140,7 @@ class Report {
|
|
|
1372
1140
|
}
|
|
1373
1141
|
getSchemaId() {
|
|
1374
1142
|
if (!this.rootSchema) {
|
|
1375
|
-
return
|
|
1143
|
+
return undefined;
|
|
1376
1144
|
}
|
|
1377
1145
|
// get the error path as an array
|
|
1378
1146
|
let path = [];
|
|
@@ -1391,16 +1159,16 @@ class Report {
|
|
|
1391
1159
|
// return id of the root
|
|
1392
1160
|
return this.rootSchema.id;
|
|
1393
1161
|
}
|
|
1394
|
-
hasError(
|
|
1162
|
+
hasError(errCode, errParams) {
|
|
1395
1163
|
let idx = this.errors.length;
|
|
1396
1164
|
while (idx--) {
|
|
1397
|
-
if (this.errors[idx].code ===
|
|
1165
|
+
if (this.errors[idx].code === errCode) {
|
|
1398
1166
|
// assume match
|
|
1399
1167
|
let match = true;
|
|
1400
1168
|
// check the params too
|
|
1401
1169
|
let idx2 = this.errors[idx].params.length;
|
|
1402
1170
|
while (idx2--) {
|
|
1403
|
-
if (this.errors[idx].params[idx2] !==
|
|
1171
|
+
if (this.errors[idx].params[idx2] !== errParams[idx2]) {
|
|
1404
1172
|
match = false;
|
|
1405
1173
|
}
|
|
1406
1174
|
}
|
|
@@ -1412,12 +1180,13 @@ class Report {
|
|
|
1412
1180
|
}
|
|
1413
1181
|
return false;
|
|
1414
1182
|
}
|
|
1415
|
-
addError(
|
|
1416
|
-
if (!
|
|
1183
|
+
addError(errCode, errParams, subReports, schema) {
|
|
1184
|
+
if (!errCode) {
|
|
1417
1185
|
throw new Error('No errorCode passed into addError()');
|
|
1418
1186
|
}
|
|
1419
|
-
this.addCustomError(
|
|
1187
|
+
this.addCustomError(errCode, Errors[errCode], errParams, subReports, schema);
|
|
1420
1188
|
}
|
|
1189
|
+
// this returns the root object being validated (the one passed into validator.validate)
|
|
1421
1190
|
getJson() {
|
|
1422
1191
|
if (this.json) {
|
|
1423
1192
|
return this.json;
|
|
@@ -1428,7 +1197,7 @@ class Report {
|
|
|
1428
1197
|
return undefined;
|
|
1429
1198
|
}
|
|
1430
1199
|
addCustomError(errorCode, errorMessage, params, subReports, schema) {
|
|
1431
|
-
if (this.errors.length >= this.reportOptions.maxErrors) {
|
|
1200
|
+
if (typeof this.reportOptions.maxErrors === 'number' && this.errors.length >= this.reportOptions.maxErrors) {
|
|
1432
1201
|
return;
|
|
1433
1202
|
}
|
|
1434
1203
|
if (!errorMessage) {
|
|
@@ -1437,9 +1206,9 @@ class Report {
|
|
|
1437
1206
|
params = params || [];
|
|
1438
1207
|
let idx = params.length;
|
|
1439
1208
|
while (idx--) {
|
|
1440
|
-
const
|
|
1441
|
-
const param =
|
|
1442
|
-
errorMessage = errorMessage.replace('{' + idx + '}', param);
|
|
1209
|
+
const paramType = whatIs(params[idx]);
|
|
1210
|
+
const param = paramType === 'object' || paramType === 'null' ? JSON.stringify(params[idx]) : params[idx];
|
|
1211
|
+
errorMessage = errorMessage.replace('{' + idx + '}', param.toString());
|
|
1443
1212
|
}
|
|
1444
1213
|
const err = {
|
|
1445
1214
|
code: errorCode,
|
|
@@ -1448,6 +1217,7 @@ class Report {
|
|
|
1448
1217
|
path: this.getPath(this.options.reportPathAsArray),
|
|
1449
1218
|
schemaId: this.getSchemaId(),
|
|
1450
1219
|
};
|
|
1220
|
+
// TODO v8: remove Symbol usage
|
|
1451
1221
|
err[schemaSymbol] = schema;
|
|
1452
1222
|
err[jsonSymbol] = this.getJson();
|
|
1453
1223
|
if (schema && typeof schema === 'string') {
|
|
@@ -1979,7 +1749,7 @@ function requireMatches () {
|
|
|
1979
1749
|
return matches.exports;
|
|
1980
1750
|
}
|
|
1981
1751
|
|
|
1982
|
-
var isEmail = {exports: {}};
|
|
1752
|
+
var isEmail$1 = {exports: {}};
|
|
1983
1753
|
|
|
1984
1754
|
var checkHost = {exports: {}};
|
|
1985
1755
|
|
|
@@ -2137,12 +1907,12 @@ function requireIsFQDN () {
|
|
|
2137
1907
|
return isFQDN.exports;
|
|
2138
1908
|
}
|
|
2139
1909
|
|
|
2140
|
-
var isIP = {exports: {}};
|
|
1910
|
+
var isIP$1 = {exports: {}};
|
|
2141
1911
|
|
|
2142
1912
|
var hasRequiredIsIP;
|
|
2143
1913
|
|
|
2144
1914
|
function requireIsIP () {
|
|
2145
|
-
if (hasRequiredIsIP) return isIP.exports;
|
|
1915
|
+
if (hasRequiredIsIP) return isIP$1.exports;
|
|
2146
1916
|
hasRequiredIsIP = 1;
|
|
2147
1917
|
(function (module, exports$1) {
|
|
2148
1918
|
|
|
@@ -2211,14 +1981,14 @@ function requireIsIP () {
|
|
|
2211
1981
|
}
|
|
2212
1982
|
module.exports = exports$1.default;
|
|
2213
1983
|
module.exports.default = exports$1.default;
|
|
2214
|
-
} (isIP, isIP.exports));
|
|
2215
|
-
return isIP.exports;
|
|
1984
|
+
} (isIP$1, isIP$1.exports));
|
|
1985
|
+
return isIP$1.exports;
|
|
2216
1986
|
}
|
|
2217
1987
|
|
|
2218
1988
|
var hasRequiredIsEmail;
|
|
2219
1989
|
|
|
2220
1990
|
function requireIsEmail () {
|
|
2221
|
-
if (hasRequiredIsEmail) return isEmail.exports;
|
|
1991
|
+
if (hasRequiredIsEmail) return isEmail$1.exports;
|
|
2222
1992
|
hasRequiredIsEmail = 1;
|
|
2223
1993
|
(function (module, exports$1) {
|
|
2224
1994
|
|
|
@@ -2394,11 +2164,11 @@ function requireIsEmail () {
|
|
|
2394
2164
|
}
|
|
2395
2165
|
module.exports = exports$1.default;
|
|
2396
2166
|
module.exports.default = exports$1.default;
|
|
2397
|
-
} (isEmail, isEmail.exports));
|
|
2398
|
-
return isEmail.exports;
|
|
2167
|
+
} (isEmail$1, isEmail$1.exports));
|
|
2168
|
+
return isEmail$1.exports;
|
|
2399
2169
|
}
|
|
2400
2170
|
|
|
2401
|
-
var isURL = {exports: {}};
|
|
2171
|
+
var isURL$1 = {exports: {}};
|
|
2402
2172
|
|
|
2403
2173
|
var includesString = {exports: {}};
|
|
2404
2174
|
|
|
@@ -2426,7 +2196,7 @@ function requireIncludesString () {
|
|
|
2426
2196
|
var hasRequiredIsURL;
|
|
2427
2197
|
|
|
2428
2198
|
function requireIsURL () {
|
|
2429
|
-
if (hasRequiredIsURL) return isURL.exports;
|
|
2199
|
+
if (hasRequiredIsURL) return isURL$1.exports;
|
|
2430
2200
|
hasRequiredIsURL = 1;
|
|
2431
2201
|
(function (module, exports$1) {
|
|
2432
2202
|
|
|
@@ -2677,8 +2447,8 @@ function requireIsURL () {
|
|
|
2677
2447
|
}
|
|
2678
2448
|
module.exports = exports$1.default;
|
|
2679
2449
|
module.exports.default = exports$1.default;
|
|
2680
|
-
} (isURL, isURL.exports));
|
|
2681
|
-
return isURL.exports;
|
|
2450
|
+
} (isURL$1, isURL$1.exports));
|
|
2451
|
+
return isURL$1.exports;
|
|
2682
2452
|
}
|
|
2683
2453
|
|
|
2684
2454
|
var isMACAddress = {exports: {}};
|
|
@@ -9379,140 +9149,359 @@ function requireValidator () {
|
|
|
9379
9149
|
var validatorExports = /*@__PURE__*/ requireValidator();
|
|
9380
9150
|
var validator = /*@__PURE__*/getDefaultExportFromCjs(validatorExports);
|
|
9381
9151
|
|
|
9382
|
-
const
|
|
9383
|
-
|
|
9384
|
-
|
|
9385
|
-
|
|
9386
|
-
|
|
9387
|
-
|
|
9388
|
-
|
|
9389
|
-
|
|
9152
|
+
const areEqual = (json1, json2, options) => {
|
|
9153
|
+
options = options || {};
|
|
9154
|
+
const caseInsensitiveComparison = options.caseInsensitiveComparison || false;
|
|
9155
|
+
// http://json-schema.org/latest/json-schema-core.html#rfc.section.3.6
|
|
9156
|
+
// Two JSON values are said to be equal if and only if:
|
|
9157
|
+
// both are nulls; or
|
|
9158
|
+
// both are booleans, and have the same value; or
|
|
9159
|
+
// both are strings, and have the same value; or
|
|
9160
|
+
// both are numbers, and have the same mathematical value; or
|
|
9161
|
+
if (json1 === json2) {
|
|
9162
|
+
return true;
|
|
9163
|
+
}
|
|
9164
|
+
if (caseInsensitiveComparison === true &&
|
|
9165
|
+
typeof json1 === 'string' &&
|
|
9166
|
+
typeof json2 === 'string' &&
|
|
9167
|
+
json1.toUpperCase() === json2.toUpperCase()) {
|
|
9168
|
+
return true;
|
|
9169
|
+
}
|
|
9170
|
+
let i, len;
|
|
9171
|
+
// both are arrays, and:
|
|
9172
|
+
if (Array.isArray(json1) && Array.isArray(json2)) {
|
|
9173
|
+
// have the same number of items; and
|
|
9174
|
+
if (json1.length !== json2.length) {
|
|
9390
9175
|
return false;
|
|
9391
9176
|
}
|
|
9392
|
-
//
|
|
9393
|
-
|
|
9394
|
-
|
|
9395
|
-
|
|
9396
|
-
|
|
9177
|
+
// items at the same index are equal according to this definition; or
|
|
9178
|
+
len = json1.length;
|
|
9179
|
+
for (i = 0; i < len; i++) {
|
|
9180
|
+
if (!areEqual(json1[i], json2[i], { caseInsensitiveComparison: caseInsensitiveComparison })) {
|
|
9181
|
+
return false;
|
|
9182
|
+
}
|
|
9397
9183
|
}
|
|
9398
9184
|
return true;
|
|
9399
|
-
}
|
|
9400
|
-
|
|
9401
|
-
|
|
9402
|
-
|
|
9403
|
-
|
|
9404
|
-
|
|
9405
|
-
|
|
9406
|
-
if (!FormatValidators.date(s[0])) {
|
|
9407
|
-
return false;
|
|
9408
|
-
}
|
|
9409
|
-
const matches = /^([0-9]{2}):([0-9]{2}):([0-9]{2})(.[0-9]+)?(z|([+-][0-9]{2}:[0-9]{2}))$/.exec(s[1]);
|
|
9410
|
-
if (matches === null) {
|
|
9185
|
+
}
|
|
9186
|
+
// both are objects, and:
|
|
9187
|
+
if (isObject(json1) && isObject(json2)) {
|
|
9188
|
+
// have the same set of property names; and
|
|
9189
|
+
const keys1 = sortedKeys(json1);
|
|
9190
|
+
const keys2 = sortedKeys(json2);
|
|
9191
|
+
if (!areEqual(keys1, keys2, { caseInsensitiveComparison: caseInsensitiveComparison })) {
|
|
9411
9192
|
return false;
|
|
9412
9193
|
}
|
|
9413
|
-
//
|
|
9414
|
-
|
|
9415
|
-
|
|
9416
|
-
|
|
9417
|
-
|
|
9418
|
-
|
|
9419
|
-
return false;
|
|
9194
|
+
// values for a same property name are equal according to this definition.
|
|
9195
|
+
len = keys1.length;
|
|
9196
|
+
for (i = 0; i < len; i++) {
|
|
9197
|
+
if (!areEqual(json1[keys1[i]], json2[keys1[i]], { caseInsensitiveComparison: caseInsensitiveComparison })) {
|
|
9198
|
+
return false;
|
|
9199
|
+
}
|
|
9420
9200
|
}
|
|
9421
9201
|
return true;
|
|
9422
|
-
}
|
|
9423
|
-
|
|
9424
|
-
|
|
9425
|
-
|
|
9426
|
-
|
|
9427
|
-
|
|
9428
|
-
|
|
9429
|
-
|
|
9430
|
-
|
|
9431
|
-
|
|
9202
|
+
}
|
|
9203
|
+
return false;
|
|
9204
|
+
};
|
|
9205
|
+
const decodeJSONPointer = (str) => {
|
|
9206
|
+
// http://tools.ietf.org/html/draft-ietf-appsawg-json-pointer-07#section-3
|
|
9207
|
+
return decodeURIComponent(str).replace(/~[0-1]/g, (x) => (x === '~1' ? '/' : '~'));
|
|
9208
|
+
};
|
|
9209
|
+
const sortedKeys = (obj) => Object.keys(obj).sort();
|
|
9210
|
+
|
|
9211
|
+
const { isEmail, isIP, isURL } = validator;
|
|
9212
|
+
const dateValidator = (date) => {
|
|
9213
|
+
if (typeof date !== 'string') {
|
|
9214
|
+
return true;
|
|
9215
|
+
}
|
|
9216
|
+
// full-date from http://tools.ietf.org/html/rfc3339#section-5.6
|
|
9217
|
+
const matches = /^([0-9]{4})-([0-9]{2})-([0-9]{2})$/.exec(date);
|
|
9218
|
+
if (matches === null) {
|
|
9219
|
+
return false;
|
|
9220
|
+
}
|
|
9221
|
+
// var year = matches[1];
|
|
9222
|
+
// var month = matches[2];
|
|
9223
|
+
// var day = matches[3];
|
|
9224
|
+
if (matches[2] < '01' || matches[2] > '12' || matches[3] < '01' || matches[3] > '31') {
|
|
9225
|
+
return false;
|
|
9226
|
+
}
|
|
9227
|
+
return true;
|
|
9228
|
+
};
|
|
9229
|
+
const dateTimeValidator = (dateTime) => {
|
|
9230
|
+
if (typeof dateTime !== 'string') {
|
|
9231
|
+
return true;
|
|
9232
|
+
}
|
|
9233
|
+
// date-time from http://tools.ietf.org/html/rfc3339#section-5.6
|
|
9234
|
+
const s = dateTime.toLowerCase().split('t');
|
|
9235
|
+
if (!dateValidator(s[0])) {
|
|
9236
|
+
return false;
|
|
9237
|
+
}
|
|
9238
|
+
const matches = /^([0-9]{2}):([0-9]{2}):([0-9]{2})(.[0-9]+)?(z|([+-][0-9]{2}:[0-9]{2}))$/.exec(s[1]);
|
|
9239
|
+
if (matches === null) {
|
|
9240
|
+
return false;
|
|
9241
|
+
}
|
|
9242
|
+
// var hour = matches[1];
|
|
9243
|
+
// var minute = matches[2];
|
|
9244
|
+
// var second = matches[3];
|
|
9245
|
+
// var fraction = matches[4];
|
|
9246
|
+
// var timezone = matches[5];
|
|
9247
|
+
if (matches[1] > '23' || matches[2] > '59' || matches[3] > '59') {
|
|
9248
|
+
return false;
|
|
9249
|
+
}
|
|
9250
|
+
return true;
|
|
9251
|
+
};
|
|
9252
|
+
const emailValidator = (email) => {
|
|
9253
|
+
if (typeof email !== 'string') {
|
|
9254
|
+
return true;
|
|
9255
|
+
}
|
|
9256
|
+
return isEmail(email, { require_tld: true });
|
|
9257
|
+
};
|
|
9258
|
+
const hostnameValidator = (hostname) => {
|
|
9259
|
+
if (typeof hostname !== 'string') {
|
|
9260
|
+
return true;
|
|
9261
|
+
}
|
|
9262
|
+
/*
|
|
9263
|
+
http://json-schema.org/latest/json-schema-validation.html#anchor114
|
|
9264
|
+
A string instance is valid against this attribute if it is a valid
|
|
9265
|
+
representation for an Internet host name, as defined by RFC 1034, section 3.1 [RFC1034].
|
|
9266
|
+
|
|
9267
|
+
http://tools.ietf.org/html/rfc1034#section-3.5
|
|
9268
|
+
|
|
9269
|
+
<digit> ::= any one of the ten digits 0 through 9
|
|
9270
|
+
var digit = /[0-9]/;
|
|
9271
|
+
|
|
9272
|
+
<letter> ::= any one of the 52 alphabetic characters A through Z in upper case and a through z in lower case
|
|
9273
|
+
var letter = /[a-zA-Z]/;
|
|
9274
|
+
|
|
9275
|
+
<let-dig> ::= <letter> | <digit>
|
|
9276
|
+
var letDig = /[0-9a-zA-Z]/;
|
|
9277
|
+
|
|
9278
|
+
<let-dig-hyp> ::= <let-dig> | "-"
|
|
9279
|
+
var letDigHyp = /[-0-9a-zA-Z]/;
|
|
9280
|
+
|
|
9281
|
+
<ldh-str> ::= <let-dig-hyp> | <let-dig-hyp> <ldh-str>
|
|
9282
|
+
var ldhStr = /[-0-9a-zA-Z]+/;
|
|
9283
|
+
|
|
9284
|
+
<label> ::= <letter> [ [ <ldh-str> ] <let-dig> ]
|
|
9285
|
+
var label = /[a-zA-Z](([-0-9a-zA-Z]+)?[0-9a-zA-Z])?/;
|
|
9286
|
+
|
|
9287
|
+
<subdomain> ::= <label> | <subdomain> "." <label>
|
|
9288
|
+
var subdomain = /^[a-zA-Z](([-0-9a-zA-Z]+)?[0-9a-zA-Z])?(\.[a-zA-Z](([-0-9a-zA-Z]+)?[0-9a-zA-Z])?)*$/;
|
|
9289
|
+
|
|
9290
|
+
<domain> ::= <subdomain> | " "
|
|
9291
|
+
var domain = null;
|
|
9292
|
+
*/
|
|
9293
|
+
const valid = /^[a-zA-Z](([-0-9a-zA-Z]+)?[0-9a-zA-Z])?(\.[a-zA-Z](([-0-9a-zA-Z]+)?[0-9a-zA-Z])?)*$/.test(hostname);
|
|
9294
|
+
if (valid) {
|
|
9295
|
+
// the sum of all label octets and label lengths is limited to 255.
|
|
9296
|
+
if (hostname.length > 255) {
|
|
9297
|
+
return false;
|
|
9432
9298
|
}
|
|
9433
|
-
|
|
9434
|
-
|
|
9435
|
-
|
|
9436
|
-
|
|
9437
|
-
|
|
9438
|
-
http://tools.ietf.org/html/rfc1034#section-3.5
|
|
9439
|
-
|
|
9440
|
-
<digit> ::= any one of the ten digits 0 through 9
|
|
9441
|
-
var digit = /[0-9]/;
|
|
9442
|
-
|
|
9443
|
-
<letter> ::= any one of the 52 alphabetic characters A through Z in upper case and a through z in lower case
|
|
9444
|
-
var letter = /[a-zA-Z]/;
|
|
9445
|
-
|
|
9446
|
-
<let-dig> ::= <letter> | <digit>
|
|
9447
|
-
var letDig = /[0-9a-zA-Z]/;
|
|
9448
|
-
|
|
9449
|
-
<let-dig-hyp> ::= <let-dig> | "-"
|
|
9450
|
-
var letDigHyp = /[-0-9a-zA-Z]/;
|
|
9451
|
-
|
|
9452
|
-
<ldh-str> ::= <let-dig-hyp> | <let-dig-hyp> <ldh-str>
|
|
9453
|
-
var ldhStr = /[-0-9a-zA-Z]+/;
|
|
9454
|
-
|
|
9455
|
-
<label> ::= <letter> [ [ <ldh-str> ] <let-dig> ]
|
|
9456
|
-
var label = /[a-zA-Z](([-0-9a-zA-Z]+)?[0-9a-zA-Z])?/;
|
|
9457
|
-
|
|
9458
|
-
<subdomain> ::= <label> | <subdomain> "." <label>
|
|
9459
|
-
var subdomain = /^[a-zA-Z](([-0-9a-zA-Z]+)?[0-9a-zA-Z])?(\.[a-zA-Z](([-0-9a-zA-Z]+)?[0-9a-zA-Z])?)*$/;
|
|
9460
|
-
|
|
9461
|
-
<domain> ::= <subdomain> | " "
|
|
9462
|
-
var domain = null;
|
|
9463
|
-
*/
|
|
9464
|
-
const valid = /^[a-zA-Z](([-0-9a-zA-Z]+)?[0-9a-zA-Z])?(\.[a-zA-Z](([-0-9a-zA-Z]+)?[0-9a-zA-Z])?)*$/.test(hostname);
|
|
9465
|
-
if (valid) {
|
|
9466
|
-
// the sum of all label octets and label lengths is limited to 255.
|
|
9467
|
-
if (hostname.length > 255) {
|
|
9299
|
+
// Each node has a label, which is zero to 63 octets in length
|
|
9300
|
+
const labels = hostname.split('.');
|
|
9301
|
+
for (let i = 0; i < labels.length; i++) {
|
|
9302
|
+
if (labels[i].length > 63) {
|
|
9468
9303
|
return false;
|
|
9469
9304
|
}
|
|
9470
|
-
|
|
9471
|
-
|
|
9472
|
-
|
|
9473
|
-
|
|
9474
|
-
|
|
9305
|
+
}
|
|
9306
|
+
}
|
|
9307
|
+
return valid;
|
|
9308
|
+
};
|
|
9309
|
+
const ipv4Validator = (ipv4) => {
|
|
9310
|
+
if (typeof ipv4 !== 'string') {
|
|
9311
|
+
return true;
|
|
9312
|
+
}
|
|
9313
|
+
return isIP(ipv4, 4);
|
|
9314
|
+
};
|
|
9315
|
+
const ipv6Validator = (ipv6) => {
|
|
9316
|
+
if (typeof ipv6 !== 'string') {
|
|
9317
|
+
return true;
|
|
9318
|
+
}
|
|
9319
|
+
return isIP(ipv6, 6);
|
|
9320
|
+
};
|
|
9321
|
+
const regexValidator = (input) => {
|
|
9322
|
+
if (typeof input !== 'string') {
|
|
9323
|
+
return false;
|
|
9324
|
+
}
|
|
9325
|
+
try {
|
|
9326
|
+
RegExp(input);
|
|
9327
|
+
return true;
|
|
9328
|
+
}
|
|
9329
|
+
catch (_e) {
|
|
9330
|
+
return false;
|
|
9331
|
+
}
|
|
9332
|
+
};
|
|
9333
|
+
const strictUriValidator = (uri) => typeof uri !== 'string' || isURL(uri);
|
|
9334
|
+
const uriValidator = function (uri) {
|
|
9335
|
+
// https://github.com/zaggino/z-schema/issues/18
|
|
9336
|
+
// RegExp from http://tools.ietf.org/html/rfc3986#appendix-B
|
|
9337
|
+
return typeof uri !== 'string' || RegExp('^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?').test(uri);
|
|
9338
|
+
};
|
|
9339
|
+
const inbuiltValidators = {
|
|
9340
|
+
date: dateValidator,
|
|
9341
|
+
'date-time': dateTimeValidator,
|
|
9342
|
+
email: emailValidator,
|
|
9343
|
+
hostname: hostnameValidator,
|
|
9344
|
+
'host-name': hostnameValidator,
|
|
9345
|
+
ipv4: ipv4Validator,
|
|
9346
|
+
ipv6: ipv6Validator,
|
|
9347
|
+
regex: regexValidator,
|
|
9348
|
+
uri: uriValidator,
|
|
9349
|
+
'strict-uri': strictUriValidator,
|
|
9350
|
+
};
|
|
9351
|
+
const customValidators = {};
|
|
9352
|
+
function getFormatValidators(options) {
|
|
9353
|
+
return {
|
|
9354
|
+
...inbuiltValidators,
|
|
9355
|
+
...(options?.strictUris ? { uri: strictUriValidator } : {}),
|
|
9356
|
+
...customValidators,
|
|
9357
|
+
};
|
|
9358
|
+
}
|
|
9359
|
+
function registerFormat(name, validatorFunction) {
|
|
9360
|
+
customValidators[name] = validatorFunction;
|
|
9361
|
+
}
|
|
9362
|
+
function unregisterFormat(name) {
|
|
9363
|
+
delete customValidators[name];
|
|
9364
|
+
}
|
|
9365
|
+
function isFormatSupported(name) {
|
|
9366
|
+
return inbuiltValidators[name] != null || customValidators[name] != null;
|
|
9367
|
+
}
|
|
9368
|
+
function getRegisteredFormats() {
|
|
9369
|
+
return sortedKeys(customValidators);
|
|
9370
|
+
}
|
|
9371
|
+
|
|
9372
|
+
/*
|
|
9373
|
+
following function comes from punycode.js library
|
|
9374
|
+
see: https://github.com/bestiejs/punycode.js
|
|
9375
|
+
*/
|
|
9376
|
+
/**
|
|
9377
|
+
* Creates an array containing the numeric code points of each Unicode
|
|
9378
|
+
* character in the string. While JavaScript uses UCS-2 internally,
|
|
9379
|
+
* this function will convert a pair of surrogate halves (each of which
|
|
9380
|
+
* UCS-2 exposes as separate characters) into a single code point,
|
|
9381
|
+
* matching UTF-16.
|
|
9382
|
+
* @see `punycode.ucs2.encode`
|
|
9383
|
+
* @see <https://mathiasbynens.be/notes/javascript-encoding>
|
|
9384
|
+
* @memberOf punycode.ucs2
|
|
9385
|
+
* @name decode
|
|
9386
|
+
* @param {String} string The Unicode input string (UCS-2).
|
|
9387
|
+
* @returns {Array} The new array of code points.
|
|
9388
|
+
*/
|
|
9389
|
+
function ucs2decode(string) {
|
|
9390
|
+
const output = [];
|
|
9391
|
+
let counter = 0;
|
|
9392
|
+
const length = string.length;
|
|
9393
|
+
let value;
|
|
9394
|
+
let extra;
|
|
9395
|
+
while (counter < length) {
|
|
9396
|
+
value = string.charCodeAt(counter++);
|
|
9397
|
+
if (value >= 0xd800 && value <= 0xdbff && counter < length) {
|
|
9398
|
+
// high surrogate, and there is a next character
|
|
9399
|
+
extra = string.charCodeAt(counter++);
|
|
9400
|
+
if ((extra & 0xfc00) == 0xdc00) {
|
|
9401
|
+
// low surrogate
|
|
9402
|
+
output.push(((value & 0x3ff) << 10) + (extra & 0x3ff) + 0x10000);
|
|
9403
|
+
}
|
|
9404
|
+
else {
|
|
9405
|
+
// unmatched surrogate; only append this code unit, in case the next
|
|
9406
|
+
// code unit is the high surrogate of a surrogate pair
|
|
9407
|
+
output.push(value);
|
|
9408
|
+
counter--;
|
|
9409
|
+
}
|
|
9410
|
+
}
|
|
9411
|
+
else {
|
|
9412
|
+
output.push(value);
|
|
9413
|
+
}
|
|
9414
|
+
}
|
|
9415
|
+
return output;
|
|
9416
|
+
}
|
|
9417
|
+
|
|
9418
|
+
const isUniqueArray = (arr, indexes) => {
|
|
9419
|
+
let i;
|
|
9420
|
+
let j;
|
|
9421
|
+
const l = arr.length;
|
|
9422
|
+
for (i = 0; i < l; i++) {
|
|
9423
|
+
for (j = i + 1; j < l; j++) {
|
|
9424
|
+
if (areEqual(arr[i], arr[j])) {
|
|
9425
|
+
if (indexes) {
|
|
9426
|
+
indexes.push(i, j);
|
|
9475
9427
|
}
|
|
9428
|
+
return false;
|
|
9476
9429
|
}
|
|
9477
9430
|
}
|
|
9478
|
-
|
|
9479
|
-
|
|
9480
|
-
|
|
9481
|
-
|
|
9482
|
-
|
|
9483
|
-
|
|
9484
|
-
|
|
9485
|
-
|
|
9431
|
+
}
|
|
9432
|
+
return true;
|
|
9433
|
+
};
|
|
9434
|
+
const difference = (bigSet, subSet) => {
|
|
9435
|
+
const arr = [];
|
|
9436
|
+
let idx = bigSet.length;
|
|
9437
|
+
while (idx--) {
|
|
9438
|
+
if (subSet.indexOf(bigSet[idx]) === -1) {
|
|
9439
|
+
arr.push(bigSet[idx]);
|
|
9486
9440
|
}
|
|
9487
|
-
|
|
9488
|
-
|
|
9489
|
-
|
|
9490
|
-
|
|
9491
|
-
|
|
9441
|
+
}
|
|
9442
|
+
return arr;
|
|
9443
|
+
};
|
|
9444
|
+
|
|
9445
|
+
const shallowClone = (src) => {
|
|
9446
|
+
if (src == null || typeof src !== 'object') {
|
|
9447
|
+
return src;
|
|
9448
|
+
}
|
|
9449
|
+
let res;
|
|
9450
|
+
let idx;
|
|
9451
|
+
if (Array.isArray(src)) {
|
|
9452
|
+
res = [];
|
|
9453
|
+
idx = src.length;
|
|
9454
|
+
while (idx--) {
|
|
9455
|
+
res[idx] = src[idx];
|
|
9492
9456
|
}
|
|
9493
|
-
|
|
9494
|
-
|
|
9495
|
-
|
|
9496
|
-
|
|
9497
|
-
|
|
9498
|
-
|
|
9457
|
+
}
|
|
9458
|
+
else {
|
|
9459
|
+
res = {};
|
|
9460
|
+
const keys = Object.keys(src);
|
|
9461
|
+
idx = keys.length;
|
|
9462
|
+
while (idx--) {
|
|
9463
|
+
const key = keys[idx];
|
|
9464
|
+
res[key] = src[key];
|
|
9499
9465
|
}
|
|
9500
|
-
|
|
9501
|
-
|
|
9466
|
+
}
|
|
9467
|
+
return res;
|
|
9468
|
+
};
|
|
9469
|
+
const deepClone = (src) => {
|
|
9470
|
+
let vidx = 0;
|
|
9471
|
+
const visited = new Map();
|
|
9472
|
+
const cloned = [];
|
|
9473
|
+
const cloneDeepInner = (src) => {
|
|
9474
|
+
if (typeof src !== 'object' || src === null) {
|
|
9475
|
+
return src;
|
|
9502
9476
|
}
|
|
9503
|
-
|
|
9504
|
-
|
|
9505
|
-
|
|
9506
|
-
|
|
9507
|
-
|
|
9508
|
-
|
|
9509
|
-
|
|
9510
|
-
|
|
9511
|
-
|
|
9512
|
-
|
|
9513
|
-
|
|
9514
|
-
|
|
9515
|
-
|
|
9477
|
+
let res;
|
|
9478
|
+
let idx;
|
|
9479
|
+
const cidx = visited.get(src);
|
|
9480
|
+
if (cidx !== undefined) {
|
|
9481
|
+
return cloned[cidx];
|
|
9482
|
+
}
|
|
9483
|
+
visited.set(src, vidx++);
|
|
9484
|
+
if (Array.isArray(src)) {
|
|
9485
|
+
res = [];
|
|
9486
|
+
cloned.push(res);
|
|
9487
|
+
idx = src.length;
|
|
9488
|
+
while (idx--) {
|
|
9489
|
+
res[idx] = cloneDeepInner(src[idx]);
|
|
9490
|
+
}
|
|
9491
|
+
}
|
|
9492
|
+
else {
|
|
9493
|
+
res = {};
|
|
9494
|
+
cloned.push(res);
|
|
9495
|
+
const keys = Object.keys(src);
|
|
9496
|
+
idx = keys.length;
|
|
9497
|
+
while (idx--) {
|
|
9498
|
+
const key = keys[idx];
|
|
9499
|
+
res[key] = cloneDeepInner(src[key]);
|
|
9500
|
+
}
|
|
9501
|
+
}
|
|
9502
|
+
return res;
|
|
9503
|
+
};
|
|
9504
|
+
return cloneDeepInner(src);
|
|
9516
9505
|
};
|
|
9517
9506
|
|
|
9518
9507
|
const shouldSkipValidate = function (options, errors) {
|
|
@@ -9524,6 +9513,12 @@ const shouldSkipValidate = function (options, errors) {
|
|
|
9524
9513
|
}));
|
|
9525
9514
|
};
|
|
9526
9515
|
const JsonValidators = {
|
|
9516
|
+
id: () => { },
|
|
9517
|
+
$ref: () => { },
|
|
9518
|
+
$schema: () => { },
|
|
9519
|
+
title: () => { },
|
|
9520
|
+
description: () => { },
|
|
9521
|
+
default: () => { },
|
|
9527
9522
|
multipleOf: function (report, schema, json) {
|
|
9528
9523
|
// http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.1.1.2
|
|
9529
9524
|
if (shouldSkipValidate(this.validateOptions, ['MULTIPLE_OF'])) {
|
|
@@ -9535,7 +9530,7 @@ const JsonValidators = {
|
|
|
9535
9530
|
const stringMultipleOf = String(schema.multipleOf);
|
|
9536
9531
|
const scale = Math.pow(10, stringMultipleOf.length - stringMultipleOf.indexOf('.') - 1);
|
|
9537
9532
|
if (whatIs((json * scale) / (schema.multipleOf * scale)) !== 'integer') {
|
|
9538
|
-
report.addError('MULTIPLE_OF', [json, schema.multipleOf],
|
|
9533
|
+
report.addError('MULTIPLE_OF', [json, schema.multipleOf], undefined, schema);
|
|
9539
9534
|
}
|
|
9540
9535
|
},
|
|
9541
9536
|
maximum: function (report, schema, json) {
|
|
@@ -9548,12 +9543,12 @@ const JsonValidators = {
|
|
|
9548
9543
|
}
|
|
9549
9544
|
if (schema.exclusiveMaximum !== true) {
|
|
9550
9545
|
if (json > schema.maximum) {
|
|
9551
|
-
report.addError('MAXIMUM', [json, schema.maximum],
|
|
9546
|
+
report.addError('MAXIMUM', [json, schema.maximum], undefined, schema);
|
|
9552
9547
|
}
|
|
9553
9548
|
}
|
|
9554
9549
|
else {
|
|
9555
9550
|
if (json >= schema.maximum) {
|
|
9556
|
-
report.addError('MAXIMUM_EXCLUSIVE', [json, schema.maximum],
|
|
9551
|
+
report.addError('MAXIMUM_EXCLUSIVE', [json, schema.maximum], undefined, schema);
|
|
9557
9552
|
}
|
|
9558
9553
|
}
|
|
9559
9554
|
},
|
|
@@ -9570,12 +9565,12 @@ const JsonValidators = {
|
|
|
9570
9565
|
}
|
|
9571
9566
|
if (schema.exclusiveMinimum !== true) {
|
|
9572
9567
|
if (json < schema.minimum) {
|
|
9573
|
-
report.addError('MINIMUM', [json, schema.minimum],
|
|
9568
|
+
report.addError('MINIMUM', [json, schema.minimum], undefined, schema);
|
|
9574
9569
|
}
|
|
9575
9570
|
}
|
|
9576
9571
|
else {
|
|
9577
9572
|
if (json <= schema.minimum) {
|
|
9578
|
-
report.addError('MINIMUM_EXCLUSIVE', [json, schema.minimum],
|
|
9573
|
+
report.addError('MINIMUM_EXCLUSIVE', [json, schema.minimum], undefined, schema);
|
|
9579
9574
|
}
|
|
9580
9575
|
}
|
|
9581
9576
|
},
|
|
@@ -9591,7 +9586,7 @@ const JsonValidators = {
|
|
|
9591
9586
|
return;
|
|
9592
9587
|
}
|
|
9593
9588
|
if (ucs2decode(json).length > schema.maxLength) {
|
|
9594
|
-
report.addError('MAX_LENGTH', [json.length, schema.maxLength],
|
|
9589
|
+
report.addError('MAX_LENGTH', [json.length, schema.maxLength], undefined, schema);
|
|
9595
9590
|
}
|
|
9596
9591
|
},
|
|
9597
9592
|
minLength: function (report, schema, json) {
|
|
@@ -9603,7 +9598,7 @@ const JsonValidators = {
|
|
|
9603
9598
|
return;
|
|
9604
9599
|
}
|
|
9605
9600
|
if (ucs2decode(json).length < schema.minLength) {
|
|
9606
|
-
report.addError('MIN_LENGTH', [json.length, schema.minLength],
|
|
9601
|
+
report.addError('MIN_LENGTH', [json.length, schema.minLength], undefined, schema);
|
|
9607
9602
|
}
|
|
9608
9603
|
},
|
|
9609
9604
|
pattern: function (report, schema, json) {
|
|
@@ -9615,7 +9610,7 @@ const JsonValidators = {
|
|
|
9615
9610
|
return;
|
|
9616
9611
|
}
|
|
9617
9612
|
if (RegExp(schema.pattern).test(json) === false) {
|
|
9618
|
-
report.addError('PATTERN', [schema.pattern, json],
|
|
9613
|
+
report.addError('PATTERN', [schema.pattern, json], undefined, schema);
|
|
9619
9614
|
}
|
|
9620
9615
|
},
|
|
9621
9616
|
additionalItems: function (report, schema, json) {
|
|
@@ -9630,12 +9625,12 @@ const JsonValidators = {
|
|
|
9630
9625
|
// the json is valid if its size is less than, or equal to, the size of "items".
|
|
9631
9626
|
if (schema.additionalItems === false && Array.isArray(schema.items)) {
|
|
9632
9627
|
if (json.length > schema.items.length) {
|
|
9633
|
-
report.addError('ARRAY_ADDITIONAL_ITEMS',
|
|
9628
|
+
report.addError('ARRAY_ADDITIONAL_ITEMS', undefined, undefined, schema);
|
|
9634
9629
|
}
|
|
9635
9630
|
}
|
|
9636
9631
|
},
|
|
9637
9632
|
items: function () {
|
|
9638
|
-
/*report, schema, json*/
|
|
9633
|
+
/*report: Report, schema: JsonSchemaInternal, json: unknown*/
|
|
9639
9634
|
// covered in additionalItems
|
|
9640
9635
|
},
|
|
9641
9636
|
maxItems: function (report, schema, json) {
|
|
@@ -9647,7 +9642,7 @@ const JsonValidators = {
|
|
|
9647
9642
|
return;
|
|
9648
9643
|
}
|
|
9649
9644
|
if (json.length > schema.maxItems) {
|
|
9650
|
-
report.addError('ARRAY_LENGTH_LONG', [json.length, schema.maxItems],
|
|
9645
|
+
report.addError('ARRAY_LENGTH_LONG', [json.length, schema.maxItems], undefined, schema);
|
|
9651
9646
|
}
|
|
9652
9647
|
},
|
|
9653
9648
|
minItems: function (report, schema, json) {
|
|
@@ -9659,7 +9654,7 @@ const JsonValidators = {
|
|
|
9659
9654
|
return;
|
|
9660
9655
|
}
|
|
9661
9656
|
if (json.length < schema.minItems) {
|
|
9662
|
-
report.addError('ARRAY_LENGTH_SHORT', [json.length, schema.minItems],
|
|
9657
|
+
report.addError('ARRAY_LENGTH_SHORT', [json.length, schema.minItems], undefined, schema);
|
|
9663
9658
|
}
|
|
9664
9659
|
},
|
|
9665
9660
|
uniqueItems: function (report, schema, json) {
|
|
@@ -9673,7 +9668,7 @@ const JsonValidators = {
|
|
|
9673
9668
|
if (schema.uniqueItems === true) {
|
|
9674
9669
|
const matches = [];
|
|
9675
9670
|
if (isUniqueArray(json, matches) === false) {
|
|
9676
|
-
report.addError('ARRAY_UNIQUE', matches,
|
|
9671
|
+
report.addError('ARRAY_UNIQUE', matches, undefined, schema);
|
|
9677
9672
|
}
|
|
9678
9673
|
}
|
|
9679
9674
|
},
|
|
@@ -9682,12 +9677,12 @@ const JsonValidators = {
|
|
|
9682
9677
|
if (shouldSkipValidate(this.validateOptions, ['OBJECT_PROPERTIES_MAXIMUM'])) {
|
|
9683
9678
|
return;
|
|
9684
9679
|
}
|
|
9685
|
-
if (
|
|
9680
|
+
if (!isObject(json)) {
|
|
9686
9681
|
return;
|
|
9687
9682
|
}
|
|
9688
9683
|
const keysCount = Object.keys(json).length;
|
|
9689
9684
|
if (keysCount > schema.maxProperties) {
|
|
9690
|
-
report.addError('OBJECT_PROPERTIES_MAXIMUM', [keysCount, schema.maxProperties],
|
|
9685
|
+
report.addError('OBJECT_PROPERTIES_MAXIMUM', [keysCount, schema.maxProperties], undefined, schema);
|
|
9691
9686
|
}
|
|
9692
9687
|
},
|
|
9693
9688
|
minProperties: function (report, schema, json) {
|
|
@@ -9695,12 +9690,12 @@ const JsonValidators = {
|
|
|
9695
9690
|
if (shouldSkipValidate(this.validateOptions, ['OBJECT_PROPERTIES_MINIMUM'])) {
|
|
9696
9691
|
return;
|
|
9697
9692
|
}
|
|
9698
|
-
if (
|
|
9693
|
+
if (!isObject(json)) {
|
|
9699
9694
|
return;
|
|
9700
9695
|
}
|
|
9701
9696
|
const keysCount = Object.keys(json).length;
|
|
9702
9697
|
if (keysCount < schema.minProperties) {
|
|
9703
|
-
report.addError('OBJECT_PROPERTIES_MINIMUM', [keysCount, schema.minProperties],
|
|
9698
|
+
report.addError('OBJECT_PROPERTIES_MINIMUM', [keysCount, schema.minProperties], undefined, schema);
|
|
9704
9699
|
}
|
|
9705
9700
|
},
|
|
9706
9701
|
required: function (report, schema, json) {
|
|
@@ -9708,14 +9703,14 @@ const JsonValidators = {
|
|
|
9708
9703
|
if (shouldSkipValidate(this.validateOptions, ['OBJECT_MISSING_REQUIRED_PROPERTY'])) {
|
|
9709
9704
|
return;
|
|
9710
9705
|
}
|
|
9711
|
-
if (
|
|
9706
|
+
if (!isObject(json)) {
|
|
9712
9707
|
return;
|
|
9713
9708
|
}
|
|
9714
9709
|
let idx = schema.required.length;
|
|
9715
9710
|
while (idx--) {
|
|
9716
9711
|
const requiredPropertyName = schema.required[idx];
|
|
9717
9712
|
if (json[requiredPropertyName] === undefined) {
|
|
9718
|
-
report.addError('OBJECT_MISSING_REQUIRED_PROPERTY', [requiredPropertyName],
|
|
9713
|
+
report.addError('OBJECT_MISSING_REQUIRED_PROPERTY', [requiredPropertyName], undefined, schema);
|
|
9719
9714
|
}
|
|
9720
9715
|
}
|
|
9721
9716
|
},
|
|
@@ -9736,7 +9731,7 @@ const JsonValidators = {
|
|
|
9736
9731
|
if (shouldSkipValidate(this.validateOptions, ['OBJECT_ADDITIONAL_PROPERTIES'])) {
|
|
9737
9732
|
return;
|
|
9738
9733
|
}
|
|
9739
|
-
if (
|
|
9734
|
+
if (!isObject(json)) {
|
|
9740
9735
|
return;
|
|
9741
9736
|
}
|
|
9742
9737
|
const properties = schema.properties !== undefined ? schema.properties : {};
|
|
@@ -9764,19 +9759,21 @@ const JsonValidators = {
|
|
|
9764
9759
|
// Validation of the json succeeds if, after these two steps, set "s" is empty.
|
|
9765
9760
|
if (s.length > 0) {
|
|
9766
9761
|
// assumeAdditional can be an array of allowed properties
|
|
9767
|
-
|
|
9768
|
-
|
|
9769
|
-
|
|
9770
|
-
|
|
9771
|
-
|
|
9772
|
-
|
|
9762
|
+
if (Array.isArray(this.options.assumeAdditional)) {
|
|
9763
|
+
let idx3 = this.options.assumeAdditional.length;
|
|
9764
|
+
if (idx3) {
|
|
9765
|
+
while (idx3--) {
|
|
9766
|
+
const io = s.indexOf(this.options.assumeAdditional[idx3]);
|
|
9767
|
+
if (io !== -1) {
|
|
9768
|
+
s.splice(io, 1);
|
|
9769
|
+
}
|
|
9773
9770
|
}
|
|
9774
9771
|
}
|
|
9775
9772
|
}
|
|
9776
9773
|
let idx4 = s.length;
|
|
9777
9774
|
if (idx4) {
|
|
9778
9775
|
while (idx4--) {
|
|
9779
|
-
report.addError('OBJECT_ADDITIONAL_PROPERTIES', [s[idx4]],
|
|
9776
|
+
report.addError('OBJECT_ADDITIONAL_PROPERTIES', [s[idx4]], undefined, schema);
|
|
9780
9777
|
}
|
|
9781
9778
|
}
|
|
9782
9779
|
}
|
|
@@ -9787,7 +9784,7 @@ const JsonValidators = {
|
|
|
9787
9784
|
if (shouldSkipValidate(this.validateOptions, ['OBJECT_DEPENDENCY_KEY'])) {
|
|
9788
9785
|
return;
|
|
9789
9786
|
}
|
|
9790
|
-
if (
|
|
9787
|
+
if (!isObject(json)) {
|
|
9791
9788
|
return;
|
|
9792
9789
|
}
|
|
9793
9790
|
const keys = Object.keys(schema.dependencies);
|
|
@@ -9797,21 +9794,21 @@ const JsonValidators = {
|
|
|
9797
9794
|
const dependencyName = keys[idx];
|
|
9798
9795
|
if (json[dependencyName]) {
|
|
9799
9796
|
const dependencyDefinition = schema.dependencies[dependencyName];
|
|
9800
|
-
if (
|
|
9801
|
-
// if dependency is a schema, validate against this schema
|
|
9802
|
-
validate.call(this, report, dependencyDefinition, json);
|
|
9803
|
-
}
|
|
9804
|
-
else {
|
|
9797
|
+
if (Array.isArray(dependencyDefinition)) {
|
|
9805
9798
|
// Array
|
|
9806
9799
|
// if dependency is an array, object needs to have all properties in this array
|
|
9807
9800
|
let idx2 = dependencyDefinition.length;
|
|
9808
9801
|
while (idx2--) {
|
|
9809
9802
|
const requiredPropertyName = dependencyDefinition[idx2];
|
|
9810
9803
|
if (json[requiredPropertyName] === undefined) {
|
|
9811
|
-
report.addError('OBJECT_DEPENDENCY_KEY', [requiredPropertyName, dependencyName],
|
|
9804
|
+
report.addError('OBJECT_DEPENDENCY_KEY', [requiredPropertyName, dependencyName], undefined, schema);
|
|
9812
9805
|
}
|
|
9813
9806
|
}
|
|
9814
9807
|
}
|
|
9808
|
+
else {
|
|
9809
|
+
// if dependency is a schema, validate against this schema
|
|
9810
|
+
validate.call(this, report, dependencyDefinition, json);
|
|
9811
|
+
}
|
|
9815
9812
|
}
|
|
9816
9813
|
}
|
|
9817
9814
|
},
|
|
@@ -9832,7 +9829,7 @@ const JsonValidators = {
|
|
|
9832
9829
|
}
|
|
9833
9830
|
if (match === false) {
|
|
9834
9831
|
const error = caseInsensitiveMatch && this.options.enumCaseInsensitiveComparison ? 'ENUM_CASE_MISMATCH' : 'ENUM_MISMATCH';
|
|
9835
|
-
report.addError(error, [json],
|
|
9832
|
+
report.addError(error, [JSON.stringify(json)], undefined, schema);
|
|
9836
9833
|
}
|
|
9837
9834
|
},
|
|
9838
9835
|
type: function (report, schema, json) {
|
|
@@ -9843,12 +9840,12 @@ const JsonValidators = {
|
|
|
9843
9840
|
const jsonType = whatIs(json);
|
|
9844
9841
|
if (typeof schema.type === 'string') {
|
|
9845
9842
|
if (jsonType !== schema.type && (jsonType !== 'integer' || schema.type !== 'number')) {
|
|
9846
|
-
report.addError('INVALID_TYPE', [schema.type, jsonType],
|
|
9843
|
+
report.addError('INVALID_TYPE', [schema.type, jsonType], undefined, schema);
|
|
9847
9844
|
}
|
|
9848
9845
|
}
|
|
9849
9846
|
else {
|
|
9850
9847
|
if (schema.type.indexOf(jsonType) === -1 && (jsonType !== 'integer' || schema.type.indexOf('number') === -1)) {
|
|
9851
|
-
report.addError('INVALID_TYPE', [schema.type, jsonType],
|
|
9848
|
+
report.addError('INVALID_TYPE', [JSON.stringify(schema.type), jsonType], undefined, schema);
|
|
9852
9849
|
}
|
|
9853
9850
|
}
|
|
9854
9851
|
},
|
|
@@ -9892,24 +9889,25 @@ const JsonValidators = {
|
|
|
9892
9889
|
report.addError('ONE_OF_MISSING', undefined, subReports, schema);
|
|
9893
9890
|
}
|
|
9894
9891
|
else if (passes > 1) {
|
|
9895
|
-
report.addError('ONE_OF_MULTIPLE',
|
|
9892
|
+
report.addError('ONE_OF_MULTIPLE', undefined, undefined, schema);
|
|
9896
9893
|
}
|
|
9897
9894
|
},
|
|
9898
9895
|
not: function (report, schema, json) {
|
|
9899
9896
|
// http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.5.6.2
|
|
9900
9897
|
const subReport = new Report(report);
|
|
9901
9898
|
if (validate.call(this, subReport, schema.not, json) === true) {
|
|
9902
|
-
report.addError('NOT_PASSED',
|
|
9899
|
+
report.addError('NOT_PASSED', undefined, undefined, schema);
|
|
9903
9900
|
}
|
|
9904
9901
|
},
|
|
9905
9902
|
definitions: function () {
|
|
9906
|
-
/*report, schema, json*/
|
|
9903
|
+
/*report: Report, schema: JsonSchemaInternal, json: unknown*/
|
|
9907
9904
|
// http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.5.7.2
|
|
9908
9905
|
// nothing to do here
|
|
9909
9906
|
},
|
|
9910
9907
|
format: function (report, schema, json) {
|
|
9911
9908
|
// http://json-schema.org/latest/json-schema-validation.html#rfc.section.7.2
|
|
9912
|
-
const
|
|
9909
|
+
const formatValidators = getFormatValidators(this.options);
|
|
9910
|
+
const formatValidatorFn = formatValidators[schema.format];
|
|
9913
9911
|
if (typeof formatValidatorFn === 'function') {
|
|
9914
9912
|
if (shouldSkipValidate(this.validateOptions, ['INVALID_FORMAT'])) {
|
|
9915
9913
|
return;
|
|
@@ -9919,12 +9917,12 @@ const JsonValidators = {
|
|
|
9919
9917
|
}
|
|
9920
9918
|
if (formatValidatorFn.length === 2) {
|
|
9921
9919
|
// async - need to clone the path here, because it will change by the time async function reports back
|
|
9922
|
-
const pathBeforeAsync =
|
|
9920
|
+
const pathBeforeAsync = shallowClone(report.path);
|
|
9923
9921
|
report.addAsyncTask(formatValidatorFn, [json], function (result) {
|
|
9924
9922
|
if (result !== true) {
|
|
9925
9923
|
const backup = report.path;
|
|
9926
9924
|
report.path = pathBeforeAsync;
|
|
9927
|
-
report.addError('INVALID_FORMAT', [schema.format, json],
|
|
9925
|
+
report.addError('INVALID_FORMAT', [schema.format, JSON.stringify(json)], undefined, schema);
|
|
9928
9926
|
report.path = backup;
|
|
9929
9927
|
}
|
|
9930
9928
|
});
|
|
@@ -9932,12 +9930,12 @@ const JsonValidators = {
|
|
|
9932
9930
|
else {
|
|
9933
9931
|
// sync
|
|
9934
9932
|
if (formatValidatorFn.call(this, json) !== true) {
|
|
9935
|
-
report.addError('INVALID_FORMAT', [schema.format, json],
|
|
9933
|
+
report.addError('INVALID_FORMAT', [schema.format, JSON.stringify(json)], undefined, schema);
|
|
9936
9934
|
}
|
|
9937
9935
|
}
|
|
9938
9936
|
}
|
|
9939
9937
|
else if (this.options.ignoreUnknownFormats !== true) {
|
|
9940
|
-
report.addError('UNKNOWN_FORMAT', [schema.format],
|
|
9938
|
+
report.addError('UNKNOWN_FORMAT', [schema.format], undefined, schema);
|
|
9941
9939
|
}
|
|
9942
9940
|
},
|
|
9943
9941
|
};
|
|
@@ -10023,18 +10021,12 @@ const recurseObject = function (report, schema, json) {
|
|
|
10023
10021
|
}
|
|
10024
10022
|
}
|
|
10025
10023
|
};
|
|
10026
|
-
/**
|
|
10027
|
-
*
|
|
10028
|
-
* @param {Report} report
|
|
10029
|
-
* @param {*} schema
|
|
10030
|
-
* @param {*} json
|
|
10031
|
-
*/
|
|
10032
10024
|
function validate(report, schema, json) {
|
|
10033
10025
|
report.commonErrorMessage = 'JSON_OBJECT_VALIDATION_FAILED';
|
|
10034
10026
|
// check if schema is an object
|
|
10035
10027
|
const to = whatIs(schema);
|
|
10036
10028
|
if (to !== 'object') {
|
|
10037
|
-
report.addError('SCHEMA_NOT_AN_OBJECT', [to],
|
|
10029
|
+
report.addError('SCHEMA_NOT_AN_OBJECT', [to], undefined, schema);
|
|
10038
10030
|
return false;
|
|
10039
10031
|
}
|
|
10040
10032
|
// check if schema is empty, everything is valid against empty schema
|
|
@@ -10054,7 +10046,7 @@ function validate(report, schema, json) {
|
|
|
10054
10046
|
let maxRefs = 99;
|
|
10055
10047
|
while (schema.$ref && maxRefs > 0) {
|
|
10056
10048
|
if (!schema.__$refResolved) {
|
|
10057
|
-
report.addError('REF_UNRESOLVED', [schema.$ref],
|
|
10049
|
+
report.addError('REF_UNRESOLVED', [schema.$ref], undefined, schema);
|
|
10058
10050
|
break;
|
|
10059
10051
|
}
|
|
10060
10052
|
else if (schema.__$refResolved === schema) {
|
|
@@ -10071,7 +10063,6 @@ function validate(report, schema, json) {
|
|
|
10071
10063
|
}
|
|
10072
10064
|
}
|
|
10073
10065
|
// type checking first
|
|
10074
|
-
const jsonType = whatIs(json);
|
|
10075
10066
|
if (schema.type) {
|
|
10076
10067
|
keys.splice(keys.indexOf('type'), 1);
|
|
10077
10068
|
JsonValidators.type.call(this, report, schema, json);
|
|
@@ -10090,10 +10081,10 @@ function validate(report, schema, json) {
|
|
|
10090
10081
|
}
|
|
10091
10082
|
}
|
|
10092
10083
|
if (report.errors.length === 0 || this.options.breakOnFirstError === false) {
|
|
10093
|
-
if (
|
|
10084
|
+
if (Array.isArray(json)) {
|
|
10094
10085
|
recurseArray.call(this, report, schema, json);
|
|
10095
10086
|
}
|
|
10096
|
-
else if (
|
|
10087
|
+
else if (isObject(json)) {
|
|
10097
10088
|
recurseObject.call(this, report, schema, json);
|
|
10098
10089
|
}
|
|
10099
10090
|
}
|
|
@@ -11972,40 +11963,156 @@ function requireLodash_isequal () {
|
|
|
11972
11963
|
var lodash_isequalExports = requireLodash_isequal();
|
|
11973
11964
|
var isequal = /*@__PURE__*/getDefaultExportFromCjs(lodash_isequalExports);
|
|
11974
11965
|
|
|
11975
|
-
|
|
11976
|
-
|
|
11977
|
-
|
|
11966
|
+
const findId = (schema, id) => {
|
|
11967
|
+
// process only arrays and objects
|
|
11968
|
+
if (typeof schema !== 'object' || schema === null) {
|
|
11969
|
+
return;
|
|
11978
11970
|
}
|
|
11979
|
-
|
|
11980
|
-
|
|
11981
|
-
|
|
11982
|
-
const isRefRelative = isRelativeUri(ref);
|
|
11983
|
-
let toRemove;
|
|
11984
|
-
if (isScopeAbsolute && isRefRelative) {
|
|
11985
|
-
toRemove = joinedScope.match(/\/[^/]*$/);
|
|
11986
|
-
if (toRemove) {
|
|
11987
|
-
joinedScope = joinedScope.slice(0, toRemove.index + 1);
|
|
11988
|
-
}
|
|
11971
|
+
// no id means root so return itself
|
|
11972
|
+
if (!id) {
|
|
11973
|
+
return schema;
|
|
11989
11974
|
}
|
|
11990
|
-
|
|
11991
|
-
|
|
11975
|
+
if (schema.id) {
|
|
11976
|
+
if (schema.id === id || (schema.id[0] === '#' && schema.id.substring(1) === id)) {
|
|
11977
|
+
return schema;
|
|
11978
|
+
}
|
|
11992
11979
|
}
|
|
11993
|
-
|
|
11994
|
-
|
|
11995
|
-
|
|
11996
|
-
|
|
11980
|
+
let idx, result;
|
|
11981
|
+
if (Array.isArray(schema)) {
|
|
11982
|
+
idx = schema.length;
|
|
11983
|
+
while (idx--) {
|
|
11984
|
+
result = findId(schema[idx], id);
|
|
11985
|
+
if (result) {
|
|
11986
|
+
return result;
|
|
11987
|
+
}
|
|
11997
11988
|
}
|
|
11998
11989
|
}
|
|
11999
|
-
|
|
12000
|
-
|
|
12001
|
-
|
|
12002
|
-
|
|
12003
|
-
|
|
12004
|
-
|
|
12005
|
-
|
|
12006
|
-
|
|
12007
|
-
|
|
12008
|
-
|
|
11990
|
+
if (isObject(schema)) {
|
|
11991
|
+
const keys = Object.keys(schema);
|
|
11992
|
+
idx = keys.length;
|
|
11993
|
+
while (idx--) {
|
|
11994
|
+
const k = keys[idx];
|
|
11995
|
+
if (k.indexOf('__$') === 0) {
|
|
11996
|
+
continue;
|
|
11997
|
+
}
|
|
11998
|
+
result = findId(schema[k], id);
|
|
11999
|
+
if (result) {
|
|
12000
|
+
return result;
|
|
12001
|
+
}
|
|
12002
|
+
}
|
|
12003
|
+
}
|
|
12004
|
+
};
|
|
12005
|
+
|
|
12006
|
+
class SchemaCache {
|
|
12007
|
+
validator;
|
|
12008
|
+
cache = {};
|
|
12009
|
+
referenceCache = [];
|
|
12010
|
+
constructor(validator) {
|
|
12011
|
+
this.validator = validator;
|
|
12012
|
+
}
|
|
12013
|
+
cacheSchemaByUri(uri, schema) {
|
|
12014
|
+
const remotePath = getRemotePath(uri);
|
|
12015
|
+
if (remotePath) {
|
|
12016
|
+
this.cache[remotePath] = schema;
|
|
12017
|
+
}
|
|
12018
|
+
}
|
|
12019
|
+
removeFromCacheByUri(uri) {
|
|
12020
|
+
const remotePath = getRemotePath(uri);
|
|
12021
|
+
if (remotePath) {
|
|
12022
|
+
delete this.cache[remotePath];
|
|
12023
|
+
}
|
|
12024
|
+
}
|
|
12025
|
+
checkCacheForUri(uri) {
|
|
12026
|
+
const remotePath = getRemotePath(uri);
|
|
12027
|
+
return remotePath ? this.cache[remotePath] != null : false;
|
|
12028
|
+
}
|
|
12029
|
+
getSchema(report, refOrSchema) {
|
|
12030
|
+
if (typeof refOrSchema === 'string') {
|
|
12031
|
+
// ref input
|
|
12032
|
+
return this.getSchemaByUri(report, refOrSchema);
|
|
12033
|
+
}
|
|
12034
|
+
if (typeof refOrSchema === 'object') {
|
|
12035
|
+
// schema obj input
|
|
12036
|
+
return this.getSchemaByReference(report, refOrSchema);
|
|
12037
|
+
}
|
|
12038
|
+
throw new Error(`unexpected code reached`);
|
|
12039
|
+
}
|
|
12040
|
+
getSchemaByUri(report, uri, root) {
|
|
12041
|
+
const remotePath = getRemotePath(uri);
|
|
12042
|
+
const queryPath = getQueryPath(uri);
|
|
12043
|
+
let result = remotePath ? this.cache[remotePath] : root;
|
|
12044
|
+
if (result && remotePath) {
|
|
12045
|
+
// we need to avoid compiling schemas in a recursive loop
|
|
12046
|
+
const compileRemote = result !== root;
|
|
12047
|
+
// now we need to compile and validate resolved schema (in case it's not already)
|
|
12048
|
+
if (compileRemote) {
|
|
12049
|
+
report.path.push(remotePath);
|
|
12050
|
+
let remoteReport;
|
|
12051
|
+
const anscestorReport = result.id ? report.getAncestor(result.id) : undefined;
|
|
12052
|
+
if (anscestorReport) {
|
|
12053
|
+
remoteReport = anscestorReport;
|
|
12054
|
+
}
|
|
12055
|
+
else {
|
|
12056
|
+
remoteReport = new Report(report);
|
|
12057
|
+
if (this.validator.sc.compileSchema(remoteReport, result)) {
|
|
12058
|
+
const savedOptions = this.validator.options;
|
|
12059
|
+
try {
|
|
12060
|
+
// If custom validationOptions were provided to setRemoteReference(),
|
|
12061
|
+
// use them instead of the default options
|
|
12062
|
+
this.validator.options = result.__$validationOptions || this.validator.options;
|
|
12063
|
+
this.validator.sv.validateSchema(remoteReport, result);
|
|
12064
|
+
}
|
|
12065
|
+
finally {
|
|
12066
|
+
this.validator.options = savedOptions;
|
|
12067
|
+
}
|
|
12068
|
+
}
|
|
12069
|
+
}
|
|
12070
|
+
const remoteReportIsValid = remoteReport.isValid();
|
|
12071
|
+
if (!remoteReportIsValid) {
|
|
12072
|
+
report.addError('REMOTE_NOT_VALID', [uri], remoteReport);
|
|
12073
|
+
}
|
|
12074
|
+
report.path.pop();
|
|
12075
|
+
if (!remoteReportIsValid) {
|
|
12076
|
+
return undefined;
|
|
12077
|
+
}
|
|
12078
|
+
}
|
|
12079
|
+
}
|
|
12080
|
+
if (result && queryPath) {
|
|
12081
|
+
const parts = queryPath.split('/');
|
|
12082
|
+
for (let idx = 0, lim = parts.length; result && idx < lim; idx++) {
|
|
12083
|
+
const key = decodeJSONPointer(parts[idx]);
|
|
12084
|
+
if (idx === 0) {
|
|
12085
|
+
// it's an id
|
|
12086
|
+
result = findId(result, key);
|
|
12087
|
+
}
|
|
12088
|
+
else {
|
|
12089
|
+
// it's a path behind id
|
|
12090
|
+
result = result[key];
|
|
12091
|
+
}
|
|
12092
|
+
}
|
|
12093
|
+
}
|
|
12094
|
+
return result;
|
|
12095
|
+
}
|
|
12096
|
+
getSchemaByReference(report, schema) {
|
|
12097
|
+
let i = this.referenceCache.length;
|
|
12098
|
+
while (i--) {
|
|
12099
|
+
if (isequal(this.referenceCache[i][0], schema)) {
|
|
12100
|
+
return this.referenceCache[i][1];
|
|
12101
|
+
}
|
|
12102
|
+
}
|
|
12103
|
+
// not found
|
|
12104
|
+
const schemaClone = deepClone(schema);
|
|
12105
|
+
this.referenceCache.push([schema, schemaClone]);
|
|
12106
|
+
return schemaClone;
|
|
12107
|
+
}
|
|
12108
|
+
}
|
|
12109
|
+
|
|
12110
|
+
const collectReferences = (obj, results, scope, path) => {
|
|
12111
|
+
results = results || [];
|
|
12112
|
+
scope = scope || [];
|
|
12113
|
+
path = path || [];
|
|
12114
|
+
if (typeof obj !== 'object' || obj === null) {
|
|
12115
|
+
return results;
|
|
12009
12116
|
}
|
|
12010
12117
|
if (typeof obj.id === 'string') {
|
|
12011
12118
|
scope.push(obj.id);
|
|
@@ -12030,7 +12137,7 @@ function collectReferences(obj, results, scope, path) {
|
|
|
12030
12137
|
if (Array.isArray(obj)) {
|
|
12031
12138
|
idx = obj.length;
|
|
12032
12139
|
while (idx--) {
|
|
12033
|
-
path.push(idx
|
|
12140
|
+
path.push(idx);
|
|
12034
12141
|
collectReferences(obj[idx], results, scope, path);
|
|
12035
12142
|
path.pop();
|
|
12036
12143
|
}
|
|
@@ -12052,175 +12159,200 @@ function collectReferences(obj, results, scope, path) {
|
|
|
12052
12159
|
scope.pop();
|
|
12053
12160
|
}
|
|
12054
12161
|
return results;
|
|
12055
|
-
}
|
|
12056
|
-
const
|
|
12057
|
-
|
|
12058
|
-
|
|
12059
|
-
|
|
12060
|
-
|
|
12061
|
-
|
|
12062
|
-
|
|
12063
|
-
|
|
12162
|
+
};
|
|
12163
|
+
const mergeReference = (scope, ref) => {
|
|
12164
|
+
if (isAbsoluteUri(ref)) {
|
|
12165
|
+
return ref;
|
|
12166
|
+
}
|
|
12167
|
+
let joinedScope = scope.join('');
|
|
12168
|
+
const isScopeAbsolute = isAbsoluteUri(joinedScope);
|
|
12169
|
+
const isScopeRelative = isRelativeUri(joinedScope);
|
|
12170
|
+
const isRefRelative = isRelativeUri(ref);
|
|
12171
|
+
let toRemove;
|
|
12172
|
+
if (isScopeAbsolute && isRefRelative) {
|
|
12173
|
+
toRemove = joinedScope.match(/\/[^/]*$/);
|
|
12174
|
+
if (toRemove) {
|
|
12175
|
+
joinedScope = joinedScope.slice(0, toRemove.index + 1);
|
|
12064
12176
|
}
|
|
12065
|
-
// copy errors to report
|
|
12066
|
-
mainReport.errors = mainReport.errors.concat(report.errors);
|
|
12067
12177
|
}
|
|
12068
|
-
|
|
12069
|
-
|
|
12070
|
-
|
|
12071
|
-
|
|
12072
|
-
|
|
12073
|
-
if (
|
|
12074
|
-
|
|
12178
|
+
else if (isScopeRelative && isRefRelative) {
|
|
12179
|
+
joinedScope = '';
|
|
12180
|
+
}
|
|
12181
|
+
else {
|
|
12182
|
+
toRemove = joinedScope.match(/[^#/]+$/);
|
|
12183
|
+
if (toRemove) {
|
|
12184
|
+
joinedScope = joinedScope.slice(0, toRemove.index);
|
|
12075
12185
|
}
|
|
12076
12186
|
}
|
|
12077
|
-
|
|
12078
|
-
|
|
12079
|
-
|
|
12080
|
-
|
|
12081
|
-
|
|
12082
|
-
|
|
12083
|
-
|
|
12084
|
-
|
|
12085
|
-
|
|
12086
|
-
|
|
12187
|
+
let res = joinedScope + ref;
|
|
12188
|
+
res = res.replace(/##/, '#');
|
|
12189
|
+
return res;
|
|
12190
|
+
};
|
|
12191
|
+
class SchemaCompiler {
|
|
12192
|
+
validator;
|
|
12193
|
+
constructor(validator) {
|
|
12194
|
+
this.validator = validator;
|
|
12195
|
+
}
|
|
12196
|
+
compileSchema(report, schema) {
|
|
12197
|
+
report.commonErrorMessage = 'SCHEMA_COMPILATION_FAILED';
|
|
12198
|
+
// if schema is a string, assume it's a uri
|
|
12199
|
+
if (typeof schema === 'string') {
|
|
12200
|
+
const loadedSchema = this.validator.scache.getSchemaByUri(report, schema);
|
|
12201
|
+
if (!loadedSchema) {
|
|
12202
|
+
report.addError('SCHEMA_NOT_REACHABLE', [schema]);
|
|
12203
|
+
return false;
|
|
12087
12204
|
}
|
|
12205
|
+
schema = loadedSchema;
|
|
12206
|
+
}
|
|
12207
|
+
// if schema is an array, assume it's an array of schemas
|
|
12208
|
+
if (Array.isArray(schema)) {
|
|
12209
|
+
return this.compileArrayOfSchemas(report, schema);
|
|
12210
|
+
}
|
|
12211
|
+
// if we have an id than it should be cached already (if this instance has compiled it)
|
|
12212
|
+
if (schema.__$compiled && schema.id && this.validator.scache.checkCacheForUri(schema.id) === false) {
|
|
12213
|
+
schema.__$compiled = undefined;
|
|
12214
|
+
}
|
|
12215
|
+
// do not re-compile schemas
|
|
12216
|
+
if (schema.__$compiled) {
|
|
12217
|
+
return true;
|
|
12088
12218
|
}
|
|
12089
|
-
|
|
12090
|
-
|
|
12091
|
-
|
|
12092
|
-
|
|
12093
|
-
//
|
|
12094
|
-
|
|
12219
|
+
if (schema.id && typeof schema.id === 'string') {
|
|
12220
|
+
// add this to our schemaCache (before compilation in case we have references including id)
|
|
12221
|
+
this.validator.scache.cacheSchemaByUri(schema.id, schema);
|
|
12222
|
+
}
|
|
12223
|
+
// this method can be called recursively, so we need to remember our root
|
|
12224
|
+
let isRoot = false;
|
|
12225
|
+
if (!report.rootSchema) {
|
|
12226
|
+
report.rootSchema = schema;
|
|
12227
|
+
isRoot = true;
|
|
12228
|
+
}
|
|
12229
|
+
// delete all __$missingReferences from previous compilation attempts
|
|
12230
|
+
const isValidExceptReferences = report.isValid();
|
|
12231
|
+
delete schema.__$missingReferences;
|
|
12232
|
+
// collect all references that need to be resolved - $ref and $schema
|
|
12233
|
+
const refs = collectReferences(schema);
|
|
12234
|
+
let idx = refs.length;
|
|
12095
12235
|
while (idx--) {
|
|
12096
|
-
|
|
12097
|
-
|
|
12098
|
-
|
|
12099
|
-
|
|
12100
|
-
|
|
12101
|
-
|
|
12102
|
-
|
|
12103
|
-
|
|
12104
|
-
|
|
12105
|
-
|
|
12106
|
-
|
|
12236
|
+
// resolve all the collected references into __xxxResolved pointer
|
|
12237
|
+
const refObj = refs[idx];
|
|
12238
|
+
let response = this.validator.scache.getSchemaByUri(report, refObj.ref, schema);
|
|
12239
|
+
// we can try to use custom schemaReader if available
|
|
12240
|
+
if (!response) {
|
|
12241
|
+
const schemaReader = this.validator.getSchemaReader();
|
|
12242
|
+
if (schemaReader) {
|
|
12243
|
+
// it's supposed to return a valid schema
|
|
12244
|
+
const s = schemaReader(refObj.ref);
|
|
12245
|
+
if (s) {
|
|
12246
|
+
// it needs to have the id
|
|
12247
|
+
s.id = refObj.ref;
|
|
12248
|
+
// try to compile the schema
|
|
12249
|
+
const subreport = new Report(report);
|
|
12250
|
+
if (!this.compileSchema(subreport, s)) {
|
|
12251
|
+
// copy errors to report
|
|
12252
|
+
report.errors = report.errors.concat(subreport.errors);
|
|
12253
|
+
}
|
|
12254
|
+
else {
|
|
12255
|
+
response = this.validator.scache.getSchemaByUri(report, refObj.ref, schema);
|
|
12256
|
+
}
|
|
12107
12257
|
}
|
|
12108
12258
|
}
|
|
12109
|
-
|
|
12110
|
-
|
|
12259
|
+
}
|
|
12260
|
+
if (!response) {
|
|
12261
|
+
const hasNotValid = report.hasError('REMOTE_NOT_VALID', [refObj.ref]);
|
|
12262
|
+
const isAbsolute = isAbsoluteUri(refObj.ref);
|
|
12263
|
+
let isDownloaded = false;
|
|
12264
|
+
const ignoreUnresolvableRemotes = this.validator.options.ignoreUnresolvableReferences === true;
|
|
12265
|
+
if (isAbsolute) {
|
|
12266
|
+
// we shouldn't add UNRESOLVABLE_REFERENCE for schemas we already have downloaded
|
|
12267
|
+
// and set through setRemoteReference method
|
|
12268
|
+
isDownloaded = this.validator.scache.checkCacheForUri(refObj.ref);
|
|
12269
|
+
}
|
|
12270
|
+
if (hasNotValid) ;
|
|
12271
|
+
else if (ignoreUnresolvableRemotes && isAbsolute) ;
|
|
12272
|
+
else if (isDownloaded) ;
|
|
12273
|
+
else {
|
|
12274
|
+
report.path.push(...refObj.path);
|
|
12275
|
+
report.addError('UNRESOLVABLE_REFERENCE', [refObj.ref]);
|
|
12276
|
+
report.path = report.path.slice(0, -refObj.path.length);
|
|
12277
|
+
// pusblish unresolved references out
|
|
12278
|
+
if (isValidExceptReferences) {
|
|
12279
|
+
schema.__$missingReferences = schema.__$missingReferences || [];
|
|
12280
|
+
schema.__$missingReferences.push(refObj);
|
|
12281
|
+
}
|
|
12111
12282
|
}
|
|
12112
12283
|
}
|
|
12284
|
+
// this might create circular references
|
|
12285
|
+
refObj.obj[`__${refObj.key}Resolved`] = response;
|
|
12113
12286
|
}
|
|
12114
|
-
|
|
12115
|
-
|
|
12116
|
-
|
|
12117
|
-
};
|
|
12118
|
-
function compileSchema(report, schema) {
|
|
12119
|
-
report.commonErrorMessage = 'SCHEMA_COMPILATION_FAILED';
|
|
12120
|
-
// if schema is a string, assume it's a uri
|
|
12121
|
-
if (typeof schema === 'string') {
|
|
12122
|
-
const loadedSchema = getSchemaByUri.call(this, report, schema);
|
|
12123
|
-
if (!loadedSchema) {
|
|
12124
|
-
report.addError('SCHEMA_NOT_REACHABLE', [schema]);
|
|
12125
|
-
return false;
|
|
12287
|
+
const isValid = report.isValid();
|
|
12288
|
+
if (isValid) {
|
|
12289
|
+
schema.__$compiled = true;
|
|
12126
12290
|
}
|
|
12127
|
-
|
|
12128
|
-
|
|
12129
|
-
|
|
12130
|
-
|
|
12131
|
-
return compileArrayOfSchemas.call(this, report, schema);
|
|
12132
|
-
}
|
|
12133
|
-
// if we have an id than it should be cached already (if this instance has compiled it)
|
|
12134
|
-
if (schema.__$compiled && schema.id && checkCacheForUri.call(this, schema.id) === false) {
|
|
12135
|
-
schema.__$compiled = undefined;
|
|
12136
|
-
}
|
|
12137
|
-
// do not re-compile schemas
|
|
12138
|
-
if (schema.__$compiled) {
|
|
12139
|
-
return true;
|
|
12140
|
-
}
|
|
12141
|
-
if (schema.id && typeof schema.id === 'string') {
|
|
12142
|
-
// add this to our schemaCache (before compilation in case we have references including id)
|
|
12143
|
-
cacheSchemaByUri.call(this, schema.id, schema);
|
|
12144
|
-
}
|
|
12145
|
-
// this method can be called recursively, so we need to remember our root
|
|
12146
|
-
let isRoot = false;
|
|
12147
|
-
if (!report.rootSchema) {
|
|
12148
|
-
report.rootSchema = schema;
|
|
12149
|
-
isRoot = true;
|
|
12150
|
-
}
|
|
12151
|
-
// delete all __$missingReferences from previous compilation attempts
|
|
12152
|
-
const isValidExceptReferences = report.isValid();
|
|
12153
|
-
delete schema.__$missingReferences;
|
|
12154
|
-
// collect all references that need to be resolved - $ref and $schema
|
|
12155
|
-
const refs = collectReferences.call(this, schema);
|
|
12156
|
-
let idx = refs.length;
|
|
12157
|
-
while (idx--) {
|
|
12158
|
-
// resolve all the collected references into __xxxResolved pointer
|
|
12159
|
-
const refObj = refs[idx];
|
|
12160
|
-
let response = getSchemaByUri.call(this, report, refObj.ref, schema);
|
|
12161
|
-
// we can try to use custom schemaReader if available
|
|
12162
|
-
if (!response) {
|
|
12163
|
-
const schemaReader = this.getSchemaReader();
|
|
12164
|
-
if (schemaReader) {
|
|
12165
|
-
// it's supposed to return a valid schema
|
|
12166
|
-
const s = schemaReader(refObj.ref);
|
|
12167
|
-
if (s) {
|
|
12168
|
-
// it needs to have the id
|
|
12169
|
-
s.id = refObj.ref;
|
|
12170
|
-
// try to compile the schema
|
|
12171
|
-
const subreport = new Report(report);
|
|
12172
|
-
if (!compileSchema.call(this, subreport, s)) {
|
|
12173
|
-
// copy errors to report
|
|
12174
|
-
report.errors = report.errors.concat(subreport.errors);
|
|
12175
|
-
}
|
|
12176
|
-
else {
|
|
12177
|
-
response = getSchemaByUri.call(this, report, refObj.ref, schema);
|
|
12178
|
-
}
|
|
12179
|
-
}
|
|
12291
|
+
else {
|
|
12292
|
+
if (schema.id && typeof schema.id === 'string') {
|
|
12293
|
+
// remove this schema from schemaCache because it failed to compile
|
|
12294
|
+
this.validator.scache.removeFromCacheByUri(schema.id);
|
|
12180
12295
|
}
|
|
12181
12296
|
}
|
|
12182
|
-
|
|
12183
|
-
|
|
12184
|
-
|
|
12185
|
-
|
|
12186
|
-
|
|
12187
|
-
|
|
12188
|
-
|
|
12189
|
-
|
|
12190
|
-
|
|
12297
|
+
// we don't need the root pointer anymore
|
|
12298
|
+
if (isRoot) {
|
|
12299
|
+
report.rootSchema = undefined;
|
|
12300
|
+
}
|
|
12301
|
+
return isValid;
|
|
12302
|
+
}
|
|
12303
|
+
compileArrayOfSchemas(report, arr) {
|
|
12304
|
+
let compiled = 0, lastLoopCompiled;
|
|
12305
|
+
do {
|
|
12306
|
+
// remove all UNRESOLVABLE_REFERENCE errors before compiling array again
|
|
12307
|
+
let idx = report.errors.length;
|
|
12308
|
+
while (idx--) {
|
|
12309
|
+
if (report.errors[idx].code === 'UNRESOLVABLE_REFERENCE') {
|
|
12310
|
+
report.errors.splice(idx, 1);
|
|
12311
|
+
}
|
|
12191
12312
|
}
|
|
12192
|
-
|
|
12193
|
-
|
|
12194
|
-
|
|
12195
|
-
|
|
12196
|
-
|
|
12197
|
-
|
|
12198
|
-
|
|
12199
|
-
|
|
12200
|
-
if (
|
|
12201
|
-
|
|
12202
|
-
|
|
12313
|
+
// remember how many were compiled in the last loop
|
|
12314
|
+
lastLoopCompiled = compiled;
|
|
12315
|
+
// count how many are compiled now
|
|
12316
|
+
compiled = this.compileArrayOfSchemasLoop(report, arr);
|
|
12317
|
+
// fix __$missingReferences if possible
|
|
12318
|
+
idx = arr.length;
|
|
12319
|
+
while (idx--) {
|
|
12320
|
+
const sch = arr[idx];
|
|
12321
|
+
if (sch.__$missingReferences) {
|
|
12322
|
+
let idx2 = sch.__$missingReferences.length;
|
|
12323
|
+
while (idx2--) {
|
|
12324
|
+
const refObj = sch.__$missingReferences[idx2];
|
|
12325
|
+
const response = arr.find((x) => x.id === refObj.ref);
|
|
12326
|
+
if (response) {
|
|
12327
|
+
// this might create circular references
|
|
12328
|
+
refObj.obj[`__${refObj.key}Resolved`] = response;
|
|
12329
|
+
// it's resolved now so delete it
|
|
12330
|
+
sch.__$missingReferences.splice(idx2, 1);
|
|
12331
|
+
}
|
|
12332
|
+
}
|
|
12333
|
+
if (sch.__$missingReferences.length === 0) {
|
|
12334
|
+
delete sch.__$missingReferences;
|
|
12335
|
+
}
|
|
12203
12336
|
}
|
|
12204
12337
|
}
|
|
12205
|
-
|
|
12206
|
-
|
|
12207
|
-
|
|
12208
|
-
}
|
|
12209
|
-
const isValid = report.isValid();
|
|
12210
|
-
if (isValid) {
|
|
12211
|
-
schema.__$compiled = true;
|
|
12338
|
+
// keep repeating if not all compiled and at least one more was compiled in the last loop
|
|
12339
|
+
} while (compiled !== arr.length && compiled !== lastLoopCompiled);
|
|
12340
|
+
return report.isValid();
|
|
12212
12341
|
}
|
|
12213
|
-
|
|
12214
|
-
|
|
12215
|
-
|
|
12216
|
-
|
|
12342
|
+
compileArrayOfSchemasLoop(mainReport, arr) {
|
|
12343
|
+
let idx = arr.length, compiledCount = 0;
|
|
12344
|
+
while (idx--) {
|
|
12345
|
+
// try to compile each schema separately
|
|
12346
|
+
const report = new Report(mainReport);
|
|
12347
|
+
const isValid = this.compileSchema(report, arr[idx]);
|
|
12348
|
+
if (isValid) {
|
|
12349
|
+
compiledCount++;
|
|
12350
|
+
}
|
|
12351
|
+
// copy errors to report
|
|
12352
|
+
mainReport.errors = mainReport.errors.concat(report.errors);
|
|
12217
12353
|
}
|
|
12354
|
+
return compiledCount;
|
|
12218
12355
|
}
|
|
12219
|
-
// we don't need the root pointer anymore
|
|
12220
|
-
if (isRoot) {
|
|
12221
|
-
report.rootSchema = undefined;
|
|
12222
|
-
}
|
|
12223
|
-
return isValid;
|
|
12224
12356
|
}
|
|
12225
12357
|
|
|
12226
12358
|
const SchemaValidators = {
|
|
@@ -12314,9 +12446,9 @@ const SchemaValidators = {
|
|
|
12314
12446
|
if (type !== 'boolean' && type !== 'object') {
|
|
12315
12447
|
report.addError('KEYWORD_TYPE_EXPECTED', ['additionalItems', ['boolean', 'object']]);
|
|
12316
12448
|
}
|
|
12317
|
-
else if (
|
|
12449
|
+
else if (isObject(schema.additionalItems)) {
|
|
12318
12450
|
report.path.push('additionalItems');
|
|
12319
|
-
validateSchema
|
|
12451
|
+
this.validateSchema(report, schema.additionalItems);
|
|
12320
12452
|
report.path.pop();
|
|
12321
12453
|
}
|
|
12322
12454
|
},
|
|
@@ -12325,15 +12457,15 @@ const SchemaValidators = {
|
|
|
12325
12457
|
const type = whatIs(schema.items);
|
|
12326
12458
|
if (type === 'object') {
|
|
12327
12459
|
report.path.push('items');
|
|
12328
|
-
validateSchema
|
|
12460
|
+
this.validateSchema(report, schema.items);
|
|
12329
12461
|
report.path.pop();
|
|
12330
12462
|
}
|
|
12331
|
-
else if (
|
|
12463
|
+
else if (Array.isArray(schema.items)) {
|
|
12332
12464
|
let idx = schema.items.length;
|
|
12333
12465
|
while (idx--) {
|
|
12334
12466
|
report.path.push('items');
|
|
12335
|
-
report.path.push(idx
|
|
12336
|
-
validateSchema
|
|
12467
|
+
report.path.push(idx);
|
|
12468
|
+
this.validateSchema(report, schema.items[idx]);
|
|
12337
12469
|
report.path.pop();
|
|
12338
12470
|
report.path.pop();
|
|
12339
12471
|
}
|
|
@@ -12418,9 +12550,9 @@ const SchemaValidators = {
|
|
|
12418
12550
|
if (type !== 'boolean' && type !== 'object') {
|
|
12419
12551
|
report.addError('KEYWORD_TYPE_EXPECTED', ['additionalProperties', ['boolean', 'object']]);
|
|
12420
12552
|
}
|
|
12421
|
-
else if (
|
|
12553
|
+
else if (isObject(schema.additionalProperties)) {
|
|
12422
12554
|
report.path.push('additionalProperties');
|
|
12423
|
-
validateSchema
|
|
12555
|
+
this.validateSchema(report, schema.additionalProperties);
|
|
12424
12556
|
report.path.pop();
|
|
12425
12557
|
}
|
|
12426
12558
|
},
|
|
@@ -12433,10 +12565,11 @@ const SchemaValidators = {
|
|
|
12433
12565
|
const keys = Object.keys(schema.properties);
|
|
12434
12566
|
let idx = keys.length;
|
|
12435
12567
|
while (idx--) {
|
|
12436
|
-
const key = keys[idx]
|
|
12568
|
+
const key = keys[idx];
|
|
12569
|
+
const val = schema.properties[key];
|
|
12437
12570
|
report.path.push('properties');
|
|
12438
12571
|
report.path.push(key);
|
|
12439
|
-
validateSchema
|
|
12572
|
+
this.validateSchema(report, val);
|
|
12440
12573
|
report.path.pop();
|
|
12441
12574
|
report.path.pop();
|
|
12442
12575
|
}
|
|
@@ -12470,8 +12603,8 @@ const SchemaValidators = {
|
|
|
12470
12603
|
report.addError('KEYWORD_PATTERN', ['patternProperties', key]);
|
|
12471
12604
|
}
|
|
12472
12605
|
report.path.push('patternProperties');
|
|
12473
|
-
report.path.push(key
|
|
12474
|
-
validateSchema
|
|
12606
|
+
report.path.push(key);
|
|
12607
|
+
this.validateSchema(report, val);
|
|
12475
12608
|
report.path.pop();
|
|
12476
12609
|
report.path.pop();
|
|
12477
12610
|
}
|
|
@@ -12489,11 +12622,13 @@ const SchemaValidators = {
|
|
|
12489
12622
|
const keys = Object.keys(schema.dependencies);
|
|
12490
12623
|
let idx = keys.length;
|
|
12491
12624
|
while (idx--) {
|
|
12492
|
-
const schemaKey = keys[idx]
|
|
12625
|
+
const schemaKey = keys[idx];
|
|
12626
|
+
const schemaDependency = schema.dependencies[schemaKey];
|
|
12627
|
+
const type = whatIs(schemaDependency);
|
|
12493
12628
|
if (type === 'object') {
|
|
12494
12629
|
report.path.push('dependencies');
|
|
12495
12630
|
report.path.push(schemaKey);
|
|
12496
|
-
validateSchema
|
|
12631
|
+
this.validateSchema(report, schemaDependency);
|
|
12497
12632
|
report.path.pop();
|
|
12498
12633
|
report.path.pop();
|
|
12499
12634
|
}
|
|
@@ -12531,8 +12666,10 @@ const SchemaValidators = {
|
|
|
12531
12666
|
},
|
|
12532
12667
|
type: function (report, schema) {
|
|
12533
12668
|
// http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.5.2.1
|
|
12534
|
-
const primitiveTypes = ['array', 'boolean', 'integer', 'number', 'null', 'object', 'string']
|
|
12535
|
-
|
|
12669
|
+
const primitiveTypes = ['array', 'boolean', 'integer', 'number', 'null', 'object', 'string'];
|
|
12670
|
+
const primitiveTypeStr = primitiveTypes.join(',');
|
|
12671
|
+
const isArray = Array.isArray(schema.type);
|
|
12672
|
+
if (Array.isArray(schema.type)) {
|
|
12536
12673
|
let idx = schema.type.length;
|
|
12537
12674
|
while (idx--) {
|
|
12538
12675
|
if (primitiveTypes.indexOf(schema.type[idx]) === -1) {
|
|
@@ -12626,8 +12763,8 @@ const SchemaValidators = {
|
|
|
12626
12763
|
let idx = schema.allOf.length;
|
|
12627
12764
|
while (idx--) {
|
|
12628
12765
|
report.path.push('allOf');
|
|
12629
|
-
report.path.push(idx
|
|
12630
|
-
validateSchema
|
|
12766
|
+
report.path.push(idx);
|
|
12767
|
+
this.validateSchema(report, schema.allOf[idx]);
|
|
12631
12768
|
report.path.pop();
|
|
12632
12769
|
report.path.pop();
|
|
12633
12770
|
}
|
|
@@ -12645,8 +12782,8 @@ const SchemaValidators = {
|
|
|
12645
12782
|
let idx = schema.anyOf.length;
|
|
12646
12783
|
while (idx--) {
|
|
12647
12784
|
report.path.push('anyOf');
|
|
12648
|
-
report.path.push(idx
|
|
12649
|
-
validateSchema
|
|
12785
|
+
report.path.push(idx);
|
|
12786
|
+
this.validateSchema(report, schema.anyOf[idx]);
|
|
12650
12787
|
report.path.pop();
|
|
12651
12788
|
report.path.pop();
|
|
12652
12789
|
}
|
|
@@ -12664,8 +12801,8 @@ const SchemaValidators = {
|
|
|
12664
12801
|
let idx = schema.oneOf.length;
|
|
12665
12802
|
while (idx--) {
|
|
12666
12803
|
report.path.push('oneOf');
|
|
12667
|
-
report.path.push(idx
|
|
12668
|
-
validateSchema
|
|
12804
|
+
report.path.push(idx);
|
|
12805
|
+
this.validateSchema(report, schema.oneOf[idx]);
|
|
12669
12806
|
report.path.pop();
|
|
12670
12807
|
report.path.pop();
|
|
12671
12808
|
}
|
|
@@ -12678,7 +12815,7 @@ const SchemaValidators = {
|
|
|
12678
12815
|
}
|
|
12679
12816
|
else {
|
|
12680
12817
|
report.path.push('not');
|
|
12681
|
-
validateSchema
|
|
12818
|
+
this.validateSchema(report, schema.not);
|
|
12682
12819
|
report.path.pop();
|
|
12683
12820
|
}
|
|
12684
12821
|
},
|
|
@@ -12694,7 +12831,7 @@ const SchemaValidators = {
|
|
|
12694
12831
|
const key = keys[idx], val = schema.definitions[key];
|
|
12695
12832
|
report.path.push('definitions');
|
|
12696
12833
|
report.path.push(key);
|
|
12697
|
-
validateSchema
|
|
12834
|
+
this.validateSchema(report, val);
|
|
12698
12835
|
report.path.pop();
|
|
12699
12836
|
report.path.pop();
|
|
12700
12837
|
}
|
|
@@ -12705,7 +12842,7 @@ const SchemaValidators = {
|
|
|
12705
12842
|
report.addError('KEYWORD_TYPE_EXPECTED', ['format', 'string']);
|
|
12706
12843
|
}
|
|
12707
12844
|
else {
|
|
12708
|
-
if (
|
|
12845
|
+
if (!isFormatSupported(schema.format) && this.options.ignoreUnknownFormats !== true) {
|
|
12709
12846
|
report.addError('UNKNOWN_FORMAT', [schema.format]);
|
|
12710
12847
|
}
|
|
12711
12848
|
}
|
|
@@ -12728,296 +12865,124 @@ const SchemaValidators = {
|
|
|
12728
12865
|
report.addError('KEYWORD_TYPE_EXPECTED', ['description', 'string']);
|
|
12729
12866
|
}
|
|
12730
12867
|
},
|
|
12731
|
-
default: function (
|
|
12868
|
+
default: function () {
|
|
12732
12869
|
// http://json-schema.org/latest/json-schema-validation.html#rfc.section.6.2
|
|
12733
12870
|
// There are no restrictions placed on the value of this keyword.
|
|
12734
12871
|
},
|
|
12735
12872
|
};
|
|
12736
|
-
|
|
12737
|
-
|
|
12738
|
-
|
|
12739
|
-
|
|
12740
|
-
*
|
|
12741
|
-
* @returns {boolean}
|
|
12742
|
-
*/
|
|
12743
|
-
const validateArrayOfSchemas = function (report, arr) {
|
|
12744
|
-
let idx = arr.length;
|
|
12745
|
-
while (idx--) {
|
|
12746
|
-
validateSchema.call(this, report, arr[idx]);
|
|
12747
|
-
}
|
|
12748
|
-
return report.isValid();
|
|
12749
|
-
};
|
|
12750
|
-
/**
|
|
12751
|
-
*
|
|
12752
|
-
* @param {Report} report
|
|
12753
|
-
* @param {*} schema
|
|
12754
|
-
*/
|
|
12755
|
-
function validateSchema(report, schema) {
|
|
12756
|
-
report.commonErrorMessage = 'SCHEMA_VALIDATION_FAILED';
|
|
12757
|
-
// if schema is an array, assume it's an array of schemas
|
|
12758
|
-
if (Array.isArray(schema)) {
|
|
12759
|
-
return validateArrayOfSchemas.call(this, report, schema);
|
|
12873
|
+
class SchemaValidator {
|
|
12874
|
+
validator;
|
|
12875
|
+
constructor(validator) {
|
|
12876
|
+
this.validator = validator;
|
|
12760
12877
|
}
|
|
12761
|
-
|
|
12762
|
-
|
|
12763
|
-
return true;
|
|
12878
|
+
get options() {
|
|
12879
|
+
return this.validator.options;
|
|
12764
12880
|
}
|
|
12765
|
-
|
|
12766
|
-
|
|
12767
|
-
|
|
12768
|
-
|
|
12769
|
-
const subReport = new Report(report);
|
|
12770
|
-
const valid = validate.call(this, subReport, schema.__$schemaResolved, schema);
|
|
12771
|
-
if (valid === false) {
|
|
12772
|
-
report.addError('PARENT_SCHEMA_VALIDATION_FAILED', null, subReport);
|
|
12773
|
-
}
|
|
12774
|
-
}
|
|
12775
|
-
else {
|
|
12776
|
-
if (this.options.ignoreUnresolvableReferences !== true) {
|
|
12777
|
-
report.addError('REF_UNRESOLVED', [schema.$schema]);
|
|
12778
|
-
}
|
|
12881
|
+
validateArrayOfSchemas(report, arr) {
|
|
12882
|
+
let idx = arr.length;
|
|
12883
|
+
while (idx--) {
|
|
12884
|
+
this.validateSchema(report, arr[idx]);
|
|
12779
12885
|
}
|
|
12886
|
+
return report.isValid();
|
|
12780
12887
|
}
|
|
12781
|
-
|
|
12782
|
-
|
|
12783
|
-
if
|
|
12784
|
-
|
|
12785
|
-
|
|
12786
|
-
|
|
12787
|
-
|
|
12788
|
-
|
|
12789
|
-
|
|
12790
|
-
|
|
12791
|
-
|
|
12792
|
-
|
|
12888
|
+
validateSchema(report, schema) {
|
|
12889
|
+
report.commonErrorMessage = 'SCHEMA_VALIDATION_FAILED';
|
|
12890
|
+
// if schema is an array, assume it's an array of schemas
|
|
12891
|
+
if (Array.isArray(schema)) {
|
|
12892
|
+
return this.validateArrayOfSchemas(report, schema);
|
|
12893
|
+
}
|
|
12894
|
+
// do not revalidate schema that has already been validated once
|
|
12895
|
+
if (schema.__$validated) {
|
|
12896
|
+
return true;
|
|
12897
|
+
}
|
|
12898
|
+
// if $schema is present, this schema should validate against that $schema
|
|
12899
|
+
const hasParentSchema = schema.$schema && schema.id !== schema.$schema;
|
|
12900
|
+
if (hasParentSchema) {
|
|
12901
|
+
if (schema.__$schemaResolved && schema.__$schemaResolved !== schema) {
|
|
12902
|
+
const subReport = new Report(report);
|
|
12903
|
+
const valid = validate.call(this.validator, subReport, schema.__$schemaResolved, schema);
|
|
12904
|
+
if (valid === false) {
|
|
12905
|
+
report.addError('PARENT_SCHEMA_VALIDATION_FAILED', undefined, subReport);
|
|
12906
|
+
}
|
|
12793
12907
|
}
|
|
12794
|
-
|
|
12795
|
-
if (
|
|
12796
|
-
|
|
12908
|
+
else {
|
|
12909
|
+
if (this.validator.options.ignoreUnresolvableReferences !== true) {
|
|
12910
|
+
report.addError('REF_UNRESOLVED', [schema.$schema]);
|
|
12797
12911
|
}
|
|
12798
|
-
});
|
|
12799
|
-
}
|
|
12800
|
-
// end issue #36
|
|
12801
|
-
if (schema.enum === undefined &&
|
|
12802
|
-
schema.type === undefined &&
|
|
12803
|
-
schema.anyOf === undefined &&
|
|
12804
|
-
schema.oneOf === undefined &&
|
|
12805
|
-
schema.not === undefined &&
|
|
12806
|
-
schema.$ref === undefined) {
|
|
12807
|
-
report.addError('KEYWORD_UNDEFINED_STRICT', ['type']);
|
|
12808
|
-
}
|
|
12809
|
-
}
|
|
12810
|
-
const keys = Object.keys(schema);
|
|
12811
|
-
let idx = keys.length;
|
|
12812
|
-
while (idx--) {
|
|
12813
|
-
const key = keys[idx];
|
|
12814
|
-
if (key.indexOf('__') === 0) {
|
|
12815
|
-
continue;
|
|
12816
|
-
}
|
|
12817
|
-
if (SchemaValidators[key] !== undefined) {
|
|
12818
|
-
SchemaValidators[key].call(this, report, schema);
|
|
12819
|
-
}
|
|
12820
|
-
else if (!hasParentSchema) {
|
|
12821
|
-
if (this.options.noExtraKeywords === true) {
|
|
12822
|
-
report.addError('KEYWORD_UNEXPECTED', [key]);
|
|
12823
12912
|
}
|
|
12824
12913
|
}
|
|
12825
|
-
|
|
12826
|
-
|
|
12827
|
-
|
|
12828
|
-
|
|
12829
|
-
|
|
12830
|
-
|
|
12831
|
-
|
|
12832
|
-
|
|
12833
|
-
|
|
12834
|
-
|
|
12835
|
-
|
|
12836
|
-
|
|
12837
|
-
|
|
12914
|
+
if (this.validator.options.noTypeless === true) {
|
|
12915
|
+
// issue #36 - inherit type to anyOf, oneOf, allOf if noTypeless is defined
|
|
12916
|
+
if (schema.type !== undefined) {
|
|
12917
|
+
let schemas = [];
|
|
12918
|
+
if (Array.isArray(schema.anyOf)) {
|
|
12919
|
+
schemas = schemas.concat(schema.anyOf);
|
|
12920
|
+
}
|
|
12921
|
+
if (Array.isArray(schema.oneOf)) {
|
|
12922
|
+
schemas = schemas.concat(schema.oneOf);
|
|
12923
|
+
}
|
|
12924
|
+
if (Array.isArray(schema.allOf)) {
|
|
12925
|
+
schemas = schemas.concat(schema.allOf);
|
|
12926
|
+
}
|
|
12927
|
+
schemas.forEach(function (sch) {
|
|
12928
|
+
if (!sch.type) {
|
|
12929
|
+
sch.type = schema.type;
|
|
12930
|
+
}
|
|
12931
|
+
});
|
|
12838
12932
|
}
|
|
12839
|
-
|
|
12840
|
-
|
|
12841
|
-
|
|
12842
|
-
|
|
12843
|
-
|
|
12844
|
-
|
|
12845
|
-
|
|
12846
|
-
|
|
12847
|
-
const isValid = report.isValid();
|
|
12848
|
-
if (isValid) {
|
|
12849
|
-
schema.__$validated = true;
|
|
12850
|
-
}
|
|
12851
|
-
return isValid;
|
|
12852
|
-
}
|
|
12853
|
-
|
|
12854
|
-
function decodeJSONPointer(str) {
|
|
12855
|
-
// http://tools.ietf.org/html/draft-ietf-appsawg-json-pointer-07#section-3
|
|
12856
|
-
return decodeURIComponent(str).replace(/~[0-1]/g, function (x) {
|
|
12857
|
-
return x === '~1' ? '/' : '~';
|
|
12858
|
-
});
|
|
12859
|
-
}
|
|
12860
|
-
function getRemotePath(uri) {
|
|
12861
|
-
const io = uri.indexOf('#');
|
|
12862
|
-
return io === -1 ? uri : uri.slice(0, io);
|
|
12863
|
-
}
|
|
12864
|
-
function getQueryPath(uri) {
|
|
12865
|
-
const io = uri.indexOf('#');
|
|
12866
|
-
const res = io === -1 ? undefined : uri.slice(io + 1);
|
|
12867
|
-
// WARN: do not slice slash, #/ means take root and go down from it
|
|
12868
|
-
// if (res && res[0] === "/") { res = res.slice(1); }
|
|
12869
|
-
return res;
|
|
12870
|
-
}
|
|
12871
|
-
function findId(schema, id) {
|
|
12872
|
-
// process only arrays and objects
|
|
12873
|
-
if (typeof schema !== 'object' || schema === null) {
|
|
12874
|
-
return;
|
|
12875
|
-
}
|
|
12876
|
-
// no id means root so return itself
|
|
12877
|
-
if (!id) {
|
|
12878
|
-
return schema;
|
|
12879
|
-
}
|
|
12880
|
-
if (schema.id) {
|
|
12881
|
-
if (schema.id === id || (schema.id[0] === '#' && schema.id.substring(1) === id)) {
|
|
12882
|
-
return schema;
|
|
12883
|
-
}
|
|
12884
|
-
}
|
|
12885
|
-
let idx, result;
|
|
12886
|
-
if (Array.isArray(schema)) {
|
|
12887
|
-
idx = schema.length;
|
|
12888
|
-
while (idx--) {
|
|
12889
|
-
result = findId(schema[idx], id);
|
|
12890
|
-
if (result) {
|
|
12891
|
-
return result;
|
|
12933
|
+
// end issue #36
|
|
12934
|
+
if (schema.enum === undefined &&
|
|
12935
|
+
schema.type === undefined &&
|
|
12936
|
+
schema.anyOf === undefined &&
|
|
12937
|
+
schema.oneOf === undefined &&
|
|
12938
|
+
schema.not === undefined &&
|
|
12939
|
+
schema.$ref === undefined) {
|
|
12940
|
+
report.addError('KEYWORD_UNDEFINED_STRICT', ['type']);
|
|
12892
12941
|
}
|
|
12893
12942
|
}
|
|
12894
|
-
}
|
|
12895
|
-
else {
|
|
12896
12943
|
const keys = Object.keys(schema);
|
|
12897
|
-
idx = keys.length;
|
|
12944
|
+
let idx = keys.length;
|
|
12898
12945
|
while (idx--) {
|
|
12899
|
-
const
|
|
12900
|
-
if (
|
|
12946
|
+
const key = keys[idx];
|
|
12947
|
+
if (key.indexOf('__') === 0) {
|
|
12901
12948
|
continue;
|
|
12902
12949
|
}
|
|
12903
|
-
|
|
12904
|
-
|
|
12905
|
-
return result;
|
|
12950
|
+
if (Object.prototype.hasOwnProperty.call(SchemaValidators, key)) {
|
|
12951
|
+
SchemaValidators[key].call(this, report, schema);
|
|
12906
12952
|
}
|
|
12907
|
-
|
|
12908
|
-
|
|
12909
|
-
|
|
12910
|
-
/**
|
|
12911
|
-
*
|
|
12912
|
-
* @param {*} uri
|
|
12913
|
-
* @param {*} schema
|
|
12914
|
-
*
|
|
12915
|
-
* @returns {void}
|
|
12916
|
-
*/
|
|
12917
|
-
function cacheSchemaByUri(uri, schema) {
|
|
12918
|
-
const remotePath = getRemotePath(uri);
|
|
12919
|
-
if (remotePath) {
|
|
12920
|
-
this.cache[remotePath] = schema;
|
|
12921
|
-
}
|
|
12922
|
-
}
|
|
12923
|
-
/**
|
|
12924
|
-
*
|
|
12925
|
-
* @param {*} uri
|
|
12926
|
-
*
|
|
12927
|
-
* @returns {void}
|
|
12928
|
-
*/
|
|
12929
|
-
function removeFromCacheByUri(uri) {
|
|
12930
|
-
const remotePath = getRemotePath(uri);
|
|
12931
|
-
if (remotePath) {
|
|
12932
|
-
delete this.cache[remotePath];
|
|
12933
|
-
}
|
|
12934
|
-
}
|
|
12935
|
-
/**
|
|
12936
|
-
*
|
|
12937
|
-
* @param {*} uri
|
|
12938
|
-
*
|
|
12939
|
-
* @returns {boolean}
|
|
12940
|
-
*/
|
|
12941
|
-
function checkCacheForUri(uri) {
|
|
12942
|
-
const remotePath = getRemotePath(uri);
|
|
12943
|
-
return remotePath ? this.cache[remotePath] != null : false;
|
|
12944
|
-
}
|
|
12945
|
-
function getSchema(report, schema) {
|
|
12946
|
-
if (typeof schema === 'object') {
|
|
12947
|
-
schema = getSchemaByReference.call(this, report, schema);
|
|
12948
|
-
}
|
|
12949
|
-
if (typeof schema === 'string') {
|
|
12950
|
-
schema = getSchemaByUri.call(this, report, schema);
|
|
12951
|
-
}
|
|
12952
|
-
return schema;
|
|
12953
|
-
}
|
|
12954
|
-
function getSchemaByReference(report, key) {
|
|
12955
|
-
let i = this.referenceCache.length;
|
|
12956
|
-
while (i--) {
|
|
12957
|
-
if (isequal(this.referenceCache[i][0], key)) {
|
|
12958
|
-
return this.referenceCache[i][1];
|
|
12959
|
-
}
|
|
12960
|
-
}
|
|
12961
|
-
// not found
|
|
12962
|
-
const schema = cloneDeep(key);
|
|
12963
|
-
this.referenceCache.push([key, schema]);
|
|
12964
|
-
return schema;
|
|
12965
|
-
}
|
|
12966
|
-
function getSchemaByUri(report, uri, root) {
|
|
12967
|
-
const remotePath = getRemotePath(uri);
|
|
12968
|
-
const queryPath = getQueryPath(uri);
|
|
12969
|
-
let result = remotePath ? this.cache[remotePath] : root;
|
|
12970
|
-
if (result && remotePath) {
|
|
12971
|
-
// we need to avoid compiling schemas in a recursive loop
|
|
12972
|
-
const compileRemote = result !== root;
|
|
12973
|
-
// now we need to compile and validate resolved schema (in case it's not already)
|
|
12974
|
-
if (compileRemote) {
|
|
12975
|
-
report.path.push(remotePath);
|
|
12976
|
-
let remoteReport;
|
|
12977
|
-
const anscestorReport = report.getAncestor(result.id);
|
|
12978
|
-
if (anscestorReport) {
|
|
12979
|
-
remoteReport = anscestorReport;
|
|
12980
|
-
}
|
|
12981
|
-
else {
|
|
12982
|
-
remoteReport = new Report(report);
|
|
12983
|
-
if (compileSchema.call(this, remoteReport, result)) {
|
|
12984
|
-
const savedOptions = this.options;
|
|
12985
|
-
try {
|
|
12986
|
-
// If custom validationOptions were provided to setRemoteReference(),
|
|
12987
|
-
// use them instead of the default options
|
|
12988
|
-
this.options = result.__$validationOptions || this.options;
|
|
12989
|
-
validateSchema.call(this, remoteReport, result);
|
|
12990
|
-
}
|
|
12991
|
-
finally {
|
|
12992
|
-
this.options = savedOptions;
|
|
12993
|
-
}
|
|
12953
|
+
else if (!hasParentSchema) {
|
|
12954
|
+
if (this.validator.options.noExtraKeywords === true) {
|
|
12955
|
+
report.addError('KEYWORD_UNEXPECTED', [key]);
|
|
12994
12956
|
}
|
|
12995
12957
|
}
|
|
12996
|
-
const remoteReportIsValid = remoteReport.isValid();
|
|
12997
|
-
if (!remoteReportIsValid) {
|
|
12998
|
-
report.addError('REMOTE_NOT_VALID', [uri], remoteReport);
|
|
12999
|
-
}
|
|
13000
|
-
report.path.pop();
|
|
13001
|
-
if (!remoteReportIsValid) {
|
|
13002
|
-
return undefined;
|
|
13003
|
-
}
|
|
13004
12958
|
}
|
|
13005
|
-
|
|
13006
|
-
|
|
13007
|
-
|
|
13008
|
-
|
|
13009
|
-
|
|
13010
|
-
|
|
13011
|
-
|
|
13012
|
-
|
|
12959
|
+
if (this.validator.options.pedanticCheck === true) {
|
|
12960
|
+
if (schema.enum) {
|
|
12961
|
+
// break recursion
|
|
12962
|
+
const tmpSchema = shallowClone(schema);
|
|
12963
|
+
delete tmpSchema.enum;
|
|
12964
|
+
delete tmpSchema.default;
|
|
12965
|
+
report.path.push('enum');
|
|
12966
|
+
idx = schema.enum.length;
|
|
12967
|
+
while (idx--) {
|
|
12968
|
+
report.path.push(idx);
|
|
12969
|
+
validate.call(this.validator, report, tmpSchema, schema.enum[idx]);
|
|
12970
|
+
report.path.pop();
|
|
12971
|
+
}
|
|
12972
|
+
report.path.pop();
|
|
13013
12973
|
}
|
|
13014
|
-
|
|
13015
|
-
|
|
13016
|
-
|
|
12974
|
+
if (schema.default) {
|
|
12975
|
+
report.path.push('default');
|
|
12976
|
+
validate.call(this.validator, report, schema, schema.default);
|
|
12977
|
+
report.path.pop();
|
|
13017
12978
|
}
|
|
13018
12979
|
}
|
|
12980
|
+
const isValid = report.isValid();
|
|
12981
|
+
if (isValid) {
|
|
12982
|
+
schema.__$validated = true;
|
|
12983
|
+
}
|
|
12984
|
+
return isValid;
|
|
13019
12985
|
}
|
|
13020
|
-
return result;
|
|
13021
12986
|
}
|
|
13022
12987
|
|
|
13023
12988
|
var id$1 = "http://json-schema.org/draft-04/schema#";
|
|
@@ -13248,7 +13213,7 @@ var dependencies = {
|
|
|
13248
13213
|
"minimum"
|
|
13249
13214
|
]
|
|
13250
13215
|
};
|
|
13251
|
-
var
|
|
13216
|
+
var _Draft4Schema = {
|
|
13252
13217
|
id: id$1,
|
|
13253
13218
|
$schema: $schema$1,
|
|
13254
13219
|
description: description,
|
|
@@ -13417,7 +13382,7 @@ var definitions = {
|
|
|
13417
13382
|
}
|
|
13418
13383
|
}
|
|
13419
13384
|
};
|
|
13420
|
-
var
|
|
13385
|
+
var _Draft4HyperSchema = {
|
|
13421
13386
|
$schema: $schema,
|
|
13422
13387
|
id: id,
|
|
13423
13388
|
title: title,
|
|
@@ -13426,6 +13391,8 @@ var Draft4HyperSchema = {
|
|
|
13426
13391
|
definitions: definitions
|
|
13427
13392
|
};
|
|
13428
13393
|
|
|
13394
|
+
const Draft4Schema = _Draft4Schema;
|
|
13395
|
+
const Draft4HyperSchema = _Draft4HyperSchema;
|
|
13429
13396
|
/**
|
|
13430
13397
|
* default options
|
|
13431
13398
|
*/
|
|
@@ -13475,11 +13442,13 @@ const defaultOptions = {
|
|
|
13475
13442
|
// function to be called on every schema
|
|
13476
13443
|
customValidator: null,
|
|
13477
13444
|
};
|
|
13478
|
-
|
|
13445
|
+
const normalizeOptions = (options) => {
|
|
13479
13446
|
let normalized;
|
|
13480
13447
|
// options
|
|
13481
13448
|
if (typeof options === 'object') {
|
|
13482
|
-
let keys = Object.keys(options)
|
|
13449
|
+
let keys = Object.keys(options);
|
|
13450
|
+
let idx = keys.length;
|
|
13451
|
+
let key;
|
|
13483
13452
|
// check that the options are correctly configured
|
|
13484
13453
|
while (idx--) {
|
|
13485
13454
|
key = keys[idx];
|
|
@@ -13493,13 +13462,13 @@ function normalizeOptions(options) {
|
|
|
13493
13462
|
while (idx--) {
|
|
13494
13463
|
key = keys[idx];
|
|
13495
13464
|
if (options[key] === undefined) {
|
|
13496
|
-
options[key] =
|
|
13465
|
+
options[key] = shallowClone(defaultOptions[key]);
|
|
13497
13466
|
}
|
|
13498
13467
|
}
|
|
13499
13468
|
normalized = options;
|
|
13500
13469
|
}
|
|
13501
13470
|
else {
|
|
13502
|
-
normalized =
|
|
13471
|
+
normalized = shallowClone(defaultOptions);
|
|
13503
13472
|
}
|
|
13504
13473
|
if (normalized.strictMode === true) {
|
|
13505
13474
|
normalized.forceAdditional = true;
|
|
@@ -13512,68 +13481,45 @@ function normalizeOptions(options) {
|
|
|
13512
13481
|
normalized.noEmptyArrays = true;
|
|
13513
13482
|
}
|
|
13514
13483
|
return normalized;
|
|
13515
|
-
}
|
|
13484
|
+
};
|
|
13516
13485
|
class ZSchema {
|
|
13517
|
-
|
|
13518
|
-
|
|
13519
|
-
* Register a custom format.
|
|
13520
|
-
*
|
|
13521
|
-
* @param name - name of the custom format
|
|
13522
|
-
* @param validatorFunction - custom format validator function.
|
|
13523
|
-
* Returns `true` if `value` matches the custom format.
|
|
13524
|
-
*/
|
|
13525
|
-
static registerFormat(formatName, validatorFunction) {
|
|
13526
|
-
FormatValidators[formatName] = validatorFunction;
|
|
13486
|
+
static registerFormat(name, validatorFunction) {
|
|
13487
|
+
return registerFormat(name, validatorFunction);
|
|
13527
13488
|
}
|
|
13528
|
-
/**
|
|
13529
|
-
* Unregister a format.
|
|
13530
|
-
*
|
|
13531
|
-
* @param name - name of the custom format
|
|
13532
|
-
*/
|
|
13533
13489
|
static unregisterFormat(name) {
|
|
13534
|
-
|
|
13490
|
+
return unregisterFormat(name);
|
|
13535
13491
|
}
|
|
13536
|
-
/**
|
|
13537
|
-
* Get the list of all registered formats.
|
|
13538
|
-
*
|
|
13539
|
-
* Both the names of the burned-in formats and the custom format names are
|
|
13540
|
-
* returned by this function.
|
|
13541
|
-
*
|
|
13542
|
-
* @returns {string[]} the list of all registered format names.
|
|
13543
|
-
*/
|
|
13544
13492
|
static getRegisteredFormats() {
|
|
13545
|
-
return
|
|
13493
|
+
return getRegisteredFormats();
|
|
13546
13494
|
}
|
|
13547
13495
|
static getDefaultOptions() {
|
|
13548
|
-
return
|
|
13496
|
+
return deepClone(defaultOptions);
|
|
13549
13497
|
}
|
|
13550
|
-
|
|
13551
|
-
|
|
13552
|
-
|
|
13498
|
+
lastReport;
|
|
13499
|
+
scache;
|
|
13500
|
+
sc;
|
|
13501
|
+
sv;
|
|
13502
|
+
validateOptions = {};
|
|
13553
13503
|
options;
|
|
13554
13504
|
constructor(options) {
|
|
13555
|
-
this.
|
|
13556
|
-
this.
|
|
13557
|
-
this.
|
|
13505
|
+
this.scache = new SchemaCache(this);
|
|
13506
|
+
this.sc = new SchemaCompiler(this);
|
|
13507
|
+
this.sv = new SchemaValidator(this);
|
|
13558
13508
|
this.options = normalizeOptions(options);
|
|
13559
13509
|
// Disable strict validation for the built-in schemas
|
|
13560
13510
|
const metaschemaOptions = normalizeOptions({});
|
|
13561
13511
|
this.setRemoteReference('http://json-schema.org/draft-04/schema', Draft4Schema, metaschemaOptions);
|
|
13562
13512
|
this.setRemoteReference('http://json-schema.org/draft-04/hyper-schema', Draft4HyperSchema, metaschemaOptions);
|
|
13563
13513
|
}
|
|
13564
|
-
/**
|
|
13565
|
-
* @param schema - JSON object representing schema
|
|
13566
|
-
* @returns {boolean} true if schema is valid.
|
|
13567
|
-
*/
|
|
13568
13514
|
validateSchema(schema) {
|
|
13569
13515
|
if (Array.isArray(schema) && schema.length === 0) {
|
|
13570
13516
|
throw new Error('.validateSchema was called with an empty array');
|
|
13571
13517
|
}
|
|
13572
13518
|
const report = new Report(this.options);
|
|
13573
|
-
schema = getSchema
|
|
13574
|
-
const compiled = compileSchema
|
|
13519
|
+
schema = this.scache.getSchema(report, schema);
|
|
13520
|
+
const compiled = this.sc.compileSchema(report, schema);
|
|
13575
13521
|
if (compiled) {
|
|
13576
|
-
validateSchema
|
|
13522
|
+
this.sv.validateSchema(report, schema);
|
|
13577
13523
|
}
|
|
13578
13524
|
this.lastReport = report;
|
|
13579
13525
|
return report.isValid();
|
|
@@ -13587,9 +13533,9 @@ class ZSchema {
|
|
|
13587
13533
|
options = {};
|
|
13588
13534
|
}
|
|
13589
13535
|
this.validateOptions = options;
|
|
13590
|
-
const
|
|
13591
|
-
if (
|
|
13592
|
-
const e = new Error('Invalid .validate call - schema must be a string or object but ' +
|
|
13536
|
+
const schemaType = whatIs(schema);
|
|
13537
|
+
if (schemaType !== 'string' && schemaType !== 'object') {
|
|
13538
|
+
const e = new Error('Invalid .validate call - schema must be a string or object but ' + schemaType + ' was passed!');
|
|
13593
13539
|
if (callback) {
|
|
13594
13540
|
setTimeout(function () {
|
|
13595
13541
|
callback(e, false);
|
|
@@ -13603,17 +13549,18 @@ class ZSchema {
|
|
|
13603
13549
|
report.json = json;
|
|
13604
13550
|
if (typeof schema === 'string') {
|
|
13605
13551
|
const schemaName = schema;
|
|
13606
|
-
|
|
13607
|
-
if (!
|
|
13552
|
+
const _schema = this.scache.getSchema(report, schemaName);
|
|
13553
|
+
if (!_schema) {
|
|
13608
13554
|
throw new Error("Schema with id '" + schemaName + "' wasn't found in the validator cache!");
|
|
13609
13555
|
}
|
|
13556
|
+
schema = _schema;
|
|
13610
13557
|
}
|
|
13611
13558
|
else {
|
|
13612
|
-
schema = getSchema
|
|
13559
|
+
schema = this.scache.getSchema(report, schema);
|
|
13613
13560
|
}
|
|
13614
13561
|
let compiled = false;
|
|
13615
13562
|
if (!foundError) {
|
|
13616
|
-
compiled = compileSchema
|
|
13563
|
+
compiled = this.sc.compileSchema(report, schema);
|
|
13617
13564
|
}
|
|
13618
13565
|
if (!compiled) {
|
|
13619
13566
|
this.lastReport = report;
|
|
@@ -13621,7 +13568,7 @@ class ZSchema {
|
|
|
13621
13568
|
}
|
|
13622
13569
|
let validated = false;
|
|
13623
13570
|
if (!foundError) {
|
|
13624
|
-
validated = validateSchema
|
|
13571
|
+
validated = this.sv.validateSchema(report, schema);
|
|
13625
13572
|
}
|
|
13626
13573
|
if (!validated) {
|
|
13627
13574
|
this.lastReport = report;
|
|
@@ -13652,6 +13599,9 @@ class ZSchema {
|
|
|
13652
13599
|
* Returns an Error object for the most recent failed validation, or null if the validation was successful.
|
|
13653
13600
|
*/
|
|
13654
13601
|
getLastError() {
|
|
13602
|
+
if (!this.lastReport) {
|
|
13603
|
+
throw new Error(`getLastError() called before doing any validation!`);
|
|
13604
|
+
}
|
|
13655
13605
|
if (this.lastReport.errors.length === 0) {
|
|
13656
13606
|
return null;
|
|
13657
13607
|
}
|
|
@@ -13669,27 +13619,29 @@ class ZSchema {
|
|
|
13669
13619
|
return this.lastReport && this.lastReport.errors.length > 0 ? this.lastReport.errors : null;
|
|
13670
13620
|
}
|
|
13671
13621
|
setRemoteReference(uri, schema, validationOptions) {
|
|
13622
|
+
let _schema;
|
|
13672
13623
|
if (typeof schema === 'string') {
|
|
13673
|
-
|
|
13624
|
+
_schema = JSON.parse(schema);
|
|
13674
13625
|
}
|
|
13675
13626
|
else {
|
|
13676
|
-
|
|
13627
|
+
_schema = deepClone(schema);
|
|
13677
13628
|
}
|
|
13678
13629
|
if (validationOptions) {
|
|
13679
|
-
|
|
13630
|
+
_schema.__$validationOptions = normalizeOptions(validationOptions);
|
|
13680
13631
|
}
|
|
13681
|
-
cacheSchemaByUri
|
|
13632
|
+
this.scache.cacheSchemaByUri(uri, _schema);
|
|
13682
13633
|
}
|
|
13683
13634
|
compileSchema(schema) {
|
|
13684
13635
|
const report = new Report(this.options);
|
|
13685
|
-
schema = getSchema
|
|
13686
|
-
compileSchema
|
|
13636
|
+
schema = this.scache.getSchema(report, schema);
|
|
13637
|
+
this.sc.compileSchema(report, schema);
|
|
13687
13638
|
this.lastReport = report;
|
|
13688
13639
|
return report.isValid();
|
|
13689
13640
|
}
|
|
13690
13641
|
getMissingReferences(arr) {
|
|
13691
|
-
arr = arr || this.lastReport
|
|
13692
|
-
let res = []
|
|
13642
|
+
arr = arr || this.lastReport?.errors || [];
|
|
13643
|
+
let res = [];
|
|
13644
|
+
let idx = arr.length;
|
|
13693
13645
|
while (idx--) {
|
|
13694
13646
|
const error = arr[idx];
|
|
13695
13647
|
if (error.code === 'UNRESOLVABLE_REFERENCE') {
|
|
@@ -13718,11 +13670,10 @@ class ZSchema {
|
|
|
13718
13670
|
}
|
|
13719
13671
|
getResolvedSchema(schema) {
|
|
13720
13672
|
const report = new Report(this.options);
|
|
13721
|
-
schema = getSchema
|
|
13673
|
+
schema = this.scache.getSchema(report, schema);
|
|
13722
13674
|
// clone before making any modifications
|
|
13723
|
-
schema =
|
|
13675
|
+
schema = deepClone(schema);
|
|
13724
13676
|
const visited = [];
|
|
13725
|
-
// clean-up the schema and resolve references
|
|
13726
13677
|
const cleanup = function (schema) {
|
|
13727
13678
|
let key;
|
|
13728
13679
|
const typeOf = whatIs(schema);
|