z-schema 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. #!/usr/bin/env node
  2. // set default exitCode for node 0.10
  3. process.exitCode = 0;
  4. var fs = require("fs");
  5. var path = require("path");
  6. var program = require("commander");
  7. var request = require("https").request;
  8. var package = require("./../package.json");
  9. var ZSchema = require("./../src/ZSchema");
  10. program
  11. .version(package.version)
  12. .usage("[options] <schema> <json1?> <json2?> <json3?>")
  13. .option("--asyncTimeout <n>", "default timeout for all async tasks", parseInt)
  14. .option("--forceAdditional", "force additionalProperties and additionalItems to be defined on \"object\" and \"array\" types")
  15. .option("--assumeAdditional", "assume additionalProperties and additionalItems are defined as \"false\" where appropriate")
  16. .option("--forceItems", "force items to be defined on \"array\" types")
  17. .option("--forceMinItems", "force minItems to be defined on \"array\" types")
  18. .option("--forceMaxItems", "force maxItems to be defined on \"array\" types")
  19. .option("--forceMinLength", "force minLength to be defined on \"string\" types")
  20. .option("--forceMaxLength", "force maxLength to be defined on \"string\" types")
  21. .option("--forceProperties", "force properties or patternProperties to be defined on \"object\" types")
  22. .option("--ignoreUnresolvableReferences", "ignore references that cannot be resolved (remote schemas)")
  23. .option("--noExtraKeywords", "disallow usage of keywords that this validator can't handle")
  24. .option("--noTypeless", "disallow usage of schema's without \"type\" defined")
  25. .option("--noEmptyStrings", "disallow zero length strings in validated objects")
  26. .option("--noEmptyArrays", "disallow zero length arrays in validated objects")
  27. .option("--strictUris", "forces \"uri\" format to be in fully rfc3986 compliant")
  28. .option("--strictMode", "turn on some of the above")
  29. .option("--reportPathAsArray", "report error paths as an array of path segments to get to the offending node")
  30. .option("--breakOnFirstError", "stops validation as soon as an error is found, true by default but can be turned off")
  31. .option("--pedanticCheck", "check if schema follow best practices and common sence")
  32. .option("--ignoreUnknownFormats", "ignore unknown formats (do not report them as an error)")
  33. .parse(process.argv);
  34. var options = {};
  35. var defaultOptions = ZSchema.getDefaultOptions();
  36. for (var key in defaultOptions) {
  37. if (program[key]) {
  38. options[key] = program[key];
  39. }
  40. }
  41. if (!program.args.length) {
  42. program.help();
  43. }
  44. function readJson(fileName) {
  45. var ret;
  46. try {
  47. ret = fs.readFileSync(fileName, { encoding: "utf8" });
  48. } catch (e) {
  49. console.error(e);
  50. throw new Error("Couldn't read the file: " + fileName);
  51. }
  52. try {
  53. ret = JSON.parse(ret);
  54. } catch (e) {
  55. console.error(e);
  56. throw new Error("Couldn't parse the file as JSON: " + fileName);
  57. }
  58. return ret;
  59. }
  60. var validator = new ZSchema(options);
  61. var schemaFilePath = program.args.shift();
  62. var schema = readJson(schemaFilePath);
  63. function validateWithAutomaticDownloads(filePath, data, schema, callback) {
  64. var lastResult;
  65. function finish() {
  66. callback(validator.getLastErrors(), lastResult);
  67. }
  68. function validate() {
  69. if (data !== undefined) {
  70. lastResult = validator.validate(data, schema);
  71. } else {
  72. lastResult = validator.validateSchema(schema);
  73. }
  74. // console.log(lastResult);
  75. // console.log(JSON.stringify(validator.getLastErrors(), null, 4));
  76. var missingReferences = validator.getMissingRemoteReferences();
  77. if (missingReferences.length > 0) {
  78. var finished = 0;
  79. missingReferences.forEach(function (url) {
  80. var urlString = "request: " + url + " - ";
  81. if (url.match(/^https?:/)) {
  82. request(url, function (response) {
  83. var body = "";
  84. response.on("data", function (chunk) { data += chunk; });
  85. response.on("end", function () {
  86. console.log(urlString + response.statusCode);
  87. validator.setRemoteReference(url, JSON.parse(body));
  88. finished++;
  89. if (finished === missingReferences.length) {
  90. validate();
  91. }
  92. });
  93. }).on("error", function (error) {
  94. console.error(urlString);
  95. console.error(error);
  96. process.exit(1);
  97. });
  98. } else {
  99. // FUTURE: maybe else if (isFile(url)) later
  100. var referencePath = path.resolve(process.cwd(), path.dirname(filePath), url);
  101. var reference = readJson(referencePath);
  102. validator.setRemoteReference(url, reference);
  103. finished++;
  104. if (finished === missingReferences.length) {
  105. validate();
  106. }
  107. }
  108. });
  109. } else {
  110. finish();
  111. }
  112. }
  113. validate();
  114. }
  115. var i = 0;
  116. function validateJsons() {
  117. if (program.args.length === 0) {
  118. process.exit(process.exitCode);
  119. return;
  120. }
  121. i++;
  122. var filePath = program.args.shift();
  123. var json = readJson(filePath);
  124. validateWithAutomaticDownloads(filePath, json, schema, function (errs, isValid) {
  125. if (!isValid) {
  126. console.log(JSON.stringify(validator.getLastErrors(), null, 4));
  127. console.log("json #" + i + " validation failed");
  128. process.exitCode = 1;
  129. } else {
  130. console.log("json #" + i + " validation passed");
  131. }
  132. validateJsons();
  133. });
  134. }
  135. // validate schema
  136. validateWithAutomaticDownloads(schemaFilePath, undefined, schema, function (errs, isValid) {
  137. if (!isValid) {
  138. console.log(JSON.stringify(validator.getLastErrors(), null, 4));
  139. console.log("schema validation failed");
  140. process.exit(1);
  141. } else {
  142. console.log("schema validation passed");
  143. validateJsons();
  144. }
  145. });