UNPKG

atlassian-connect-validator

Version:

Utility to validate an Atlassian Connect add-on descriptor

91 lines (75 loc) 3.08 kB
var util = require('util'), _ = require('lodash'), Validator = require('jsonschema').Validator, helpers = require('jsonschema/lib/helpers'); var isDevMode = process.env.NODE_ENV === 'development' if (isDevMode) { require('longjohn'); } function getModuleName(path) { if ('instance' === path) { return 'Root'; } else { return path.substr(9); } } function normalizePath(path) { return ((path.length > 0 && path[0] != '/') ? '/' : '') + encodeURIComponent(path); } /** * Rewrites a schema to not allow additional properties where they would usually be allowed. * @param schema The original JSON schema * @returns {Object} A copy of the schema with the 'additionalProperties' fields set to false at the root */ function noAdditionalRootProperties(schema) { var copy = _.clone(schema); copy.additionalProperties = false; return copy; } function difference(strictErrors, errors) { return _.differenceBy(strictErrors, errors, function(value) { return value.module + value.description; }); } var parseValidationErrors = function(descriptor, errors) { isDevMode && console.log(util.inspect(errors, { colors: true })); var baseUrl = descriptor.baseUrl; var validationErrors = []; _.forEach(errors, function(e) { var validationError = { module: getModuleName(e.property), description: e.message, error: e }; if ('enum' === e.name) { validationError.description = "'" + e.instance + "' is not a valid enum value"; validationError.validValues = e.argument; } // 'jsonschema' rejects relative URLs for fields that are annotated with uri (and it doesn't handle uri-template). // So we are constructing the absolute URL here and validate it again. If this second validation fails, // we record the error, otherwise we can ignore it. if ('format' === e.name && ('uri' === e.argument || 'uri-template' === e.argument) && baseUrl && e.instance != null) { var absolute = baseUrl + normalizePath(e.instance); if (!helpers.isFormat(absolute, 'uri')) { validationErrors.push(validationError); } } else { validationErrors.push(validationError); } }); return validationErrors; }; module.exports = { validateDescriptor: function(descriptor, schema, callback) { var result = new Validator().validate(descriptor, schema); var validationErrors = parseValidationErrors(descriptor, result.errors); var strictResult = new Validator().validate(descriptor, noAdditionalRootProperties(schema)); var strictValidationErrors = parseValidationErrors(descriptor, strictResult.errors); var validationWarnings = difference(strictValidationErrors, validationErrors); if (callback) { callback(validationErrors.length > 0 ? validationErrors: null, validationWarnings.length > 0 ? validationWarnings : null); } } };