Skip to content

Commit

Permalink
feat!: switch template from nunjucks to react rendering engine (#267)
Browse files Browse the repository at this point in the history
Co-authored-by: Lukasz Gornicki <[email protected]>
  • Loading branch information
kaushik-rishi and derberg authored Mar 22, 2024
1 parent 1efc15c commit 391dd6f
Show file tree
Hide file tree
Showing 26 changed files with 11,950 additions and 7,509 deletions.
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
__transpiled/
node_modules
test/temp
template/src/lib/config.js
Expand Down
13 changes: 10 additions & 3 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,19 @@ env:
plugins:
- jest
- sonarjs
- react

extends:
- plugin:sonarjs/recommended
- plugin:react/recommended

parserOptions:
ecmaVersion: 2018


sourceType: module

rules:
# Ignore Rules
react/react-in-jsx-scope: 0
strict: 0
no-underscore-dangle: 0
no-mixed-requires: 0
Expand Down Expand Up @@ -98,4 +100,9 @@ rules:
prefer-arrow-callback: 2
prefer-const: 2
prefer-spread: 2
prefer-template: 2
prefer-template: 2
space-before-function-paren: "off"

react/prop-types: "off"
react/jsx-key: "off"
sonarjs/no-nested-template-literals: "off"
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
node_modules
output
test/temp
__transpiled/
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
- [Specification requirements](#specification-requirements)
- [Supported protocols](#supported-protocols)
- [How to use the template](#how-to-use-the-template)
* [CLI](#cli)
* [Adding custom code / handlers](#adding-custom-code--handlers)
- [CLI](#cli)
- [Adding custom code / handlers](#adding-custom-code--handlers)
- [Template configuration](#template-configuration)
- [Development](#development)
- [Contributors](#contributors)
Expand Down Expand Up @@ -231,7 +231,7 @@ $ ag https://bit.ly/asyncapi ./ -o output -p server=production
```

For local development, you need different variations of this command. First of all, you need to know about three important CLI flags:
- `--debug` enables the debug mode in Nunjucks engine what makes filters debugging simpler.
- `--debug` enables the debug mode in React rendering engine what makes filters debugging simpler.
- `--watch-template` enables a watcher of changes that you make in the template. It regenerates your template whenever it detects a change.
- `--install` enforces reinstallation of the template.

Expand Down
115 changes: 33 additions & 82 deletions filters/all.js → helpers/channels-topics.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
const filter = module.exports;
const { URL } = require('url');
const filenamify = require('filenamify');
const _ = require('lodash');
import { URL } from 'url';
import filenamify from 'filenamify';
import _ from 'lodash';

function queueName(title, version) {
export function queueName(title, version) {
return _.kebabCase(`${title}-${version}`.toLowerCase()).split('-').join('.');
}
filter.queueName = queueName;

function toMqttTopic(topics, shouldAppendWildcard = false) {
export function toMqttTopic(topics, shouldAppendWildcard = false) {
const toMqtt = (str, appendWildcard = false) => {
let result = str;
if (result === '/') return '#';
Expand All @@ -21,9 +19,8 @@ function toMqttTopic(topics, shouldAppendWildcard = false) {
if (typeof topics === 'string') return toMqtt(topics, shouldAppendWildcard);
if (Array.isArray(topics)) return topics.map(toMqtt);
}
filter.toMqttTopic = toMqttTopic;

function toKafkaTopic(topics) {
export function toKafkaTopic(topics) {
const toKafka = (str) => {
let result = str;
if (result.startsWith('/')) result = result.substr(1);
Expand All @@ -34,9 +31,8 @@ function toKafkaTopic(topics) {
if (typeof topics === 'string') return toKafka(topics);
if (Array.isArray(topics)) return topics.map(toKafka);
}
filter.toKafkaTopic = toKafkaTopic;

function toAmqpTopic(topics, shouldAppendWildcard = false) {
export function toAmqpTopic(topics, shouldAppendWildcard = false) {
const toAmqp = (str, appendWildcard = false) => {
let result = str;
if (result === '/') return '#';
Expand All @@ -49,98 +45,50 @@ function toAmqpTopic(topics, shouldAppendWildcard = false) {
if (typeof topics === 'string') return toAmqp(topics, shouldAppendWildcard);
if (Array.isArray(topics)) return topics.map(toAmqp);
}
filter.toAmqpTopic = toAmqpTopic;

function toHermesTopic(str) {
export function toHermesTopic(str) {
return str.replace(/\{([^}]+)\}/g, ':$1');
}
filter.toHermesTopic = toHermesTopic;

function commonChannel(asyncapi, removeTrailingParameters = false) {
const channelNames = asyncapi.channelNames().sort().map(ch => ch.split('/'));
if (!channelNames.length) return '';
if (channelNames.length === 1) return asyncapi.channelNames()[0];

let result = [];
for (let i = 0; i < channelNames.length - 1; i++) {
let ch1;
if (i === 0) {
ch1 = channelNames[0];
} else {
ch1 = result.concat(); // Makes a copy
result = [];
}
const ch2 = channelNames[i + 1];
let x = 0;
let shouldContinue = true;
while (shouldContinue) {
if (x > Math.max(ch1.length, ch2.length) - 1 || ch1[x] !== ch2[x]) {
shouldContinue = false;
} else {
result.push(ch1[x]);
x++;
}
}
}

if (removeTrailingParameters) {
for (let index = result.length - 1; index >= 0; index--) {
const chunk = result[index];
if (chunk.match(/^\{.+\}$/)) {
result.pop();
}
}
}

return result.join('/');
}

filter.commonChannel = commonChannel;

function channelNamesWithPublish(asyncapi) {
export function channelNamesWithPublish(asyncapi) {
const result = [];
asyncapi.channelNames().forEach(name => {
asyncapi.channelNames().forEach((name) => {
if (asyncapi.channel(name).hasPublish()) result.push(name);
});
return result;
}
filter.channelNamesWithPublish = channelNamesWithPublish;

function host(url) {
export function host(url) {
const u = new URL(url);
return u.host;
}
filter.host = host;

function port(url, defaultPort) {
export function port(url, defaultPort) {
const u = new URL(url);
return u.port || defaultPort;
}
filter.port = port;

function stripProtocol(url) {
export function stripProtocol(url) {
if (!url.includes('://')) {
return url;
}
const u = new URL(url);
return url.substr(u.protocol.length + 2);
}
filter.stripProtocol = stripProtocol;

function trimLastChar(string) {
export function trimLastChar(string) {
return string.substr(0, string.length - 1);
}
filter.trimLastChar = trimLastChar;

function convertOpertionIdToMiddlewareFn(operationId) {
const capitalizedOperationId = operationId.charAt(0).toUpperCase() + operationId.slice(1);
return `register${ capitalizedOperationId }Middleware`;
export function convertOpertionIdToMiddlewareFn(operationId) {
const capitalizedOperationId =
operationId.charAt(0).toUpperCase() + operationId.slice(1);
return `register${capitalizedOperationId}Middleware`;
}
filter.convertOpertionIdToMiddlewareFn = convertOpertionIdToMiddlewareFn;

function toJS(objFromJSON, indent = 2) {
export function toJS(objFromJSON, indent = 2) {
if (typeof objFromJSON !== 'object' || Array.isArray(objFromJSON)) {
// not an object, stringify using native function
// not an object, stringify using native export function
if (typeof objFromJSON === 'string') {
const templateVars = objFromJSON.match(/\$\{[\w\d\.]+\}/g);
if (templateVars) return `\`${objFromJSON}\``;
Expand All @@ -156,18 +104,18 @@ function toJS(objFromJSON, indent = 2) {

// Implements recursive object serialization according to JSON spec
// but without quotes around the keys.
const props = Object
.keys(objFromJSON)
.map(key => `${' '.repeat(indent)}${maybeQuote(key)}: ${toJS(objFromJSON[key])}`)
const props = Object.keys(objFromJSON)
.map(
(key) =>
`${' '.repeat(indent)}${maybeQuote(key)}: ${toJS(objFromJSON[key])}`
)
.join(',\n');
return `{\n${props}\n}`;
}
filter.toJS = toJS;

function convertToFilename(string, options) {
export function convertToFilename(string, options) {
return filenamify(string, options || { replacement: '-', maxLength: 255 });
}
filter.convertToFilename = convertToFilename;

/**
* Replaces variables in the server url with its declared values. Default or first enum in case of default is not declared
Expand All @@ -178,7 +126,7 @@ filter.convertToFilename = convertToFilename;
* @return {String}
*/

function getConfig(p) {
export function getConfig(p) {
let protocol = p;
let configName = 'broker';

Expand All @@ -191,13 +139,16 @@ function getConfig(p) {

return `config.${configName}.${protocol}`;
}
filter.getConfig = getConfig;

function getProtocol(p) {
export function getProtocol(p) {
let protocol = p;

if (p === 'kafka-secure') protocol = 'kafka';

return protocol;
}
filter.getProtocol = getProtocol;

// https://mozilla.github.io/nunjucks/templating.html#dump
export function dump(obj) {
return JSON.stringify(obj);
}
22 changes: 22 additions & 0 deletions helpers/general.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import _ from 'lodash';

export function camelCase(string) {
return _.camelCase(string);
}

export function pascalCase(string) {
string = _.camelCase(string);
return string.charAt(0).toUpperCase() + string.slice(1);
}

export function kebabCase(string) {
return _.kebabCase(string);
}

export function capitalize(string) {
return _.capitalize(string);
}

export function oneLine(string) {
return string.replace(/\n/g, ' ').trim();
}
2 changes: 2 additions & 0 deletions helpers/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './general';
export * from './channels-topics';
64 changes: 64 additions & 0 deletions hooks/beautify-output.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
const fs = require('fs');
const path = require('path');
const beautify = require('js-beautify').js;

const beautifyConfig = {
indent_size: '2',
indent_char: ' ',
max_preserve_newlines: '2',
preserve_newlines: true,
keep_array_indentation: false,
break_chained_methods: false,
indent_scripts: 'normal',
brace_style: 'collapse',
space_before_conditional: true,
unescape_strings: false,
jslint_happy: false,
end_with_newline: false,
wrap_line_length: '0',
indent_inner_html: false,
comma_first: false,
e4x: false,
indent_empty_lines: false,
};

const beautifySingleFile = (filePath) => {
const fileData = fs.readFileSync(filePath);
const beautifiedData = beautify(fileData.toString(), beautifyConfig);
fs.writeFileSync(filePath, beautifiedData);
};

/**
* Recursively beautify all files in directory
*
* @param {string} dirPath to recursively beautify files in
*/
const beautifyAllOutputFiles = function (dirPath) {
const files = fs.readdirSync(dirPath);
files.forEach((file) => {
const filePath = path.join(dirPath, file);
if (fs.statSync(filePath).isDirectory()) {
beautifyAllOutputFiles(filePath);
} else {
beautifySingleFile(filePath);
}
});
};

/**
* Format all source files with indentations and new lines
*/
module.exports = {
'generate:after': (generator) => {
const entryPointFilePath = path.resolve(
generator.targetDir,
'src/api/index.js'
);
const handlersPath = path.resolve(generator.targetDir, 'src/api/handlers');
const routesPath = path.resolve(generator.targetDir, 'src/api/routes');

beautifyAllOutputFiles(handlersPath);
beautifyAllOutputFiles(routesPath);
beautifySingleFile(entryPointFilePath);
},
};
Loading

0 comments on commit 391dd6f

Please sign in to comment.