z-schema 3.19.1 → 3.23.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "z-schema",
3
- "version": "3.19.1",
3
+ "version": "3.23.0",
4
4
  "description": "JSON schema validator",
5
5
  "homepage": "https://github.com/zaggino/z-schema",
6
6
  "authors": [
@@ -31,8 +31,8 @@
31
31
  "README.md"
32
32
  ],
33
33
  "scripts": {
34
- "prepublish": "grunt",
35
- "test": "grunt test && grunt lint"
34
+ "prepublish": "npm test && grunt",
35
+ "test": "jasmine-node test/ && grunt lint"
36
36
  },
37
37
  "testling": {
38
38
  "scripts": [
@@ -60,7 +60,7 @@
60
60
  "dependencies": {
61
61
  "lodash.get": "^4.0.0",
62
62
  "lodash.isequal": "^4.0.0",
63
- "validator": "^9.0.0"
63
+ "validator": "^10.0.0"
64
64
  },
65
65
  "optionalDependencies": {
66
66
  "commander": "^2.7.1"
@@ -74,8 +74,6 @@
74
74
  "grunt-contrib-jasmine": "^1.1.0",
75
75
  "grunt-contrib-jshint": "^1.1.0",
76
76
  "grunt-contrib-uglify": "^3.1.0",
77
- "grunt-jasmine-node": "^0.3.1",
78
- "grunt-jasmine-node-coverage": "^2.0.1",
79
77
  "grunt-jscs": "^3.0.1",
80
78
  "grunt-lineending": "^1.0.0",
81
79
  "jasmine-node": "^1.14.5",
package/src/Errors.js CHANGED
@@ -5,6 +5,7 @@ module.exports = {
5
5
  INVALID_TYPE: "Expected type {0} but found type {1}",
6
6
  INVALID_FORMAT: "Object didn't pass validation for format {0}: {1}",
7
7
  ENUM_MISMATCH: "No enum match for: {0}",
8
+ ENUM_CASE_MISMATCH: "Enum does not match case for: {0}",
8
9
  ANY_OF_MISSING: "Data does not match any schemas from 'anyOf'",
9
10
  ONE_OF_MISSING: "Data does not match any schemas from 'oneOf'",
10
11
  ONE_OF_MULTIPLE: "Data is valid against more than one schema from 'oneOf'",
@@ -1,8 +1,8 @@
1
1
  "use strict";
2
2
 
3
- var FormatValidators = require("./FormatValidators"),
4
- Report = require("./Report"),
5
- Utils = require("./Utils");
3
+ var FormatValidators = require("./FormatValidators"),
4
+ Report = require("./Report"),
5
+ Utils = require("./Utils");
6
6
 
7
7
  var JsonValidators = {
8
8
  multipleOf: function (report, schema, json) {
@@ -11,7 +11,7 @@ var JsonValidators = {
11
11
  return;
12
12
  }
13
13
  if (Utils.whatIs(json / schema.multipleOf) !== "integer") {
14
- report.addError("MULTIPLE_OF", [json, schema.multipleOf], null, schema.description);
14
+ report.addError("MULTIPLE_OF", [json, schema.multipleOf], null, schema);
15
15
  }
16
16
  },
17
17
  maximum: function (report, schema, json) {
@@ -21,11 +21,11 @@ var JsonValidators = {
21
21
  }
22
22
  if (schema.exclusiveMaximum !== true) {
23
23
  if (json > schema.maximum) {
24
- report.addError("MAXIMUM", [json, schema.maximum], null, schema.description);
24
+ report.addError("MAXIMUM", [json, schema.maximum], null, schema);
25
25
  }
26
26
  } else {
27
27
  if (json >= schema.maximum) {
28
- report.addError("MAXIMUM_EXCLUSIVE", [json, schema.maximum], null, schema.description);
28
+ report.addError("MAXIMUM_EXCLUSIVE", [json, schema.maximum], null, schema);
29
29
  }
30
30
  }
31
31
  },
@@ -39,11 +39,11 @@ var JsonValidators = {
39
39
  }
40
40
  if (schema.exclusiveMinimum !== true) {
41
41
  if (json < schema.minimum) {
42
- report.addError("MINIMUM", [json, schema.minimum], null, schema.description);
42
+ report.addError("MINIMUM", [json, schema.minimum], null, schema);
43
43
  }
44
44
  } else {
45
45
  if (json <= schema.minimum) {
46
- report.addError("MINIMUM_EXCLUSIVE", [json, schema.minimum], null, schema.description);
46
+ report.addError("MINIMUM_EXCLUSIVE", [json, schema.minimum], null, schema);
47
47
  }
48
48
  }
49
49
  },
@@ -56,7 +56,7 @@ var JsonValidators = {
56
56
  return;
57
57
  }
58
58
  if (Utils.ucs2decode(json).length > schema.maxLength) {
59
- report.addError("MAX_LENGTH", [json.length, schema.maxLength], null, schema.description);
59
+ report.addError("MAX_LENGTH", [json.length, schema.maxLength], null, schema);
60
60
  }
61
61
  },
62
62
  minLength: function (report, schema, json) {
@@ -65,7 +65,7 @@ var JsonValidators = {
65
65
  return;
66
66
  }
67
67
  if (Utils.ucs2decode(json).length < schema.minLength) {
68
- report.addError("MIN_LENGTH", [json.length, schema.minLength], null, schema.description);
68
+ report.addError("MIN_LENGTH", [json.length, schema.minLength], null, schema);
69
69
  }
70
70
  },
71
71
  pattern: function (report, schema, json) {
@@ -74,7 +74,7 @@ var JsonValidators = {
74
74
  return;
75
75
  }
76
76
  if (RegExp(schema.pattern).test(json) === false) {
77
- report.addError("PATTERN", [schema.pattern, json], null, schema.description);
77
+ report.addError("PATTERN", [schema.pattern, json], null, schema);
78
78
  }
79
79
  },
80
80
  additionalItems: function (report, schema, json) {
@@ -86,7 +86,7 @@ var JsonValidators = {
86
86
  // the json is valid if its size is less than, or equal to, the size of "items".
87
87
  if (schema.additionalItems === false && Array.isArray(schema.items)) {
88
88
  if (json.length > schema.items.length) {
89
- report.addError("ARRAY_ADDITIONAL_ITEMS", null, null, schema.description);
89
+ report.addError("ARRAY_ADDITIONAL_ITEMS", null, null, schema);
90
90
  }
91
91
  }
92
92
  },
@@ -99,7 +99,7 @@ var JsonValidators = {
99
99
  return;
100
100
  }
101
101
  if (json.length > schema.maxItems) {
102
- report.addError("ARRAY_LENGTH_LONG", [json.length, schema.maxItems], null, schema.description);
102
+ report.addError("ARRAY_LENGTH_LONG", [json.length, schema.maxItems], null, schema);
103
103
  }
104
104
  },
105
105
  minItems: function (report, schema, json) {
@@ -108,7 +108,7 @@ var JsonValidators = {
108
108
  return;
109
109
  }
110
110
  if (json.length < schema.minItems) {
111
- report.addError("ARRAY_LENGTH_SHORT", [json.length, schema.minItems], null, schema.description);
111
+ report.addError("ARRAY_LENGTH_SHORT", [json.length, schema.minItems], null, schema);
112
112
  }
113
113
  },
114
114
  uniqueItems: function (report, schema, json) {
@@ -119,7 +119,7 @@ var JsonValidators = {
119
119
  if (schema.uniqueItems === true) {
120
120
  var matches = [];
121
121
  if (Utils.isUniqueArray(json, matches) === false) {
122
- report.addError("ARRAY_UNIQUE", matches, null, schema.description);
122
+ report.addError("ARRAY_UNIQUE", matches, null, schema);
123
123
  }
124
124
  }
125
125
  },
@@ -130,7 +130,7 @@ var JsonValidators = {
130
130
  }
131
131
  var keysCount = Object.keys(json).length;
132
132
  if (keysCount > schema.maxProperties) {
133
- report.addError("OBJECT_PROPERTIES_MAXIMUM", [keysCount, schema.maxProperties], null, schema.description);
133
+ report.addError("OBJECT_PROPERTIES_MAXIMUM", [keysCount, schema.maxProperties], null, schema);
134
134
  }
135
135
  },
136
136
  minProperties: function (report, schema, json) {
@@ -140,7 +140,7 @@ var JsonValidators = {
140
140
  }
141
141
  var keysCount = Object.keys(json).length;
142
142
  if (keysCount < schema.minProperties) {
143
- report.addError("OBJECT_PROPERTIES_MINIMUM", [keysCount, schema.minProperties], null, schema.description);
143
+ report.addError("OBJECT_PROPERTIES_MINIMUM", [keysCount, schema.minProperties], null, schema);
144
144
  }
145
145
  },
146
146
  required: function (report, schema, json) {
@@ -152,7 +152,7 @@ var JsonValidators = {
152
152
  while (idx--) {
153
153
  var requiredPropertyName = schema.required[idx];
154
154
  if (json[requiredPropertyName] === undefined) {
155
- report.addError("OBJECT_MISSING_REQUIRED_PROPERTY", [requiredPropertyName], null, schema.description);
155
+ report.addError("OBJECT_MISSING_REQUIRED_PROPERTY", [requiredPropertyName], null, schema);
156
156
  }
157
157
  }
158
158
  },
@@ -208,7 +208,7 @@ var JsonValidators = {
208
208
  }
209
209
  }
210
210
  if (s.length > 0) {
211
- report.addError("OBJECT_ADDITIONAL_PROPERTIES", [s], null, schema.description);
211
+ report.addError("OBJECT_ADDITIONAL_PROPERTIES", [s], null, schema);
212
212
  }
213
213
  }
214
214
  }
@@ -236,7 +236,7 @@ var JsonValidators = {
236
236
  while (idx2--) {
237
237
  var requiredPropertyName = dependencyDefinition[idx2];
238
238
  if (json[requiredPropertyName] === undefined) {
239
- report.addError("OBJECT_DEPENDENCY_KEY", [requiredPropertyName, dependencyName], null, schema.description);
239
+ report.addError("OBJECT_DEPENDENCY_KEY", [requiredPropertyName, dependencyName], null, schema);
240
240
  }
241
241
  }
242
242
  }
@@ -246,23 +246,35 @@ var JsonValidators = {
246
246
  enum: function (report, schema, json) {
247
247
  // http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.5.1.2
248
248
  var match = false,
249
+ caseInsensitiveMatch = false,
249
250
  idx = schema.enum.length;
250
251
  while (idx--) {
251
252
  if (Utils.areEqual(json, schema.enum[idx])) {
252
253
  match = true;
253
254
  break;
255
+ } else if (Utils.areEqual(json, schema.enum[idx]), { caseInsensitiveComparison: true }) {
256
+ caseInsensitiveMatch = true;
254
257
  }
255
258
  }
259
+
256
260
  if (match === false) {
257
- report.addError("ENUM_MISMATCH", [json], null, schema.description);
261
+ var error = caseInsensitiveMatch && this.options.enumCaseInsensitiveComparison ? "ENUM_CASE_MISMATCH" : "ENUM_MISMATCH";
262
+ report.addError(error, [json], null, schema);
258
263
  }
259
264
  },
260
- /*
261
265
  type: function (report, schema, json) {
262
266
  // http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.5.2.2
263
- // type is handled before this is called so ignore
267
+ var jsonType = Utils.whatIs(json);
268
+ if (typeof schema.type === "string") {
269
+ if (jsonType !== schema.type && (jsonType !== "integer" || schema.type !== "number")) {
270
+ report.addError("INVALID_TYPE", [schema.type, jsonType], null, schema);
271
+ }
272
+ } else {
273
+ if (schema.type.indexOf(jsonType) === -1 && (jsonType !== "integer" || schema.type.indexOf("number") === -1)) {
274
+ report.addError("INVALID_TYPE", [schema.type, jsonType], null, schema);
275
+ }
276
+ }
264
277
  },
265
- */
266
278
  allOf: function (report, schema, json) {
267
279
  // http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.5.3.2
268
280
  var idx = schema.allOf.length;
@@ -286,7 +298,7 @@ var JsonValidators = {
286
298
  }
287
299
 
288
300
  if (passed === false) {
289
- report.addError("ANY_OF_MISSING", undefined, subReports, schema.description);
301
+ report.addError("ANY_OF_MISSING", undefined, subReports, schema);
290
302
  }
291
303
  },
292
304
  oneOf: function (report, schema, json) {
@@ -304,16 +316,16 @@ var JsonValidators = {
304
316
  }
305
317
 
306
318
  if (passes === 0) {
307
- report.addError("ONE_OF_MISSING", undefined, subReports, schema.description);
319
+ report.addError("ONE_OF_MISSING", undefined, subReports, schema);
308
320
  } else if (passes > 1) {
309
- report.addError("ONE_OF_MULTIPLE", null, null, schema.description);
321
+ report.addError("ONE_OF_MULTIPLE", null, null, schema);
310
322
  }
311
323
  },
312
324
  not: function (report, schema, json) {
313
325
  // http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.5.6.2
314
326
  var subReport = new Report(report);
315
327
  if (exports.validate.call(this, subReport, schema.not, json) === true) {
316
- report.addError("NOT_PASSED", null, null, schema.description);
328
+ report.addError("NOT_PASSED", null, null, schema);
317
329
  }
318
330
  },
319
331
  definitions: function () { /*report, schema, json*/
@@ -328,17 +340,17 @@ var JsonValidators = {
328
340
  // async
329
341
  report.addAsyncTask(formatValidatorFn, [json], function (result) {
330
342
  if (result !== true) {
331
- report.addError("INVALID_FORMAT", [schema.format, json], null, schema.description);
343
+ report.addError("INVALID_FORMAT", [schema.format, json], null, schema);
332
344
  }
333
345
  });
334
346
  } else {
335
347
  // sync
336
348
  if (formatValidatorFn.call(this, json) !== true) {
337
- report.addError("INVALID_FORMAT", [schema.format, json], null, schema.description);
349
+ report.addError("INVALID_FORMAT", [schema.format, json], null, schema);
338
350
  }
339
351
  }
340
352
  } else if (this.options.ignoreUnknownFormats !== true) {
341
- report.addError("UNKNOWN_FORMAT", [schema.format], null, schema.description);
353
+ report.addError("UNKNOWN_FORMAT", [schema.format], null, schema);
342
354
  }
343
355
  }
344
356
  };
