@asyncapi/generator 2.8.4 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +39 -0
- package/docs/api.md +2 -51
- package/docs/asyncapi-document.md +1 -1
- package/docs/configuration-file.md +0 -4
- package/docs/file-templates.md +1 -59
- package/docs/generator-template-java.md +0 -2
- package/docs/generator-template.md +1 -4
- package/docs/index.md +2 -2
- package/docs/jsdoc2md-handlebars/main-index/global-index/global-index-dl.hbs +13 -0
- package/docs/jsdoc2md-handlebars/member-index-grouped.hbs +6 -0
- package/docs/jsdoc2md-handlebars/member-index-list.hbs +6 -0
- package/docs/jsdoc2md-handlebars/members.hbs +1 -0
- package/docs/react-render-engine.md +5 -37
- package/docs/template-development.md +2 -7
- package/docs/template.md +2 -2
- package/docs/typescript-support.md +3 -5
- package/jest.config.js +3 -6
- package/lib/__mocks__/utils.js +0 -3
- package/lib/generator.js +4 -20
- package/lib/templates/bakedInTemplates/core-template-client-kafka-java-quarkus/.ageneratorrc +2 -4
- package/lib/templates/bakedInTemplates/core-template-client-kafka-java-quarkus/__transpiled/jest.config.js +13 -0
- package/lib/templates/bakedInTemplates/core-template-client-kafka-java-quarkus/__transpiled/jest.config.js.map +1 -0
- package/lib/templates/bakedInTemplates/core-template-client-kafka-java-quarkus/jest.config.js +14 -0
- package/lib/templates/bakedInTemplates/core-template-client-kafka-java-quarkus/package.json +3 -17
- package/lib/templates/bakedInTemplates/core-template-client-websocket-dart/.ageneratorrc +0 -1
- package/lib/templates/bakedInTemplates/core-template-client-websocket-dart/__transpiled/jest.config.js +13 -0
- package/lib/templates/bakedInTemplates/core-template-client-websocket-dart/__transpiled/jest.config.js.map +1 -0
- package/lib/templates/bakedInTemplates/core-template-client-websocket-dart/jest.config.js +14 -0
- package/lib/templates/bakedInTemplates/core-template-client-websocket-dart/package.json +3 -17
- package/lib/templates/bakedInTemplates/core-template-client-websocket-java-quarkus/.ageneratorrc +0 -2
- package/lib/templates/bakedInTemplates/core-template-client-websocket-java-quarkus/__transpiled/jest.config.js +13 -0
- package/lib/templates/bakedInTemplates/core-template-client-websocket-java-quarkus/__transpiled/jest.config.js.map +1 -0
- package/lib/templates/bakedInTemplates/core-template-client-websocket-java-quarkus/jest.config.js +14 -0
- package/lib/templates/bakedInTemplates/core-template-client-websocket-java-quarkus/package.json +4 -18
- package/lib/templates/bakedInTemplates/core-template-client-websocket-javascript/.ageneratorrc +8 -1
- package/lib/templates/bakedInTemplates/core-template-client-websocket-javascript/__transpiled/components/ClientClass.js +5 -1
- package/lib/templates/bakedInTemplates/core-template-client-websocket-javascript/__transpiled/components/ClientClass.js.map +1 -1
- package/lib/templates/bakedInTemplates/core-template-client-websocket-javascript/__transpiled/components/CompileOperationSchemas.js +48 -0
- package/lib/templates/bakedInTemplates/core-template-client-websocket-javascript/__transpiled/components/CompileOperationSchemas.js.map +1 -0
- package/lib/templates/bakedInTemplates/core-template-client-websocket-javascript/__transpiled/components/Constructor.js +7 -1
- package/lib/templates/bakedInTemplates/core-template-client-websocket-javascript/__transpiled/components/Constructor.js.map +1 -1
- package/lib/templates/bakedInTemplates/core-template-client-websocket-javascript/__transpiled/jest.config.js +13 -0
- package/lib/templates/bakedInTemplates/core-template-client-websocket-javascript/__transpiled/jest.config.js.map +1 -0
- package/lib/templates/bakedInTemplates/core-template-client-websocket-javascript/__transpiled/template/README.md.js +5 -153
- package/lib/templates/bakedInTemplates/core-template-client-websocket-javascript/__transpiled/template/README.md.js.map +1 -1
- package/lib/templates/bakedInTemplates/core-template-client-websocket-javascript/__transpiled/template/client.js.js +52 -3
- package/lib/templates/bakedInTemplates/core-template-client-websocket-javascript/__transpiled/template/client.js.js.map +1 -1
- package/lib/templates/bakedInTemplates/core-template-client-websocket-javascript/components/ClientClass.js +4 -2
- package/lib/templates/bakedInTemplates/core-template-client-websocket-javascript/components/CompileOperationSchemas.js +40 -0
- package/lib/templates/bakedInTemplates/core-template-client-websocket-javascript/components/Constructor.js +7 -1
- package/lib/templates/bakedInTemplates/core-template-client-websocket-javascript/jest.config.js +14 -0
- package/lib/templates/bakedInTemplates/core-template-client-websocket-javascript/package.json +7 -20
- package/lib/templates/bakedInTemplates/core-template-client-websocket-javascript/template/README.md.js +2 -103
- package/lib/templates/bakedInTemplates/core-template-client-websocket-javascript/template/client.js.js +5 -1
- package/lib/templates/bakedInTemplates/core-template-client-websocket-python/.ageneratorrc +0 -1
- package/lib/templates/bakedInTemplates/core-template-client-websocket-python/__transpiled/jest.config.js +13 -0
- package/lib/templates/bakedInTemplates/core-template-client-websocket-python/__transpiled/jest.config.js.map +1 -0
- package/lib/templates/bakedInTemplates/core-template-client-websocket-python/__transpiled/template/README.md.js +18 -0
- package/lib/templates/bakedInTemplates/core-template-client-websocket-python/__transpiled/template/README.md.js.map +1 -0
- package/lib/templates/bakedInTemplates/core-template-client-websocket-python/jest.config.js +14 -0
- package/lib/templates/bakedInTemplates/core-template-client-websocket-python/package.json +3 -17
- package/lib/templates/bakedInTemplates/core-template-client-websocket-python/template/README.md.js +5 -0
- package/lib/templates/config/validator.js +3 -3
- package/lib/utils.js +0 -21
- package/package.json +7 -14
- package/Dockerfile +0 -20
- package/cli.js +0 -205
- package/docs/migration-cli.md +0 -70
- package/docs/migration-nunjucks-react.md +0 -144
- package/docs/nunjucks-render-engine.md +0 -83
- package/lib/filtersRegistry.js +0 -134
- package/lib/renderer/nunjucks.js +0 -42
- package/lib/templates/bakedInTemplates/core-template-client-websocket-javascript/__transpiled/components/AvailableOperations.js +0 -34
- package/lib/templates/bakedInTemplates/core-template-client-websocket-javascript/__transpiled/components/AvailableOperations.js.map +0 -1
- package/lib/templates/bakedInTemplates/core-template-client-websocket-javascript/__transpiled/components/MessageExamples.js +0 -29
- package/lib/templates/bakedInTemplates/core-template-client-websocket-javascript/__transpiled/components/MessageExamples.js.map +0 -1
- package/lib/templates/bakedInTemplates/core-template-client-websocket-javascript/__transpiled/components/OperationHeader.js +0 -19
- package/lib/templates/bakedInTemplates/core-template-client-websocket-javascript/__transpiled/components/OperationHeader.js.map +0 -1
- package/lib/templates/bakedInTemplates/core-template-client-websocket-javascript/components/AvailableOperations.js +0 -20
- package/lib/templates/bakedInTemplates/core-template-client-websocket-javascript/components/MessageExamples.js +0 -25
- package/lib/templates/bakedInTemplates/core-template-client-websocket-javascript/components/OperationHeader.js +0 -12
- package/lib/watcher.js +0 -147
package/Dockerfile
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
FROM node:18-alpine
|
|
2
|
-
|
|
3
|
-
ARG ASYNCAPI_GENERATOR_VERSION=1.10.9
|
|
4
|
-
|
|
5
|
-
WORKDIR /app
|
|
6
|
-
|
|
7
|
-
# Since 0.14.0 release of html-template chromium is needed for pdf generation
|
|
8
|
-
ENV PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium-browser
|
|
9
|
-
ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true
|
|
10
|
-
|
|
11
|
-
# Since 0.30.0 release Git is supported and required as a dependency
|
|
12
|
-
# Since 0.14.0 release of html-template chromium is needed for pdf generation.
|
|
13
|
-
# More custom packages for specific template should not be added to this dockerfile. Instead, we should come up with some extensibility solution.
|
|
14
|
-
# Installing latest released npm package
|
|
15
|
-
RUN apk --update add git chromium && \
|
|
16
|
-
rm /var/cache/apk/* && \
|
|
17
|
-
npm install --ignore-scripts -g "@asyncapi/generator@${ASYNCAPI_GENERATOR_VERSION}"
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
ENTRYPOINT [ "ag" ]
|
package/cli.js
DELETED
|
@@ -1,205 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
const path = require('path');
|
|
4
|
-
const os = require('os');
|
|
5
|
-
const program = require('commander');
|
|
6
|
-
const xfs = require('fs.extra');
|
|
7
|
-
const { DiagnosticSeverity } = require('@asyncapi/parser/cjs');
|
|
8
|
-
const packageInfo = require('./package.json');
|
|
9
|
-
const Generator = require('./lib/generator');
|
|
10
|
-
const Watcher = require('./lib/watcher');
|
|
11
|
-
const { isLocalTemplate, isFilePath } = require('./lib/utils');
|
|
12
|
-
|
|
13
|
-
const red = text => `\x1b[31m${text}\x1b[0m`;
|
|
14
|
-
const magenta = text => `\x1b[35m${text}\x1b[0m`;
|
|
15
|
-
const yellow = text => `\x1b[33m${text}\x1b[0m`;
|
|
16
|
-
const green = text => `\x1b[32m${text}\x1b[0m`;
|
|
17
|
-
|
|
18
|
-
let asyncapiDocPath;
|
|
19
|
-
let template;
|
|
20
|
-
const params = {};
|
|
21
|
-
const noOverwriteGlobs = [];
|
|
22
|
-
const disabledHooks = {};
|
|
23
|
-
const mapBaseUrlToFolder = {};
|
|
24
|
-
|
|
25
|
-
const parseOutput = dir => path.resolve(dir);
|
|
26
|
-
|
|
27
|
-
const paramParser = v => {
|
|
28
|
-
if (!v.includes('=')) throw new Error(`Invalid param ${v}. It must be in the format of --param name=value.`);
|
|
29
|
-
const [paramName, paramValue] = v.split(/=(.+)/, 2);
|
|
30
|
-
params[paramName] = paramValue;
|
|
31
|
-
return v;
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
const noOverwriteParser = v => noOverwriteGlobs.push(v);
|
|
35
|
-
|
|
36
|
-
const disableHooksParser = v => {
|
|
37
|
-
const [hookType, hookNames] = v.split(/=/);
|
|
38
|
-
if (!hookType) throw new Error('Invalid --disable-hook flag. It must be in the format of: --disable-hook <hookType> or --disable-hook <hookType>=<hookName1>,<hookName2>,...');
|
|
39
|
-
if (hookNames) {
|
|
40
|
-
disabledHooks[hookType] = hookNames.split(/,/);
|
|
41
|
-
} else {
|
|
42
|
-
disabledHooks[hookType] = true;
|
|
43
|
-
}
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
const mapBaseUrlParser = v => {
|
|
47
|
-
// Example value for regular expression: https://schema.example.com/crm/:./test/docs/
|
|
48
|
-
// it splits on last occurrence of : into the groups all, url and folder
|
|
49
|
-
const re = /(.*):(.*)/g;
|
|
50
|
-
let mapping = [];
|
|
51
|
-
if ((mapping = re.exec(v))===null || mapping.length!==3) {
|
|
52
|
-
throw new Error('Invalid --map-base-url flag. A mapping <url>:<folder> with delimiter : expected.');
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// Folder is without trailing slash, so make sure that url has also no trailing slash:
|
|
56
|
-
mapBaseUrlToFolder.url = mapping[1].replace(/\/$/, '');
|
|
57
|
-
mapBaseUrlToFolder.folder = path.resolve(mapping[2]);
|
|
58
|
-
|
|
59
|
-
const isURL = /^https?:/;
|
|
60
|
-
if (!isURL.test(mapBaseUrlToFolder.url.toLowerCase())) {
|
|
61
|
-
throw new Error('Invalid --map-base-url flag. The mapping <url>:<folder> requires a valid http/https url and valid folder with delimiter `:`.');
|
|
62
|
-
}
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
const showError = err => {
|
|
66
|
-
console.error(red('Something went wrong:'));
|
|
67
|
-
console.error(red(err.stack || err.message));
|
|
68
|
-
if (err.diagnostics) {
|
|
69
|
-
const errorDiagnostics = err.diagnostics.filter(diagnostic => diagnostic.severity === DiagnosticSeverity.Error);
|
|
70
|
-
console.error(red(`Errors:\n${JSON.stringify(errorDiagnostics, undefined, 2)}`));
|
|
71
|
-
}
|
|
72
|
-
};
|
|
73
|
-
const showErrorAndExit = err => {
|
|
74
|
-
showError(err);
|
|
75
|
-
process.exit(1);
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
program
|
|
79
|
-
.version(packageInfo.version)
|
|
80
|
-
.arguments('<asyncapi> <template>')
|
|
81
|
-
.action((fileLoc, tmpl) => {
|
|
82
|
-
asyncapiDocPath = fileLoc;
|
|
83
|
-
template = tmpl;
|
|
84
|
-
})
|
|
85
|
-
.option('-d, --disable-hook [hooks...]', 'disable a specific hook type or hooks from given hook type', disableHooksParser)
|
|
86
|
-
.option('--debug', 'enable more specific errors in the console')
|
|
87
|
-
.option('-i, --install', 'installs the template and its dependencies (defaults to false)')
|
|
88
|
-
.option('-n, --no-overwrite <glob>', 'glob or path of the file(s) to skip when regenerating', noOverwriteParser)
|
|
89
|
-
.option('-o, --output <outputDir>', 'directory where to put the generated files (defaults to current directory)', parseOutput, process.cwd())
|
|
90
|
-
.option('-p, --param <name=value>', 'additional param to pass to templates', paramParser)
|
|
91
|
-
.option('--force-write', 'force writing of the generated files to given directory even if it is a git repo with unstaged files or not empty dir (defaults to false)')
|
|
92
|
-
.option('--disable-warning', 'disable "ag" deprecation warning (defaults to false)')
|
|
93
|
-
.option('--watch-template', 'watches the template directory and the AsyncAPI document, and re-generate the files when changes occur. Ignores the output directory. This flag should be used only for template development.')
|
|
94
|
-
.option('--map-base-url <url:folder>','maps all schema references from base url to local folder',mapBaseUrlParser)
|
|
95
|
-
.parse(process.argv);
|
|
96
|
-
|
|
97
|
-
if (!program.disableWarning) {
|
|
98
|
-
console.warn(yellow(
|
|
99
|
-
'Warning: The "ag" CLI is deprecated and will be removed in a future release. Please use the AsyncAPI CLI instead. See release notes for details: https://github.com/asyncapi/generator/releases/tag/%40asyncapi%2Fgenerator%402.6.0. You can hide this working using --disable-warning flag.')
|
|
100
|
-
);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
if (!asyncapiDocPath) {
|
|
104
|
-
console.error(red('> Path or URL to AsyncAPI file not provided.'));
|
|
105
|
-
program.help(); // This exits the process
|
|
106
|
-
}
|
|
107
|
-
const isAsyncapiDocLocal = isFilePath(asyncapiDocPath);
|
|
108
|
-
|
|
109
|
-
xfs.mkdirp(program.output, async err => {
|
|
110
|
-
if (err) return showErrorAndExit(err);
|
|
111
|
-
try {
|
|
112
|
-
await generate(program.output);
|
|
113
|
-
} catch (e) {
|
|
114
|
-
return showErrorAndExit(e);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
// If we want to watch for changes do that
|
|
118
|
-
if (program.watchTemplate) {
|
|
119
|
-
let watcher;
|
|
120
|
-
const watchDir = path.resolve(template);
|
|
121
|
-
const outputPath = path.resolve(watchDir, program.output);
|
|
122
|
-
const transpiledTemplatePath = path.resolve(watchDir, Generator.TRANSPILED_TEMPLATE_LOCATION);
|
|
123
|
-
const ignorePaths = [outputPath, transpiledTemplatePath];
|
|
124
|
-
// Template name is needed as it is not always a part of the cli commad
|
|
125
|
-
// There is a use case that you run generator from a root of the template with `./` path
|
|
126
|
-
const templateName = require(path.resolve(watchDir,'package.json')).name;
|
|
127
|
-
|
|
128
|
-
if (isAsyncapiDocLocal) {
|
|
129
|
-
console.log(`[WATCHER] Watching for changes in the template directory ${magenta(watchDir)} and in the AsyncAPI file ${magenta(asyncapiDocPath)}`);
|
|
130
|
-
watcher = new Watcher([asyncapiDocPath, watchDir], ignorePaths);
|
|
131
|
-
} else {
|
|
132
|
-
console.log(`[WATCHER] Watching for changes in the template directory ${magenta(watchDir)}`);
|
|
133
|
-
watcher = new Watcher(watchDir, ignorePaths);
|
|
134
|
-
}
|
|
135
|
-
// Must check template in its installation path in generator to use isLocalTemplate function
|
|
136
|
-
if (!await isLocalTemplate(path.resolve(Generator.DEFAULT_TEMPLATES_DIR, templateName))) {
|
|
137
|
-
console.warn(`WARNING: ${template} is a remote template. Changes may be lost on subsequent installations.`);
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
await watcher.watch(watcherHandler, (paths) => {
|
|
141
|
-
showErrorAndExit({ message: `[WATCHER] Could not find the file path ${paths}, are you sure it still exists? If it has been deleted or moved please rerun the generator.` });
|
|
142
|
-
});
|
|
143
|
-
}
|
|
144
|
-
});
|
|
145
|
-
|
|
146
|
-
/**
|
|
147
|
-
* Generates the files based on the template.
|
|
148
|
-
* @param {*} targetDir The path to the target directory.
|
|
149
|
-
*/
|
|
150
|
-
function generate(targetDir) {
|
|
151
|
-
return new Promise(async (resolve, reject) => {
|
|
152
|
-
try {
|
|
153
|
-
const generator = new Generator(template, targetDir || path.resolve(os.tmpdir(), 'asyncapi-generator'), {
|
|
154
|
-
templateParams: params,
|
|
155
|
-
noOverwriteGlobs,
|
|
156
|
-
disabledHooks,
|
|
157
|
-
forceWrite: program.forceWrite,
|
|
158
|
-
install: program.install,
|
|
159
|
-
debug: program.debug,
|
|
160
|
-
mapBaseUrlToFolder
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
if (isAsyncapiDocLocal) {
|
|
164
|
-
await generator.generateFromFile(path.resolve(asyncapiDocPath));
|
|
165
|
-
} else {
|
|
166
|
-
await generator.generateFromURL(asyncapiDocPath);
|
|
167
|
-
}
|
|
168
|
-
console.log(green('\n\nDone! ✨'));
|
|
169
|
-
console.log(`${yellow('Check out your shiny new generated files at ') + magenta(program.output) + yellow('.')}\n`);
|
|
170
|
-
resolve();
|
|
171
|
-
} catch (e) {
|
|
172
|
-
reject(e);
|
|
173
|
-
}
|
|
174
|
-
});
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
async function watcherHandler(changedFiles) {
|
|
178
|
-
console.clear();
|
|
179
|
-
console.log('[WATCHER] Change detected');
|
|
180
|
-
for (const [, value] of Object.entries(changedFiles)) {
|
|
181
|
-
let eventText;
|
|
182
|
-
switch (value.eventType) {
|
|
183
|
-
case 'changed':
|
|
184
|
-
eventText = green(value.eventType);
|
|
185
|
-
break;
|
|
186
|
-
case 'removed':
|
|
187
|
-
eventText = red(value.eventType);
|
|
188
|
-
break;
|
|
189
|
-
case 'renamed':
|
|
190
|
-
eventText = yellow(value.eventType);
|
|
191
|
-
break;
|
|
192
|
-
default:
|
|
193
|
-
eventText = yellow(value.eventType);
|
|
194
|
-
}
|
|
195
|
-
console.log(`\t${magenta(value.path)} was ${eventText}`);
|
|
196
|
-
}
|
|
197
|
-
console.log('Generating files');
|
|
198
|
-
try {
|
|
199
|
-
await generate(program.output);
|
|
200
|
-
} catch (e) {
|
|
201
|
-
showError(e);
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
process.on('unhandledRejection', showErrorAndExit);
|
package/docs/migration-cli.md
DELETED
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: "Migrating from `ag` CLI to AsyncAPI CLI"
|
|
3
|
-
weight: 260
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
This guide provides detailed instructions on how to transition from the old `ag` Generator CLI to the new AsyncAPI CLI.
|
|
7
|
-
|
|
8
|
-
## Options Overview
|
|
9
|
-
|
|
10
|
-
Here is a list of `ag` options and their equivalents in the AsyncAPI CLI:
|
|
11
|
-
|
|
12
|
-
- **-d, --disable-hook [hooks...]**
|
|
13
|
-
- **AsyncAPI CLI equivalent:** `asyncapi generate fromTemplate <ASYNCAPI> <TEMPLATE> --disable-hook <hookType>=<hookName>`
|
|
14
|
-
|
|
15
|
-
- **--debug**
|
|
16
|
-
- **AsyncAPI CLI equivalent:** `asyncapi generate fromTemplate <ASYNCAPI> <TEMPLATE> --debug`
|
|
17
|
-
|
|
18
|
-
- **-i, --install**
|
|
19
|
-
- **AsyncAPI CLI equivalent:** `asyncapi generate fromTemplate <ASYNCAPI> <TEMPLATE> --install`
|
|
20
|
-
|
|
21
|
-
- **-n, --no-overwrite <glob>**
|
|
22
|
-
- **AsyncAPI CLI equivalent:** `asyncapi generate fromTemplate <ASYNCAPI> <TEMPLATE> --no-overwrite <glob>`
|
|
23
|
-
|
|
24
|
-
- **-o, --output <outputDir>**
|
|
25
|
-
- **AsyncAPI CLI equivalent:** `asyncapi generate fromTemplate <ASYNCAPI> <TEMPLATE> --output <outputDir>`
|
|
26
|
-
|
|
27
|
-
- **-p, --param <name=value>**
|
|
28
|
-
- **AsyncAPI CLI equivalent:** `asyncapi generate fromTemplate <ASYNCAPI> <TEMPLATE> --param <name=value>`
|
|
29
|
-
|
|
30
|
-
- **--force-write**
|
|
31
|
-
- **AsyncAPI CLI equivalent:** `asyncapi generate fromTemplate <ASYNCAPI> <TEMPLATE> --force-write`
|
|
32
|
-
|
|
33
|
-
- **--watch-template**
|
|
34
|
-
- **AsyncAPI CLI equivalent:** `asyncapi generate fromTemplate <ASYNCAPI> <TEMPLATE> --watch`
|
|
35
|
-
|
|
36
|
-
- **--map-base-url <url:folder>**
|
|
37
|
-
- **AsyncAPI CLI equivalent:** `asyncapi generate fromTemplate <ASYNCAPI> <TEMPLATE> --map-base-url <url:folder>`
|
|
38
|
-
|
|
39
|
-
## Migration Steps
|
|
40
|
-
|
|
41
|
-
### 1. Install AsyncAPI CLI
|
|
42
|
-
|
|
43
|
-
There are multiple different artifacts that AsyncAPI CLI is provided as. Get familiar with the [official CLI installation guide](https://www.asyncapi.com/docs/tools/cli/installation).
|
|
44
|
-
|
|
45
|
-
### 2. Update Your Commands
|
|
46
|
-
|
|
47
|
-
Replace the deprecated `ag` commands with the AsyncAPI CLI equivalents. Below are examples of how to update your commands:
|
|
48
|
-
|
|
49
|
-
**Using `ag`**:
|
|
50
|
-
```
|
|
51
|
-
ag ./asyncapi.yaml ./template -o ./output -p param1=value1 --debug --install --disable-hook hookType=hookName
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
**Using AsyncAPI CLI**:
|
|
55
|
-
```
|
|
56
|
-
asyncapi generate fromTemplate ./asyncapi.yaml ./template -o ./output -p param1=value1 --debug --install --disable-hook hookType=hookName
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
Notice that the change basically related to changing from `ag` to `asyncapi generate fromTemplate`.
|
|
60
|
-
|
|
61
|
-
### 3. Verify and Test
|
|
62
|
-
|
|
63
|
-
Run the updated commands to ensure they work as expected and verify that the output files are generated correctly.
|
|
64
|
-
|
|
65
|
-
## Additional Resources
|
|
66
|
-
|
|
67
|
-
**CLI Documentation**: [AsyncAPI CLI Documentation](https://www.asyncapi.com/docs/tools/cli)
|
|
68
|
-
**Installation**: [AsyncAPI CLI Installation](https://www.asyncapi.com/docs/tools/cli/installation)
|
|
69
|
-
**Usage**: [AsyncAPI CLI Usage](https://www.asyncapi.com/docs/tools/cli/usage)
|
|
70
|
-
**Support**: For any issues with CLI, create an issue in [CLI repository](https://github.com/asyncapi/cli).
|
|
@@ -1,144 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: "Migrating from Nunjucks to React render engine"
|
|
3
|
-
weight: 250
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
The AsyncAPI Generator is moving away from Nunjucks templates in favor of React templates. This guide will help you migrate your existing Nunjucks templates to React. For a comprehensive understanding of why we introduced React as an alternative in 2021 and why we're now removing Nunjucks entirely, please read our article [React as a Generator Engine](https://www.asyncapi.com/blog/react-as-generator-engine). The principles discussed in this article still apply to our current transition.
|
|
7
|
-
|
|
8
|
-
## Step-by-step migration guide
|
|
9
|
-
|
|
10
|
-
### 1. Update package.json
|
|
11
|
-
|
|
12
|
-
Change your template configuration in `package.json`:
|
|
13
|
-
|
|
14
|
-
```json
|
|
15
|
-
{
|
|
16
|
-
"generator": {
|
|
17
|
-
"renderer": "react"
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
Once the deprecation period has ended, and we remove the default Nunjucks, the React render engine will be used by default and this setting will no longer be needed to configure
|
|
23
|
-
|
|
24
|
-
### 2. Install dependencies
|
|
25
|
-
|
|
26
|
-
Install the necessary React dependencies:
|
|
27
|
-
|
|
28
|
-
```bash
|
|
29
|
-
npm install @asyncapi/generator-react-sdk
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
### 3. File naming
|
|
33
|
-
|
|
34
|
-
In Nunjucks, the template's filename directly corresponds to the output file. For example, a template named **index.html** will generate an **index.html** file.
|
|
35
|
-
|
|
36
|
-
In React, the filename of the generated file is not controlled by the file itself, but rather by the `File` component. The React component itself can be named anything with a `.js` extension because the output filename is controlled by the `name` attribute of the `File` component used inside the template file. Below you can see some examples of filenames:
|
|
37
|
-
|
|
38
|
-
Nunjucks: `index.html`
|
|
39
|
-
React: `index.js` or `index.html.js` or `anything-you-want.js`
|
|
40
|
-
|
|
41
|
-
### 4. Basic template structure
|
|
42
|
-
|
|
43
|
-
Nunjucks:
|
|
44
|
-
```js
|
|
45
|
-
<h1>{{ asyncapi.info().title() }}</h1>
|
|
46
|
-
<p>{{ asyncapi.info().description() }}</p>
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
React:
|
|
50
|
-
```js
|
|
51
|
-
import { File } from '@asyncapi/generator-react-sdk';
|
|
52
|
-
|
|
53
|
-
export default function({ asyncapi }) {
|
|
54
|
-
return (
|
|
55
|
-
<File name="index.html">
|
|
56
|
-
<h1>{asyncapi.info().title()}</h1>
|
|
57
|
-
<p>{asyncapi.info().description()}</p>
|
|
58
|
-
</File>
|
|
59
|
-
);
|
|
60
|
-
}
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
### 5. Macros and Partials
|
|
64
|
-
|
|
65
|
-
Replace macros with React components:
|
|
66
|
-
|
|
67
|
-
Nunjucks:
|
|
68
|
-
```js
|
|
69
|
-
{% macro renderChannel(channel) %}
|
|
70
|
-
<div class="channel">
|
|
71
|
-
<h3>{{ channel.address() }}</h3>
|
|
72
|
-
<p>{{ channel.description() }}</p>
|
|
73
|
-
</div>
|
|
74
|
-
{% endmacro %}
|
|
75
|
-
|
|
76
|
-
{{ renderChannel(someChannel) }}
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
React:
|
|
80
|
-
```js
|
|
81
|
-
// components/Channel.js
|
|
82
|
-
import { Text } from '@asyncapi/generator-react-sdk';
|
|
83
|
-
|
|
84
|
-
export function Channel({ channel }) {
|
|
85
|
-
return (
|
|
86
|
-
<Text>
|
|
87
|
-
<div className="channel">
|
|
88
|
-
<h3>{channel.address()}</h3>
|
|
89
|
-
<p>{channel.description()}</p>
|
|
90
|
-
</div>
|
|
91
|
-
</Text>
|
|
92
|
-
);
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// Main template
|
|
96
|
-
import { File, Text } from '@asyncapi/generator-react-sdk';
|
|
97
|
-
import { Channel } from './components/Channel';
|
|
98
|
-
|
|
99
|
-
export default function({ asyncapi }) {
|
|
100
|
-
return (
|
|
101
|
-
<File name="channels.html">
|
|
102
|
-
<Text>
|
|
103
|
-
<h2>Channels</h2>
|
|
104
|
-
</Text>
|
|
105
|
-
{asyncapi.channels().map(channel => (
|
|
106
|
-
<Channel channel={channel} />
|
|
107
|
-
))}
|
|
108
|
-
</File>
|
|
109
|
-
);
|
|
110
|
-
}
|
|
111
|
-
```
|
|
112
|
-
|
|
113
|
-
### 6. File template
|
|
114
|
-
|
|
115
|
-
Check the [detailed guide on file templates](file-templates) to learn what is the difference between templating multiple file outputs in Nunjucks and React.
|
|
116
|
-
|
|
117
|
-
### 7. Models generation
|
|
118
|
-
|
|
119
|
-
If you have a template written with Nunjucks, it is almost certain that you have your own custom models, classes, or types templates in place. Instead of migrating them to React render engine we strongly advise you to delegate models generation to AsyncAPI Modelina project. Learn more about [how to add models generation using Modelina](https://www.asyncapi.com/docs/tools/generator/model-generation).
|
|
120
|
-
|
|
121
|
-
## Additional Resources and Information
|
|
122
|
-
|
|
123
|
-
### Template Examples
|
|
124
|
-
For a complete example of React features in use, please refer to the [AsyncAPI Template for Generator Templates](https://github.com/asyncapi/template-for-generator-templates). The `master` branch demonstrates all React features, while the `nunjucks` branch shows the old Nunjucks implementation. This comparison can be particularly helpful in understanding the differences and migration process.
|
|
125
|
-
|
|
126
|
-
### Filters to Helpers
|
|
127
|
-
If you've been using Nunjucks filters placed in the `filters` directory, you can still use this functionality in React. However, they should be treated as normal functions that you import into your components. We recommend renaming the `filters` directory to `helpers` to better reflect their new usage in React.
|
|
128
|
-
|
|
129
|
-
### Hooks Remain Unchanged
|
|
130
|
-
It's important to note that hooks remain unchanged in this migration process. Hooks are not related to the render engine functionality, so you can continue to use them as you have been.
|
|
131
|
-
|
|
132
|
-
### Testing your migration
|
|
133
|
-
|
|
134
|
-
After migrating, test your template thoroughly:
|
|
135
|
-
|
|
136
|
-
1. Run the generator using your new React template
|
|
137
|
-
2. Compare the output with the previous Nunjucks template output
|
|
138
|
-
3. Check for any missing or incorrectly rendered content
|
|
139
|
-
|
|
140
|
-
Consider implementing snapshot tests for your template before starting the migration. This will ease the review of changes in comparing the content rendered after render engine changes. Snapshot tests allow you to have tests that will persist expected output from Nunjucks template, and compare it with output generated after the migration. Check out an [example of such snapshot integration test for our internal react template we use for development and testing](https://github.com/asyncapi/generator/blob/master/apps/generator/test/integration.test.js#L66).
|
|
141
|
-
|
|
142
|
-
## Conclusion
|
|
143
|
-
|
|
144
|
-
Migrating from Nunjucks to React templates may require some initial effort, but it will result in more maintainable code. You can learn more about why we introduced the React render engine from article [React as a Generator Engine](https://www.asyncapi.com/blog/react-as-generator-engine).
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: "Nunjucks render engine"
|
|
3
|
-
weight: 120
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
> **Note**: Nunjucks renderer engine is deprecated and will be removed in the future. Use the React renderer engine instead. For more details read notes from release [@asyncapi/generator@2.6.0](https://github.com/asyncapi/generator/releases/tag/%40asyncapi%2Fgenerator%402.6.0).
|
|
7
|
-
|
|
8
|
-
[Nunjucks](https://mozilla.github.io/nunjucks) is the default render engine, however, we strongly recommend adopting the [React](#react) engine.
|
|
9
|
-
|
|
10
|
-
### Common assumptions
|
|
11
|
-
|
|
12
|
-
1. Templates may contain [Nunjucks filters or helper functions](https://mozilla.github.io/nunjucks/templating.html#builtin-filters). [Read more about filters](#filters).
|
|
13
|
-
1. Templates may contain `partials` (reusable chunks). They must be stored in the `.partials` directory under the template directory. [Read more about partials](#partials).
|
|
14
|
-
1. Templates may contain multiple files. Unless stated otherwise, all files will be rendered.
|
|
15
|
-
1. The default variables you have access to in any the template file are the following:
|
|
16
|
-
- `asyncapi` that is a parsed spec file object. Read the [API](https://github.com/asyncapi/parser-api/blob/master/docs/api.md#asyncapidocument) of the Parser to understand what structure you have access to in this parameter.
|
|
17
|
-
- `originalAsyncAPI` that is an original spec file before it is parsed.
|
|
18
|
-
- `params` that contain the parameters provided when generating.
|
|
19
|
-
|
|
20
|
-
### Partials
|
|
21
|
-
|
|
22
|
-
Files from the `.partials` directory do not end up with other generated files in the target directory. In this directory you should keep reusable templates chunks that you can [include](https://mozilla.github.io/nunjucks/templating.html#include) in your templates. You can also put there [macros](https://mozilla.github.io/nunjucks/templating.html#macro) to use them in templates, like in below example:
|
|
23
|
-
|
|
24
|
-
```html
|
|
25
|
-
{# tags.html #}
|
|
26
|
-
{% macro tags(tagList) %}
|
|
27
|
-
<div class="mt-4">
|
|
28
|
-
{% for tag in tagList %}
|
|
29
|
-
<span class="bg-grey-dark font-normal text-sm no-underline text-white rounded lowercase mr-2 px-2 py-1" title="{{tag.description()}}">{{tag.name()}}</span>
|
|
30
|
-
{% endfor %}
|
|
31
|
-
</div>
|
|
32
|
-
{% endmacro %}
|
|
33
|
-
|
|
34
|
-
{# operations.html #}
|
|
35
|
-
{% from "./tags.html" import tags %}
|
|
36
|
-
{{ tags(operation.tags()) }}
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
### Filters
|
|
40
|
-
|
|
41
|
-
A filter is a helper function that you can create to perform complex tasks. They are JavaScript files that register one or many [Nunjuck filters](https://mozilla.github.io/nunjucks/api.html#custom-filters). The generator parses all the files in the `filters` directory. Functions exported from these files are registered as filters.
|
|
42
|
-
|
|
43
|
-
You can use the filter function in your template as in the following example:
|
|
44
|
-
|
|
45
|
-
```js
|
|
46
|
-
const {{ channelName | camelCase }} = '{{ channelName }}';
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
The generator also supports asynchronous filters. Asynchronous filters receive as the last argument a callback to resume rendering. Asynchronous filters must be annotated with the `async` keyword. Make sure to call the callback with two arguments: `callback(err, res)`. `err` can be `null`. See the following example of how to use asynchronous filters:
|
|
50
|
-
|
|
51
|
-
```js
|
|
52
|
-
const filter = module.exports;
|
|
53
|
-
|
|
54
|
-
async function asyncCamelCase(str, callback) {
|
|
55
|
-
try {
|
|
56
|
-
const result = // logic for camel casing str
|
|
57
|
-
callback(null, result);
|
|
58
|
-
} catch (error) {
|
|
59
|
-
callback(error);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
filter.renderAsyncContent = renderAsyncContent;
|
|
63
|
-
|
|
64
|
-
// using in template
|
|
65
|
-
{{ channelName | asyncCamelCase }}
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
Unfortunately, if you need to use Promise, filter still must be annotated with the `async` keyword:
|
|
69
|
-
|
|
70
|
-
```js
|
|
71
|
-
async function asyncCamelCase(str, callback) {
|
|
72
|
-
return new Promise((resolve, reject) => {
|
|
73
|
-
// logic with callback
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
In case you have more than one template and want to reuse filters, you can put them in a single library. You can configure such a library in the template configuration under `filters` property. To learn how to add such filters to configuration, [read more about the configuration file](configuration-file).
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
You can also use the official AsyncAPI [nunjucks-filters](https://github.com/asyncapi/generator/tree/master/apps/nunjucks-filters) which is included by default in the generator library.
|
|
82
|
-
|
|
83
|
-
> **Note:** The nunjucks-filters is deprecated, and you should migrate to react-renderer instead. For more details, read notes from release [@asyncapi/generator@2.6.0](https://github.com/asyncapi/generator/releases/tag/%40asyncapi%2Fgenerator%402.6.0).
|
package/lib/filtersRegistry.js
DELETED
|
@@ -1,134 +0,0 @@
|
|
|
1
|
-
const path = require('path');
|
|
2
|
-
const fs = require('fs');
|
|
3
|
-
const xfs = require('fs.extra');
|
|
4
|
-
const { isAsyncFunction, registerTypeScript } = require('./utils');
|
|
5
|
-
const nunjucksFilters = require('@asyncapi/nunjucks-filters');
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Registers all template filters.
|
|
9
|
-
* @deprecated This method is deprecated. For more details, see the release notes: https://github.com/asyncapi/generator/releases/tag/%40asyncapi%2Fgenerator%402.6.0
|
|
10
|
-
* @param {Object} nunjucks Nunjucks environment.
|
|
11
|
-
* @param {Object} templateConfig Template configuration.
|
|
12
|
-
* @param {String} templateDir Directory where template is located.
|
|
13
|
-
* @param {String} filtersDir Directory where local filters are located.
|
|
14
|
-
*/
|
|
15
|
-
module.exports.registerFilters = async (nunjucks, templateConfig, templateDir, filtersDir) => {
|
|
16
|
-
await registerLocalFilters(nunjucks, templateDir, filtersDir);
|
|
17
|
-
registerConfigFilters(nunjucks, templateDir, templateConfig);
|
|
18
|
-
|
|
19
|
-
// Register Nunjucks filters from the 'nunjucks-filters' module without needing to list them in package.json or .ageneratorrc file.
|
|
20
|
-
addFilters(nunjucks, nunjucksFilters);
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Registers the local template filters.
|
|
25
|
-
* @deprecated This method is deprecated. For more details, see the release notes: https://github.com/asyncapi/generator/releases/tag/%40asyncapi%2Fgenerator%402.6.0
|
|
26
|
-
* @private
|
|
27
|
-
* @param {Object} nunjucks Nunjucks environment.
|
|
28
|
-
* @param {String} templateDir Directory where template is located.
|
|
29
|
-
* @param {String} filtersDir Directory where local filters are located.
|
|
30
|
-
*/
|
|
31
|
-
function registerLocalFilters(nunjucks, templateDir, filtersDir) {
|
|
32
|
-
return new Promise((resolve, reject) => {
|
|
33
|
-
const localFilters = path.resolve(templateDir, filtersDir);
|
|
34
|
-
|
|
35
|
-
if (!fs.existsSync(localFilters)) return resolve();
|
|
36
|
-
|
|
37
|
-
const walker = xfs.walk(localFilters, {
|
|
38
|
-
followLinks: false
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
walker.on('file', async (root, stats, next) => {
|
|
42
|
-
try {
|
|
43
|
-
const filePath = path.resolve(
|
|
44
|
-
templateDir,
|
|
45
|
-
path.resolve(root, stats.name)
|
|
46
|
-
);
|
|
47
|
-
|
|
48
|
-
registerTypeScript(filePath);
|
|
49
|
-
// If it's a module constructor, inject dependencies to ensure consistent usage in remote templates in other projects or plain directories.
|
|
50
|
-
delete require.cache[require.resolve(filePath)];
|
|
51
|
-
const mod = require(filePath);
|
|
52
|
-
|
|
53
|
-
addFilters(nunjucks, mod);
|
|
54
|
-
|
|
55
|
-
next();
|
|
56
|
-
} catch (e) {
|
|
57
|
-
reject(e);
|
|
58
|
-
}
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
walker.on('errors', (root, nodeStatsArray) => {
|
|
62
|
-
reject(nodeStatsArray);
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
walker.on('end', async () => {
|
|
66
|
-
resolve();
|
|
67
|
-
});
|
|
68
|
-
});
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Registers the additionally configured filters.
|
|
73
|
-
* @deprecated This method is deprecated. For more details, see the release notes: https://github.com/asyncapi/generator/releases/tag/%40asyncapi%2Fgenerator%402.6.0
|
|
74
|
-
* @private
|
|
75
|
-
* @param {Object} nunjucks Nunjucks environment.
|
|
76
|
-
* @param {String} templateDir Directory where template is located.
|
|
77
|
-
* @param {Object} templateConfig Template configuration.
|
|
78
|
-
*/
|
|
79
|
-
async function registerConfigFilters(nunjucks, templateDir, templateConfig) {
|
|
80
|
-
const confFilters = templateConfig.filters;
|
|
81
|
-
const DEFAULT_MODULES_DIR = 'node_modules';
|
|
82
|
-
if (!Array.isArray(confFilters)) return;
|
|
83
|
-
|
|
84
|
-
const promises = confFilters.map(async filtersModule => {
|
|
85
|
-
let mod;
|
|
86
|
-
let filterName = filtersModule;
|
|
87
|
-
try {
|
|
88
|
-
//first we try to grab module with filters by the module name
|
|
89
|
-
//this is when generation is used on production using remote templates
|
|
90
|
-
mod = require(filterName);
|
|
91
|
-
} catch (error) {
|
|
92
|
-
//in case template is local but was not installed in node_modules of the generator then we need to explicitly provide modules location
|
|
93
|
-
try {
|
|
94
|
-
filterName = path.resolve(templateDir, DEFAULT_MODULES_DIR, filtersModule);
|
|
95
|
-
mod = require(filterName);
|
|
96
|
-
} catch (e) {
|
|
97
|
-
//sometimes it may happen that template is located in node_modules with other templates and its filter package is on the same level as template, as it is shared with other templates
|
|
98
|
-
try {
|
|
99
|
-
filterName = path.resolve(templateDir, '../..', filtersModule);
|
|
100
|
-
mod = require(filterName);
|
|
101
|
-
} catch (error) {
|
|
102
|
-
//in rare cases, especially in isolated tests, it may happen that installation
|
|
103
|
-
//ends but is not yet fully completed, so initial require of the same path do not work
|
|
104
|
-
//but in next attempt it works
|
|
105
|
-
//we need to keep this workaround until we find a solution
|
|
106
|
-
mod = require(filterName);
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
return addFilters(nunjucks, mod);
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
await Promise.all(promises);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
* Add filter functions to Nunjucks environment. Only owned functions from the module are added.
|
|
118
|
-
* @deprecated This method is deprecated. For more details, see the release notes: https://github.com/asyncapi/generator/releases/tag/%40asyncapi%2Fgenerator%402.6.0
|
|
119
|
-
* @private
|
|
120
|
-
* @param {Object} nunjucks Nunjucks environment.
|
|
121
|
-
* @param {Object} filters Module with functions.
|
|
122
|
-
*/
|
|
123
|
-
function addFilters(nunjucks, filters) {
|
|
124
|
-
Object.getOwnPropertyNames(filters).forEach((key) => {
|
|
125
|
-
const value = filters[key];
|
|
126
|
-
if (!(value instanceof Function)) return;
|
|
127
|
-
|
|
128
|
-
if (isAsyncFunction(value)) {
|
|
129
|
-
nunjucks.addFilter(key, value, true);
|
|
130
|
-
} else {
|
|
131
|
-
nunjucks.addFilter(key, value);
|
|
132
|
-
}
|
|
133
|
-
});
|
|
134
|
-
}
|