Skip to content

Commit

Permalink
throw exception if apiVersion is not valid
Browse files Browse the repository at this point in the history
  • Loading branch information
smoya committed May 12, 2023
1 parent cc43d87 commit dbb27c4
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 19 deletions.
44 changes: 27 additions & 17 deletions lib/templateConfigValidator.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ const levenshtein = require('levenshtein-edit-distance');

const ajv = new Ajv({ allErrors: true });

// See https://github.com/asyncapi/parser-api
const supportedParserAPIMajorVersions = [
'v1',
];

/**
* Validates the template configuration.
*
Expand All @@ -14,10 +19,10 @@ const ajv = new Ajv({ allErrors: true });
* @return {Boolean}
*/
module.exports.validateTemplateConfig = (templateConfig, templateParams, asyncapiDocument) => {
const { parameters, supportedProtocols, conditionalFiles, generator } = templateConfig;
const { parameters, supportedProtocols, conditionalFiles, generator, apiVersion } = templateConfig;

validateConditionalFiles(conditionalFiles);
isTemplateCompatible(generator);
isTemplateCompatible(generator, apiVersion);
isRequiredParamProvided(parameters, templateParams);
isProvidedTemplateRendererSupported(templateConfig);
if (asyncapiDocument) {
Expand All @@ -34,24 +39,29 @@ module.exports.validateTemplateConfig = (templateConfig, templateParams, asyncap
* Checks if template is compatible with the version of the generator that is used
* @private
* @param {String} generator Information about supported generator version that is part of the template configuration
* @param {String} generator Information about supported Parser-API version that is part of the template configuration
*/
function isTemplateCompatible(generator) {
function isTemplateCompatible(generator, apiVersion) {
const generatorVersion = getGeneratorVersion();
if (typeof generator === 'string' && !semver.satisfies(generatorVersion, generator, {includePrerelease: true})) {
throw new Error(`This template is not compatible with the current version of the generator (${generatorVersion}). This template is compatible with the following version range: ${generator}.`);
}
}

if (typeof apiVersion === 'string' && !supportedParserAPIMajorVersions.includes(apiVersion)) {
throw new Error(`The version specified in apiVersion is not supported by this Generator version. Supported versions are: ${supportedParserAPIMajorVersions.toString()}`);
}
}

/**
* Checks if parameters described in template configuration as required are passed to the generator
* @private
* @param {Object} configParams Parameters specified in template configuration
* @param {Object} templateParams All parameters provided to generator
* @param {Object} templateParams All parameters provided to generator
*/
function isRequiredParamProvided(configParams, templateParams) {
const missingParams = Object.keys(configParams || {})
.filter(key => configParams[key].required && !templateParams[key]);

if (missingParams.length) {
throw new Error(`This template requires the following missing params: ${missingParams}.`);
}
Expand All @@ -74,29 +84,29 @@ function getParamSuggestion(wrongParam, configParams) {
* Checks if parameters provided to generator is supported by the template
* @private
* @param {Object} configParams Parameters specified in template configuration
* @param {Object} templateParams All parameters provided to generator
* @param {Object} templateParams All parameters provided to generator
*/
function isProvidedParameterSupported(configParams, templateParams) {
const wrongParams = Object.keys(templateParams || {}).filter(key => !configParams || !configParams[key]);

if (!wrongParams.length) return;
if (!configParams) throw new Error('This template doesn\'t have any params.');

let suggestionsString = '';
wrongParams.forEach(wp => {

wrongParams.forEach(wp => {
suggestionsString += `\nDid you mean "${getParamSuggestion(wp,configParams)}" instead of "${wp}"?`;
});

throw new Error(`This template doesn't have the following params: ${wrongParams}.${suggestionsString}`);
}

/**
* Checks if given AsyncAPI document has servers with protocol that is supported by the template
* @private
* @param {Object} server Server object from AsyncAPI file
* @param {String[]} supportedProtocols Supported protocols specified in template configuration
* @param {String} paramsServerName Name of the server specified as a param for the generator
* @param {String} paramsServerName Name of the server specified as a param for the generator
*/
function isServerProtocolSupported(server, supportedProtocols, paramsServerName) {
if (server && Array.isArray(supportedProtocols) && !supportedProtocols.includes(server.protocol())) {
Expand All @@ -106,15 +116,15 @@ function isServerProtocolSupported(server, supportedProtocols, paramsServerName)

/**
* Checks if the the provided renderer are supported (no renderer are also supported, defaults to nunjucks)
*
*
* @param {Object} templateConfig Template configuration.
*/
function isProvidedTemplateRendererSupported(templateConfig) {
const supportedRenderers = [undefined, 'react', 'nunjucks'];
if (supportedRenderers.includes(templateConfig.renderer)) {
return;
}

throw new Error(`We do not support '${templateConfig.renderer}' as a renderer for a template. Only 'react' or 'nunjucks' are supported.`);
}

Expand All @@ -136,12 +146,12 @@ function isServerProvidedInDocument(server, paramsServerName) {
function validateConditionalFiles(conditionalFiles) {
if (typeof conditionalFiles === 'object') {
const fileNames = Object.keys(conditionalFiles);

fileNames.forEach(fileName => {
const def = conditionalFiles[fileName];
if (typeof def.subject !== 'string') throw new Error(`Invalid conditional file subject for ${fileName}: ${def.subject}.`);
if (typeof def.validation !== 'object') throw new Error(`Invalid conditional file validation object for ${fileName}: ${def.validation}.`);
conditionalFiles[fileName].validate = ajv.compile(conditionalFiles[fileName].validation);
});
}
}
}
16 changes: 14 additions & 2 deletions test/templateConfigValidator.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ describe('Template Configuration Validator', () => {
const { document } = await parser.parse(dummyYAML);
asyncapiDocument = document;
});

it('Validation doesn\'t throw errors if params are not passed and template has no config', () => {
const templateParams = {};
const templateConfig = {};
Expand Down Expand Up @@ -48,7 +48,7 @@ describe('Template Configuration Validator', () => {
expect(() => validateTemplateConfig(templateConfig, templateParams)).toThrow('We do not support \'non_existing\' as a renderer for a template. Only \'react\' or \'nunjucks\' are supported.');
});

it('Validation throw error if template is not compatible', () => {
it('Validation throw error if template is not compatible because of generator version', () => {
const utils = require('../lib/utils');
utils.__generatorVersion = '1.0.0';

Expand All @@ -60,6 +60,18 @@ describe('Template Configuration Validator', () => {
expect(() => validateTemplateConfig(templateConfig, templateParams)).toThrow('This template is not compatible with the current version of the generator (1.0.0). This template is compatible with the following version range: >1.0.1.');
});

it('Validation throw error if template is not compatible because of non-supported apiVersion value', () => {
const utils = require('../lib/utils');
utils.__generatorVersion = '1.0.0';

const templateParams = {};
const templateConfig = {
apiVersion: '999999'
};

expect(() => validateTemplateConfig(templateConfig, templateParams)).toThrow('The version specified in apiVersion is not supported by this Generator version. Supported versions are: v1');
});

it('Validation throw error if required params not provided', () => {
const templateParams = {};
const templateConfig = {
Expand Down

0 comments on commit dbb27c4

Please sign in to comment.