Skip to content

Commit

Permalink
feat: add Parser-API version 2 support (#1017)
Browse files Browse the repository at this point in the history
  • Loading branch information
jonaslagoni authored Sep 14, 2023
1 parent 3f761ec commit 60f8e62
Show file tree
Hide file tree
Showing 8 changed files with 468 additions and 11,256 deletions.
4 changes: 2 additions & 2 deletions docs/configuration-file.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ The `generator` property from `package.json` file must contain a JSON object tha
|Name|Type|Description|
|---|---|---|
|`renderer`| String | Its value can be either `react` or `nunjucks` (default).
|`apiVersion`| String | Determines which **major** version of the [Parser-API](https://github.com/asyncapi/parser-api) the template uses. For example, `v1` for `v1.x.x`. If not specified, the Generator assumes the template is not compatible with the Parser-API so it will use the [Parser-JS v1 API](https://github.com/asyncapi/parser-js/tree/v1.18.1#api-documentation). If the template uses a version of the Parser-API that is not supported by the Generator, the Generator will throw an error.
|`apiVersion`| String | Determines which **major** version of the [Parser-API](https://github.com/asyncapi/parser-api) the template uses. For example, `v2` for `v2.x.x`. If not specified, the Generator assumes the template is not compatible with the Parser-API so it will use the [Parser-JS v1 API](https://github.com/asyncapi/parser-js/tree/v1.18.1#api-documentation). For templates that need to support AsyncAPI specification v3 make sure to use `v2` [Parser-API](https://github.com/asyncapi/parser-api). If the template uses a version of the Parser-API that is not supported by the Generator, the Generator will throw an error.
|`supportedProtocols`| [String] | A list with all the protocols this template supports.
|`parameters`| Object[String, Object] | An object with all the parameters that can be passed when generating the template. When using the command line, it's done by indicating `--param name=value` or `-p name=value`.
|`parameters[param].description`| String | A user-friendly description about the parameter.
Expand All @@ -28,7 +28,7 @@ The `generator` property from `package.json` file must contain a JSON object tha
"generator":
{
"renderer": "react",
"apiVersion": "v1",
"apiVersion": "v2",
"supportedProtocols": ["amqp", "mqtt"],
"parameters": {
"server": {
Expand Down
6 changes: 3 additions & 3 deletions lib/generator.js
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ class Generator {
validateTemplateConfig(this.templateConfig, this.templateParams, asyncapiDocument);
await this.configureTemplate();

// use new or old document API based on `templateConfig.apiVersion` value
// use the expected document API based on `templateConfig.apiVersion` value
this.asyncapi = asyncapiDocument = getProperApiDocument(asyncapiDocument, this.templateConfig);

if (!isReactTemplate(this.templateConfig)) {
Expand Down Expand Up @@ -261,7 +261,7 @@ class Generator {
/** @type {AsyncAPIDocument} Parsed AsyncAPI schema. See {@link https://github.com/asyncapi/parser-js/blob/master/API.md#module_@asyncapi/parser+AsyncAPIDocument|AsyncAPIDocument} for details on object structure. */
const { document, diagnostics } = await parse(asyncapiString, parseOptions, this);
if (!document) {
const err = new Error('Input is not a corrent AsyncAPI document so it cannot be processed.');
const err = new Error('Input is not a correct AsyncAPI document so it cannot be processed.');
err.diagnostics = diagnostics;
throw err;
}
Expand Down Expand Up @@ -436,7 +436,7 @@ class Generator {
}
});
}

if (asyncapiDocument.hasComponents()) {
for (const [key, value] of Object.entries(asyncapiDocument.components().parameters())) {
parameters.set(key, value);
Expand Down
50 changes: 32 additions & 18 deletions lib/parser.js
Original file line number Diff line number Diff line change
@@ -1,33 +1,47 @@
const fs = require('fs');

const { Parser, convertToOldAPI } = require('@asyncapi/parser/cjs');
const { OpenAPISchemaParser } = require('@asyncapi/openapi-schema-parser');
const { AvroSchemaParser } = require('@asyncapi/avro-schema-parser');
const { RamlDTSchemaParser } = require('@asyncapi/raml-dt-schema-parser');
const { ProtoBuffSchemaParser } = require('@asyncapi/protobuf-schema-parser');
const { convertToOldAPI } = require('@asyncapi/parser');
const { ConvertDocumentParserAPIVersion, NewParser } = require('@smoya/multi-parser');

const parser = module.exports;

const defaultParser = new Parser({
schemaParsers: [
OpenAPISchemaParser(),
AvroSchemaParser(),
RamlDTSchemaParser(),
ProtoBuffSchemaParser(),
],
});
/**
* Conver the template defined value `apiVersion: 'v1'` to only contain the numeric value `1`.
*/
parser.sanitizeTemplateApiVersion = (apiVersion) => {
if (apiVersion && apiVersion.length > 1) {
return apiVersion.substring('1');
}
return apiVersion;
};

parser.parse = (asyncapi, oldOptions, generator) => {
let apiVersion = this.sanitizeTemplateApiVersion(generator.templateConfig.apiVersion);
// Defaulting to apiVersion v1 to convert it to the Parser-API v1 afterwards.
if (!this.usesNewAPI(generator.templateConfig)) {
apiVersion = '1';
}
const options = convertOldOptionsToNew(oldOptions, generator);
return defaultParser.parse(asyncapi, options);
const parser = NewParser(apiVersion, {parserOptions: options, includeSchemaParsers: true});
return parser.parse(asyncapi, options);
};

/**
* If the template expect one of the Parser-API versions, it must be above 0
*/
parser.usesNewAPI = (templateConfig = {}) => {
return templateConfig.apiVersion === 'v1';
return Number(this.sanitizeTemplateApiVersion(templateConfig.apiVersion)) > 0;
};

parser.getProperApiDocument = (asyncapiDocument, templateConfig) => {
return parser.usesNewAPI(templateConfig) ? asyncapiDocument : convertToOldAPI(asyncapiDocument);
/**
* Based on the current parsed AsyncAPI document, convert it to expected API version from the template.
*/
parser.getProperApiDocument = (asyncapiDocument, templateConfig = {}) => {
const apiVersion = this.sanitizeTemplateApiVersion(templateConfig.apiVersion);
if (apiVersion === undefined) {
// Convert to old API from JS Parser v1
return convertToOldAPI(asyncapiDocument);
}
return ConvertDocumentParserAPIVersion(asyncapiDocument, apiVersion);
};

// The new options for the v2 Parser are different from those for the v1 version, but in order not to release Generator v2, we are converting the old options of Parser to the new ones.
Expand Down
1 change: 1 addition & 0 deletions lib/templateConfigValidator.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const ajv = new Ajv({ allErrors: true });
// See https://github.com/asyncapi/parser-api
const supportedParserAPIMajorVersions = [
'v1',
'v2'
];

/**
Expand Down
Loading

0 comments on commit 60f8e62

Please sign in to comment.