z-schema 6.0.2 → 7.0.0-beta.1
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 +154 -134
- package/bin/z-schema +128 -124
- package/dist/Errors.js +50 -0
- package/dist/FormatValidators.js +136 -0
- package/{src → dist}/JsonValidation.js +184 -213
- package/dist/Report.js +220 -0
- package/{src → dist}/SchemaCache.js +67 -82
- package/{src → dist}/SchemaCompilation.js +89 -129
- package/dist/SchemaValidation.js +631 -0
- package/{src → dist}/Utils.js +96 -104
- package/dist/ZSchema-umd-min.js +1 -0
- package/dist/ZSchema-umd.js +13791 -0
- package/dist/ZSchema.cjs +13785 -0
- package/dist/ZSchema.js +366 -0
- package/dist/schemas/hyper-schema.json +156 -0
- package/dist/schemas/schema.json +151 -0
- package/dist/types/Errors.d.ts +44 -0
- package/dist/types/FormatValidators.d.ts +12 -0
- package/dist/types/JsonValidation.d.ts +37 -0
- package/dist/types/Report.d.ts +87 -0
- package/dist/types/SchemaCache.d.ts +26 -0
- package/dist/types/SchemaCompilation.d.ts +1 -0
- package/dist/types/SchemaValidation.d.ts +6 -0
- package/dist/types/Utils.d.ts +64 -0
- package/dist/types/ZSchema.d.ts +97 -0
- package/package.json +54 -43
- package/src/Errors.ts +56 -0
- package/src/FormatValidators.ts +136 -0
- package/src/JsonValidation.ts +624 -0
- package/src/Report.ts +337 -0
- package/src/SchemaCache.ts +189 -0
- package/src/SchemaCompilation.ts +293 -0
- package/src/SchemaValidation.ts +629 -0
- package/src/Utils.ts +286 -0
- package/src/ZSchema.ts +469 -0
- package/src/schemas/_ +0 -0
- package/dist/ZSchema-browser-min.js +0 -2
- package/dist/ZSchema-browser-min.js.map +0 -1
- package/dist/ZSchema-browser-test.js +0 -32247
- package/dist/ZSchema-browser.js +0 -12745
- package/index.d.ts +0 -175
- package/src/Errors.js +0 -60
- package/src/FormatValidators.js +0 -129
- package/src/Polyfills.js +0 -16
- package/src/Report.js +0 -299
- package/src/SchemaValidation.js +0 -619
- package/src/ZSchema.js +0 -409
package/bin/z-schema
CHANGED
|
@@ -3,45 +3,52 @@
|
|
|
3
3
|
// set default exitCode for node 0.10
|
|
4
4
|
process.exitCode = 0;
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
6
|
+
import fs from 'fs';
|
|
7
|
+
import path from 'path';
|
|
8
|
+
import { program } from 'commander';
|
|
9
|
+
import { request } from 'https';
|
|
10
|
+
import pkg from '../package.json' with { type: 'json' };
|
|
11
|
+
import ZSchema from '../dist/ZSchema.js';
|
|
12
12
|
|
|
13
13
|
program
|
|
14
|
-
.version(
|
|
15
|
-
.usage(
|
|
16
|
-
.option(
|
|
17
|
-
.option(
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
.option(
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
.option(
|
|
26
|
-
.option(
|
|
27
|
-
.option(
|
|
28
|
-
.option(
|
|
29
|
-
.option(
|
|
30
|
-
.option(
|
|
31
|
-
.option(
|
|
32
|
-
.option(
|
|
33
|
-
.option(
|
|
34
|
-
.option(
|
|
35
|
-
.option(
|
|
14
|
+
.version(pkg.version)
|
|
15
|
+
.usage('[options] <schema> <json1?> <json2?> <json3?>')
|
|
16
|
+
.option('--asyncTimeout <n>', 'default timeout for all async tasks', parseInt)
|
|
17
|
+
.option(
|
|
18
|
+
'--forceAdditional',
|
|
19
|
+
'force additionalProperties and additionalItems to be defined on "object" and "array" types'
|
|
20
|
+
)
|
|
21
|
+
.option(
|
|
22
|
+
'--assumeAdditional',
|
|
23
|
+
'assume additionalProperties and additionalItems are defined as "false" where appropriate'
|
|
24
|
+
)
|
|
25
|
+
.option('--forceItems', 'force items to be defined on "array" types')
|
|
26
|
+
.option('--forceMinItems', 'force minItems to be defined on "array" types')
|
|
27
|
+
.option('--forceMaxItems', 'force maxItems to be defined on "array" types')
|
|
28
|
+
.option('--forceMinLength', 'force minLength to be defined on "string" types')
|
|
29
|
+
.option('--forceMaxLength', 'force maxLength to be defined on "string" types')
|
|
30
|
+
.option('--forceProperties', 'force properties or patternProperties to be defined on "object" types')
|
|
31
|
+
.option('--ignoreUnresolvableReferences', 'ignore references that cannot be resolved (remote schemas)')
|
|
32
|
+
.option('--noExtraKeywords', "disallow usage of keywords that this validator can't handle")
|
|
33
|
+
.option('--noTypeless', 'disallow usage of schema\'s without "type" defined')
|
|
34
|
+
.option('--noEmptyStrings', 'disallow zero length strings in validated objects')
|
|
35
|
+
.option('--noEmptyArrays', 'disallow zero length arrays in validated objects')
|
|
36
|
+
.option('--strictUris', 'forces "uri" format to be in fully rfc3986 compliant')
|
|
37
|
+
.option('--strictMode', 'turn on some of the above')
|
|
38
|
+
.option('--reportPathAsArray', 'report error paths as an array of path segments to get to the offending node')
|
|
39
|
+
.option('--breakOnFirstError', 'stops validation as soon as an error is found, true by default but can be turned off')
|
|
40
|
+
.option('--pedanticCheck', 'check if schema follow best practices and common sence')
|
|
41
|
+
.option('--ignoreUnknownFormats', 'ignore unknown formats (do not report them as an error)')
|
|
42
|
+
.allowExcessArguments()
|
|
36
43
|
.parse(process.argv);
|
|
37
|
-
|
|
38
|
-
var options = {};
|
|
44
|
+
|
|
45
|
+
var options = {};
|
|
39
46
|
var defaultOptions = ZSchema.getDefaultOptions();
|
|
40
47
|
|
|
41
48
|
for (var key in defaultOptions) {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
49
|
+
if (program[key]) {
|
|
50
|
+
options[key] = program[key];
|
|
51
|
+
}
|
|
45
52
|
}
|
|
46
53
|
|
|
47
54
|
if (!program.args.length) {
|
|
@@ -49,20 +56,20 @@ if (!program.args.length) {
|
|
|
49
56
|
}
|
|
50
57
|
|
|
51
58
|
function readJson(fileName) {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
59
|
+
var ret;
|
|
60
|
+
try {
|
|
61
|
+
ret = fs.readFileSync(fileName, { encoding: 'utf8' });
|
|
62
|
+
} catch (e) {
|
|
63
|
+
console.error(e);
|
|
64
|
+
throw new Error("Couldn't read the file: " + fileName);
|
|
65
|
+
}
|
|
66
|
+
try {
|
|
67
|
+
ret = JSON.parse(ret);
|
|
68
|
+
} catch (e) {
|
|
69
|
+
console.error(e);
|
|
70
|
+
throw new Error("Couldn't parse the file as JSON: " + fileName);
|
|
71
|
+
}
|
|
72
|
+
return ret;
|
|
66
73
|
}
|
|
67
74
|
|
|
68
75
|
var validator = new ZSchema(options);
|
|
@@ -70,100 +77,97 @@ var schemaFilePath = program.args.shift();
|
|
|
70
77
|
var schema = readJson(schemaFilePath);
|
|
71
78
|
|
|
72
79
|
function validateWithAutomaticDownloads(filePath, data, schema, callback) {
|
|
80
|
+
var lastResult;
|
|
73
81
|
|
|
74
|
-
|
|
82
|
+
function finish() {
|
|
83
|
+
callback(validator.getLastErrors(), lastResult);
|
|
84
|
+
}
|
|
75
85
|
|
|
76
|
-
|
|
77
|
-
|
|
86
|
+
function validate() {
|
|
87
|
+
if (data !== undefined) {
|
|
88
|
+
lastResult = validator.validate(data, schema);
|
|
89
|
+
} else {
|
|
90
|
+
lastResult = validator.validateSchema(schema);
|
|
78
91
|
}
|
|
79
92
|
|
|
80
|
-
|
|
93
|
+
// console.log(lastResult);
|
|
94
|
+
// console.log(JSON.stringify(validator.getLastErrors(), null, 4));
|
|
81
95
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
console.log(urlString + response.statusCode);
|
|
104
|
-
|
|
105
|
-
validator.setRemoteReference(url, JSON.parse(body));
|
|
106
|
-
finished++;
|
|
107
|
-
if (finished === missingReferences.length) {
|
|
108
|
-
validate();
|
|
109
|
-
}
|
|
110
|
-
});
|
|
111
|
-
}).on("error", function (error) {
|
|
112
|
-
console.error(urlString);
|
|
113
|
-
console.error(error);
|
|
114
|
-
process.exit(1);
|
|
115
|
-
});
|
|
116
|
-
} else {
|
|
117
|
-
// FUTURE: maybe else if (isFile(url)) later
|
|
118
|
-
var referencePath = path.resolve(process.cwd(), path.dirname(filePath), url);
|
|
119
|
-
var reference = readJson(referencePath);
|
|
120
|
-
validator.setRemoteReference(url, reference);
|
|
121
|
-
finished++;
|
|
122
|
-
if (finished === missingReferences.length) {
|
|
123
|
-
validate();
|
|
124
|
-
}
|
|
125
|
-
}
|
|
96
|
+
var missingReferences = validator.getMissingRemoteReferences();
|
|
97
|
+
if (missingReferences.length > 0) {
|
|
98
|
+
var finished = 0;
|
|
99
|
+
missingReferences.forEach(function (url) {
|
|
100
|
+
var urlString = 'request: ' + url + ' - ';
|
|
101
|
+
|
|
102
|
+
if (url.match(/^https?:/)) {
|
|
103
|
+
request(url, function (response) {
|
|
104
|
+
var body = '';
|
|
105
|
+
response.on('data', function (chunk) {
|
|
106
|
+
data += chunk;
|
|
107
|
+
});
|
|
108
|
+
response.on('end', function () {
|
|
109
|
+
console.log(urlString + response.statusCode);
|
|
110
|
+
|
|
111
|
+
validator.setRemoteReference(url, JSON.parse(body));
|
|
112
|
+
finished++;
|
|
113
|
+
if (finished === missingReferences.length) {
|
|
114
|
+
validate();
|
|
115
|
+
}
|
|
126
116
|
});
|
|
117
|
+
}).on('error', function (error) {
|
|
118
|
+
console.error(urlString);
|
|
119
|
+
console.error(error);
|
|
120
|
+
process.exit(1);
|
|
121
|
+
});
|
|
127
122
|
} else {
|
|
128
|
-
|
|
123
|
+
// FUTURE: maybe else if (isFile(url)) later
|
|
124
|
+
var referencePath = path.resolve(process.cwd(), path.dirname(filePath), url);
|
|
125
|
+
var reference = readJson(referencePath);
|
|
126
|
+
validator.setRemoteReference(url, reference);
|
|
127
|
+
finished++;
|
|
128
|
+
if (finished === missingReferences.length) {
|
|
129
|
+
validate();
|
|
130
|
+
}
|
|
129
131
|
}
|
|
130
|
-
|
|
132
|
+
});
|
|
133
|
+
} else {
|
|
134
|
+
finish();
|
|
131
135
|
}
|
|
136
|
+
}
|
|
132
137
|
|
|
133
|
-
|
|
134
|
-
|
|
138
|
+
validate();
|
|
135
139
|
}
|
|
136
140
|
|
|
137
141
|
var i = 0;
|
|
138
142
|
function validateJsons() {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
143
|
+
if (program.args.length === 0) {
|
|
144
|
+
process.exit(process.exitCode);
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
i++;
|
|
148
|
+
|
|
149
|
+
var filePath = program.args.shift();
|
|
150
|
+
var json = readJson(filePath);
|
|
151
|
+
validateWithAutomaticDownloads(filePath, json, schema, function (errs, isValid) {
|
|
152
|
+
if (!isValid) {
|
|
153
|
+
console.log(JSON.stringify(validator.getLastErrors(), null, 4));
|
|
154
|
+
console.log('json #' + i + ' validation failed');
|
|
155
|
+
process.exitCode = 1;
|
|
156
|
+
} else {
|
|
157
|
+
console.log('json #' + i + ' validation passed');
|
|
142
158
|
}
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
var filePath = program.args.shift();
|
|
146
|
-
var json = readJson(filePath);
|
|
147
|
-
validateWithAutomaticDownloads(filePath, json, schema, function (errs, isValid) {
|
|
148
|
-
if (!isValid) {
|
|
149
|
-
console.log(JSON.stringify(validator.getLastErrors(), null, 4));
|
|
150
|
-
console.log("json #" + i + " validation failed");
|
|
151
|
-
process.exitCode = 1;
|
|
152
|
-
} else {
|
|
153
|
-
console.log("json #" + i + " validation passed");
|
|
154
|
-
}
|
|
155
|
-
validateJsons();
|
|
156
|
-
});
|
|
159
|
+
validateJsons();
|
|
160
|
+
});
|
|
157
161
|
}
|
|
158
162
|
|
|
159
163
|
// validate schema
|
|
160
164
|
validateWithAutomaticDownloads(schemaFilePath, undefined, schema, function (errs, isValid) {
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
165
|
+
if (!isValid) {
|
|
166
|
+
console.log(JSON.stringify(validator.getLastErrors(), null, 4));
|
|
167
|
+
console.log('schema validation failed');
|
|
168
|
+
process.exit(1);
|
|
169
|
+
} else {
|
|
170
|
+
console.log('schema validation passed');
|
|
171
|
+
validateJsons();
|
|
172
|
+
}
|
|
169
173
|
});
|
package/dist/Errors.js
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
export const Errors = {
|
|
2
|
+
INVALID_TYPE: 'Expected type {0} but found type {1}',
|
|
3
|
+
INVALID_FORMAT: "Object didn't pass validation for format {0}: {1}",
|
|
4
|
+
ENUM_MISMATCH: 'No enum match for: {0}',
|
|
5
|
+
ENUM_CASE_MISMATCH: 'Enum does not match case for: {0}',
|
|
6
|
+
ANY_OF_MISSING: "Data does not match any schemas from 'anyOf'",
|
|
7
|
+
ONE_OF_MISSING: "Data does not match any schemas from 'oneOf'",
|
|
8
|
+
ONE_OF_MULTIPLE: "Data is valid against more than one schema from 'oneOf'",
|
|
9
|
+
NOT_PASSED: "Data matches schema from 'not'",
|
|
10
|
+
// Array errors
|
|
11
|
+
ARRAY_LENGTH_SHORT: 'Array is too short ({0}), minimum {1}',
|
|
12
|
+
ARRAY_LENGTH_LONG: 'Array is too long ({0}), maximum {1}',
|
|
13
|
+
ARRAY_UNIQUE: 'Array items are not unique (indexes {0} and {1})',
|
|
14
|
+
ARRAY_ADDITIONAL_ITEMS: 'Additional items not allowed',
|
|
15
|
+
// Numeric errors
|
|
16
|
+
MULTIPLE_OF: 'Value {0} is not a multiple of {1}',
|
|
17
|
+
MINIMUM: 'Value {0} is less than minimum {1}',
|
|
18
|
+
MINIMUM_EXCLUSIVE: 'Value {0} is equal or less than exclusive minimum {1}',
|
|
19
|
+
MAXIMUM: 'Value {0} is greater than maximum {1}',
|
|
20
|
+
MAXIMUM_EXCLUSIVE: 'Value {0} is equal or greater than exclusive maximum {1}',
|
|
21
|
+
// Object errors
|
|
22
|
+
OBJECT_PROPERTIES_MINIMUM: 'Too few properties defined ({0}), minimum {1}',
|
|
23
|
+
OBJECT_PROPERTIES_MAXIMUM: 'Too many properties defined ({0}), maximum {1}',
|
|
24
|
+
OBJECT_MISSING_REQUIRED_PROPERTY: 'Missing required property: {0}',
|
|
25
|
+
OBJECT_ADDITIONAL_PROPERTIES: 'Additional properties not allowed: {0}',
|
|
26
|
+
OBJECT_DEPENDENCY_KEY: 'Dependency failed - key must exist: {0} (due to key: {1})',
|
|
27
|
+
// String errors
|
|
28
|
+
MIN_LENGTH: 'String is too short ({0} chars), minimum {1}',
|
|
29
|
+
MAX_LENGTH: 'String is too long ({0} chars), maximum {1}',
|
|
30
|
+
PATTERN: 'String does not match pattern {0}: {1}',
|
|
31
|
+
// Schema validation errors
|
|
32
|
+
KEYWORD_TYPE_EXPECTED: "Keyword '{0}' is expected to be of type '{1}'",
|
|
33
|
+
KEYWORD_UNDEFINED_STRICT: "Keyword '{0}' must be defined in strict mode",
|
|
34
|
+
KEYWORD_UNEXPECTED: "Keyword '{0}' is not expected to appear in the schema",
|
|
35
|
+
KEYWORD_MUST_BE: "Keyword '{0}' must be {1}",
|
|
36
|
+
KEYWORD_DEPENDENCY: "Keyword '{0}' requires keyword '{1}'",
|
|
37
|
+
KEYWORD_PATTERN: "Keyword '{0}' is not a valid RegExp pattern: {1}",
|
|
38
|
+
KEYWORD_VALUE_TYPE: "Each element of keyword '{0}' array must be a '{1}'",
|
|
39
|
+
UNKNOWN_FORMAT: "There is no validation function for format '{0}'",
|
|
40
|
+
CUSTOM_MODE_FORCE_PROPERTIES: '{0} must define at least one property if present',
|
|
41
|
+
// Remote errors
|
|
42
|
+
REF_UNRESOLVED: 'Reference has not been resolved during compilation: {0}',
|
|
43
|
+
UNRESOLVABLE_REFERENCE: 'Reference could not be resolved: {0}',
|
|
44
|
+
SCHEMA_NOT_REACHABLE: 'Validator was not able to read schema with uri: {0}',
|
|
45
|
+
SCHEMA_TYPE_EXPECTED: "Schema is expected to be of type 'object'",
|
|
46
|
+
SCHEMA_NOT_AN_OBJECT: 'Schema is not an object: {0}',
|
|
47
|
+
ASYNC_TIMEOUT: '{0} asynchronous task(s) have timed out after {1} ms',
|
|
48
|
+
PARENT_SCHEMA_VALIDATION_FAILED: 'Schema failed to validate against its parent schema, see inner errors for details.',
|
|
49
|
+
REMOTE_NOT_VALID: "Remote reference didn't compile successfully: {0}",
|
|
50
|
+
};
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import validator from 'validator';
|
|
2
|
+
export const FormatValidators = {
|
|
3
|
+
date: function (date) {
|
|
4
|
+
if (typeof date !== 'string') {
|
|
5
|
+
return true;
|
|
6
|
+
}
|
|
7
|
+
// full-date from http://tools.ietf.org/html/rfc3339#section-5.6
|
|
8
|
+
const matches = /^([0-9]{4})-([0-9]{2})-([0-9]{2})$/.exec(date);
|
|
9
|
+
if (matches === null) {
|
|
10
|
+
return false;
|
|
11
|
+
}
|
|
12
|
+
// var year = matches[1];
|
|
13
|
+
// var month = matches[2];
|
|
14
|
+
// var day = matches[3];
|
|
15
|
+
if (matches[2] < '01' || matches[2] > '12' || matches[3] < '01' || matches[3] > '31') {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
return true;
|
|
19
|
+
},
|
|
20
|
+
'date-time': function (dateTime) {
|
|
21
|
+
if (typeof dateTime !== 'string') {
|
|
22
|
+
return true;
|
|
23
|
+
}
|
|
24
|
+
// date-time from http://tools.ietf.org/html/rfc3339#section-5.6
|
|
25
|
+
const s = dateTime.toLowerCase().split('t');
|
|
26
|
+
if (!FormatValidators.date(s[0])) {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
const matches = /^([0-9]{2}):([0-9]{2}):([0-9]{2})(.[0-9]+)?(z|([+-][0-9]{2}:[0-9]{2}))$/.exec(s[1]);
|
|
30
|
+
if (matches === null) {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
// var hour = matches[1];
|
|
34
|
+
// var minute = matches[2];
|
|
35
|
+
// var second = matches[3];
|
|
36
|
+
// var fraction = matches[4];
|
|
37
|
+
// var timezone = matches[5];
|
|
38
|
+
if (matches[1] > '23' || matches[2] > '59' || matches[3] > '59') {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
return true;
|
|
42
|
+
},
|
|
43
|
+
email: function (email) {
|
|
44
|
+
if (typeof email !== 'string') {
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
return validator.isEmail(email, { require_tld: true });
|
|
48
|
+
},
|
|
49
|
+
hostname: function (hostname) {
|
|
50
|
+
if (typeof hostname !== 'string') {
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
/*
|
|
54
|
+
http://json-schema.org/latest/json-schema-validation.html#anchor114
|
|
55
|
+
A string instance is valid against this attribute if it is a valid
|
|
56
|
+
representation for an Internet host name, as defined by RFC 1034, section 3.1 [RFC1034].
|
|
57
|
+
|
|
58
|
+
http://tools.ietf.org/html/rfc1034#section-3.5
|
|
59
|
+
|
|
60
|
+
<digit> ::= any one of the ten digits 0 through 9
|
|
61
|
+
var digit = /[0-9]/;
|
|
62
|
+
|
|
63
|
+
<letter> ::= any one of the 52 alphabetic characters A through Z in upper case and a through z in lower case
|
|
64
|
+
var letter = /[a-zA-Z]/;
|
|
65
|
+
|
|
66
|
+
<let-dig> ::= <letter> | <digit>
|
|
67
|
+
var letDig = /[0-9a-zA-Z]/;
|
|
68
|
+
|
|
69
|
+
<let-dig-hyp> ::= <let-dig> | "-"
|
|
70
|
+
var letDigHyp = /[-0-9a-zA-Z]/;
|
|
71
|
+
|
|
72
|
+
<ldh-str> ::= <let-dig-hyp> | <let-dig-hyp> <ldh-str>
|
|
73
|
+
var ldhStr = /[-0-9a-zA-Z]+/;
|
|
74
|
+
|
|
75
|
+
<label> ::= <letter> [ [ <ldh-str> ] <let-dig> ]
|
|
76
|
+
var label = /[a-zA-Z](([-0-9a-zA-Z]+)?[0-9a-zA-Z])?/;
|
|
77
|
+
|
|
78
|
+
<subdomain> ::= <label> | <subdomain> "." <label>
|
|
79
|
+
var subdomain = /^[a-zA-Z](([-0-9a-zA-Z]+)?[0-9a-zA-Z])?(\.[a-zA-Z](([-0-9a-zA-Z]+)?[0-9a-zA-Z])?)*$/;
|
|
80
|
+
|
|
81
|
+
<domain> ::= <subdomain> | " "
|
|
82
|
+
var domain = null;
|
|
83
|
+
*/
|
|
84
|
+
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);
|
|
85
|
+
if (valid) {
|
|
86
|
+
// the sum of all label octets and label lengths is limited to 255.
|
|
87
|
+
if (hostname.length > 255) {
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
// Each node has a label, which is zero to 63 octets in length
|
|
91
|
+
const labels = hostname.split('.');
|
|
92
|
+
for (let i = 0; i < labels.length; i++) {
|
|
93
|
+
if (labels[i].length > 63) {
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return valid;
|
|
99
|
+
},
|
|
100
|
+
'host-name': function (hostname) {
|
|
101
|
+
return FormatValidators.hostname.call(this, hostname);
|
|
102
|
+
},
|
|
103
|
+
ipv4: function (ipv4) {
|
|
104
|
+
if (typeof ipv4 !== 'string') {
|
|
105
|
+
return true;
|
|
106
|
+
}
|
|
107
|
+
return validator.isIP(ipv4, 4);
|
|
108
|
+
},
|
|
109
|
+
ipv6: function (ipv6) {
|
|
110
|
+
if (typeof ipv6 !== 'string') {
|
|
111
|
+
return true;
|
|
112
|
+
}
|
|
113
|
+
return validator.isIP(ipv6, 6);
|
|
114
|
+
},
|
|
115
|
+
regex: function (str) {
|
|
116
|
+
try {
|
|
117
|
+
RegExp(str);
|
|
118
|
+
return true;
|
|
119
|
+
}
|
|
120
|
+
catch (_e) {
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
uri: function (...args) {
|
|
125
|
+
if (this.options.strictUris) {
|
|
126
|
+
return FormatValidators['strict-uri'].apply(this, args);
|
|
127
|
+
}
|
|
128
|
+
const [uri] = args;
|
|
129
|
+
// https://github.com/zaggino/z-schema/issues/18
|
|
130
|
+
// RegExp from http://tools.ietf.org/html/rfc3986#appendix-B
|
|
131
|
+
return typeof uri !== 'string' || RegExp('^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?').test(uri);
|
|
132
|
+
},
|
|
133
|
+
'strict-uri': function (uri) {
|
|
134
|
+
return typeof uri !== 'string' || validator.isURL(uri);
|
|
135
|
+
},
|
|
136
|
+
};
|