Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add Parser-API version 2 support #1017

Merged
merged 9 commits into from
Sep 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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",
jonaslagoni marked this conversation as resolved.
Show resolved Hide resolved
"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';
jonaslagoni marked this conversation as resolved.
Show resolved Hide resolved
}
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