z-schema 7.0.5 → 7.0.7
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 +0 -9
- package/cjs/index.d.ts +179 -119
- package/cjs/index.js +1048 -1101
- 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 +6 -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} +69 -84
- package/package.json +6 -3
- package/src/{Errors.ts → errors.ts} +4 -0
- package/src/format-validators.ts +191 -0
- package/src/index.ts +8 -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} +112 -121
- package/umd/ZSchema.js +1048 -1101
- package/umd/ZSchema.min.js +1 -1
- package/dist/FormatValidators.js +0 -136
- package/dist/SchemaCache.js +0 -172
- 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 -99
- package/src/SchemaCache.ts +0 -188
- 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,33 +11963,425 @@ function requireLodash_isequal () {
|
|
|
11972
11963
|
var lodash_isequalExports = requireLodash_isequal();
|
|
11973
11964
|
var isequal = /*@__PURE__*/getDefaultExportFromCjs(lodash_isequalExports);
|
|
11974
11965
|
|
|
11975
|
-
const
|
|
11976
|
-
|
|
11977
|
-
|
|
11978
|
-
|
|
11979
|
-
|
|
11980
|
-
|
|
11981
|
-
|
|
11982
|
-
|
|
11983
|
-
|
|
11984
|
-
|
|
11985
|
-
if (
|
|
11986
|
-
|
|
11987
|
-
}
|
|
11988
|
-
},
|
|
11989
|
-
multipleOf: function (report, schema) {
|
|
11990
|
-
// http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.1.1.1
|
|
11991
|
-
if (typeof schema.multipleOf !== 'number') {
|
|
11992
|
-
report.addError('KEYWORD_TYPE_EXPECTED', ['multipleOf', 'number']);
|
|
11993
|
-
}
|
|
11994
|
-
else if (schema.multipleOf <= 0) {
|
|
11995
|
-
report.addError('KEYWORD_MUST_BE', ['multipleOf', 'strictly greater than 0']);
|
|
11966
|
+
const findId = (schema, id) => {
|
|
11967
|
+
// process only arrays and objects
|
|
11968
|
+
if (typeof schema !== 'object' || schema === null) {
|
|
11969
|
+
return;
|
|
11970
|
+
}
|
|
11971
|
+
// no id means root so return itself
|
|
11972
|
+
if (!id) {
|
|
11973
|
+
return schema;
|
|
11974
|
+
}
|
|
11975
|
+
if (schema.id) {
|
|
11976
|
+
if (schema.id === id || (schema.id[0] === '#' && schema.id.substring(1) === id)) {
|
|
11977
|
+
return schema;
|
|
11996
11978
|
}
|
|
11997
|
-
}
|
|
11998
|
-
|
|
11999
|
-
|
|
12000
|
-
|
|
12001
|
-
|
|
11979
|
+
}
|
|
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
|
+
}
|
|
11988
|
+
}
|
|
11989
|
+
}
|
|
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;
|
|
12116
|
+
}
|
|
12117
|
+
if (typeof obj.id === 'string') {
|
|
12118
|
+
scope.push(obj.id);
|
|
12119
|
+
}
|
|
12120
|
+
if (typeof obj.$ref === 'string' && typeof obj.__$refResolved === 'undefined') {
|
|
12121
|
+
results.push({
|
|
12122
|
+
ref: mergeReference(scope, obj.$ref),
|
|
12123
|
+
key: '$ref',
|
|
12124
|
+
obj: obj,
|
|
12125
|
+
path: path.slice(0),
|
|
12126
|
+
});
|
|
12127
|
+
}
|
|
12128
|
+
if (typeof obj.$schema === 'string' && typeof obj.__$schemaResolved === 'undefined') {
|
|
12129
|
+
results.push({
|
|
12130
|
+
ref: mergeReference(scope, obj.$schema),
|
|
12131
|
+
key: '$schema',
|
|
12132
|
+
obj: obj,
|
|
12133
|
+
path: path.slice(0),
|
|
12134
|
+
});
|
|
12135
|
+
}
|
|
12136
|
+
let idx;
|
|
12137
|
+
if (Array.isArray(obj)) {
|
|
12138
|
+
idx = obj.length;
|
|
12139
|
+
while (idx--) {
|
|
12140
|
+
path.push(idx);
|
|
12141
|
+
collectReferences(obj[idx], results, scope, path);
|
|
12142
|
+
path.pop();
|
|
12143
|
+
}
|
|
12144
|
+
}
|
|
12145
|
+
else {
|
|
12146
|
+
const keys = Object.keys(obj);
|
|
12147
|
+
idx = keys.length;
|
|
12148
|
+
while (idx--) {
|
|
12149
|
+
// do not recurse through resolved references and other z-schema props
|
|
12150
|
+
if (keys[idx].indexOf('__$') === 0) {
|
|
12151
|
+
continue;
|
|
12152
|
+
}
|
|
12153
|
+
path.push(keys[idx]);
|
|
12154
|
+
collectReferences(obj[keys[idx]], results, scope, path);
|
|
12155
|
+
path.pop();
|
|
12156
|
+
}
|
|
12157
|
+
}
|
|
12158
|
+
if (typeof obj.id === 'string') {
|
|
12159
|
+
scope.pop();
|
|
12160
|
+
}
|
|
12161
|
+
return results;
|
|
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);
|
|
12176
|
+
}
|
|
12177
|
+
}
|
|
12178
|
+
else if (isScopeRelative && isRefRelative) {
|
|
12179
|
+
joinedScope = '';
|
|
12180
|
+
}
|
|
12181
|
+
else {
|
|
12182
|
+
toRemove = joinedScope.match(/[^#/]+$/);
|
|
12183
|
+
if (toRemove) {
|
|
12184
|
+
joinedScope = joinedScope.slice(0, toRemove.index);
|
|
12185
|
+
}
|
|
12186
|
+
}
|
|
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;
|
|
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;
|
|
12218
|
+
}
|
|
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;
|
|
12235
|
+
while (idx--) {
|
|
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
|
+
}
|
|
12257
|
+
}
|
|
12258
|
+
}
|
|
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
|
+
}
|
|
12282
|
+
}
|
|
12283
|
+
}
|
|
12284
|
+
// this might create circular references
|
|
12285
|
+
refObj.obj[`__${refObj.key}Resolved`] = response;
|
|
12286
|
+
}
|
|
12287
|
+
const isValid = report.isValid();
|
|
12288
|
+
if (isValid) {
|
|
12289
|
+
schema.__$compiled = true;
|
|
12290
|
+
}
|
|
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);
|
|
12295
|
+
}
|
|
12296
|
+
}
|
|
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
|
+
}
|
|
12312
|
+
}
|
|
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
|
+
}
|
|
12336
|
+
}
|
|
12337
|
+
}
|
|
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();
|
|
12341
|
+
}
|
|
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);
|
|
12353
|
+
}
|
|
12354
|
+
return compiledCount;
|
|
12355
|
+
}
|
|
12356
|
+
}
|
|
12357
|
+
|
|
12358
|
+
const SchemaValidators = {
|
|
12359
|
+
$ref: function (report, schema) {
|
|
12360
|
+
// http://tools.ietf.org/html/draft-ietf-appsawg-json-pointer-07
|
|
12361
|
+
// http://tools.ietf.org/html/draft-pbryan-zyp-json-ref-03
|
|
12362
|
+
if (typeof schema.$ref !== 'string') {
|
|
12363
|
+
report.addError('KEYWORD_TYPE_EXPECTED', ['$ref', 'string']);
|
|
12364
|
+
}
|
|
12365
|
+
},
|
|
12366
|
+
$schema: function (report, schema) {
|
|
12367
|
+
// http://json-schema.org/latest/json-schema-core.html#rfc.section.6
|
|
12368
|
+
if (typeof schema.$schema !== 'string') {
|
|
12369
|
+
report.addError('KEYWORD_TYPE_EXPECTED', ['$schema', 'string']);
|
|
12370
|
+
}
|
|
12371
|
+
},
|
|
12372
|
+
multipleOf: function (report, schema) {
|
|
12373
|
+
// http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.1.1.1
|
|
12374
|
+
if (typeof schema.multipleOf !== 'number') {
|
|
12375
|
+
report.addError('KEYWORD_TYPE_EXPECTED', ['multipleOf', 'number']);
|
|
12376
|
+
}
|
|
12377
|
+
else if (schema.multipleOf <= 0) {
|
|
12378
|
+
report.addError('KEYWORD_MUST_BE', ['multipleOf', 'strictly greater than 0']);
|
|
12379
|
+
}
|
|
12380
|
+
},
|
|
12381
|
+
maximum: function (report, schema) {
|
|
12382
|
+
// http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.1.2.1
|
|
12383
|
+
if (typeof schema.maximum !== 'number') {
|
|
12384
|
+
report.addError('KEYWORD_TYPE_EXPECTED', ['maximum', 'number']);
|
|
12002
12385
|
}
|
|
12003
12386
|
},
|
|
12004
12387
|
exclusiveMaximum: function (report, schema) {
|
|
@@ -12063,9 +12446,9 @@ const SchemaValidators = {
|
|
|
12063
12446
|
if (type !== 'boolean' && type !== 'object') {
|
|
12064
12447
|
report.addError('KEYWORD_TYPE_EXPECTED', ['additionalItems', ['boolean', 'object']]);
|
|
12065
12448
|
}
|
|
12066
|
-
else if (
|
|
12449
|
+
else if (isObject(schema.additionalItems)) {
|
|
12067
12450
|
report.path.push('additionalItems');
|
|
12068
|
-
validateSchema
|
|
12451
|
+
this.validateSchema(report, schema.additionalItems);
|
|
12069
12452
|
report.path.pop();
|
|
12070
12453
|
}
|
|
12071
12454
|
},
|
|
@@ -12074,15 +12457,15 @@ const SchemaValidators = {
|
|
|
12074
12457
|
const type = whatIs(schema.items);
|
|
12075
12458
|
if (type === 'object') {
|
|
12076
12459
|
report.path.push('items');
|
|
12077
|
-
validateSchema
|
|
12460
|
+
this.validateSchema(report, schema.items);
|
|
12078
12461
|
report.path.pop();
|
|
12079
12462
|
}
|
|
12080
|
-
else if (
|
|
12463
|
+
else if (Array.isArray(schema.items)) {
|
|
12081
12464
|
let idx = schema.items.length;
|
|
12082
12465
|
while (idx--) {
|
|
12083
12466
|
report.path.push('items');
|
|
12084
|
-
report.path.push(idx
|
|
12085
|
-
validateSchema
|
|
12467
|
+
report.path.push(idx);
|
|
12468
|
+
this.validateSchema(report, schema.items[idx]);
|
|
12086
12469
|
report.path.pop();
|
|
12087
12470
|
report.path.pop();
|
|
12088
12471
|
}
|
|
@@ -12167,9 +12550,9 @@ const SchemaValidators = {
|
|
|
12167
12550
|
if (type !== 'boolean' && type !== 'object') {
|
|
12168
12551
|
report.addError('KEYWORD_TYPE_EXPECTED', ['additionalProperties', ['boolean', 'object']]);
|
|
12169
12552
|
}
|
|
12170
|
-
else if (
|
|
12553
|
+
else if (isObject(schema.additionalProperties)) {
|
|
12171
12554
|
report.path.push('additionalProperties');
|
|
12172
|
-
validateSchema
|
|
12555
|
+
this.validateSchema(report, schema.additionalProperties);
|
|
12173
12556
|
report.path.pop();
|
|
12174
12557
|
}
|
|
12175
12558
|
},
|
|
@@ -12182,10 +12565,11 @@ const SchemaValidators = {
|
|
|
12182
12565
|
const keys = Object.keys(schema.properties);
|
|
12183
12566
|
let idx = keys.length;
|
|
12184
12567
|
while (idx--) {
|
|
12185
|
-
const key = keys[idx]
|
|
12568
|
+
const key = keys[idx];
|
|
12569
|
+
const val = schema.properties[key];
|
|
12186
12570
|
report.path.push('properties');
|
|
12187
12571
|
report.path.push(key);
|
|
12188
|
-
validateSchema
|
|
12572
|
+
this.validateSchema(report, val);
|
|
12189
12573
|
report.path.pop();
|
|
12190
12574
|
report.path.pop();
|
|
12191
12575
|
}
|
|
@@ -12219,8 +12603,8 @@ const SchemaValidators = {
|
|
|
12219
12603
|
report.addError('KEYWORD_PATTERN', ['patternProperties', key]);
|
|
12220
12604
|
}
|
|
12221
12605
|
report.path.push('patternProperties');
|
|
12222
|
-
report.path.push(key
|
|
12223
|
-
validateSchema
|
|
12606
|
+
report.path.push(key);
|
|
12607
|
+
this.validateSchema(report, val);
|
|
12224
12608
|
report.path.pop();
|
|
12225
12609
|
report.path.pop();
|
|
12226
12610
|
}
|
|
@@ -12238,11 +12622,13 @@ const SchemaValidators = {
|
|
|
12238
12622
|
const keys = Object.keys(schema.dependencies);
|
|
12239
12623
|
let idx = keys.length;
|
|
12240
12624
|
while (idx--) {
|
|
12241
|
-
const schemaKey = keys[idx]
|
|
12625
|
+
const schemaKey = keys[idx];
|
|
12626
|
+
const schemaDependency = schema.dependencies[schemaKey];
|
|
12627
|
+
const type = whatIs(schemaDependency);
|
|
12242
12628
|
if (type === 'object') {
|
|
12243
12629
|
report.path.push('dependencies');
|
|
12244
12630
|
report.path.push(schemaKey);
|
|
12245
|
-
validateSchema
|
|
12631
|
+
this.validateSchema(report, schemaDependency);
|
|
12246
12632
|
report.path.pop();
|
|
12247
12633
|
report.path.pop();
|
|
12248
12634
|
}
|
|
@@ -12280,8 +12666,10 @@ const SchemaValidators = {
|
|
|
12280
12666
|
},
|
|
12281
12667
|
type: function (report, schema) {
|
|
12282
12668
|
// http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.5.2.1
|
|
12283
|
-
const primitiveTypes = ['array', 'boolean', 'integer', 'number', 'null', 'object', 'string']
|
|
12284
|
-
|
|
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)) {
|
|
12285
12673
|
let idx = schema.type.length;
|
|
12286
12674
|
while (idx--) {
|
|
12287
12675
|
if (primitiveTypes.indexOf(schema.type[idx]) === -1) {
|
|
@@ -12375,8 +12763,8 @@ const SchemaValidators = {
|
|
|
12375
12763
|
let idx = schema.allOf.length;
|
|
12376
12764
|
while (idx--) {
|
|
12377
12765
|
report.path.push('allOf');
|
|
12378
|
-
report.path.push(idx
|
|
12379
|
-
validateSchema
|
|
12766
|
+
report.path.push(idx);
|
|
12767
|
+
this.validateSchema(report, schema.allOf[idx]);
|
|
12380
12768
|
report.path.pop();
|
|
12381
12769
|
report.path.pop();
|
|
12382
12770
|
}
|
|
@@ -12394,8 +12782,8 @@ const SchemaValidators = {
|
|
|
12394
12782
|
let idx = schema.anyOf.length;
|
|
12395
12783
|
while (idx--) {
|
|
12396
12784
|
report.path.push('anyOf');
|
|
12397
|
-
report.path.push(idx
|
|
12398
|
-
validateSchema
|
|
12785
|
+
report.path.push(idx);
|
|
12786
|
+
this.validateSchema(report, schema.anyOf[idx]);
|
|
12399
12787
|
report.path.pop();
|
|
12400
12788
|
report.path.pop();
|
|
12401
12789
|
}
|
|
@@ -12413,8 +12801,8 @@ const SchemaValidators = {
|
|
|
12413
12801
|
let idx = schema.oneOf.length;
|
|
12414
12802
|
while (idx--) {
|
|
12415
12803
|
report.path.push('oneOf');
|
|
12416
|
-
report.path.push(idx
|
|
12417
|
-
validateSchema
|
|
12804
|
+
report.path.push(idx);
|
|
12805
|
+
this.validateSchema(report, schema.oneOf[idx]);
|
|
12418
12806
|
report.path.pop();
|
|
12419
12807
|
report.path.pop();
|
|
12420
12808
|
}
|
|
@@ -12427,7 +12815,7 @@ const SchemaValidators = {
|
|
|
12427
12815
|
}
|
|
12428
12816
|
else {
|
|
12429
12817
|
report.path.push('not');
|
|
12430
|
-
validateSchema
|
|
12818
|
+
this.validateSchema(report, schema.not);
|
|
12431
12819
|
report.path.pop();
|
|
12432
12820
|
}
|
|
12433
12821
|
},
|
|
@@ -12443,7 +12831,7 @@ const SchemaValidators = {
|
|
|
12443
12831
|
const key = keys[idx], val = schema.definitions[key];
|
|
12444
12832
|
report.path.push('definitions');
|
|
12445
12833
|
report.path.push(key);
|
|
12446
|
-
validateSchema
|
|
12834
|
+
this.validateSchema(report, val);
|
|
12447
12835
|
report.path.pop();
|
|
12448
12836
|
report.path.pop();
|
|
12449
12837
|
}
|
|
@@ -12454,7 +12842,7 @@ const SchemaValidators = {
|
|
|
12454
12842
|
report.addError('KEYWORD_TYPE_EXPECTED', ['format', 'string']);
|
|
12455
12843
|
}
|
|
12456
12844
|
else {
|
|
12457
|
-
if (
|
|
12845
|
+
if (!isFormatSupported(schema.format) && this.options.ignoreUnknownFormats !== true) {
|
|
12458
12846
|
report.addError('UNKNOWN_FORMAT', [schema.format]);
|
|
12459
12847
|
}
|
|
12460
12848
|
}
|
|
@@ -12477,547 +12865,124 @@ const SchemaValidators = {
|
|
|
12477
12865
|
report.addError('KEYWORD_TYPE_EXPECTED', ['description', 'string']);
|
|
12478
12866
|
}
|
|
12479
12867
|
},
|
|
12480
|
-
default: function (
|
|
12868
|
+
default: function () {
|
|
12481
12869
|
// http://json-schema.org/latest/json-schema-validation.html#rfc.section.6.2
|
|
12482
12870
|
// There are no restrictions placed on the value of this keyword.
|
|
12483
12871
|
},
|
|
12484
12872
|
};
|
|
12485
|
-
|
|
12486
|
-
|
|
12487
|
-
|
|
12488
|
-
|
|
12489
|
-
*
|
|
12490
|
-
* @returns {boolean}
|
|
12491
|
-
*/
|
|
12492
|
-
const validateArrayOfSchemas = function (report, arr) {
|
|
12493
|
-
let idx = arr.length;
|
|
12494
|
-
while (idx--) {
|
|
12495
|
-
validateSchema.call(this, report, arr[idx]);
|
|
12873
|
+
class SchemaValidator {
|
|
12874
|
+
validator;
|
|
12875
|
+
constructor(validator) {
|
|
12876
|
+
this.validator = validator;
|
|
12496
12877
|
}
|
|
12497
|
-
|
|
12498
|
-
|
|
12499
|
-
/**
|
|
12500
|
-
*
|
|
12501
|
-
* @param {Report} report
|
|
12502
|
-
* @param {*} schema
|
|
12503
|
-
*/
|
|
12504
|
-
function validateSchema(report, schema) {
|
|
12505
|
-
report.commonErrorMessage = 'SCHEMA_VALIDATION_FAILED';
|
|
12506
|
-
// if schema is an array, assume it's an array of schemas
|
|
12507
|
-
if (Array.isArray(schema)) {
|
|
12508
|
-
return validateArrayOfSchemas.call(this, report, schema);
|
|
12878
|
+
get options() {
|
|
12879
|
+
return this.validator.options;
|
|
12509
12880
|
}
|
|
12510
|
-
|
|
12511
|
-
|
|
12512
|
-
return true;
|
|
12513
|
-
}
|
|
12514
|
-
// if $schema is present, this schema should validate against that $schema
|
|
12515
|
-
const hasParentSchema = schema.$schema && schema.id !== schema.$schema;
|
|
12516
|
-
if (hasParentSchema) {
|
|
12517
|
-
if (schema.__$schemaResolved && schema.__$schemaResolved !== schema) {
|
|
12518
|
-
const subReport = new Report(report);
|
|
12519
|
-
const valid = validate.call(this, subReport, schema.__$schemaResolved, schema);
|
|
12520
|
-
if (valid === false) {
|
|
12521
|
-
report.addError('PARENT_SCHEMA_VALIDATION_FAILED', null, subReport);
|
|
12522
|
-
}
|
|
12523
|
-
}
|
|
12524
|
-
else {
|
|
12525
|
-
if (this.options.ignoreUnresolvableReferences !== true) {
|
|
12526
|
-
report.addError('REF_UNRESOLVED', [schema.$schema]);
|
|
12527
|
-
}
|
|
12528
|
-
}
|
|
12529
|
-
}
|
|
12530
|
-
if (this.options.noTypeless === true) {
|
|
12531
|
-
// issue #36 - inherit type to anyOf, oneOf, allOf if noTypeless is defined
|
|
12532
|
-
if (schema.type !== undefined) {
|
|
12533
|
-
let schemas = [];
|
|
12534
|
-
if (Array.isArray(schema.anyOf)) {
|
|
12535
|
-
schemas = schemas.concat(schema.anyOf);
|
|
12536
|
-
}
|
|
12537
|
-
if (Array.isArray(schema.oneOf)) {
|
|
12538
|
-
schemas = schemas.concat(schema.oneOf);
|
|
12539
|
-
}
|
|
12540
|
-
if (Array.isArray(schema.allOf)) {
|
|
12541
|
-
schemas = schemas.concat(schema.allOf);
|
|
12542
|
-
}
|
|
12543
|
-
schemas.forEach(function (sch) {
|
|
12544
|
-
if (!sch.type) {
|
|
12545
|
-
sch.type = schema.type;
|
|
12546
|
-
}
|
|
12547
|
-
});
|
|
12548
|
-
}
|
|
12549
|
-
// end issue #36
|
|
12550
|
-
if (schema.enum === undefined &&
|
|
12551
|
-
schema.type === undefined &&
|
|
12552
|
-
schema.anyOf === undefined &&
|
|
12553
|
-
schema.oneOf === undefined &&
|
|
12554
|
-
schema.not === undefined &&
|
|
12555
|
-
schema.$ref === undefined) {
|
|
12556
|
-
report.addError('KEYWORD_UNDEFINED_STRICT', ['type']);
|
|
12557
|
-
}
|
|
12558
|
-
}
|
|
12559
|
-
const keys = Object.keys(schema);
|
|
12560
|
-
let idx = keys.length;
|
|
12561
|
-
while (idx--) {
|
|
12562
|
-
const key = keys[idx];
|
|
12563
|
-
if (key.indexOf('__') === 0) {
|
|
12564
|
-
continue;
|
|
12565
|
-
}
|
|
12566
|
-
if (SchemaValidators[key] !== undefined) {
|
|
12567
|
-
SchemaValidators[key].call(this, report, schema);
|
|
12568
|
-
}
|
|
12569
|
-
else if (!hasParentSchema) {
|
|
12570
|
-
if (this.options.noExtraKeywords === true) {
|
|
12571
|
-
report.addError('KEYWORD_UNEXPECTED', [key]);
|
|
12572
|
-
}
|
|
12573
|
-
}
|
|
12574
|
-
}
|
|
12575
|
-
if (this.options.pedanticCheck === true) {
|
|
12576
|
-
if (schema.enum) {
|
|
12577
|
-
// break recursion
|
|
12578
|
-
const tmpSchema = clone(schema);
|
|
12579
|
-
delete tmpSchema.enum;
|
|
12580
|
-
delete tmpSchema.default;
|
|
12581
|
-
report.path.push('enum');
|
|
12582
|
-
idx = schema.enum.length;
|
|
12583
|
-
while (idx--) {
|
|
12584
|
-
report.path.push(idx.toString());
|
|
12585
|
-
validate.call(this, report, tmpSchema, schema.enum[idx]);
|
|
12586
|
-
report.path.pop();
|
|
12587
|
-
}
|
|
12588
|
-
report.path.pop();
|
|
12589
|
-
}
|
|
12590
|
-
if (schema.default) {
|
|
12591
|
-
report.path.push('default');
|
|
12592
|
-
validate.call(this, report, schema, schema.default);
|
|
12593
|
-
report.path.pop();
|
|
12594
|
-
}
|
|
12595
|
-
}
|
|
12596
|
-
const isValid = report.isValid();
|
|
12597
|
-
if (isValid) {
|
|
12598
|
-
schema.__$validated = true;
|
|
12599
|
-
}
|
|
12600
|
-
return isValid;
|
|
12601
|
-
}
|
|
12602
|
-
|
|
12603
|
-
function decodeJSONPointer(str) {
|
|
12604
|
-
// http://tools.ietf.org/html/draft-ietf-appsawg-json-pointer-07#section-3
|
|
12605
|
-
return decodeURIComponent(str).replace(/~[0-1]/g, function (x) {
|
|
12606
|
-
return x === '~1' ? '/' : '~';
|
|
12607
|
-
});
|
|
12608
|
-
}
|
|
12609
|
-
function getRemotePath(uri) {
|
|
12610
|
-
const io = uri.indexOf('#');
|
|
12611
|
-
return io === -1 ? uri : uri.slice(0, io);
|
|
12612
|
-
}
|
|
12613
|
-
function getQueryPath(uri) {
|
|
12614
|
-
const io = uri.indexOf('#');
|
|
12615
|
-
const res = io === -1 ? undefined : uri.slice(io + 1);
|
|
12616
|
-
// WARN: do not slice slash, #/ means take root and go down from it
|
|
12617
|
-
// if (res && res[0] === "/") { res = res.slice(1); }
|
|
12618
|
-
return res;
|
|
12619
|
-
}
|
|
12620
|
-
function findId$1(schema, id) {
|
|
12621
|
-
// process only arrays and objects
|
|
12622
|
-
if (typeof schema !== 'object' || schema === null) {
|
|
12623
|
-
return;
|
|
12624
|
-
}
|
|
12625
|
-
// no id means root so return itself
|
|
12626
|
-
if (!id) {
|
|
12627
|
-
return schema;
|
|
12628
|
-
}
|
|
12629
|
-
if (schema.id) {
|
|
12630
|
-
if (schema.id === id || (schema.id[0] === '#' && schema.id.substring(1) === id)) {
|
|
12631
|
-
return schema;
|
|
12632
|
-
}
|
|
12633
|
-
}
|
|
12634
|
-
let idx, result;
|
|
12635
|
-
if (Array.isArray(schema)) {
|
|
12636
|
-
idx = schema.length;
|
|
12881
|
+
validateArrayOfSchemas(report, arr) {
|
|
12882
|
+
let idx = arr.length;
|
|
12637
12883
|
while (idx--) {
|
|
12638
|
-
|
|
12639
|
-
if (result) {
|
|
12640
|
-
return result;
|
|
12641
|
-
}
|
|
12884
|
+
this.validateSchema(report, arr[idx]);
|
|
12642
12885
|
}
|
|
12886
|
+
return report.isValid();
|
|
12643
12887
|
}
|
|
12644
|
-
|
|
12645
|
-
|
|
12646
|
-
|
|
12647
|
-
|
|
12648
|
-
|
|
12649
|
-
|
|
12650
|
-
|
|
12651
|
-
|
|
12652
|
-
|
|
12653
|
-
if (result) {
|
|
12654
|
-
return result;
|
|
12655
|
-
}
|
|
12656
|
-
}
|
|
12657
|
-
}
|
|
12658
|
-
}
|
|
12659
|
-
/**
|
|
12660
|
-
*
|
|
12661
|
-
* @param {*} uri
|
|
12662
|
-
* @param {*} schema
|
|
12663
|
-
*
|
|
12664
|
-
* @returns {void}
|
|
12665
|
-
*/
|
|
12666
|
-
function cacheSchemaByUri(uri, schema) {
|
|
12667
|
-
const remotePath = getRemotePath(uri);
|
|
12668
|
-
if (remotePath) {
|
|
12669
|
-
this.cache[remotePath] = schema;
|
|
12670
|
-
}
|
|
12671
|
-
}
|
|
12672
|
-
/**
|
|
12673
|
-
*
|
|
12674
|
-
* @param {*} uri
|
|
12675
|
-
*
|
|
12676
|
-
* @returns {void}
|
|
12677
|
-
*/
|
|
12678
|
-
function removeFromCacheByUri(uri) {
|
|
12679
|
-
const remotePath = getRemotePath(uri);
|
|
12680
|
-
if (remotePath) {
|
|
12681
|
-
delete this.cache[remotePath];
|
|
12682
|
-
}
|
|
12683
|
-
}
|
|
12684
|
-
/**
|
|
12685
|
-
*
|
|
12686
|
-
* @param {*} uri
|
|
12687
|
-
*
|
|
12688
|
-
* @returns {boolean}
|
|
12689
|
-
*/
|
|
12690
|
-
function checkCacheForUri(uri) {
|
|
12691
|
-
const remotePath = getRemotePath(uri);
|
|
12692
|
-
return remotePath ? this.cache[remotePath] != null : false;
|
|
12693
|
-
}
|
|
12694
|
-
function getSchema(report, schema) {
|
|
12695
|
-
if (typeof schema === 'object') {
|
|
12696
|
-
schema = getSchemaByReference.call(this, report, schema);
|
|
12697
|
-
}
|
|
12698
|
-
if (typeof schema === 'string') {
|
|
12699
|
-
schema = getSchemaByUri.call(this, report, schema);
|
|
12700
|
-
}
|
|
12701
|
-
return schema;
|
|
12702
|
-
}
|
|
12703
|
-
function getSchemaByReference(report, key) {
|
|
12704
|
-
let i = this.referenceCache.length;
|
|
12705
|
-
while (i--) {
|
|
12706
|
-
if (isequal(this.referenceCache[i][0], key)) {
|
|
12707
|
-
return this.referenceCache[i][1];
|
|
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;
|
|
12708
12897
|
}
|
|
12709
|
-
|
|
12710
|
-
|
|
12711
|
-
|
|
12712
|
-
|
|
12713
|
-
|
|
12714
|
-
|
|
12715
|
-
|
|
12716
|
-
|
|
12717
|
-
|
|
12718
|
-
let result = remotePath ? this.cache[remotePath] : root;
|
|
12719
|
-
if (result && remotePath) {
|
|
12720
|
-
// we need to avoid compiling schemas in a recursive loop
|
|
12721
|
-
const compileRemote = result !== root;
|
|
12722
|
-
// now we need to compile and validate resolved schema (in case it's not already)
|
|
12723
|
-
if (compileRemote) {
|
|
12724
|
-
report.path.push(remotePath);
|
|
12725
|
-
let remoteReport;
|
|
12726
|
-
const anscestorReport = report.getAncestor(result.id);
|
|
12727
|
-
if (anscestorReport) {
|
|
12728
|
-
remoteReport = anscestorReport;
|
|
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
|
+
}
|
|
12729
12907
|
}
|
|
12730
12908
|
else {
|
|
12731
|
-
|
|
12732
|
-
|
|
12733
|
-
const savedOptions = this.options;
|
|
12734
|
-
try {
|
|
12735
|
-
// If custom validationOptions were provided to setRemoteReference(),
|
|
12736
|
-
// use them instead of the default options
|
|
12737
|
-
this.options = result.__$validationOptions || this.options;
|
|
12738
|
-
validateSchema.call(this, remoteReport, result);
|
|
12739
|
-
}
|
|
12740
|
-
finally {
|
|
12741
|
-
this.options = savedOptions;
|
|
12742
|
-
}
|
|
12909
|
+
if (this.validator.options.ignoreUnresolvableReferences !== true) {
|
|
12910
|
+
report.addError('REF_UNRESOLVED', [schema.$schema]);
|
|
12743
12911
|
}
|
|
12744
12912
|
}
|
|
12745
|
-
const remoteReportIsValid = remoteReport.isValid();
|
|
12746
|
-
if (!remoteReportIsValid) {
|
|
12747
|
-
report.addError('REMOTE_NOT_VALID', [uri], remoteReport);
|
|
12748
|
-
}
|
|
12749
|
-
report.path.pop();
|
|
12750
|
-
if (!remoteReportIsValid) {
|
|
12751
|
-
return undefined;
|
|
12752
|
-
}
|
|
12753
12913
|
}
|
|
12754
|
-
|
|
12755
|
-
|
|
12756
|
-
|
|
12757
|
-
|
|
12758
|
-
|
|
12759
|
-
|
|
12760
|
-
|
|
12761
|
-
|
|
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
|
+
});
|
|
12762
12932
|
}
|
|
12763
|
-
|
|
12764
|
-
|
|
12765
|
-
|
|
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']);
|
|
12766
12941
|
}
|
|
12767
12942
|
}
|
|
12768
|
-
|
|
12769
|
-
|
|
12770
|
-
}
|
|
12771
|
-
|
|
12772
|
-
function mergeReference(scope, ref) {
|
|
12773
|
-
if (isAbsoluteUri(ref)) {
|
|
12774
|
-
return ref;
|
|
12775
|
-
}
|
|
12776
|
-
let joinedScope = scope.join('');
|
|
12777
|
-
const isScopeAbsolute = isAbsoluteUri(joinedScope);
|
|
12778
|
-
const isScopeRelative = isRelativeUri(joinedScope);
|
|
12779
|
-
const isRefRelative = isRelativeUri(ref);
|
|
12780
|
-
let toRemove;
|
|
12781
|
-
if (isScopeAbsolute && isRefRelative) {
|
|
12782
|
-
toRemove = joinedScope.match(/\/[^/]*$/);
|
|
12783
|
-
if (toRemove) {
|
|
12784
|
-
joinedScope = joinedScope.slice(0, toRemove.index + 1);
|
|
12785
|
-
}
|
|
12786
|
-
}
|
|
12787
|
-
else if (isScopeRelative && isRefRelative) {
|
|
12788
|
-
joinedScope = '';
|
|
12789
|
-
}
|
|
12790
|
-
else {
|
|
12791
|
-
toRemove = joinedScope.match(/[^#/]+$/);
|
|
12792
|
-
if (toRemove) {
|
|
12793
|
-
joinedScope = joinedScope.slice(0, toRemove.index);
|
|
12794
|
-
}
|
|
12795
|
-
}
|
|
12796
|
-
let res = joinedScope + ref;
|
|
12797
|
-
res = res.replace(/##/, '#');
|
|
12798
|
-
return res;
|
|
12799
|
-
}
|
|
12800
|
-
function collectReferences(obj, results, scope, path) {
|
|
12801
|
-
results = results || [];
|
|
12802
|
-
scope = scope || [];
|
|
12803
|
-
path = path || [];
|
|
12804
|
-
if (typeof obj !== 'object' || obj === null) {
|
|
12805
|
-
return results;
|
|
12806
|
-
}
|
|
12807
|
-
if (typeof obj.id === 'string') {
|
|
12808
|
-
scope.push(obj.id);
|
|
12809
|
-
}
|
|
12810
|
-
if (typeof obj.$ref === 'string' && typeof obj.__$refResolved === 'undefined') {
|
|
12811
|
-
results.push({
|
|
12812
|
-
ref: mergeReference(scope, obj.$ref),
|
|
12813
|
-
key: '$ref',
|
|
12814
|
-
obj: obj,
|
|
12815
|
-
path: path.slice(0),
|
|
12816
|
-
});
|
|
12817
|
-
}
|
|
12818
|
-
if (typeof obj.$schema === 'string' && typeof obj.__$schemaResolved === 'undefined') {
|
|
12819
|
-
results.push({
|
|
12820
|
-
ref: mergeReference(scope, obj.$schema),
|
|
12821
|
-
key: '$schema',
|
|
12822
|
-
obj: obj,
|
|
12823
|
-
path: path.slice(0),
|
|
12824
|
-
});
|
|
12825
|
-
}
|
|
12826
|
-
let idx;
|
|
12827
|
-
if (Array.isArray(obj)) {
|
|
12828
|
-
idx = obj.length;
|
|
12829
|
-
while (idx--) {
|
|
12830
|
-
path.push(idx.toString());
|
|
12831
|
-
collectReferences(obj[idx], results, scope, path);
|
|
12832
|
-
path.pop();
|
|
12833
|
-
}
|
|
12834
|
-
}
|
|
12835
|
-
else {
|
|
12836
|
-
const keys = Object.keys(obj);
|
|
12837
|
-
idx = keys.length;
|
|
12943
|
+
const keys = Object.keys(schema);
|
|
12944
|
+
let idx = keys.length;
|
|
12838
12945
|
while (idx--) {
|
|
12839
|
-
|
|
12840
|
-
if (
|
|
12946
|
+
const key = keys[idx];
|
|
12947
|
+
if (key.indexOf('__') === 0) {
|
|
12841
12948
|
continue;
|
|
12842
12949
|
}
|
|
12843
|
-
|
|
12844
|
-
|
|
12845
|
-
path.pop();
|
|
12846
|
-
}
|
|
12847
|
-
}
|
|
12848
|
-
if (typeof obj.id === 'string') {
|
|
12849
|
-
scope.pop();
|
|
12850
|
-
}
|
|
12851
|
-
return results;
|
|
12852
|
-
}
|
|
12853
|
-
const compileArrayOfSchemasLoop = function (mainReport, arr) {
|
|
12854
|
-
let idx = arr.length, compiledCount = 0;
|
|
12855
|
-
while (idx--) {
|
|
12856
|
-
// try to compile each schema separately
|
|
12857
|
-
const report = new Report(mainReport);
|
|
12858
|
-
const isValid = compileSchema.call(this, report, arr[idx]);
|
|
12859
|
-
if (isValid) {
|
|
12860
|
-
compiledCount++;
|
|
12861
|
-
}
|
|
12862
|
-
// copy errors to report
|
|
12863
|
-
mainReport.errors = mainReport.errors.concat(report.errors);
|
|
12864
|
-
}
|
|
12865
|
-
return compiledCount;
|
|
12866
|
-
};
|
|
12867
|
-
function findId(arr, id) {
|
|
12868
|
-
let idx = arr.length;
|
|
12869
|
-
while (idx--) {
|
|
12870
|
-
if (arr[idx].id === id) {
|
|
12871
|
-
return arr[idx];
|
|
12872
|
-
}
|
|
12873
|
-
}
|
|
12874
|
-
return null;
|
|
12875
|
-
}
|
|
12876
|
-
const compileArrayOfSchemas = function (report, arr) {
|
|
12877
|
-
let compiled = 0, lastLoopCompiled;
|
|
12878
|
-
do {
|
|
12879
|
-
// remove all UNRESOLVABLE_REFERENCE errors before compiling array again
|
|
12880
|
-
let idx = report.errors.length;
|
|
12881
|
-
while (idx--) {
|
|
12882
|
-
if (report.errors[idx].code === 'UNRESOLVABLE_REFERENCE') {
|
|
12883
|
-
report.errors.splice(idx, 1);
|
|
12950
|
+
if (Object.prototype.hasOwnProperty.call(SchemaValidators, key)) {
|
|
12951
|
+
SchemaValidators[key].call(this, report, schema);
|
|
12884
12952
|
}
|
|
12885
|
-
|
|
12886
|
-
|
|
12887
|
-
|
|
12888
|
-
// count how many are compiled now
|
|
12889
|
-
compiled = compileArrayOfSchemasLoop.call(this, report, arr);
|
|
12890
|
-
// fix __$missingReferences if possible
|
|
12891
|
-
idx = arr.length;
|
|
12892
|
-
while (idx--) {
|
|
12893
|
-
const sch = arr[idx];
|
|
12894
|
-
if (sch.__$missingReferences) {
|
|
12895
|
-
let idx2 = sch.__$missingReferences.length;
|
|
12896
|
-
while (idx2--) {
|
|
12897
|
-
const refObj = sch.__$missingReferences[idx2];
|
|
12898
|
-
const response = findId(arr, refObj.ref);
|
|
12899
|
-
if (response) {
|
|
12900
|
-
// this might create circular references
|
|
12901
|
-
refObj.obj['__' + refObj.key + 'Resolved'] = response;
|
|
12902
|
-
// it's resolved now so delete it
|
|
12903
|
-
sch.__$missingReferences.splice(idx2, 1);
|
|
12904
|
-
}
|
|
12905
|
-
}
|
|
12906
|
-
if (sch.__$missingReferences.length === 0) {
|
|
12907
|
-
delete sch.__$missingReferences;
|
|
12953
|
+
else if (!hasParentSchema) {
|
|
12954
|
+
if (this.validator.options.noExtraKeywords === true) {
|
|
12955
|
+
report.addError('KEYWORD_UNEXPECTED', [key]);
|
|
12908
12956
|
}
|
|
12909
12957
|
}
|
|
12910
12958
|
}
|
|
12911
|
-
|
|
12912
|
-
|
|
12913
|
-
|
|
12914
|
-
|
|
12915
|
-
|
|
12916
|
-
|
|
12917
|
-
|
|
12918
|
-
|
|
12919
|
-
|
|
12920
|
-
|
|
12921
|
-
|
|
12922
|
-
|
|
12923
|
-
}
|
|
12924
|
-
schema = loadedSchema;
|
|
12925
|
-
}
|
|
12926
|
-
// if schema is an array, assume it's an array of schemas
|
|
12927
|
-
if (Array.isArray(schema)) {
|
|
12928
|
-
return compileArrayOfSchemas.call(this, report, schema);
|
|
12929
|
-
}
|
|
12930
|
-
// if we have an id than it should be cached already (if this instance has compiled it)
|
|
12931
|
-
if (schema.__$compiled && schema.id && checkCacheForUri.call(this, schema.id) === false) {
|
|
12932
|
-
schema.__$compiled = undefined;
|
|
12933
|
-
}
|
|
12934
|
-
// do not re-compile schemas
|
|
12935
|
-
if (schema.__$compiled) {
|
|
12936
|
-
return true;
|
|
12937
|
-
}
|
|
12938
|
-
if (schema.id && typeof schema.id === 'string') {
|
|
12939
|
-
// add this to our schemaCache (before compilation in case we have references including id)
|
|
12940
|
-
cacheSchemaByUri.call(this, schema.id, schema);
|
|
12941
|
-
}
|
|
12942
|
-
// this method can be called recursively, so we need to remember our root
|
|
12943
|
-
let isRoot = false;
|
|
12944
|
-
if (!report.rootSchema) {
|
|
12945
|
-
report.rootSchema = schema;
|
|
12946
|
-
isRoot = true;
|
|
12947
|
-
}
|
|
12948
|
-
// delete all __$missingReferences from previous compilation attempts
|
|
12949
|
-
const isValidExceptReferences = report.isValid();
|
|
12950
|
-
delete schema.__$missingReferences;
|
|
12951
|
-
// collect all references that need to be resolved - $ref and $schema
|
|
12952
|
-
const refs = collectReferences.call(this, schema);
|
|
12953
|
-
let idx = refs.length;
|
|
12954
|
-
while (idx--) {
|
|
12955
|
-
// resolve all the collected references into __xxxResolved pointer
|
|
12956
|
-
const refObj = refs[idx];
|
|
12957
|
-
let response = getSchemaByUri.call(this, report, refObj.ref, schema);
|
|
12958
|
-
// we can try to use custom schemaReader if available
|
|
12959
|
-
if (!response) {
|
|
12960
|
-
const schemaReader = this.getSchemaReader();
|
|
12961
|
-
if (schemaReader) {
|
|
12962
|
-
// it's supposed to return a valid schema
|
|
12963
|
-
const s = schemaReader(refObj.ref);
|
|
12964
|
-
if (s) {
|
|
12965
|
-
// it needs to have the id
|
|
12966
|
-
s.id = refObj.ref;
|
|
12967
|
-
// try to compile the schema
|
|
12968
|
-
const subreport = new Report(report);
|
|
12969
|
-
if (!compileSchema.call(this, subreport, s)) {
|
|
12970
|
-
// copy errors to report
|
|
12971
|
-
report.errors = report.errors.concat(subreport.errors);
|
|
12972
|
-
}
|
|
12973
|
-
else {
|
|
12974
|
-
response = getSchemaByUri.call(this, report, refObj.ref, schema);
|
|
12975
|
-
}
|
|
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();
|
|
12976
12971
|
}
|
|
12972
|
+
report.path.pop();
|
|
12977
12973
|
}
|
|
12978
|
-
|
|
12979
|
-
|
|
12980
|
-
|
|
12981
|
-
|
|
12982
|
-
let isDownloaded = false;
|
|
12983
|
-
const ignoreUnresolvableRemotes = this.options.ignoreUnresolvableReferences === true;
|
|
12984
|
-
if (isAbsolute) {
|
|
12985
|
-
// we shouldn't add UNRESOLVABLE_REFERENCE for schemas we already have downloaded
|
|
12986
|
-
// and set through setRemoteReference method
|
|
12987
|
-
isDownloaded = checkCacheForUri.call(this, refObj.ref);
|
|
12988
|
-
}
|
|
12989
|
-
if (hasNotValid) ;
|
|
12990
|
-
else if (ignoreUnresolvableRemotes && isAbsolute) ;
|
|
12991
|
-
else if (isDownloaded) ;
|
|
12992
|
-
else {
|
|
12993
|
-
Array.prototype.push.apply(report.path, refObj.path);
|
|
12994
|
-
report.addError('UNRESOLVABLE_REFERENCE', [refObj.ref]);
|
|
12995
|
-
report.path = report.path.slice(0, -refObj.path.length);
|
|
12996
|
-
// pusblish unresolved references out
|
|
12997
|
-
if (isValidExceptReferences) {
|
|
12998
|
-
schema.__$missingReferences = schema.__$missingReferences || [];
|
|
12999
|
-
schema.__$missingReferences.push(refObj);
|
|
13000
|
-
}
|
|
12974
|
+
if (schema.default) {
|
|
12975
|
+
report.path.push('default');
|
|
12976
|
+
validate.call(this.validator, report, schema, schema.default);
|
|
12977
|
+
report.path.pop();
|
|
13001
12978
|
}
|
|
13002
12979
|
}
|
|
13003
|
-
|
|
13004
|
-
|
|
13005
|
-
|
|
13006
|
-
const isValid = report.isValid();
|
|
13007
|
-
if (isValid) {
|
|
13008
|
-
schema.__$compiled = true;
|
|
13009
|
-
}
|
|
13010
|
-
else {
|
|
13011
|
-
if (schema.id && typeof schema.id === 'string') {
|
|
13012
|
-
// remove this schema from schemaCache because it failed to compile
|
|
13013
|
-
removeFromCacheByUri.call(this, schema.id);
|
|
12980
|
+
const isValid = report.isValid();
|
|
12981
|
+
if (isValid) {
|
|
12982
|
+
schema.__$validated = true;
|
|
13014
12983
|
}
|
|
12984
|
+
return isValid;
|
|
13015
12985
|
}
|
|
13016
|
-
// we don't need the root pointer anymore
|
|
13017
|
-
if (isRoot) {
|
|
13018
|
-
report.rootSchema = undefined;
|
|
13019
|
-
}
|
|
13020
|
-
return isValid;
|
|
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,72 +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
|
-
/** Used by SchemaCache to break circular dependency with SchemaCompilation */
|
|
13565
|
-
_compileSchema(report, schema) {
|
|
13566
|
-
return compileSchema.call(this, report, schema);
|
|
13567
|
-
}
|
|
13568
|
-
/**
|
|
13569
|
-
* @param schema - JSON object representing schema
|
|
13570
|
-
* @returns {boolean} true if schema is valid.
|
|
13571
|
-
*/
|
|
13572
13514
|
validateSchema(schema) {
|
|
13573
13515
|
if (Array.isArray(schema) && schema.length === 0) {
|
|
13574
13516
|
throw new Error('.validateSchema was called with an empty array');
|
|
13575
13517
|
}
|
|
13576
13518
|
const report = new Report(this.options);
|
|
13577
|
-
schema = getSchema
|
|
13578
|
-
const compiled = compileSchema
|
|
13519
|
+
schema = this.scache.getSchema(report, schema);
|
|
13520
|
+
const compiled = this.sc.compileSchema(report, schema);
|
|
13579
13521
|
if (compiled) {
|
|
13580
|
-
validateSchema
|
|
13522
|
+
this.sv.validateSchema(report, schema);
|
|
13581
13523
|
}
|
|
13582
13524
|
this.lastReport = report;
|
|
13583
13525
|
return report.isValid();
|
|
@@ -13591,9 +13533,9 @@ class ZSchema {
|
|
|
13591
13533
|
options = {};
|
|
13592
13534
|
}
|
|
13593
13535
|
this.validateOptions = options;
|
|
13594
|
-
const
|
|
13595
|
-
if (
|
|
13596
|
-
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!');
|
|
13597
13539
|
if (callback) {
|
|
13598
13540
|
setTimeout(function () {
|
|
13599
13541
|
callback(e, false);
|
|
@@ -13605,19 +13547,20 @@ class ZSchema {
|
|
|
13605
13547
|
let foundError = false;
|
|
13606
13548
|
const report = new Report(this.options);
|
|
13607
13549
|
report.json = json;
|
|
13550
|
+
let _schema;
|
|
13608
13551
|
if (typeof schema === 'string') {
|
|
13609
13552
|
const schemaName = schema;
|
|
13610
|
-
|
|
13611
|
-
if (!
|
|
13553
|
+
_schema = this.scache.getSchema(report, schemaName);
|
|
13554
|
+
if (!_schema) {
|
|
13612
13555
|
throw new Error("Schema with id '" + schemaName + "' wasn't found in the validator cache!");
|
|
13613
13556
|
}
|
|
13614
13557
|
}
|
|
13615
13558
|
else {
|
|
13616
|
-
|
|
13559
|
+
_schema = this.scache.getSchema(report, schema);
|
|
13617
13560
|
}
|
|
13618
13561
|
let compiled = false;
|
|
13619
13562
|
if (!foundError) {
|
|
13620
|
-
compiled = compileSchema
|
|
13563
|
+
compiled = this.sc.compileSchema(report, _schema);
|
|
13621
13564
|
}
|
|
13622
13565
|
if (!compiled) {
|
|
13623
13566
|
this.lastReport = report;
|
|
@@ -13625,21 +13568,21 @@ class ZSchema {
|
|
|
13625
13568
|
}
|
|
13626
13569
|
let validated = false;
|
|
13627
13570
|
if (!foundError) {
|
|
13628
|
-
validated = validateSchema
|
|
13571
|
+
validated = this.sv.validateSchema(report, _schema);
|
|
13629
13572
|
}
|
|
13630
13573
|
if (!validated) {
|
|
13631
13574
|
this.lastReport = report;
|
|
13632
13575
|
foundError = true;
|
|
13633
13576
|
}
|
|
13634
13577
|
if (options.schemaPath) {
|
|
13635
|
-
report.rootSchema =
|
|
13636
|
-
|
|
13637
|
-
if (!
|
|
13578
|
+
report.rootSchema = _schema;
|
|
13579
|
+
_schema = get(_schema, options.schemaPath);
|
|
13580
|
+
if (!_schema) {
|
|
13638
13581
|
throw new Error("Schema path '" + options.schemaPath + "' wasn't found in the schema!");
|
|
13639
13582
|
}
|
|
13640
13583
|
}
|
|
13641
13584
|
if (!foundError) {
|
|
13642
|
-
validate.call(this, report,
|
|
13585
|
+
validate.call(this, report, _schema, json);
|
|
13643
13586
|
}
|
|
13644
13587
|
if (callback) {
|
|
13645
13588
|
report.processAsyncTasks(this.options.asyncTimeout, callback);
|
|
@@ -13656,6 +13599,9 @@ class ZSchema {
|
|
|
13656
13599
|
* Returns an Error object for the most recent failed validation, or null if the validation was successful.
|
|
13657
13600
|
*/
|
|
13658
13601
|
getLastError() {
|
|
13602
|
+
if (!this.lastReport) {
|
|
13603
|
+
throw new Error(`getLastError() called before doing any validation!`);
|
|
13604
|
+
}
|
|
13659
13605
|
if (this.lastReport.errors.length === 0) {
|
|
13660
13606
|
return null;
|
|
13661
13607
|
}
|
|
@@ -13673,27 +13619,29 @@ class ZSchema {
|
|
|
13673
13619
|
return this.lastReport && this.lastReport.errors.length > 0 ? this.lastReport.errors : null;
|
|
13674
13620
|
}
|
|
13675
13621
|
setRemoteReference(uri, schema, validationOptions) {
|
|
13622
|
+
let _schema;
|
|
13676
13623
|
if (typeof schema === 'string') {
|
|
13677
|
-
|
|
13624
|
+
_schema = JSON.parse(schema);
|
|
13678
13625
|
}
|
|
13679
13626
|
else {
|
|
13680
|
-
|
|
13627
|
+
_schema = deepClone(schema);
|
|
13681
13628
|
}
|
|
13682
13629
|
if (validationOptions) {
|
|
13683
|
-
|
|
13630
|
+
_schema.__$validationOptions = normalizeOptions(validationOptions);
|
|
13684
13631
|
}
|
|
13685
|
-
cacheSchemaByUri
|
|
13632
|
+
this.scache.cacheSchemaByUri(uri, _schema);
|
|
13686
13633
|
}
|
|
13687
13634
|
compileSchema(schema) {
|
|
13688
13635
|
const report = new Report(this.options);
|
|
13689
|
-
schema = getSchema
|
|
13690
|
-
compileSchema
|
|
13636
|
+
schema = this.scache.getSchema(report, schema);
|
|
13637
|
+
this.sc.compileSchema(report, schema);
|
|
13691
13638
|
this.lastReport = report;
|
|
13692
13639
|
return report.isValid();
|
|
13693
13640
|
}
|
|
13694
13641
|
getMissingReferences(arr) {
|
|
13695
|
-
arr = arr || this.lastReport
|
|
13696
|
-
let res = []
|
|
13642
|
+
arr = arr || this.lastReport?.errors || [];
|
|
13643
|
+
let res = [];
|
|
13644
|
+
let idx = arr.length;
|
|
13697
13645
|
while (idx--) {
|
|
13698
13646
|
const error = arr[idx];
|
|
13699
13647
|
if (error.code === 'UNRESOLVABLE_REFERENCE') {
|
|
@@ -13722,11 +13670,10 @@ class ZSchema {
|
|
|
13722
13670
|
}
|
|
13723
13671
|
getResolvedSchema(schema) {
|
|
13724
13672
|
const report = new Report(this.options);
|
|
13725
|
-
schema = getSchema
|
|
13673
|
+
schema = this.scache.getSchema(report, schema);
|
|
13726
13674
|
// clone before making any modifications
|
|
13727
|
-
schema =
|
|
13675
|
+
schema = deepClone(schema);
|
|
13728
13676
|
const visited = [];
|
|
13729
|
-
// clean-up the schema and resolve references
|
|
13730
13677
|
const cleanup = function (schema) {
|
|
13731
13678
|
let key;
|
|
13732
13679
|
const typeOf = whatIs(schema);
|