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 all recommended and must supported schema formats #365

Merged
Merged
4 changes: 1 addition & 3 deletions definitions/3.0.0/asyncapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,7 @@
"properties": {
"asyncapi": {
"type": "string",
"enum": [
"3.0.0"
],
"const": "3.0.0",
"description": "The AsyncAPI specification version of this document."
},
"id": {
Expand Down
33 changes: 32 additions & 1 deletion definitions/3.0.0/multiFormatSchema.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,44 @@
},
"properties": {
"schemaFormat": {
"type": "string"
"anyOf": [
{
"type": "string"
},
{
"description": "All the schema formats tooling MUST support",
"enum": [
"application/schema+json;version=draft-07",
"application/schema+yaml;version=draft-07",

"application/vnd.aai.asyncapi;version=3.0.0",
"application/vnd.aai.asyncapi+json;version=3.0.0",
"application/vnd.aai.asyncapi+yaml;version=3.0.0"
]
},
{
"description": "All the schema formats tools are RECOMMENDED to support",
"enum": [
"application/vnd.oai.openapi;version=3.0.0",
"application/vnd.oai.openapi+json;version=3.0.0",
"application/vnd.oai.openapi+yaml;version=3.0.0",

"application/vnd.apache.avro;version=1.9.0",
"application/vnd.apache.avro+json;version=1.9.0",
"application/vnd.apache.avro+yaml;version=1.9.0",

"application/raml+yaml;version=1.0"
]
}
]
},
"schema": {}
},
"allOf": [
{
"if": {
"not": {
"description": "If no schemaFormat has been defined, default to schema or reference",
"required": [
"schemaFormat"
]
Expand All @@ -47,6 +77,7 @@
},
{
"if": {
"description": "If schemaFormat has been defined check if it's one of the AsyncAPI Schema Object formats",
"required": [
"schemaFormat"
],
Expand Down
70 changes: 67 additions & 3 deletions scripts/add-new-version.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
const path = require('path');
/**
* This script adds a new version of the spec with examples, by copying the latest one as baseline.
*/
Expand All @@ -23,6 +24,63 @@ function execute(command) {
});
}

/**
* Add the new AsyncAPI schema object as values to schemaFormat
*
* If a major version change, replaces all old AsyncAPI schemaFormat values with fresh ones
* if minor or fix, it add new ones
*/
function addNewSchemaVersion(newVersion, newVersionDir, latestVersion) {
const newSchemaFormats = [
`application/vnd.aai.asyncapi;version=${newVersion}`,
`application/vnd.aai.asyncapi+json;version=${newVersion}`,
`application/vnd.aai.asyncapi+yaml;version=${newVersion}`
];
//Did the major version (first char) change from last to new version?
const isMajorVersionChange = newVersion.charAt(0) !== latestVersion.charAt(0);
const objFile = path.resolve(newVersionDir, 'multiFormatSchema.json');
const obj = require(objFile);

// Adapt all the MUST supported schema formats
let mustSupportedSchemaFormats = [] = obj?.else?.properties?.schemaFormat?.anyOf[1]?.enum;

//Add new version to the list of available schemaFormat values
if(mustSupportedSchemaFormats) {
if(isMajorVersionChange) {
//Remove all old AsyncAPI schema formats because we want a clean slate
mustSupportedSchemaFormats = mustSupportedSchemaFormats.filter((format) => !format.includes('application/vnd.aai.asyncapi'));
}
//Add new schema formats
mustSupportedSchemaFormats.push(...newSchemaFormats);
obj.else.properties.schemaFormat.anyOf[1].enum = mustSupportedSchemaFormats;
} else {
throw new Error("Could not find object to add schemaFormat values to");
}

//Make sure new versions apply the right schema
let enumsForValidatingSchema = [] = obj?.else?.allOf[1]?.if?.properties?.schemaFormat?.enum;
if(enumsForValidatingSchema) {
//Add new schema formats
enumsForValidatingSchema.push(...newSchemaFormats);
obj.else.allOf[1].if.properties.schemaFormat.enum = enumsForValidatingSchema;
} else {
throw new Error("Could not find location for schemaFormats that applies the AsyncAPI Schema object to the schema property");
}

fs.writeFileSync(objFile, JSON.stringify(obj, null, 2));
}

/**
* Adapt the root title and .asyncapi property
*/
function adaptRootObject(newVersion, newVersionDir) {
const objFile = path.resolve(newVersionDir, 'asyncapi.json');
const obj = require(objFile);
obj.title = `AsyncAPI ${newVersion} schema.`;
obj.properties.asyncapi.const = newVersion;
fs.writeFileSync(objFile, JSON.stringify(obj, null, 2));
}

async function addNewVersion(newVersion) {
const newVersionDir = `./definitions/${newVersion}`;
const newExampleVersionDir = `./examples/${newVersion}`;
Expand All @@ -38,11 +96,17 @@ async function addNewVersion(newVersion) {
await execute(`cp -R ./definitions/${latestVersion} ${newVersionDir}`);

const latestExampleVersion = (await execute('ls -d ./examples/* | sort -V -r | head -1 | xargs -n 1 basename')).trim();
await execute(`cp -R ./definitions/${latestVersion} ${newVersionDir}`);
await execute(`cp -R ./examples/${latestExampleVersion} ${newExampleVersionDir}`);

// Replace old version numbers with new
await execute(`find ${newVersionDir} -name '*.json' -exec sed -i '' "s+${latestVersion}+${newVersion}+g" {} +`);
// Replace $ref and $id paths such as `/3.0.0/` with new version (http://asyncapi.com/definitions/3.0.0/specificationExtension.json)
await execute(`find ${newVersionDir} -name '*.json' -exec sed -i '' \"s+\/${latestVersion}\/+\/${newVersion}\/+g\" {} +`);

// Replace .asyncapi version from old to new version
// Replace old version in title with new version
adaptRootObject(newVersion, newVersionDir);

// Add new schemaFormat version entries
addNewSchemaVersion(newVersion, newVersionDir, latestVersion);

console.log(`New version added to ${newVersionDir}`)
}
Expand Down