@asyncapi/generator 2.4.1 → 2.6.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 +18 -0
- package/cli.js +7 -0
- package/docs/api.md +12 -3
- package/docs/configuration-file.md +3 -2
- package/docs/file-templates.md +78 -5
- package/docs/generator-template.md +1 -1
- package/docs/hooks.md +43 -6
- package/docs/migration-cli.md +70 -0
- package/docs/migration-nunjucks-react.md +144 -0
- package/docs/nunjucks-render-engine.md +2 -0
- package/lib/filtersRegistry.js +4 -0
- package/lib/generator.js +8 -8
- package/lib/logMessages.js +2 -2
- package/lib/parser.js +1 -1
- package/lib/renderer/nunjucks.js +2 -2
- package/lib/templateConfigValidator.js +1 -1
- package/lib/utils.js +1 -1
- package/package.json +6 -6
- package/test/__snapshots__/integration.test.js.snap +394 -0
- package/test/integration.test.js +9 -6
- package/test/renderer.test.js +2 -2
- package/test/test-project/package.json +0 -1
- package/test/test-project/test.sh +5 -0
- package/test/test-project/verdaccio/config.yaml +6 -0
- package/test/test-templates/nunjucks-template/package-lock.json +74 -71
- package/test/test-templates/nunjucks-template/package.json +1 -1
- package/test/test-templates/react-template/package.json +9 -2
- package/test/test-templates/react-template/template/models.js +6 -0
- package/test/test-templates/react-template/__transpiled/test-file.md.js +0 -24
- package/test/test-templates/react-template/__transpiled/test-file.md.js.map +0 -1
- package/test/test-templates/react-template/package-lock.json +0 -4135
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# @asyncapi/generator
|
|
2
2
|
|
|
3
|
+
## 2.6.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- fd5dfd7: - **Deprecation of `ag` CLI**: The `ag` CLI is deprecated in favour of the `AsyncAPI CLI` that is a single entry point for all the AsyncAPI tools. No new features will be added to `ag` and it will be completely removed. The official documentation of AsyncAPI Generator has not mentioned `ag` for over a year, instead only using `AsyncAPI CLI` and `asyncapi generate fromTemplate` commands. Refer to the [migration guide](https://www.asyncapi.com/docs/tools/generator/migration-cli) that will help you understand how to migrate your `ag` commands to the new `AsyncAPI CLI` command.
|
|
8
|
+
|
|
9
|
+
- **Deprecation of Nunjucks render engine:** The [Nunjucks render engine](https://www.asyncapi.com/docs/tools/generator/nunjucks-render-engine) is deprecated and will be removed in October 2025. It is recommended to switch to the [React render engine](https://www.asyncapi.com/docs/tools/generator/react-render-engine) instead. If you are using Nunjucks in production, read the [migration guide](https://www.asyncapi.com/docs/tools/generator/migration-nunjucks-react) that will help you understand how to migrate to the new engine. The removal of the Nunjucks render engine results also in removal of [Nunjucks-filters](apps/nunjucks-filters) library.
|
|
10
|
+
|
|
11
|
+
Removal of both deprecated parts of the generator is planned for October 2025, which gives you 9 months to migrate.
|
|
12
|
+
|
|
13
|
+
## 2.5.0
|
|
14
|
+
|
|
15
|
+
### Minor Changes
|
|
16
|
+
|
|
17
|
+
- 2d16234: - Package `@asyncapi/generator-hooks` is now part of `generator` repo and won't be released separately. Theource code is stored under `apps/hooks` but the `package/library` name stays as it was originally for backward compatibility,
|
|
18
|
+
- By default, the `@asyncapi/generator-hooks` package, known as **package** contains many different hooks used in templates and is available in the generator. You no longer have to configure it in your `package.json` in `dependencies`. The package, `@asyncapi/generator-hooks` will no longer be published to NPM separately and is deprecated. You can still have your own hooks, store them in a separate package, and configure them with your template.
|
|
19
|
+
- Remember that the fact that the hooks package is now included by default, doesn't mean all hooks from it are enabled by default. You still have to enable a given hook in the configuration file explicitly because some hooks can execute automatically without passing a specific parameter. Also, a hook's supported parameters need to be defined in your template's config.
|
|
20
|
+
|
|
3
21
|
## 2.4.1
|
|
4
22
|
|
|
5
23
|
### Patch Changes
|
package/cli.js
CHANGED
|
@@ -89,10 +89,17 @@ program
|
|
|
89
89
|
.option('-o, --output <outputDir>', 'directory where to put the generated files (defaults to current directory)', parseOutput, process.cwd())
|
|
90
90
|
.option('-p, --param <name=value>', 'additional param to pass to templates', paramParser)
|
|
91
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)')
|
|
92
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.')
|
|
93
94
|
.option('--map-base-url <url:folder>','maps all schema references from base url to local folder',mapBaseUrlParser)
|
|
94
95
|
.parse(process.argv);
|
|
95
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
|
+
|
|
96
103
|
if (!asyncapiDocPath) {
|
|
97
104
|
console.error(red('> Path or URL to AsyncAPI file not provided.'));
|
|
98
105
|
program.help(); // This exits the process
|
package/docs/api.md
CHANGED
|
@@ -13,6 +13,7 @@ Reference API documentation for AsyncAPI Generator library.
|
|
|
13
13
|
* [Generator](#Generator)
|
|
14
14
|
* [new Generator(templateName, targetDir, options)](#new_Generator_new)
|
|
15
15
|
* _instance_
|
|
16
|
+
* [.compile](#Generator+compile) : `Boolean`
|
|
16
17
|
* [.registry](#Generator+registry) : `Object`
|
|
17
18
|
* [.templateName](#Generator+templateName) : `String`
|
|
18
19
|
* [.targetDir](#Generator+targetDir) : `String`
|
|
@@ -38,9 +39,9 @@ Reference API documentation for AsyncAPI Generator library.
|
|
|
38
39
|
* [.executeAfterHook()](#Generator+executeAfterHook) ⇒ `Promise.<void>`
|
|
39
40
|
* [.parseInput()](#Generator+parseInput)
|
|
40
41
|
* [.configureTemplate()](#Generator+configureTemplate)
|
|
41
|
-
* ~~[.generateFromString(asyncapiString, [parseOptions])](#Generator+generateFromString) ⇒ `Promise
|
|
42
|
-
* [.generateFromURL(asyncapiURL)](#Generator+generateFromURL) ⇒ `Promise
|
|
43
|
-
* [.generateFromFile(asyncapiFile)](#Generator+generateFromFile) ⇒ `Promise
|
|
42
|
+
* ~~[.generateFromString(asyncapiString, [parseOptions])](#Generator+generateFromString) ⇒ `Promise.<(TemplateRenderResult|undefined)>`~~
|
|
43
|
+
* [.generateFromURL(asyncapiURL)](#Generator+generateFromURL) ⇒ `Promise.<(TemplateRenderResult|undefined)>`
|
|
44
|
+
* [.generateFromFile(asyncapiFile)](#Generator+generateFromFile) ⇒ `Promise.<(TemplateRenderResult|undefined)>`
|
|
44
45
|
* [.installTemplate([force])](#Generator+installTemplate)
|
|
45
46
|
* _static_
|
|
46
47
|
* [.getTemplateFile(templateName, filePath, [templatesDir])](#Generator.getTemplateFile) ⇒ `Promise`
|
|
@@ -64,6 +65,7 @@ Instantiates a new Generator object.
|
|
|
64
65
|
- [.forceWrite] `Boolean` ` = false` - Force writing of the generated files to given directory even if it is a git repo with unstaged files or not empty dir. Default is set to false.
|
|
65
66
|
- [.install] `Boolean` ` = false` - Install the template and its dependencies, even when the template has already been installed.
|
|
66
67
|
- [.debug] `Boolean` ` = false` - Enable more specific errors in the console. At the moment it only shows specific errors about filters. Keep in mind that as a result errors about template are less descriptive.
|
|
68
|
+
- [.compile] `Boolean` ` = true` - Whether to compile the template or use the cached transpiled version provided by template in '__transpiled' folder
|
|
67
69
|
- [.mapBaseUrlToFolder] `Object.<String, String>` - Optional parameter to map schema references from a base url to a local base folder e.g. url=https://schema.example.com/crm/ folder=./test/docs/ .
|
|
68
70
|
- [.registry] `Object` - Optional parameter with private registry configuration
|
|
69
71
|
- [.url] `String` - Parameter to pass npm registry url
|
|
@@ -85,6 +87,13 @@ const generator = new Generator('@asyncapi/html-template', path.resolve(__dirnam
|
|
|
85
87
|
});
|
|
86
88
|
```
|
|
87
89
|
|
|
90
|
+
<a name="Generator+compile"></a>
|
|
91
|
+
|
|
92
|
+
* generator.compile : `Boolean`** :
|
|
93
|
+
Whether to compile the template or use the cached transpiled version provided by template in '__transpiled' folder.
|
|
94
|
+
|
|
95
|
+
**Kind**: instance property of [`Generator`](#Generator)
|
|
96
|
+
|
|
88
97
|
<a name="Generator+registry"></a>
|
|
89
98
|
|
|
90
99
|
* generator.registry : `Object`** :
|
|
@@ -20,7 +20,7 @@ The `generator` property from `package.json` file must contain a JSON object tha
|
|
|
20
20
|
|`nonRenderableFiles`| [String] | A list of file paths or [globs](https://en.wikipedia.org/wiki/Glob_(programming)) that must be copied "as-is" to the target directory, i.e., without performing any rendering process. This is useful when you want to copy binary files.
|
|
21
21
|
|`generator`| [String] | A string representing the generator version-range the template is compatible with. This value must follow the [semver](https://nodejs.dev/learn/semantic-versioning-using-npm) syntax. E.g., `>=1.0.0`, `>=1.0.0 <=2.0.0`, `~1.0.0`, `^1.0.0`, `1.0.0`, etc. [Read more about semver](https://docs.npmjs.com/about-semantic-versioning).
|
|
22
22
|
|`filters`| [String] | A list of modules containing functions that can be used as Nunjucks filters. In case of external modules, remember they need to be added as a dependency in `package.json` of your template.
|
|
23
|
-
|`hooks`| Object[String, String] or Object[String, Array[String]] | A list of modules containing hooks, except for the ones you keep locally in your template in default location. For each module you must specify the exact name of the hook that should be used in the template. For a single hook you can specify it as a string
|
|
23
|
+
|`hooks`| Object[String, String] or Object[String, Array[String]] | A list of modules containing hooks, except for the ones you keep locally in your template in the default location. For each module you must specify the exact name of the hook that should be used in the template. For a single hook, you can specify it as a string; for more hooks, you must pass an array of strings. In the case of external modules, remember they need to be added as a dependency in `package.json` of your template. There is also [an official hooks library](hooks#official-library) always included in the generator. As this is a library of multiple hooks, you still need to explicitly specify in the configuration which one you want to use. Use `@asyncapi/generator-hooks` as the library name.
|
|
24
24
|
|
|
25
25
|
### Example
|
|
26
26
|
|
|
@@ -64,7 +64,8 @@ The `generator` property from `package.json` file must contain a JSON object tha
|
|
|
64
64
|
"my-package-with-filters"
|
|
65
65
|
],
|
|
66
66
|
"hooks": {
|
|
67
|
-
"@asyncapi/generator-hooks": "hookFunctionName"
|
|
67
|
+
"@asyncapi/generator-hooks": "hookFunctionName",
|
|
68
|
+
"my-custom-hooks-package": ["myHook", "andAnotherOne"]
|
|
68
69
|
}
|
|
69
70
|
}
|
|
70
71
|
```
|
package/docs/file-templates.md
CHANGED
|
@@ -3,7 +3,13 @@ title: "File templates"
|
|
|
3
3
|
weight: 140
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
## Generating files with the Nunjucks render engine
|
|
7
|
+
|
|
8
|
+
> **Note**: This section applies only to the Nunjucks render engine. For information on using the React render engine, refer to the [Generating files with the React render engine](#generating-files-with-the-react-render-engine) section below.
|
|
9
|
+
|
|
10
|
+
> **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).
|
|
11
|
+
|
|
12
|
+
It is possible to generate files for each specific object in your AsyncAPI documentation using the Nunjucks render engine. For example, you can specify a filename like `$$channel$$.js` to generate a file for each channel defined in your AsyncAPI. The following file-template names and extra variables are available:
|
|
7
13
|
|
|
8
14
|
- `$$channel$$`, within the template-file you have access to two variables [`channel`](https://github.com/asyncapi/parser-api/blob/master/docs/api.md#channel) and [`channelName`](https://github.com/asyncapi/parser-api/blob/master/docs/api.md#channels). Where the `channel` contains the current channel being rendered.
|
|
9
15
|
- `$$message$$`, within the template-file you have access to two variables [`message`](https://github.com/asyncapi/parser-api/blob/master/docs/api.md#message) and [`messageName`](https://github.com/asyncapi/parser-api/blob/master/docs/api.md#message). Where `message` contains the current message being rendered.
|
|
@@ -25,7 +31,7 @@ Schema name is '{{schemaName}}' and properties are:
|
|
|
25
31
|
{% endfor %}
|
|
26
32
|
```
|
|
27
33
|
|
|
28
|
-
With following AsyncAPI:
|
|
34
|
+
With the following AsyncAPI:
|
|
29
35
|
```
|
|
30
36
|
components:
|
|
31
37
|
schemas:
|
|
@@ -53,15 +59,82 @@ Schema name is 'people' and properties are:
|
|
|
53
59
|
- id
|
|
54
60
|
```
|
|
55
61
|
|
|
56
|
-
|
|
62
|
+
> You can see an example of a file template that uses the Nunjucks render engine [here](https://github.com/asyncapi/template-for-generator-templates/tree/nunjucks/template/schemas).
|
|
63
|
+
|
|
64
|
+
## Generating files with the React render engine
|
|
57
65
|
|
|
58
|
-
The above
|
|
66
|
+
The above method of rendering **file templates** only works for the Nunjucks render engine. To use the React render engine, you need to follow a different approach. The React render engine allows for a more generic way to render multiple files by returning an array of `File` components in the rendering component. This can be particularly useful for complex templates or when you need to generate a large number of files with varying content.
|
|
67
|
+
|
|
68
|
+
### Example 1: Rendering hardcoded files
|
|
69
|
+
|
|
70
|
+
The following is a simple hardcoded example of how to render multiple files using the React render engine:
|
|
59
71
|
|
|
60
72
|
```tsx
|
|
73
|
+
import { File} from "@asyncapi/generator-react-sdk";
|
|
74
|
+
|
|
61
75
|
export default function({ asyncapi }) {
|
|
62
76
|
return [
|
|
63
77
|
<File name={`file1.html`}>Content</File>,
|
|
64
78
|
<File name={`file2.html`}>Content</File>
|
|
65
79
|
]
|
|
66
80
|
}
|
|
67
|
-
```
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Example 2: Rendering files based on the AsyncAPI Schema
|
|
84
|
+
|
|
85
|
+
In practice, to render the multiple files, that are generated from the data defined in your AsyncAPI, you'll iterate over the array of schemas and generate a file for each schema as shown in the example below:
|
|
86
|
+
|
|
87
|
+
```js
|
|
88
|
+
import { File} from "@asyncapi/generator-react-sdk";
|
|
89
|
+
|
|
90
|
+
/*
|
|
91
|
+
* To render multiple files, it is enough to return an array of `File` components in the rendering component, like in following example.
|
|
92
|
+
*/
|
|
93
|
+
export default function({ asyncapi }) {
|
|
94
|
+
const schemas = asyncapi.allSchemas();
|
|
95
|
+
const files = [];
|
|
96
|
+
// schemas is an instance of the Map
|
|
97
|
+
schemas.forEach((schema) => {
|
|
98
|
+
|
|
99
|
+
files.push(
|
|
100
|
+
// We return a react file component and each time we do it, the name of the generated file will be a schema name
|
|
101
|
+
// Content of the file will be a variable representing schema
|
|
102
|
+
<File name={`${schema.id()}.js`}>
|
|
103
|
+
const { schema.id() } = { JSON.stringify(schema._json, null, 2) }
|
|
104
|
+
</File>
|
|
105
|
+
);
|
|
106
|
+
});
|
|
107
|
+
return files;
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Example 3: Rendering files for each channel
|
|
112
|
+
|
|
113
|
+
Additionally, you can generate multiple files for each channel defined in your AsyncAPI specification using the React render engine as shown in the example below:
|
|
114
|
+
|
|
115
|
+
```js
|
|
116
|
+
import { File, Text } from "@asyncapi/generator-react-sdk";
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
export default function ({ asyncapi }) {
|
|
120
|
+
const files = [];
|
|
121
|
+
|
|
122
|
+
// Generate files for channels
|
|
123
|
+
asyncapi.channels().forEach((channel) => {
|
|
124
|
+
const channelName = channel.id();
|
|
125
|
+
|
|
126
|
+
files.push(
|
|
127
|
+
<File name={`${channelName}.md`}>
|
|
128
|
+
<Text newLines={2}># Channel: {channelName}</Text>
|
|
129
|
+
<Text>
|
|
130
|
+
{channel.hasDescription() && `${channel.description()}`}
|
|
131
|
+
</Text>
|
|
132
|
+
</File>
|
|
133
|
+
);
|
|
134
|
+
});
|
|
135
|
+
return files;
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
The code snippet above uses the `Text` component to write file content to the `.md` markdown file. The `newline` property is used to ensure that the content isn't all rendered in one line in the markdown file. In summary, the code snippet above is a practical guide on generating properly formatted multiline Markdown files for each channel in an AsyncAPI document.
|
|
139
|
+
|
|
140
|
+
> You can see an example of a file template that uses the React render engine [here](https://github.com/asyncapi/template-for-generator-templates/blob/master/template/schemas/schema.js).
|
|
@@ -159,7 +159,7 @@ To see this in action, navigate to the **python-mqtt-client-template** directory
|
|
|
159
159
|
|
|
160
160
|
``` cmd
|
|
161
161
|
Generation in progress. Keep calm and wait a bit... done
|
|
162
|
-
Check out your shiny new generated files at
|
|
162
|
+
Check out your shiny new generated files at test/project.
|
|
163
163
|
```
|
|
164
164
|
|
|
165
165
|
Navigating to the **test/project** directory. You should see a **client.py** file; the only content is `Temperature Service`.
|
package/docs/hooks.md
CHANGED
|
@@ -4,21 +4,26 @@ weight: 130
|
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
Hooks are functions called by the generator on a specific moment in the generation process. Hooks can be anonymous functions but you can also add function names. These hooks can have arguments provided to them or being expected to return a value.
|
|
7
|
+
|
|
8
|
+
## Types
|
|
9
|
+
|
|
7
10
|
The following types of hooks are currently supported:
|
|
8
11
|
|
|
9
12
|
|Hook type|Description| Return type | Arguments
|
|
10
13
|
|---|---|---|---|
|
|
11
|
-
| `generate:before` | Called after registration of all filters and before the generator starts processing of the template. | void : Nothing is expected to be returned. | [The generator instance](
|
|
12
|
-
| `generate:after` | Called at the very end of the generation. | void : Nothing is expected to be returned. | [The generator instance](
|
|
13
|
-
| `setFileTemplateName ` | Called right before saving a new file generated by [file template](./file-templates.md). | string : a new filename for the generator to use for the file template. | [The generator instance](
|
|
14
|
+
| `generate:before` | Called after registration of all filters and before the generator starts processing of the template. | void : Nothing is expected to be returned. | [The generator instance](/api)
|
|
15
|
+
| `generate:after` | Called at the very end of the generation. | void : Nothing is expected to be returned. | [The generator instance](/api)
|
|
16
|
+
| `setFileTemplateName ` | Called right before saving a new file generated by [file template](./file-templates.md). | string : a new filename for the generator to use for the file template. | [The generator instance](/api) and object in the form of `{ "originalFilename" : string }`
|
|
17
|
+
|
|
18
|
+
## Location
|
|
14
19
|
|
|
15
20
|
The generator parses:
|
|
16
21
|
- All the files in the `.hooks` directory inside the template.
|
|
17
|
-
- All modules listed in the template configuration and triggers only hooks
|
|
22
|
+
- All modules listed in the template configuration and triggers only hooks whose names were added to the config. You can use an [official hooks library](#official-library) that is bundled together with the generator. To learn how to add hooks to configuration [read more about the configuration file](configuration-file).
|
|
18
23
|
|
|
19
|
-
|
|
24
|
+
## Examples
|
|
20
25
|
|
|
21
|
-
> Some of the examples have names of hook functions provided and some not. Keep in mind that hook functions kept in template in default location do not require a name. Name is required only if you keep hooks in non default location or in a separate library, because such hooks need to be explicitly configured in the configuration file. For more details on hooks configuration [read more about the configuration file](
|
|
26
|
+
> Some of the examples have names of hook functions provided and some not. Keep in mind that hook functions kept in template in default location do not require a name. Name is required only if you keep hooks in non default location or in a separate library, because such hooks need to be explicitly configured in the configuration file. For more details on hooks configuration [read more about the configuration file](configuration-file).
|
|
22
27
|
|
|
23
28
|
Most basic modules with hooks look like this:
|
|
24
29
|
```js
|
|
@@ -79,3 +84,35 @@ module.exports = {
|
|
|
79
84
|
};
|
|
80
85
|
};
|
|
81
86
|
```
|
|
87
|
+
|
|
88
|
+
## Official library
|
|
89
|
+
|
|
90
|
+
It is a library of reusable hooks that you can use in your templates. You only have to add its name to the configuration: `@asyncapi/generator-hooks` and specify which hook you want to enable.
|
|
91
|
+
|
|
92
|
+
This library consists of the following hooks:
|
|
93
|
+
|Hook name|Hook type|Description|
|
|
94
|
+
|---|---|---|
|
|
95
|
+
| `createAsyncapiFile` | `generate:after` | It creates an AsyncAPI file with the content of the spec file passed to the generator. By default, it creates the file in the root of the generation output directory. This hook also supports custom parameters that the user can pass to template generation. The parameter called `asyncapiFileDir` allows the user to specify the location where the spec file should be created. To make your template users use this parameter, you need to add it to the configuration of your template like other parameters |
|
|
96
|
+
|
|
97
|
+
1. In your template configuration in `package.json` specify you want to use this library and what hook exactly:
|
|
98
|
+
```json
|
|
99
|
+
{
|
|
100
|
+
"generator": {
|
|
101
|
+
"hooks": {
|
|
102
|
+
"@asyncapi/generator-hooks": "createAsyncapiFile"
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
1. Some hooks support custom parameters that template's user can use to specify different behaviour of the hook. To enable these, you need to also add them to the list of your template's parameters:
|
|
108
|
+
```json
|
|
109
|
+
{
|
|
110
|
+
"generator": {
|
|
111
|
+
"parameters": {
|
|
112
|
+
"asyncapiFileDir": {
|
|
113
|
+
"description": "This template by default also outputs the AsyncAPI document that was passed as input. You can specify with this parameter what should be the location of this AsyncAPI document, relative to specified template output."
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
```
|
|
@@ -0,0 +1,70 @@
|
|
|
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).
|
|
@@ -0,0 +1,144 @@
|
|
|
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.md) 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).
|
|
@@ -3,6 +3,8 @@ title: "Nunjucks render engine"
|
|
|
3
3
|
weight: 120
|
|
4
4
|
---
|
|
5
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
|
+
|
|
6
8
|
[Nunjucks](https://mozilla.github.io/nunjucks) is the default render engine, however, we strongly recommend adopting the [React](#react) engine.
|
|
7
9
|
|
|
8
10
|
### Common assumptions
|
package/lib/filtersRegistry.js
CHANGED
|
@@ -6,6 +6,7 @@ const nunjucksFilters = require('@asyncapi/nunjucks-filters');
|
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
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
|
|
9
10
|
* @param {Object} nunjucks Nunjucks environment.
|
|
10
11
|
* @param {Object} templateConfig Template configuration.
|
|
11
12
|
* @param {String} templateDir Directory where template is located.
|
|
@@ -21,6 +22,7 @@ module.exports.registerFilters = async (nunjucks, templateConfig, templateDir, f
|
|
|
21
22
|
|
|
22
23
|
/**
|
|
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
|
|
24
26
|
* @private
|
|
25
27
|
* @param {Object} nunjucks Nunjucks environment.
|
|
26
28
|
* @param {String} templateDir Directory where template is located.
|
|
@@ -68,6 +70,7 @@ function registerLocalFilters(nunjucks, templateDir, filtersDir) {
|
|
|
68
70
|
|
|
69
71
|
/**
|
|
70
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
|
|
71
74
|
* @private
|
|
72
75
|
* @param {Object} nunjucks Nunjucks environment.
|
|
73
76
|
* @param {String} templateDir Directory where template is located.
|
|
@@ -112,6 +115,7 @@ async function registerConfigFilters(nunjucks, templateDir, templateConfig) {
|
|
|
112
115
|
|
|
113
116
|
/**
|
|
114
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
|
|
115
119
|
* @private
|
|
116
120
|
* @param {Object} nunjucks Nunjucks environment.
|
|
117
121
|
* @param {Object} filters Module with functions.
|
package/lib/generator.js
CHANGED
|
@@ -134,7 +134,7 @@ class Generator {
|
|
|
134
134
|
Object.defineProperty(this.templateParams, key, {
|
|
135
135
|
enumerable: true,
|
|
136
136
|
get() {
|
|
137
|
-
if (!self.templateConfig.parameters
|
|
137
|
+
if (!self.templateConfig.parameters?.[key]) {
|
|
138
138
|
throw new Error(`Template parameter "${key}" has not been defined in the package.json file under generator property. Please make sure it's listed there before you use it in your template.`);
|
|
139
139
|
}
|
|
140
140
|
return templateParams[key];
|
|
@@ -436,7 +436,7 @@ class Generator {
|
|
|
436
436
|
* @param {String} asyncapiString AsyncAPI string to use as source.
|
|
437
437
|
* @param {Object} [parseOptions={}] AsyncAPI Parser parse options. Check out {@link https://www.github.com/asyncapi/parser-js|@asyncapi/parser} for more information.
|
|
438
438
|
* @deprecated Use the `generate` function instead. Just change the function name and it works out of the box.
|
|
439
|
-
* @return {Promise}
|
|
439
|
+
* @return {Promise<TemplateRenderResult|undefined>}
|
|
440
440
|
*/
|
|
441
441
|
async generateFromString(asyncapiString, parseOptions = {}) {
|
|
442
442
|
const isParsableCompatible = asyncapiString && typeof asyncapiString === 'string';
|
|
@@ -466,7 +466,7 @@ class Generator {
|
|
|
466
466
|
* }
|
|
467
467
|
*
|
|
468
468
|
* @param {String} asyncapiURL Link to AsyncAPI file
|
|
469
|
-
* @return {Promise}
|
|
469
|
+
* @return {Promise<TemplateRenderResult|undefined>}
|
|
470
470
|
*/
|
|
471
471
|
async generateFromURL(asyncapiURL) {
|
|
472
472
|
const doc = await fetchSpec(asyncapiURL);
|
|
@@ -493,7 +493,7 @@ class Generator {
|
|
|
493
493
|
* }
|
|
494
494
|
*
|
|
495
495
|
* @param {String} asyncapiFile AsyncAPI file to use as source.
|
|
496
|
-
* @return {Promise}
|
|
496
|
+
* @return {Promise<TemplateRenderResult|undefined>}
|
|
497
497
|
*/
|
|
498
498
|
async generateFromFile(asyncapiFile) {
|
|
499
499
|
const doc = await readFile(asyncapiFile, { encoding: 'utf8' });
|
|
@@ -562,8 +562,8 @@ class Generator {
|
|
|
562
562
|
|
|
563
563
|
try {
|
|
564
564
|
installedPkg = getTemplateDetails(this.templateName, PACKAGE_JSON_FILENAME);
|
|
565
|
-
pkgPath = installedPkg
|
|
566
|
-
packageVersion = installedPkg
|
|
565
|
+
pkgPath = installedPkg?.pkgPath;
|
|
566
|
+
packageVersion = installedPkg?.version;
|
|
567
567
|
log.debug(logMessage.templateSource(pkgPath));
|
|
568
568
|
if (packageVersion) log.debug(logMessage.templateVersion(packageVersion));
|
|
569
569
|
|
|
@@ -759,7 +759,7 @@ class Generator {
|
|
|
759
759
|
// Check if the filename dictates it should be separated
|
|
760
760
|
let wasSeparated = false;
|
|
761
761
|
for (const prop in fileNamesForSeparation) {
|
|
762
|
-
if (Object.
|
|
762
|
+
if (Object.hasOwn(fileNamesForSeparation, prop) && stats.name.includes(`$$${prop}$$`)) {
|
|
763
763
|
await this.generateSeparateFiles(asyncapiDocument, fileNamesForSeparation[prop], prop, stats.name, root);
|
|
764
764
|
const templateFilePath = path.relative(this.templateContentDir, path.resolve(root, stats.name));
|
|
765
765
|
fs.unlink(path.resolve(this.targetDir, templateFilePath), next);
|
|
@@ -875,7 +875,7 @@ class Generator {
|
|
|
875
875
|
const shouldOverwriteFile = await this.shouldOverwriteFile(relativeTargetFile);
|
|
876
876
|
if (!shouldOverwriteFile) return;
|
|
877
877
|
|
|
878
|
-
if (this.templateConfig.conditionalFiles
|
|
878
|
+
if (this.templateConfig.conditionalFiles?.[relativeSourceFile]) {
|
|
879
879
|
const server = this.templateParams.server && asyncapiDocument.servers().get(this.templateParams.server);
|
|
880
880
|
const source = jmespath.search({
|
|
881
881
|
...asyncapiDocument.json(),
|
package/lib/logMessages.js
CHANGED
|
@@ -2,7 +2,7 @@ const TEMPLATE_INSTALL_FLAG_MSG = 'because you passed --install flag';
|
|
|
2
2
|
|
|
3
3
|
const TEMPLATE_INSTALL_DISK_MSG = 'because the template cannot be found on disk';
|
|
4
4
|
|
|
5
|
-
const NODE_MODULES_INSTALL ='Remember that your local template must have its own node_modules installed first,
|
|
5
|
+
const NODE_MODULES_INSTALL = 'Remember that your local template must have its own node_modules installed first, "npm install" is not triggered by the generator.';
|
|
6
6
|
|
|
7
7
|
const NPM_INSTALL_TRIGGER = 'Installation of template located on disk technically means symlink creation betweed node_modules of the generator and template sources. Your local template must have its own node_modules, "npm install" is not triggered.';
|
|
8
8
|
|
|
@@ -19,7 +19,7 @@ function templateNotFound(templateName) {
|
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
function packageNotAvailable(packageDetails) {
|
|
22
|
-
if (packageDetails
|
|
22
|
+
if (packageDetails?.pkgPath) {
|
|
23
23
|
return `Unable to resolve template location at ${packageDetails.pkgPath}. Package is not available locally.`;
|
|
24
24
|
}
|
|
25
25
|
|
package/lib/parser.js
CHANGED
|
@@ -63,7 +63,7 @@ function convertOldOptionsToNew(oldOptions, generator) {
|
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
const resolvers = [];
|
|
66
|
-
if (generator
|
|
66
|
+
if (generator?.mapBaseUrlToFolder?.url) {
|
|
67
67
|
resolvers.push(...getMapBaseUrlToFolderResolvers(generator.mapBaseUrlToFolder));
|
|
68
68
|
}
|
|
69
69
|
if (oldOptions.resolve) {
|