@asyncapi/nunjucks-filters
Version:
Library with Nunjucks filters for templates using AsyncAPI Generator
225 lines (195 loc) • 5.88 kB
JavaScript
const Markdown = require('markdown-it');
const _ = require('lodash');
const OpenAPISampler = require('openapi-sampler');
const filter = module.exports;
/**
* Turns Markdown into HTML
* @md {string} - String with valid Markdown syntax
* @returns {string} HTML string
*/
function markdown2html(md) {
return Markdown().render(md || '');
}
filter.markdown2html = markdown2html;
/**
* Logs input to server logs to stdout
* @str {string} Info that is logged
*/
function log(str) {
console.log(str);
}
filter.log = log;
/**
* Logs input to server as error to stderr
* @str {string} Info that is logged
*/
function logError(str) {
console.error(str);
}
filter.logError = logError;
/**
* Extracts example from the message payload
* @msg {object} - Parser Message function
* @returns {object}
*/
function getPayloadExamples(msg) {
const examples = msg.examples();
if (Array.isArray(examples) && examples.some(e => e.payload)) {
// Instead of flat or flatmap use this.
const messageExamples = _.flatMap(examples)
.map(e => {
if (!e.payload) return;
return {
name: e.name,
summary: e.summary,
example: e.payload,
};
})
.filter(Boolean);
if (messageExamples.length > 0) {
return messageExamples;
}
}
const payload = msg.payload();
if (payload && payload.examples()) {
return payload.examples().map(example => ({ example }));
}
}
filter.getPayloadExamples = getPayloadExamples;
/**
* Extracts example from the message header
* @msg {object} - Parser Message function
* @returns {object}
*/
function getHeadersExamples(msg) {
const examples = msg.examples();
if (Array.isArray(examples) && examples.some(e => e.headers)) {
// Instead of flat or flatmap use this.
const messageExamples = _.flatMap(examples)
.map(e => {
if (!e.headers) return;
return {
name: e.name,
summary: e.summary,
example: e.headers,
};
})
.filter(Boolean);
if (messageExamples.length > 0) {
return messageExamples;
}
}
const headers = msg.headers();
if (headers && headers.examples()) {
return headers.examples().map(example => ({ example }));
}
}
filter.getHeadersExamples = getHeadersExamples;
/**
* Generate string with example from provided schema
* @schema {object} - Schema object as JSON and not Schema model map
* @options {object} - Options object. Supported options are listed here https://github.com/Redocly/openapi-sampler#usage
* @returns {string}
*/
function generateExample(schema, options) {
return JSON.stringify(OpenAPISampler.sample(schema, options || {}) || '', null, 2);
}
filter.generateExample = generateExample;
/**
* Turns multiline string into one liner
* @str {string} - Any multiline string
* @returns {string}
*/
function oneLine(str) {
if (!str) return str;
return str.replace(/\n/g, ' ');
}
filter.oneLine = oneLine;
/**
* Generate JSDoc from message properties of the header and the payload
*
* @example
* docline(
* Schema {
* _json: {
* type: 'integer',
* minimum: 0,
* maximum: 100,
* 'x-parser-schema-id': '<anonymous-schema-3>'
* }
* },
* my-app-header,
* options.message.headers
* )
*
* Returned value will be -> * @param {integer} options.message.headers.my-app-header
*
* @field {object} - Property object
* @fieldName {string} - Name of documented property
* @scopePropName {string} - Name of param for JSDocs
* @returns {string} JSDoc compatible entry
*/
function docline(field, fieldName, scopePropName) {
/* eslint-disable sonarjs/cognitive-complexity */
const buildLine = (f, fName, pName) => {
const type = f.type() ? f.type() : 'string';
const description = f.description() ? ` - ${f.description().replace(/\r?\n|\r/g, '')}` : '';
let def = f.default();
if (def && type === 'string') def = `'${def}'`;
let line;
if (def !== undefined) {
line = ` * @param {${type}} [${pName ? `${pName}.` : ''}${fName}=${def}]`;
} else {
line = ` * @param {${type}} ${pName ? `${pName}.` : ''}${fName}`;
}
if (type === 'object') {
let lines = `${line}\n`;
let first = true;
for (const propName in f.properties()) {
lines = `${lines}${first ? '' : '\n'}${buildLine(f.properties()[propName], propName, `${pName ? `${pName}.` : ''}${fName}`)}`;
first = false;
}
return lines;
}
return `${line}${description}`;
};
return buildLine(field, fieldName, scopePropName);
}
filter.docline = docline;
/**
* Helper function to replace server variables in the url with actual values
* @url {string} - url string
* @serverserverVariables {Object} - Variables model map
* @returns {string}
*/
function replaceServerVariablesWithValues(url, serverVariables) {
const getVariablesNamesFromUrl = (inputUrl) => {
const result = [];
let array = [];
const regEx = /{([^}]+)}/g;
while ((array = regEx.exec(inputUrl)) !== null) {
result.push([array[0], array[1]]);
}
return result;
};
const getVariableValue = (object, variable) => {
const keyValue = object[variable]._json;
if (keyValue) return keyValue.default || (keyValue.enum && keyValue.enum[0]);
};
const urlVariables = getVariablesNamesFromUrl(url);
const declaredVariables =
urlVariables.filter(el => serverVariables.hasOwnProperty(el[1]));
if (urlVariables.length !== 0 && declaredVariables.length !== 0) {
let value;
let newUrl = url;
urlVariables.forEach(el => {
value = getVariableValue(serverVariables, el[1]);
if (value) {
newUrl = newUrl.replace(el[0], value);
}
});
return newUrl;
}
return url;
}
filter.replaceServerVariablesWithValues = replaceServerVariablesWithValues;