@asyncapi/parser
Advanced tools
Comparing version 1.0.2 to 1.1.0
const ParserError = require('./errors/parser-error'); | ||
const { parseUrlVariables, getMissingProps, groupValidationErrors, tilde } = require('./utils'); | ||
const { parseUrlVariables, getMissingProps, groupValidationErrors, tilde, parseUrlQueryParameters, setNotProvidedParams } = require('./utils'); | ||
const validationError = 'validation-errors'; | ||
@@ -28,5 +28,5 @@ | ||
notProvidedVariables.set(tilde(key), | ||
notProvidedServerVars | ||
? notProvidedServerVars.concat(missingServerVariables) | ||
notProvidedVariables.set(tilde(key), | ||
notProvidedServerVars | ||
? notProvidedServerVars.concat(missingServerVariables) | ||
: missingServerVariables); | ||
@@ -48,45 +48,2 @@ }); | ||
/** | ||
* Validates if parameters specified in the channel have corresponding parameters object defined | ||
* | ||
* @private | ||
* @param {Object} parsedJSON parsed AsyncAPI document | ||
* @param {String} asyncapiYAMLorJSON AsyncAPI document in string | ||
* @param {String} initialFormat information of the document was oryginally JSON or YAML | ||
* @returns {Boolean} true in case the document is valid, otherwise throws ParserError | ||
*/ | ||
function validateChannelParams(parsedJSON, asyncapiYAMLorJSON, initialFormat) { | ||
const chnls = parsedJSON.channels; | ||
if (!chnls) return true; | ||
const chnlsMap = new Map(Object.entries(chnls)); | ||
const notProvidedParams = new Map(); | ||
chnlsMap.forEach((val, key) => { | ||
const variables = parseUrlVariables(key); | ||
const notProvidedChannelParams = notProvidedParams.get(tilde(key)); | ||
if (!variables) return; | ||
const missingChannelParams = getMissingProps(variables, val.parameters); | ||
if (!missingChannelParams.length) return; | ||
notProvidedParams.set(tilde(key), | ||
notProvidedChannelParams | ||
? notProvidedChannelParams.concat(missingChannelParams) | ||
: missingChannelParams); | ||
}); | ||
if (notProvidedParams.size) { | ||
throw new ParserError({ | ||
type: validationError, | ||
title: 'Not all channel parameters are described with parameter object', | ||
parsedJSON, | ||
validationErrors: groupValidationErrors('channels', 'channel does not have a corresponding parameter object for', notProvidedParams, asyncapiYAMLorJSON, initialFormat) | ||
}); | ||
} | ||
return true; | ||
} | ||
/** | ||
* Validates if operationIds are duplicated in the document | ||
@@ -108,16 +65,16 @@ * | ||
const allOperations = []; | ||
const addDuplicateToMap = (op, channelName, opName) => { | ||
const operationId = op.operationId; | ||
if (!operationId) return; | ||
const operationPath = `${ tilde(channelName) }/${ opName }/operationId`; | ||
const isOperationIdDuplicated = allOperations.filter(v => v[0] === operationId); | ||
const operationPath = `${tilde(channelName)}/${opName}/operationId`; | ||
const isOperationIdDuplicated = allOperations.filter(v => v[0] === operationId); | ||
if (!isOperationIdDuplicated.length) return allOperations.push([operationId, operationPath]); | ||
//isOperationIdDuplicated always holds one record and it is an array of paths, the one that is a duplicate and the one that is duplicated | ||
duplicatedOperations.set(operationPath, isOperationIdDuplicated[0][1]); | ||
duplicatedOperations.set(operationPath, isOperationIdDuplicated[0][1]); | ||
}; | ||
chnlsMap.forEach((chnlObj,chnlName) => { | ||
chnlsMap.forEach((chnlObj, chnlName) => { | ||
operations.forEach(opName => { | ||
@@ -154,3 +111,3 @@ const op = chnlObj[String(opName)]; | ||
if (!srvs) return true; | ||
const root = 'servers'; | ||
@@ -213,6 +170,6 @@ const srvsMap = new Map(Object.entries(srvs)); | ||
function findSecuritySchema(securityName, components) { | ||
const secSchemes = components && components.securitySchemes; | ||
const secSchemesMap = secSchemes ? new Map(Object.entries(secSchemes)) : new Map(); | ||
const secSchemes = components && components.securitySchemes; | ||
const secSchemesMap = secSchemes ? new Map(Object.entries(secSchemes)) : new Map(); | ||
const schemaInfo = []; | ||
//using for loop here as there is no point to iterate over all entries as it is enough to find first matching element | ||
@@ -247,7 +204,59 @@ for (const [schemaName, schema] of secSchemesMap.entries()) { | ||
/** | ||
* Validates if parameters specified in the channel have corresponding parameters object defined and if name does not contain url parameters | ||
* | ||
* @private | ||
* @param {Object} parsedJSON parsed AsyncAPI document | ||
* @param {String} asyncapiYAMLorJSON AsyncAPI document in string | ||
* @param {String} initialFormat information of the document was oryginally JSON or YAML | ||
* @returns {Boolean} true in case the document is valid, otherwise throws ParserError | ||
*/ | ||
function validateChannels(parsedJSON, asyncapiYAMLorJSON, initialFormat) { | ||
const chnls = parsedJSON.channels; | ||
if (!chnls) return true; | ||
const chnlsMap = new Map(Object.entries(chnls)); | ||
const notProvidedParams = new Map(); //return object for missing parameters | ||
const invalidChannelName = new Map(); //return object for invalid channel names with query parameters | ||
chnlsMap.forEach((val, key) => { | ||
const variables = parseUrlVariables(key); | ||
const notProvidedChannelParams = notProvidedParams.get(tilde(key)); | ||
const queryParameters = parseUrlQueryParameters(key); | ||
//channel variable validation: fill return obeject with missing parameters | ||
if (variables) { | ||
setNotProvidedParams(variables, val, key, notProvidedChannelParams, notProvidedParams); | ||
} | ||
//channel name validation: fill return object with channels containing query parameters | ||
if (queryParameters) { | ||
invalidChannelName.set(tilde(key), | ||
queryParameters); | ||
} | ||
}); | ||
//combine validation errors of both checks and output them as one array | ||
const parameterValidationErrors = groupValidationErrors('channels', 'channel does not have a corresponding parameter object for', notProvidedParams, asyncapiYAMLorJSON, initialFormat); | ||
const nameValidationErrors = groupValidationErrors('channels', 'channel contains invalid name with url query parameters', invalidChannelName, asyncapiYAMLorJSON, initialFormat); | ||
const allValidationErrors = parameterValidationErrors.concat(nameValidationErrors); | ||
//channel variable validation: throw exception if channel validation failes | ||
if (notProvidedParams.size || invalidChannelName.size) { | ||
throw new ParserError({ | ||
type: validationError, | ||
title: 'Channel validation failed', | ||
parsedJSON, | ||
validationErrors: allValidationErrors | ||
}); | ||
} | ||
return true; | ||
} | ||
module.exports = { | ||
validateChannelParams, | ||
validateServerVariables, | ||
validateOperationId, | ||
validateServerSecurity | ||
validateServerSecurity, | ||
validateChannels | ||
}; |
@@ -8,3 +8,3 @@ const path = require('path'); | ||
const ParserError = require('./errors/parser-error'); | ||
const { validateChannelParams, validateServerVariables, validateOperationId, validateServerSecurity } = require('./customValidators.js'); | ||
const { validateChannels, validateServerVariables, validateOperationId, validateServerSecurity } = require('./customValidators.js'); | ||
const { toJS, findRefs, getLocationOf, improveAjvErrors } = require('./utils'); | ||
@@ -174,3 +174,3 @@ const AsyncAPIDocument = require('./models/asyncapi'); | ||
validateChannelParams(parsedJSON, asyncapiYAMLorJSON, initialFormat); | ||
validateChannels(parsedJSON, asyncapiYAMLorJSON, initialFormat); | ||
validateOperationId(parsedJSON, asyncapiYAMLorJSON, initialFormat, OPERATIONS); | ||
@@ -177,0 +177,0 @@ |
@@ -265,2 +265,15 @@ const YAML = require('js-yaml'); | ||
/** | ||
* It parses the string and returns url parameters as string | ||
* @function parseUrlQueryParameters | ||
* @private | ||
*/ | ||
utils.parseUrlQueryParameters = str => { | ||
if (typeof str !== 'string') return; | ||
const channelName = str; | ||
const url = new URL(`http://${channelName}`); | ||
return url.search; | ||
}; | ||
/** | ||
* Returns an array of not existing properties in provided object with names specified in provided array | ||
@@ -308,1 +321,23 @@ * @function getMissingProps | ||
}; | ||
/** | ||
* extend map with channel params missing corresponding param object | ||
* | ||
* @function setNotProvidedParams | ||
* @private | ||
* @param {Array<String>} variables array of all identified URL variables in a channel name | ||
* @param {Object} val the channel object for which to identify the missing parameters | ||
* @param {String} key the channel name. | ||
* @param {Array<Object>} notProvidedChannelParams concatinated list of missing parameters for all channels | ||
* @param {Map} notProvidedParams result map of all missing parameters extended by this function | ||
*/ | ||
utils.setNotProvidedParams = (variables, val, key, notProvidedChannelParams, notProvidedParams) => { | ||
const missingChannelParams = utils.getMissingProps(variables, val.parameters); | ||
if (missingChannelParams.length) { | ||
notProvidedParams.set(utils.tilde(key), | ||
notProvidedChannelParams | ||
? notProvidedChannelParams.concat(missingChannelParams) | ||
: missingChannelParams); | ||
} | ||
}; |
{ | ||
"name": "@asyncapi/parser", | ||
"version": "1.0.2", | ||
"version": "1.1.0", | ||
"description": "JavaScript AsyncAPI parser.", | ||
@@ -5,0 +5,0 @@ "main": "lib/index.js", |
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
1097474
6545