@@ -450,7 +462,7 @@ exports.validate = function (report, schema, json) {
450
462
  // check if schema is an object
451
463
  var to = Utils.whatIs(schema);
452
464
  if (to !== "object") {
453
- report.addError("SCHEMA_NOT_AN_OBJECT", [to], null, schema.description);
465
+ report.addError("SCHEMA_NOT_AN_OBJECT", [to], null, schema);
454
466
  return false;
455
467
  }
456
468
 
@@ -473,7 +485,7 @@ exports.validate = function (report, schema, json) {
473
485
  var maxRefs = 99;
474
486
  while (schema.$ref && maxRefs > 0) {
475
487
  if (!schema.__$refResolved) {
476
- report.addError("REF_UNRESOLVED", [schema.$ref], null, schema.description);
488
+ report.addError("REF_UNRESOLVED", [schema.$ref], null, schema);
477
489
  break;
478
490
  } else if (schema.__$refResolved === schema) {
479
491
  break;
@@ -489,23 +501,12 @@ exports.validate = function (report, schema, json) {
489
501
  }
490
502
 
491
503
  // type checking first
492
- // http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.5.2.2
493
504
  var jsonType = Utils.whatIs(json);
494
505
  if (schema.type) {
495
- if (typeof schema.type === "string") {
496
- if (jsonType !== schema.type && (jsonType !== "integer" || schema.type !== "number")) {
497
- report.addError("INVALID_TYPE", [schema.type, jsonType], null, schema.description);
498
- if (this.options.breakOnFirstError) {
499
- return false;
500
- }
501
- }
502
- } else {
503
- if (schema.type.indexOf(jsonType) === -1 && (jsonType !== "integer" || schema.type.indexOf("number") === -1)) {
504
- report.addError("INVALID_TYPE", [schema.type, jsonType], null, schema.description);
505
- if (this.options.breakOnFirstError) {
506
- return false;
507
- }
508
- }
506
+ keys.splice(keys.indexOf("type"), 1);
507
+ JsonValidators.type.call(this, report, schema, json);
508
+ if (report.errors.length && this.options.breakOnFirstError) {
509
+ return false;
509
510
  }
510
511
  }
511
512
 
package/src/Report.js CHANGED
@@ -42,7 +42,7 @@ Report.prototype.processAsyncTasks = function (timeout, callback) {
42
42
  function finish() {
43
43
  process.nextTick(function () {
44
44
  var valid = self.errors.length === 0,
45
- err = valid ? undefined : self.errors;
45
+ err = valid ? undefined : self.errors;
46
46
  callback(err, valid);
47
47
  });
48
48
  }
@@ -145,13 +145,13 @@ Report.prototype.hasError = function (errorCode, params) {
145
145
  return false;
146
146
  };
147
147
 
148
- Report.prototype.addError = function (errorCode, params, subReports, schemaDescription) {
148
+ Report.prototype.addError = function (errorCode, params, subReports, schema) {
149
149
  if (!errorCode) { throw new Error("No errorCode passed into addError()"); }
150
150
 
151
- this.addCustomError(errorCode, Errors[errorCode], params, subReports, schemaDescription);
151
+ this.addCustomError(errorCode, Errors[errorCode], params, subReports, schema);
152
152
  };
153
153
 
154
- Report.prototype.addCustomError = function (errorCode, errorMessage, params, subReports, schemaDescription) {
154
+ Report.prototype.addCustomError = function (errorCode, errorMessage, params, subReports, schema) {
155
155
  if (this.errors.length >= this.reportOptions.maxErrors) {
156
156
  return;
157
157
  }
@@ -175,8 +175,15 @@ Report.prototype.addCustomError = function (errorCode, errorMessage, params, sub
175
175
  schemaId: this.getSchemaId()
176
176
  };
177
177
 
178
- if (schemaDescription) {
179
- err.description = schemaDescription;
178
+ if (schema && typeof schema === "string") {
179
+ err.description = schema;
180
+ } else if (schema && typeof schema === "object") {
181
+ if (schema.title) {
182
+ err.title = schema.title;
183
+ }
184
+ if (schema.description) {
185
+ err.description = schema.description;
186
+ }
180
187
  }
181
188
 
182
189
  if (subReports != null) {
package/src/Utils.js CHANGED
@@ -41,7 +41,11 @@ exports.whatIs = function (what) {
41
41
 
42
42
  };
43
43
 
44
- exports.areEqual = function areEqual(json1, json2) {
44
+ exports.areEqual = function areEqual(json1, json2, options) {
45
+
46
+ options = options || {};
47
+ var caseInsensitiveComparison = options.caseInsensitiveComparison || false;
48
+
45
49
  // http://json-schema.org/latest/json-schema-core.html#rfc.section.3.6
46
50
 
47
51
  // Two JSON values are said to be equal if and only if:
@@ -52,6 +56,12 @@ exports.areEqual = function areEqual(json1, json2) {
52
56
  if (json1 === json2) {
53
57
  return true;
54
58
  }
59
+ if (
60
+ caseInsensitiveComparison === true &&
61
+ typeof json1 === "string" && typeof json2 === "string" &&
62
+ json1.toUpperCase() === json2.toUpperCase()) {
63
+ return true;
64
+ }
55
65
 
56
66
  var i, len;
57
67
 
@@ -64,7 +74,7 @@ exports.areEqual = function areEqual(json1, json2) {
64
74
  // items at the same index are equal according to this definition; or
65
75
  len = json1.length;
66
76
  for (i = 0; i < len; i++) {
67
- if (!areEqual(json1[i], json2[i])) {
77
+ if (!areEqual(json1[i], json2[i], { caseInsensitiveComparison: caseInsensitiveComparison })) {
68
78
  return false;
69
79
  }
70
80
  }
@@ -76,13 +86,13 @@ exports.areEqual = function areEqual(json1, json2) {
76
86
  // have the same set of property names; and
77
87
  var keys1 = Object.keys(json1);
78
88
  var keys2 = Object.keys(json2);
79
- if (!areEqual(keys1, keys2)) {
89
+ if (!areEqual(keys1, keys2, { caseInsensitiveComparison: caseInsensitiveComparison })) {
80
90
  return false;
81
91
  }
82
92
  // values for a same property name are equal according to this definition.
83
93
  len = keys1.length;
84
94
  for (i = 0; i < len; i++) {
85
- if (!areEqual(json1[keys1[i]], json2[keys1[i]])) {
95
+ if (!areEqual(json1[keys1[i]], json2[keys1[i]], { caseInsensitiveComparison: caseInsensitiveComparison })) {
86
96
  return false;
87
97
  }
88
98
  }
package/src/ZSchema.js CHANGED
@@ -22,6 +22,8 @@ var defaultOptions = {
22
22
  forceAdditional: false,
23
23
  // assume additionalProperties and additionalItems are defined as "false" where appropriate
24
24
  assumeAdditional: false,
25
+ // do case insensitive comparison for enums
26
+ enumCaseInsensitiveComparison: false,
25
27
  // force items to be defined on "array" types
26
28
  forceItems: false,
27
29
  // force minItems to be defined on "array" types
@@ -112,6 +114,7 @@ function normalizeOptions(options) {
112
114
  function ZSchema(options) {
113
115
  this.cache = {};
114
116
  this.referenceCache = [];
117
+ this.validateOptions = {};
115
118
 
116
119
  this.options = normalizeOptions(options);
117
120
 
@@ -158,6 +161,8 @@ ZSchema.prototype.validate = function (json, schema, options, callback) {
158
161
  }
159
162
  if (!options) { options = {}; }
160
163
 
164
+ this.validateOptions = options;
165
+
161
166
  var whatIs = Utils.whatIs(schema);
162
167
  if (whatIs !== "string" && whatIs !== "object") {
163
168
  var e = new Error("Invalid .validate call - schema must be an string or object but " + whatIs + " was passed!");