@asyncapi/generator 1.9.4 → 1.9.7

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/.releaserc ADDED
@@ -0,0 +1,10 @@
1
+ ---
2
+ branches:
3
+ - master
4
+ plugins:
5
+ - - "@semantic-release/commit-analyzer"
6
+ - preset: conventionalcommits
7
+ - - "@semantic-release/release-notes-generator"
8
+ - preset: conventionalcommits
9
+ - "@semantic-release/npm"
10
+ - "@semantic-release/github"
@@ -0,0 +1,46 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to make participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
6
+
7
+ ## Our Standards
8
+
9
+ Examples of behavior that contributes to creating a positive environment include:
10
+
11
+ - Using welcoming and inclusive language
12
+ - Being respectful of differing viewpoints and experiences
13
+ - Gracefully accepting constructive criticism
14
+ - Focusing on what is best for the community
15
+ - Showing empathy towards other community members
16
+
17
+ Examples of unacceptable behavior by participants include:
18
+
19
+ - The use of sexualized language or imagery and unwelcome sexual attention or advances
20
+ - Trolling, insulting/derogatory comments, and personal or political attacks
21
+ - Public or private harassment
22
+ - Publishing others' private information, such as a physical or electronic address, without explicit permission
23
+ - Other conduct which could reasonably be considered inappropriate in a professional setting
24
+
25
+ ## Our Responsibilities
26
+
27
+ Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
28
+
29
+ Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
30
+
31
+ ## Scope
32
+
33
+ This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
34
+
35
+ ## Enforcement
36
+
37
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at fmvilas@gmail.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
38
+
39
+ Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
40
+
41
+ ## Attribution
42
+
43
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
44
+
45
+ [homepage]: http://contributor-covenant.org
46
+ [version]: http://contributor-covenant.org/version/1/4/
package/CONTRIBUTING.md CHANGED
@@ -1,38 +1,61 @@
1
- ## Overview
1
+ # Contributing to AsyncAPI
2
+ We love your input! We want to make contributing to this project as easy and transparent as possible.
2
3
 
3
- Contributions are more than welcome. If you want to contribute, please make sure you go through the following steps:
4
+ ## Contribution recogniton
4
5
 
5
- 1. Pick or create an issue.
6
- - It's always a good idea to leave a message saying that you're going to work on it before you start any actual work.
7
- - Consider contacting us on [slack](https://www.asyncapi.com/slack-invite/) to discuss the topic first
8
- 2. Fork the repository and work there.
9
- 3. Open a Pull Request pointing to the `master` branch.
10
- 4. A maintainer will review and, eventually, merge your Pull Request. Please, be patient as most of us are doing this in our spare time.
6
+ We use [All Contributors](https://allcontributors.org/docs/en/specification) specification to handle recognitions. For more details read [this](https://github.com/asyncapi/community/blob/master/recognize-contributors.md) document.
11
7
 
12
- ## Code validation
8
+ ## Summary of the contribution flow
13
9
 
14
- Before creating a Pull Request you should validate your code with ESLint.
10
+ The following is a summary of the ideal contribution flow. Please, note that Pull Requests can also be rejected by the maintainers when appropriate.
15
11
 
16
12
  ```
17
- npm run lint
13
+ ┌───────────────────────┐
14
+ │ │
15
+ │ Open an issue │
16
+ │ (a bug report or a │
17
+ │ feature request) │
18
+ │ │
19
+ └───────────────────────┘
20
+
21
+ ┌───────────────────────┐
22
+ │ │
23
+ │ Open a Pull Request │
24
+ │ (only after issue │
25
+ │ is approved) │
26
+ │ │
27
+ └───────────────────────┘
28
+
29
+ ┌───────────────────────┐
30
+ │ │
31
+ │ Your changes will │
32
+ │ be merged and │
33
+ │ published on the next │
34
+ │ release │
35
+ │ │
36
+ └───────────────────────┘
18
37
  ```
19
38
 
20
- ## Developing with Docker
39
+ ## Code of Conduct
40
+ AsyncAPI has adopted a Code of Conduct that we expect project participants to adhere to. Please [read the full text](./CODE_OF_CONDUCT.md) so that you can understand what sort of behaviour is expected.
21
41
 
22
- In case you want to quickly build a docker image locally to check if it works then run `npm run docker-build`
42
+ ## Our Development Process
43
+ We use Github to host code, to track issues and feature requests, as well as accept pull requests.
23
44
 
24
- In case you don't have a local node environment you can run
45
+ ## Issues
46
+ [Open an issue](https://github.com/asyncapi/asyncapi/issues/new) **only** if you want to report a bug or a feature. Don't open issues for questions or support, instead join our [Slack workspace](https://www.asyncapi.com/slack-invite) and ask there. Don't forget to follow our [Slack Etiquette](https://github.com/asyncapi/community/blob/master/slack-etiquette.md) while interacting with community members! It's more likely you'll get help, and much faster!
25
47
 
26
- ```
27
- docker build -t asyncapi/generator:latest .
28
- docker run -v `pwd`:`pwd` -w `pwd` -it --rm --entrypoint /bin/sh asyncapi/generator:latest
29
- npm install
30
- ./cli.js --help
31
- ```
48
+ ## Bug Reports and Feature Requests
49
+
50
+ Please use our issues templates that provide you with hints on what information we need from you to help you out.
51
+
52
+ ## Pull Requests
53
+
54
+ **Please, make sure you open an issue before starting with a Pull Request, unless it's a typo or a really obvious error.** Pull requests are the best way to propose changes to the specification. Get familiar with our document that explains [Git workflow](https://github.com/asyncapi/community/blob/master/git-workflow.md) used in our repositories.
32
55
 
33
56
  ## Conventional commits
34
57
 
35
- This project follows [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/#summary) specification. Releasing to GitHub and NPM is done with the support of [semantic-release](https://semantic-release.gitbook.io/semantic-release/).
58
+ Our repositories follow [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/#summary) specification. Releasing to GitHub and NPM is done with the support of [semantic-release](https://semantic-release.gitbook.io/semantic-release/).
36
59
 
37
60
  Pull requests should have a title that follows the specification, otherwise, merging is blocked. If you are not familiar with the specification simply ask maintainers to modify. You can also use this cheatsheet if you want:
38
61
 
@@ -48,3 +71,9 @@ What about MAJOR release? just add `!` to the prefix, like `fix!: ` or `refactor
48
71
  Prefix that follows specification is not enough though. Remember that the title must be clear and descriptive with usage of [imperative mood](https://chris.beams.io/posts/git-commit/#imperative).
49
72
 
50
73
  Happy contributing :heart:
74
+
75
+ ## License
76
+ When you submit changes, your submissions are understood to be under the same [Apache 2.0 License](https://github.com/asyncapi/asyncapi/blob/master/LICENSE) that covers the project. Feel free to [contact the maintainers](https://www.asyncapi.com/slack-invite) if that's a concern.
77
+
78
+ ## References
79
+ This document was adapted from the open-source contribution guidelines for [Facebook's Draft](https://github.com/facebook/draft-js/blob/master/CONTRIBUTING.md).
package/README.md CHANGED
@@ -286,9 +286,8 @@ Before using newer versions of the template, always look at the [changelog](http
286
286
  ## How to create a template
287
287
 
288
288
  To create your own template, for example code generator for some specific language and technology, learn from the following resources:
289
- - Read the documentation about [authoring templates](docs/authoring.md)
289
+ - Read the [documentation](docs/README.md)
290
290
  - Use [Template for Generator Templates](https://github.com/asyncapi/template-for-generator-templates) that showcases Generator features
291
- - Check the [list of templates recipes](docs/templates-recipes.md)
292
291
 
293
292
  ## Contributing
294
293
 
@@ -317,6 +316,9 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
317
316
  <td align="center"><a href="https://github.com/muenchhausen"><img src="https://avatars.githubusercontent.com/u/1210783?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Derk Muenchhausen</b></sub></a><br /><a href="https://github.com/asyncapi/generator/commits?author=muenchhausen" title="Code">💻</a></td>
318
317
  <td align="center"><a href="http://ben.timby.com/"><img src="https://avatars.githubusercontent.com/u/669270?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Ben Timby</b></sub></a><br /><a href="https://github.com/asyncapi/generator/commits?author=btimby" title="Code">💻</a></td>
319
318
  </tr>
319
+ <tr>
320
+ <td align="center"><a href="https://github.com/lkmandy"><img src="https://avatars.githubusercontent.com/u/17765231?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Amanda Shafack </b></sub></a><br /><a href="https://github.com/asyncapi/generator/commits?author=lkmandy" title="Documentation">📖</a></td>
321
+ </tr>
320
322
  </table>
321
323
 
322
324
  <!-- markdownlint-restore -->
package/docs/README.md ADDED
@@ -0,0 +1,15 @@
1
+ Table of Contents
2
+
3
+ - [Introduction](index.md)
4
+ - [AsyncAPI Specification File](asyncapi-file.md)
5
+ - [Configuration File](configuration-file.md)
6
+ - [Templates](template.md)
7
+ - [Authoring Templates](authoring-templates.md)
8
+ - [React Render Engine](react-render-engine.md)
9
+ - [Nunjucks Render Engine](nunjucks-render-engine.md)
10
+ - [AsyncAPI Context](asyncapi-context.md)
11
+ - [Parser](parser.md)
12
+ - [Hooks](hooks.md)
13
+ - [File Templates](file-templates.md)
14
+ - [TypeScript Support](typescript-support.md)
15
+ - [Special file names](special-file-names.md)
@@ -0,0 +1,6 @@
1
+ ---
2
+ title: "AsyncAPI Context"
3
+ weight: 80
4
+ ---
5
+
6
+ >This document is under construction.
@@ -0,0 +1,6 @@
1
+ ---
2
+ title: "AsyncAPI Specification File"
3
+ weight: 20
4
+ ---
5
+
6
+ >This document is under construction.
@@ -0,0 +1,17 @@
1
+ ---
2
+ title: "Authoring Templates"
3
+ weight: 50
4
+ ---
5
+
6
+ The AsyncAPI generator has been built with extensibility in mind. The package uses a set of default templates to let you generate documentation and code. However, you can create and use your own templates. In this section, you learn how to create your own one.
7
+
8
+ To work on a template, you need an AsyncAPI specification file that you can use for testing. For this purpose, you can use [this](../test/docs/dummy.yml) dummy file as it's purpose is to cover as many features of AsyncAPI as possible. Do not copy this file to your template but use it directly from this repo like this: `ag https://raw.githubusercontent.com/asyncapi/generator/master/test/docs/dummy.yml ./your-template`
9
+
10
+ > In case you find some features missing or other possible improvements in the dummy file, suggest changes. The goal is to build a file that all templates can use and check their specification features coverage.
11
+
12
+ 1. A template is a directory in your file system.
13
+ 1. The template can have own dependencies. Just create `package.json` for the template. The generator makes sure to trigger the installation of dependencies.
14
+ 1. Templates can be configured. Configuration must be stored in the `package.json` file under custom `generator` property. [Read more about the configuration file](#configuration-file).
15
+ 1. The template engine can be either [React](#react) (recommended) or [Nunjucks](#nunjucks) (default). This can be controlled with the `renderer` property in the [template configuration](#template-configuration).
16
+ 1. Templates may contain `hooks` that are functions invoked during specific moment of the generation. In the template, they must be stored in the `hooks` directory under the template directory. They can also be stored in other modules and external libraries and configured inside the template [Read more about hooks](#hooks).
17
+ 1. There are parameters with special meaning. [Read more about special parameters](#special-parameters).
@@ -0,0 +1,78 @@
1
+ ---
2
+ title: "Configuration File"
3
+ weight: 30
4
+ ---
5
+
6
+ The `generator` property from `package.json` file must contain a JSON object that may have the following information:
7
+
8
+ |Name|Type|Description|
9
+ |---|---|---|
10
+ |`renderer`| String | Its value can be either `react` or `nunjucks` (default).
11
+ |`supportedProtocols`| [String] | A list with all the protocols this template supports.
12
+ |`parameters`| Object[String, Object] | An object with all the parameters that can be passed when generating the template. When using the command line, it's done by indicating `--param name=value` or `-p name=value`.
13
+ |`parameters[param].description`| String | A user-friendly description about the parameter.
14
+ |`parameters[param].default`| Any | Default value of the parameter if not specified. Shouldn't be used for mandatory `required=true` parameters.
15
+ |`parameters[param].required`| Boolean | Whether the parameter is required or not.
16
+ |`conditionalFiles`| Object[String, Object] | An object containing all the file paths that should be conditionally rendered. Each key represents a file path and each value must be an object with the keys `subject` and `validation`. The file path should be relative to the `template` directory inside the template.
17
+ |`conditionalFiles[filePath].subject`| String | The `subject` is a [JMESPath](http://jmespath.org/) query to grab the value you want to apply the condition to. It queries an object with the whole AsyncAPI document and, when specified, the given server. The object looks like this: `{ asyncapi: { ... }, server: { ... } }`. If the template supports `server` parameter, you can access server details like for example protocol this way: `server.protocol`. During validation with `conditionalFiles` only the server that template user selected is available in the specification file. For more information about `server` parameter [read about special parameters](#special-parameters).
18
+ |`conditionalFiles[filePath].validation`| Object | The `validation` is a JSON Schema Draft 07 object. This JSON Schema definition will be applied to the JSON value resulting from the `subject` query. If validation doesn't have errors, the condition is met, and therefore the given file will be rendered. Otherwise, the file is ignored. Check [JSON Schema Validation](https://json-schema.org/draft-07/json-schema-validation.html#rfc.section.6) document for a list of all possible validation keywords.
19
+ |`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.
20
+ |`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).
21
+ |`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.
22
+ |`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, for more you must pass an array of strings. In case of external modules, remember they need to be added as a dependency in `package.json` of your template.
23
+
24
+ ### Example
25
+
26
+ ```json
27
+ "generator":
28
+ {
29
+ "renderer": "react",
30
+ "supportedProtocols": ["amqp", "mqtt"],
31
+ "parameters": {
32
+ "server": {
33
+ "description": "The server you want to use in the code.",
34
+ "required": true
35
+ },
36
+ "dummyParameter": {
37
+ "description": "Example of parameter with default value.",
38
+ "default": "just a string",
39
+ "required": false
40
+ }
41
+ },
42
+ "conditionalFiles": {
43
+ "path/to/file/that/is/relative/to/template/dir/test-amqp.js": {
44
+ "subject": "server.protocol",
45
+ "validation": {
46
+ "const": "amqp"
47
+ }
48
+ },
49
+ "path/to/file/that/is/relative/to/template/dir/support.html": {
50
+ "subject": "info.contact",
51
+ "validation": {
52
+ "required": ["url"]
53
+ }
54
+ }
55
+ },
56
+ "nonRenderableFiles": [
57
+ "src/api/middlewares/*.*",
58
+ "lib/lib/config.js"
59
+ ],
60
+ "generator": "<2.0.0",
61
+ "filters": [
62
+ "@asyncapi/generator-filters"
63
+ ],
64
+ "hooks": {
65
+ "@asyncapi/generator-hooks": "hookFunctionName"
66
+ }
67
+ }
68
+ ```
69
+
70
+ ## Special parameters
71
+
72
+ There are some template parameters that have a special meaning:
73
+
74
+ |Name|Description|
75
+ |---|---|
76
+ |`server`| It is used to let the template know which server from the AsyncAPI specification file you want to use. In some cases, this may be required. For instance, when generating code that connects to a specific server. Use this parameter in case your template relies on users' information about what server from the specification file they want to use during generation. You also need this parameter if you want to use `server.protocol` notation within `conditionalFiles` configuration option. Once you decide to specify this parameter for your template, it is recommended you make it a mandatory parameter otherwise a feature like `conditionalFiles` is not going to work if your users do not use this parameter obligatory.
77
+
78
+
@@ -0,0 +1,67 @@
1
+ ---
2
+ title: "File templates"
3
+ weight: 110
4
+ ---
5
+
6
+ It is possible to generate files for each specific object in your AsyncAPI documentation. 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 in them are available:
7
+
8
+ - `$$channel$$`, within the template-file you have access to two variables [`channel`](https://github.com/asyncapi/parser-js/blob/master/API.md#Channel) and [`channelName`](https://github.com/asyncapi/parser-js/blob/master/API.md#AsyncAPIDocument+channels). Where the `channel` contains the current channel being rendered.
9
+ - `$$message$$`, within the template-file you have access to two variables [`message`](https://github.com/asyncapi/parser-js/blob/master/API.md#Message) and [`messageName`](https://github.com/asyncapi/parser-js/blob/master/API.md#Message+uid). Where `message` contains the current message being rendered.
10
+ - `$$schema$$`, within the template-file you have access to two variables [`schema`](https://github.com/asyncapi/parser-js/blob/master/API.md#Schema) and [`schemaName`](https://github.com/asyncapi/parser-js/blob/master/API.md#Schema+uid). Where `schema` contains the current schema being rendered. Only schemas from [Components object](https://www.asyncapi.com/docs/specifications/2.0.0/#a-name-componentsobject-a-components-object) are used.
11
+ - `$$everySchema$$`, within the template-file you have access to two variables [`schema`](https://github.com/asyncapi/parser-js/blob/master/API.md#Schema) and [`schemaName`](https://github.com/asyncapi/parser-js/blob/master/API.md#Schema+uid). Where `schema` contains the current schema being rendered. Every [Schema object](https://www.asyncapi.com/docs/specifications/2.0.0/#schemaObject) from the entire AsyncAPI file is used.
12
+ - `$$objectSchema$$`, within the template-file you have access to two variables [`schema`](https://github.com/asyncapi/parser-js/blob/master/API.md#Schema) and [`schemaName`](https://github.com/asyncapi/parser-js/blob/master/API.md#Schema+uid). Where `schema` contains the current schema being rendered. All the [Schema objects](https://www.asyncapi.com/docs/specifications/2.0.0/#schemaObject) with type object is used.
13
+ - `$$parameter$$`, within the template-file you have access to two variables [`parameter`](https://github.com/asyncapi/parser-js/blob/master/API.md#ChannelParameter) and [`parameterName`](https://github.com/asyncapi/parser-js/blob/master/API.md#Channel+parameters). Where the `parameter` contains the current parameter being rendered.
14
+ - `$$securityScheme$$`, within the template-file you have access to two variables [`securityScheme`](https://github.com/asyncapi/parser-js/blob/master/API.md#SecurityScheme) and [`securitySchemeName`](https://github.com/asyncapi/parser-js/blob/master/API.md#Components+securitySchemes). Where `securityScheme` contains the current security scheme being rendered.
15
+
16
+ The file name will be equal to `*Name` variable.
17
+
18
+ ### Example
19
+
20
+ The file name is `$$schema$$.txt`, the content of this file is:
21
+ ```
22
+ Schema name is '{{schemaName}}' and properties are:
23
+ {% for propName, prop in schema.properties() %}
24
+ - {{prop.uid()}}
25
+ {% endfor %}
26
+ ```
27
+
28
+ With following AsyncAPI:
29
+ ```
30
+ components:
31
+ schemas:
32
+ peoplePayload:
33
+ type: object
34
+ properties:
35
+ event:
36
+ $ref: "#/components/schemas/people"
37
+ people:
38
+ type: object
39
+ properties:
40
+ id:
41
+ type: integer
42
+ ```
43
+
44
+ The generator creates two files `peoplePayload.txt` and `people.txt` with the following content:
45
+ ```
46
+ Schema name is 'peoplePayload' and properties are:
47
+ - people
48
+ ```
49
+
50
+ and
51
+ ```
52
+ Schema name is 'people' and properties are:
53
+ - id
54
+ ```
55
+
56
+ ### React
57
+
58
+ The above way of rendering **file templates** works for both `nunjucks` and `react` render engines, but `react` also has another, more generic way to render multiple files. It is enough to return an array of `File` components in the rendering component. See the following example:
59
+
60
+ ```tsx
61
+ export default function({ asyncapi }) {
62
+ return [
63
+ <File name={`file1.html`}>Content</File>,
64
+ <File name={`file2.html`}>Content</File>
65
+ ]
66
+ }
67
+ ```
package/docs/hooks.md ADDED
@@ -0,0 +1,81 @@
1
+ ---
2
+ title: "Hooks"
3
+ weight: 100
4
+ ---
5
+
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
+ The following types of hooks are currently supported:
8
+
9
+ |Hook type|Description| Return type | Arguments
10
+ |---|---|---|---|
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](https://github.com/asyncapi/generator/blob/master/docs/api.md)
12
+ | `generate:after` | Called at the very end of the generation. | void : Nothing is expected to be returned. | [The generator instance](https://github.com/asyncapi/generator/blob/master/docs/api.md)
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](https://github.com/asyncapi/generator/blob/master/docs/api.md) and object in the form of `{ "originalFilename" : string }`
14
+
15
+ The generator parses:
16
+ - All the files in the `.hooks` directory inside the template.
17
+ - All modules listed in the template configuration and triggers only hooks that names were added to the config. You can use the official AsyncAPI [hooks library](https://github.com/asyncapi/generator-hooks). To learn how to add hooks to configuration [read more about the configuration file](#configuration-file).
18
+
19
+ ### Examples
20
+
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](#configuration-file).
22
+
23
+ Most basic modules with hooks look like this:
24
+ ```js
25
+ module.exports = {
26
+ 'generate:after': generator => console.log('This runs after generation is complete')
27
+ }
28
+ ```
29
+
30
+ Below you have an example Hook that after generation creates an AsyncAPI file.
31
+
32
+ ```js
33
+ const fs = require('fs');
34
+ const path = require('path');
35
+
36
+ module.exports = {
37
+ 'generate:after': generator => {
38
+ const asyncapi = generator.originalAsyncAPI;
39
+ let extension;
40
+
41
+ try {
42
+ JSON.parse(asyncapi);
43
+ extension = 'json';
44
+ } catch (e) {
45
+ extension = 'yaml';
46
+ }
47
+
48
+ fs.writeFileSync(path.resolve(generator.targetDir, `asyncapi.${extension}`), asyncapi);
49
+ }
50
+ };
51
+ ```
52
+ And here an example Hook that before generation switches `publish` and `subscribe` operations for each channel.
53
+
54
+ ```js
55
+ module.exports = {
56
+ 'generate:before': function switchOperations(generator) {
57
+ const asyncapi = generator.asyncapi;
58
+ for (let [key, value] of Object.entries(asyncapi.channels())) {
59
+ let publish = value._json.publish;
60
+ value._json.publish = value._json.subscribe;
61
+ value._json.subscribe = publish;
62
+ if (!value._json.subscribe) {
63
+ delete value._json.subscribe;
64
+ }
65
+ if (!value._json.publish) {
66
+ delete value._json.publish;
67
+ }
68
+ }
69
+ };
70
+ };
71
+ ```
72
+
73
+ Example hook for changing the filename of a template file. Replaces all '-' characters with '_'.
74
+ ```js
75
+ module.exports = {
76
+ 'setFileTemplateName': (generator, hookArguments) => {
77
+ const currentFilename = hookArguments.originalFilename ;
78
+ return currentFilename.replace('-', '_')
79
+ };
80
+ };
81
+ ```
package/docs/index.md ADDED
@@ -0,0 +1,6 @@
1
+ ---
2
+ title: "Introduction"
3
+ weight: 10
4
+ ---
5
+
6
+ >This document is under construction.
@@ -0,0 +1,78 @@
1
+ ---
2
+ title: "Nunjucks Render Engine"
3
+ weight: 70
4
+ ---
5
+
6
+ [Nunjucks](https://mozilla.github.io/nunjucks) is the default render engine, however, we strongly recommend adopting the [React](#react) engine.
7
+
8
+ ### Common assumptions
9
+
10
+ 1. Templates may contain [Nunjucks filters or helper functions](https://mozilla.github.io/nunjucks/templating.html#builtin-filters). [Read more about filters](#filters).
11
+ 1. Templates may contain `partials` (reusable chunks). They must be stored in the `.partials` directory under the template directory. [Read more about partials](#partials).
12
+ 1. Templates may contain multiple files. Unless stated otherwise, all files will be rendered.
13
+ 1. The default variables you have access to in any the template file are the following:
14
+ - `asyncapi` that is a parsed spec file object. Read the [API](https://github.com/asyncapi/parser-js/blob/master/API.md#AsyncAPIDocument) of the Parser to understand what structure you have access to in this parameter.
15
+ - `originalAsyncAPI` that is an original spec file before it is parsed.
16
+ - `params` that contain the parameters provided when generating.
17
+
18
+ ### Partials
19
+
20
+ 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:
21
+
22
+ ```html
23
+ {# tags.html #}
24
+ {% macro tags(tagList) %}
25
+ <div class="mt-4">
26
+ {% for tag in tagList %}
27
+ <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>
28
+ {% endfor %}
29
+ </div>
30
+ {% endmacro %}
31
+
32
+ {# operations.html #}
33
+ {% from "./tags.html" import tags %}
34
+ {{ tags(operation.tags()) }}
35
+ ```
36
+
37
+ ### Filters
38
+
39
+ 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.
40
+
41
+ You can use the filter function in your template as in the following example:
42
+
43
+ ```js
44
+ const {{ channelName | camelCase }} = '{{ channelName }}';
45
+ ```
46
+
47
+ 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:
48
+
49
+ ```js
50
+ const filter = module.exports;
51
+
52
+ async function asyncCamelCase(str, callback) {
53
+ try {
54
+ const result = // logic for camel casing str
55
+ callback(null, result);
56
+ } catch (error) {
57
+ callback(error);
58
+ }
59
+ }
60
+ filter.renderAsyncContent = renderAsyncContent;
61
+
62
+ // using in template
63
+ {{ channelName | asyncCamelCase }}
64
+ ```
65
+
66
+ Unfortunately, if you need to use Promise, filter still must be annotated with the `async` keyword:
67
+
68
+ ```js
69
+ async function asyncCamelCase(str, callback) {
70
+ return new Promise((resolve, reject) => {
71
+ // logic with callback
72
+ });
73
+ }
74
+ ```
75
+
76
+ 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. You can also use the official AsyncAPI [filters library](https://github.com/asyncapi/generator-filters). To learn how to add such filters to configuration [read more about the configuration file](#configuration-file).
77
+
78
+
package/docs/parser.md ADDED
@@ -0,0 +1,6 @@
1
+ ---
2
+ title: "Parser"
3
+ weight: 90
4
+ ---
5
+
6
+ >This document is under construction.
@@ -0,0 +1,80 @@
1
+ ---
2
+ title: "React Render Engine"
3
+ weight: 60
4
+ ---
5
+
6
+ [React](https://reactjs.org) is the render engine that we strongly suggest you should use for any new templates. The only reason it is not the default render engine is to stay backward compatible.
7
+
8
+ * It enables the possibility of [debugging](#debugging-react-template) your template (this is not possible with Nunjucks).
9
+ * It provides better error stack traces.
10
+ * Provides better support for separating code into more manageable chunks/components.
11
+ * The readability of the template is much better compared to Nunjucks syntax.
12
+ * Better tool support for development.
13
+ * Introduces testability of components which is not possible with Nunjucks.
14
+
15
+ When writing React templates you decide whether to use CommonJS, ES5, or ES6 modules since everything is bundled together before the rendering process takes over. We use our own React renderer which can be found in the [Generator React SDK](https://github.com/asyncapi/generator-react-sdk).
16
+ There you can find information about how the renderer works or how we transpile your template files.
17
+
18
+ Your React template always require `@asyncapi/generator-react-sdk` as a dependency. `@asyncapi/generator-react-sdk` is required to access the `File` component which is required as a root component for a file to be rendered. Furthermore it provides some common components to make your development easier, like `Text` or `Indent`.
19
+
20
+ Let's consider a basic React template as the one below called `MyTemplate.js`:
21
+
22
+ ```js
23
+ import { File, Text } from "@asyncapi/generator-react-sdk";
24
+
25
+ export default function({ asyncapi, params, originalAsyncAPI }) {
26
+ return (
27
+ <File name="asyncapi.md">
28
+ <Text>Some text that should render as is</Text>
29
+ </File>
30
+ );
31
+ }
32
+ ```
33
+
34
+ The exported default function returns a `File` component as a root component which the [Generator](https://github.com/asyncapi/generator) uses to figure out what file should be generated. In our case we overwrite the default functionality of saving the file as `MyTemplate.js` but instead use the filename `asyncapi.md`. It is then specified that we should render `Some text that should render as is\n` within that file. Notice the `\n` character at the end, this is something that is automatically added after the `Text` component.
35
+
36
+ For further information about components, props etc. see the [Generator React SDK](https://github.com/asyncapi/generator-react-sdk)
37
+
38
+ ### Common assumptions
39
+
40
+ 1. Generator renders all files located in the `template` directory if they meet the following conditions:
41
+ - `File` is the root component
42
+ - The file is not in the list of `nonRenderableFiles` in the template configuration
43
+ 1. New lines are automatically added after each `Text` component.
44
+ 1. The props you have access to in rendering function is:
45
+ - `asyncapi` that is a parsed spec file object. Read the [API](https://github.com/asyncapi/parser-js/blob/master/API.md#AsyncAPIDocument) of the Parser to understand what structure you have access to in this parameter.
46
+ - `originalAsyncAPI` that is an original spec file before it is parsed.
47
+ - `params` that contain the parameters provided when generating.
48
+ 1. All the file templates are supported where the variables are provided after the default props as listed above.
49
+
50
+ ### Debugging React template in VSCode
51
+
52
+ With React, it enables you to debug your templates. For Visual Studio Code, we have created a boilerplate [launch configuration](https://code.visualstudio.com/docs/editor/debugging#_launch-configurations) to enable debug in your template. Add the following launch configuration:
53
+
54
+ ```json
55
+ {
56
+ "version": "0.2.0",
57
+ "configurations": [
58
+ {
59
+ "type": "node",
60
+ "request": "launch",
61
+ "name": "Debug template",
62
+ "timeout": 10000,
63
+ "sourceMaps": true,
64
+ "args": [
65
+ "./asyncapi.yml",
66
+ "./template",
67
+ "--output",
68
+ "./output",
69
+ "--install",
70
+ "--force-write"
71
+ ],
72
+ "program": "ag"
73
+ }
74
+ ]
75
+ }
76
+ ```
77
+
78
+ Now replace `./asyncapi.yml` with your document of choice. Replace `./template` with the path to your React template. You can now debug your template by adding any breakpoints you want and inspect your code.
79
+
80
+
@@ -0,0 +1,11 @@
1
+ ---
2
+ title: "Special file names"
3
+ weight: 130
4
+ ---
5
+
6
+ We use NPM behind the scenes to download and install the templates. Since NPM will not fetch files like `.gitignore`, you should name them differently. Luckily, the Generator will take care of renaming them back for you. The following is a table of the special file names:
7
+
8
+ |Special file name|Output file name|
9
+ |---|---|
10
+ |`{.gitignore}`|`.gitignore`|
11
+ |`{.npmignore}`|`.npmignore`|
@@ -0,0 +1,6 @@
1
+ ---
2
+ title: "Template"
3
+ weight: 40
4
+ ---
5
+
6
+ >This document is under construction.
@@ -0,0 +1,13 @@
1
+ ---
2
+ title: "TypeScript Support"
3
+ weight: 120
4
+ ---
5
+
6
+ The AsyncAPI generator has TypeScript support for [hooks](#hooks) and Nunjucks's [filters](#filters). Assumptions:
7
+
8
+ - Installing the `typescript` package and creating the` tsconfig.json` file isn't necessary.
9
+ - Source code of the hook/filter must have `.ts` extension.
10
+ - Each package related to the typings for TypeScript like `@types/node` must be installed in the template under `dependencies` array. This is because the Generator transpiles the TypeScript code on-the-fly while rendering the template, and cannot use packages under `devDependencies`.
11
+ - Each template should have `@types/node` package installed to enable support for typings for Node.
12
+
13
+
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@asyncapi/generator",
3
- "version": "1.9.4",
3
+ "version": "1.9.7",
4
4
  "description": "The AsyncAPI generator. It can generate documentation, code, anything!",
5
5
  "main": "./lib/generator.js",
6
6
  "bin": {
@@ -19,7 +19,6 @@
19
19
  "test:cli": "node cli.js ./test/docs/dummy.yml @asyncapi/html-template -o test/output --force-write --debug && test -e test/output/index.html",
20
20
  "test:cleanup": "rimraf \"test/temp\"",
21
21
  "docs": "jsdoc2md lib/generator.js > docs/api.md",
22
- "release": "semantic-release",
23
22
  "docker:build": "docker build -t asyncapi/generator:latest .",
24
23
  "lint": "eslint --max-warnings 0 --config .eslintrc .",
25
24
  "lint:tpl:validator": "eslint --fix --config .eslintrc .github/templates-list-validator",
@@ -48,15 +47,16 @@
48
47
  "license": "Apache-2.0",
49
48
  "homepage": "https://github.com/asyncapi/generator",
50
49
  "dependencies": {
51
- "@asyncapi/avro-schema-parser": "^1.0.0",
50
+ "@asyncapi/avro-schema-parser": "^1.1.0",
52
51
  "@asyncapi/generator-react-sdk": "^0.2.23",
53
52
  "@asyncapi/openapi-schema-parser": "^2.0.1",
54
- "@asyncapi/parser": "^1.15.0",
53
+ "@asyncapi/parser": "^1.15.1",
55
54
  "@asyncapi/raml-dt-schema-parser": "^2.0.1",
56
55
  "@npmcli/arborist": "^2.2.4",
57
56
  "ajv": "^6.10.2",
58
57
  "chokidar": "^3.4.0",
59
58
  "commander": "^6.1.0",
59
+ "conventional-changelog-conventionalcommits": "^5.0.0",
60
60
  "filenamify": "^4.1.0",
61
61
  "fs.extra": "^1.3.2",
62
62
  "global-dirs": "^3.0.0",
@@ -77,12 +77,6 @@
77
77
  "typescript": "^4.2.2"
78
78
  },
79
79
  "devDependencies": {
80
- "@semantic-release/commit-analyzer": "^8.0.1",
81
- "@semantic-release/github": "^7.0.4",
82
- "@semantic-release/npm": "^7.0.6",
83
- "@semantic-release/release-notes-generator": "^9.0.1",
84
- "all-contributors-cli": "^6.14.2",
85
- "conventional-changelog-conventionalcommits": "^4.4.0",
86
80
  "eslint": "^6.8.0",
87
81
  "eslint-plugin-jest": "^23.8.2",
88
82
  "eslint-plugin-sonarjs": "^0.5.0",
@@ -90,28 +84,6 @@
90
84
  "jsdoc-to-markdown": "^5.0.0",
91
85
  "markdown-toc": "^1.2.0",
92
86
  "rimraf": "^3.0.2",
93
- "semantic-release": "^17.2.2",
94
87
  "unixify": "^1.0.0"
95
- },
96
- "release": {
97
- "branches": [
98
- "master"
99
- ],
100
- "plugins": [
101
- [
102
- "@semantic-release/commit-analyzer",
103
- {
104
- "preset": "conventionalcommits"
105
- }
106
- ],
107
- [
108
- "@semantic-release/release-notes-generator",
109
- {
110
- "preset": "conventionalcommits"
111
- }
112
- ],
113
- "@semantic-release/npm",
114
- "@semantic-release/github"
115
- ]
116
88
  }
117
89
  }
package/docs/authoring.md DELETED
@@ -1,402 +0,0 @@
1
- # Authoring templates
2
-
3
- The AsyncAPI generator has been built with extensibility in mind. The package uses a set of default templates to let you generate documentation and code. However, you can create and use your own templates. In this section, you learn how to create your own one.
4
-
5
- To work on a template, you need an AsyncAPI specification file that you can use for testing. For this purpose, you can use [this](../test/docs/dummy.yml) dummy file as it's purpose is to cover as many features of AsyncAPI as possible. Do not copy this file to your template but use it directly from this repo like this: `ag https://raw.githubusercontent.com/asyncapi/generator/master/test/docs/dummy.yml ./your-template`
6
-
7
- > In case you find some features missing or other possible improvements in the dummy file, suggest changes. The goal is to build a file that all templates can use and check their specification features coverage.
8
-
9
- ## Common assumptions
10
-
11
- 1. A template is a directory in your file system.
12
- 1. The template can have own dependencies. Just create `package.json` for the template. The generator makes sure to trigger the installation of dependencies.
13
- 1. Templates can be configured. Configuration must be stored in the `package.json` file under custom `generator` property. [Read more about the configuration file](#configuration-file).
14
- 1. The template engine can be either [React](#react) (recommended) or [Nunjucks](#nunjucks) (default). This can be controlled with the `renderer` property in the [template configuration](#template-configuration).
15
- 1. Templates may contain `hooks` that are functions invoked during specific moment of the generation. In the template, they must be stored in the `hooks` directory under the template directory. They can also be stored in other modules and external libraries and configured inside the template [Read more about hooks](#hooks).
16
- 1. There are parameters with special meaning. [Read more about special parameters](#special-parameters).
17
-
18
- ## Special file names
19
-
20
- We use NPM behind the scenes to download and install the templates. Since NPM will not fetch files like `.gitignore`, you should name them differently. Luckily, the Generator will take care of renaming them back for you. The following is a table of the special file names:
21
-
22
- |Special file name|Output file name|
23
- |---|---|
24
- |`{.gitignore}`|`.gitignore`|
25
- |`{.npmignore}`|`.npmignore`|
26
-
27
- ## File templates
28
-
29
- It is possible to generate files for each specific object in your AsyncAPI documentation. 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 in them are available:
30
-
31
- - `$$channel$$`, within the template-file you have access to two variables [`channel`](https://github.com/asyncapi/parser-js/blob/master/API.md#Channel) and [`channelName`](https://github.com/asyncapi/parser-js/blob/master/API.md#AsyncAPIDocument+channels). Where `channel` contains the current channel being rendered.
32
- - `$$message$$`, within the template-file you have access to two variables [`message`](https://github.com/asyncapi/parser-js/blob/master/API.md#Message) and [`messageName`](https://github.com/asyncapi/parser-js/blob/master/API.md#Message+uid). Where `message` contains the current message being rendered.
33
- - `$$schema$$`, within the template-file you have access to two variables [`schema`](https://github.com/asyncapi/parser-js/blob/master/API.md#Schema) and [`schemaName`](https://github.com/asyncapi/parser-js/blob/master/API.md#Schema+uid). Where `schema` contains the current schema being rendered. Only schemas from [Components object](https://www.asyncapi.com/docs/specifications/2.0.0/#a-name-componentsobject-a-components-object) are used.
34
- - `$$everySchema$$`, within the template-file you have access to two variables [`schema`](https://github.com/asyncapi/parser-js/blob/master/API.md#Schema) and [`schemaName`](https://github.com/asyncapi/parser-js/blob/master/API.md#Schema+uid). Where `schema` contains the current schema being rendered. Every [Schema object](https://www.asyncapi.com/docs/specifications/2.0.0/#schemaObject) from the entire AsyncAPI file is used.
35
- - `$$objectSchema$$`, within the template-file you have access to two variables [`schema`](https://github.com/asyncapi/parser-js/blob/master/API.md#Schema) and [`schemaName`](https://github.com/asyncapi/parser-js/blob/master/API.md#Schema+uid). Where `schema` contains the current schema being rendered. All the [Schema objects](https://www.asyncapi.com/docs/specifications/2.0.0/#schemaObject) with type object is used.
36
- - `$$parameter$$`, within the template-file you have access to two variables [`parameter`](https://github.com/asyncapi/parser-js/blob/master/API.md#ChannelParameter) and [`parameterName`](https://github.com/asyncapi/parser-js/blob/master/API.md#Channel+parameters). Where `parameter` contains the current parameter being rendered.
37
- - `$$securityScheme$$`, within the template-file you have access to two variables [`securityScheme`](https://github.com/asyncapi/parser-js/blob/master/API.md#SecurityScheme) and [`securitySchemeName`](https://github.com/asyncapi/parser-js/blob/master/API.md#Components+securitySchemes). Where `securityScheme` contains the current security scheme being rendered.
38
-
39
- The file name will be equal to `*Name` variable.
40
-
41
- ### Example
42
-
43
- The file name is `$$schema$$.txt`, the content of this file is:
44
- ```
45
- Schema name is '{{schemaName}}' and properties are:
46
- {% for propName, prop in schema.properties() %}
47
- - {{prop.uid()}}
48
- {% endfor %}
49
- ```
50
-
51
- With following AsyncAPI:
52
- ```
53
- components:
54
- schemas:
55
- peoplePayload:
56
- type: object
57
- properties:
58
- event:
59
- $ref: "#/components/schemas/people"
60
- people:
61
- type: object
62
- properties:
63
- id:
64
- type: integer
65
- ```
66
-
67
- The generator creates two files `peoplePayload.txt` and `people.txt` with the following content:
68
- ```
69
- Schema name is 'peoplePayload' and properties are:
70
- - people
71
- ```
72
-
73
- and
74
- ```
75
- Schema name is 'people' and properties are:
76
- - id
77
- ```
78
-
79
- ### React
80
-
81
- The above way of rendering **file templates** works for both `nunjucks` and `react` render engines, but `react` also has another, more generic way to render multiple files. It is enough to return an array of `File` components in the rendering component. See the following example:
82
-
83
- ```tsx
84
- export default function({ asyncapi }) {
85
- return [
86
- <File name={`file1.html`}>Content</File>,
87
- <File name={`file2.html`}>Content</File>
88
- ]
89
- }
90
- ```
91
-
92
- ## Hooks
93
-
94
- 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.
95
- The following types of hooks are currently supported:
96
-
97
- |Hook type|Description| Return type | Arguments
98
- |---|---|---|---|
99
- | `generate:before` | Called after registration of all filters and before generator starts processing of the template. | void : Nothing is expected to be returned. | [The generator instance](https://github.com/asyncapi/generator/blob/master/docs/api.md)
100
- | `generate:after` | Called at the very end of the generation. | void : Nothing is expected to be returned. | [The generator instance](https://github.com/asyncapi/generator/blob/master/docs/api.md)
101
- | `setFileTemplateName ` | Called right before saving a new file generated by [file template](https://github.com/asyncapi/generator/blob/master/docs/authoring.md#file-templates). | string : a new filename for the generator to use for the file template. | [The generator instance](https://github.com/asyncapi/generator/blob/master/docs/api.md) and object in the form of `{ "originalFilename" : string }`
102
-
103
- The generator parses:
104
- - All the files in the `.hooks` directory inside the template.
105
- - All modules listed in the template configuration and triggers only hooks that names were added to the config. You can use the official AsyncAPI [hooks library](https://github.com/asyncapi/generator-hooks). To learn how to add hooks to configuration [read more about the configuration file](#configuration-file).
106
-
107
- ### Examples
108
-
109
- > Some of examples have name 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).
110
-
111
- Most basic module with hooks looke like this:
112
- ```js
113
- module.exports = {
114
- 'generate:after': generator => console.log('This runs after generation is complete')
115
- }
116
- ```
117
-
118
- Below you have an example Hook that after generation creates an AsyncAPI file.
119
-
120
- ```js
121
- const fs = require('fs');
122
- const path = require('path');
123
-
124
- module.exports = {
125
- 'generate:after': generator => {
126
- const asyncapi = generator.originalAsyncAPI;
127
- let extension;
128
-
129
- try {
130
- JSON.parse(asyncapi);
131
- extension = 'json';
132
- } catch (e) {
133
- extension = 'yaml';
134
- }
135
-
136
- fs.writeFileSync(path.resolve(generator.targetDir, `asyncapi.${extension}`), asyncapi);
137
- }
138
- };
139
- ```
140
- And here an example Hook that before generation switches `publish` and `subscribe` operations for each channel.
141
-
142
- ```js
143
- module.exports = {
144
- 'generate:before': function switchOperations(generator) {
145
- const asyncapi = generator.asyncapi;
146
- for (let [key, value] of Object.entries(asyncapi.channels())) {
147
- let publish = value._json.publish;
148
- value._json.publish = value._json.subscribe;
149
- value._json.subscribe = publish;
150
- if (!value._json.subscribe) {
151
- delete value._json.subscribe;
152
- }
153
- if (!value._json.publish) {
154
- delete value._json.publish;
155
- }
156
- }
157
- };
158
- };
159
- ```
160
-
161
- Example hook for changing the filename of a template file. Replaces all '-' characters with '_'.
162
- ```js
163
- module.exports = {
164
- 'setFileTemplateName': (generator, hookArguments) => {
165
- const currentFilename = hookArguments.originalFilename ;
166
- return currentFilename.replace('-', '_')
167
- };
168
- };
169
- ```
170
-
171
- ## Configuration File
172
-
173
- The `generator` property from `package.json` file must contain a JSON object that may have the following information:
174
-
175
- |Name|Type|Description|
176
- |---|---|---|
177
- |`renderer`| String | Its value can be either `react` or `nunjucks` (default).
178
- |`supportedProtocols`| [String] | A list with all the protocols this template supports.
179
- |`parameters`| Object[String, Object] | An object with all the parameters that can be passed when generating the template. When using the command line, it's done by indicating `--param name=value` or `-p name=value`.
180
- |`parameters[param].description`| String | A user-friendly description about the parameter.
181
- |`parameters[param].default`| Any | Default value of the parameter if not specified. Shouldn't be used for mandatory `required=true` parameters.
182
- |`parameters[param].required`| Boolean | Whether the parameter is required or not.
183
- |`conditionalFiles`| Object[String, Object] | An object containing all the file paths that should be conditionally rendered. Each key represents a file path and each value must be an object with the keys `subject` and `validation`. The file path should be relative to the `template` directory inside the template.
184
- |`conditionalFiles[filePath].subject`| String | The `subject` is a [JMESPath](http://jmespath.org/) query to grab the value you want to apply the condition to. It queries an object with the whole AsyncAPI document and, when specified, the given server. The object looks like this: `{ asyncapi: { ... }, server: { ... } }`. If template supports `server` parameter, you can access server details like for example protocol this way: `server.protocol`. During validation with `conditionalFiles` only the server that template user selected is available in the specification file. For more information about `server` parameter [read about special parameters](#special-parameters).
185
- |`conditionalFiles[filePath].validation`| Object | The `validation` is a JSON Schema Draft 07 object. This JSON Schema definition will be applied to the JSON value resulting from the `subject` query. If validation doesn't have errors, the condition is met, and therefore the given file will be rendered. Otherwise, the file is ignored. Check [JSON Schema Validation](https://json-schema.org/draft-07/json-schema-validation.html#rfc.section.6) document for a list of all possible validation keywords.
186
- |`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.
187
- |`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).
188
- |`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.
189
- |`hooks`| Object[String, String] or Object[String, Array[String]] | A list of modules containing hooks, except of the ones you keep locally in your template in default location. For each module you must specify exact name of the hook that should be used in the template. For single hook you can specify it as a string, for more you must pass an array of strings. In case of external modules, remember they need to be added as a dependency in `package.json` of your template.
190
-
191
- ### Example
192
-
193
- ```json
194
- "generator":
195
- {
196
- "renderer": "react",
197
- "supportedProtocols": ["amqp", "mqtt"],
198
- "parameters": {
199
- "server": {
200
- "description": "The server you want to use in the code.",
201
- "required": true
202
- },
203
- "dummyParameter": {
204
- "description": "Example of parameter with default value.",
205
- "default": "just a string",
206
- "required": false
207
- }
208
- },
209
- "conditionalFiles": {
210
- "path/to/file/that/is/relative/to/template/dir/test-amqp.js": {
211
- "subject": "server.protocol",
212
- "validation": {
213
- "const": "amqp"
214
- }
215
- },
216
- "path/to/file/that/is/relative/to/template/dir/support.html": {
217
- "subject": "info.contact",
218
- "validation": {
219
- "required": ["url"]
220
- }
221
- }
222
- },
223
- "nonRenderableFiles": [
224
- "src/api/middlewares/*.*",
225
- "lib/lib/config.js"
226
- ],
227
- "generator": "<2.0.0",
228
- "filters": [
229
- "@asyncapi/generator-filters"
230
- ],
231
- "hooks": {
232
- "@asyncapi/generator-hooks": "hookFunctionName"
233
- }
234
- }
235
- ```
236
-
237
- ## Special parameters
238
-
239
- There are some template parameters that have a special meaning:
240
-
241
- |Name|Description|
242
- |---|---|
243
- |`server`| It is used to let the template know which server from the AsyncAPI specification file you want to use. In some cases, this may be required. For instance, when generating code that connects to a specific server. Use this parameter in case your template relies on users' information about what server from the specification file they want to use during generation. You also need this parameter if you want to use `server.protocol` notation within `conditionalFiles` configuration option. Once you decide to specify this parameter for your template, it is recommended you make it a mandatory parameter otherwise feature like `conditionalFiles` is not going to work if your users do not use this parameter obligatory.
244
-
245
- ## React
246
-
247
- [React](https://reactjs.org) is the render engine that we strongly suggest you should use for any new templates. The only reason it is not the default render engine is to stay backward compatible.
248
-
249
- * It enables the possiblity of [debugging](#debugging-react-template) your template (this is not possible with Nunjucks).
250
- * It provides better error stack traces.
251
- * Provides better support for separating code into more manageable chunks/components.
252
- * The readability of the template is much better compared to Nunjucks syntax.
253
- * Better tool support for development.
254
- * Introduces testability of components which is not possible with Nunjucks.
255
-
256
- When writing React templates you decide whether to use CommonJS, ES5, or ES6 modules since everything is bundled together before the rendering process takes over. We use our own React renderer which can be found in the [Generator React SDK](https://github.com/asyncapi/generator-react-sdk).
257
- There you can find information about how the renderer works or how we transpile your template files.
258
-
259
- Your React template always require `@asyncapi/generator-react-sdk` as a dependency. `@asyncapi/generator-react-sdk` is required to access the `File` component which is required as a root component for a file to be rendered. Furthermore it provides some common components to make your development easier, like `Text` or `Indent`.
260
-
261
- Let's consider a basic React template as the one below called `MyTemplate.js`:
262
-
263
- ```js
264
- import { File, Text } from "@asyncapi/generator-react-sdk";
265
-
266
- export default function({ asyncapi, params, originalAsyncAPI }) {
267
- return (
268
- <File name="asyncapi.md">
269
- <Text>Some text that should render as is</Text>
270
- </File>
271
- );
272
- }
273
- ```
274
-
275
- The exported default function returns a `File` component as a root component which the [Generator](https://github.com/asyncapi/generator) uses to figure out what file should be generated. In our case we overwrite the default functionality of saving the file as `MyTemplate.js` but instead use the filename `asyncapi.md`. It is then specified that we should render `Some text that should render as is\n` within that file. Notice the `\n` character at the end, this is something that is automatically added after the `Text` component.
276
-
277
- For further information about components, props etc. see the [Generator React SDK](https://github.com/asyncapi/generator-react-sdk)
278
-
279
- ### Common assumptions
280
-
281
- 1. Generator renders all files located in the `template` directory if they meet the following conditions:
282
- - `File` is the root component
283
- - The file is not in the list of `nonRenderableFiles` in the template configuration
284
- 1. New lines are automatically added after each `Text` component.
285
- 1. The props you have access to in rendering function is:
286
- - `asyncapi` that is a parsed spec file object. Read the [API](https://github.com/asyncapi/parser-js/blob/master/API.md#AsyncAPIDocument) of the Parser to understand to what structure you have access in this parameter.
287
- - `originalAsyncAPI` that is an original spec file before it is parsed.
288
- - `params` that contains the parameters provided when generating.
289
- 1. All the file templates are supported where the variables are provided after the default props as listed above.
290
-
291
- ### Debugging React template in VSCode
292
-
293
- With React, it enables you to debug your templates. For Visual Studio Code, we have created a boilerplate [launch configuration](https://code.visualstudio.com/docs/editor/debugging#_launch-configurations) to enable debug in your template. Add the following launch configuration:
294
-
295
- ```json
296
- {
297
- "version": "0.2.0",
298
- "configurations": [
299
- {
300
- "type": "node",
301
- "request": "launch",
302
- "name": "Debug template",
303
- "timeout": 10000,
304
- "sourceMaps": true,
305
- "args": [
306
- "./asyncapi.yml",
307
- "./template",
308
- "--output",
309
- "./output",
310
- "--install",
311
- "--force-write"
312
- ],
313
- "program": "ag"
314
- }
315
- ]
316
- }
317
- ```
318
-
319
- Now replace `./asyncapi.yml` with your document of choice. Replace `./template` with the path to your React template. You can now debug your template by adding any breakpoints you want and inspect your code.
320
-
321
- ## Nunjucks
322
-
323
- [Nunjucks](https://mozilla.github.io/nunjucks) is the default render engine, however, we strongly recommend adopting the [React](#react) engine.
324
-
325
- ### Common assumptions
326
-
327
- 1. Templates may contain [Nunjucks filters or helper functions](https://mozilla.github.io/nunjucks/templating.html#builtin-filters). [Read more about filters](#filters).
328
- 1. Templates may contain `partials` (reusable chunks). They must be stored in the `.partials` directory under the template directory. [Read more about partials](#partials).
329
- 1. Templates may contain multiple files. Unless stated otherwise, all files will be rendered.
330
- 1. The default variables you have access to in any the template file are the following:
331
- - `asyncapi` that is a parsed spec file object. Read the [API](https://github.com/asyncapi/parser-js/blob/master/API.md#AsyncAPIDocument) of the Parser to understand to what structure you have access in this parameter.
332
- - `originalAsyncAPI` that is an original spec file before it is parsed.
333
- - `params` that contains the parameters provided when generating.
334
-
335
- ### Partials
336
-
337
- 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:
338
-
339
- ```html
340
- {# tags.html #}
341
- {% macro tags(tagList) %}
342
- <div class="mt-4">
343
- {% for tag in tagList %}
344
- <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>
345
- {% endfor %}
346
- </div>
347
- {% endmacro %}
348
-
349
- {# operations.html #}
350
- {% from "./tags.html" import tags %}
351
- {{ tags(operation.tags()) }}
352
- ```
353
-
354
- ### Filters
355
-
356
- 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.
357
-
358
- You can use the filter function in your template as in the following example:
359
-
360
- ```js
361
- const {{ channelName | camelCase }} = '{{ channelName }}';
362
- ```
363
-
364
- The generator also supports asynchronous filters. Asynchronous filters receive as 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:
365
-
366
- ```js
367
- const filter = module.exports;
368
-
369
- async function asyncCamelCase(str, callback) {
370
- try {
371
- const result = // logic for camel casing str
372
- callback(null, result);
373
- } catch (error) {
374
- callback(error);
375
- }
376
- }
377
- filter.renderAsyncContent = renderAsyncContent;
378
-
379
- // using in template
380
- {{ channelName | asyncCamelCase }}
381
- ```
382
-
383
- Unfornatelly, if you need to use Promise, filter still must be annotated with the `async` keyword:
384
-
385
- ```js
386
- async function asyncCamelCase(str, callback) {
387
- return new Promise((resolve, reject) => {
388
- // logic with callback
389
- });
390
- }
391
- ```
392
-
393
- 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. You can also use the official AsyncAPI [filters library](https://github.com/asyncapi/generator-filters). To learn how to add such filters to configuration [read more about the configuration file](#configuration-file).
394
-
395
- ## TypeScript support
396
-
397
- The AsyncAPI generator has TypeScript support for [hooks](#hooks) and Nunjucks's [filters](#filters). Assumptions:
398
-
399
- - Installing the `typescript` package and creating the` tsconfig.json` file isn't necessary.
400
- - Source code of the hook/filter must have `.ts` extension.
401
- - Each package related to the typings for TypeScript like `@types/node` must be installed in the template under `dependencies` array. This is because the Generator transpiles the TypeScript code on-the-fly while rendering the template, and cannot use packages under `devDependencies`.
402
- - Each template should have `@types/node` package installed to enable support for typings for Node.
@@ -1,110 +0,0 @@
1
- # Templates recipes
2
-
3
- In this document you can find recipes for templates that you might want to copy and reuse them for your need to speed up template development. Feel free to create a Pull Request with your recipe.
4
-
5
- ## Prerequisites
6
-
7
- You must be familiar with [Nunjucks](https://mozilla.github.io/nunjucks/) templating engine and [how it is supported in the generator](./authoring.md).
8
-
9
- ## Recipes
10
-
11
- - [Using Schema objects to generate types for a given programming language](#using-schema-objects-to-generate-types-for-a-given-programming-language)
12
- - [Displaying separate lists for different channels operations](#displaying-separate-lists-for-different-channels-operations)
13
-
14
- ### Using Schema objects to generate types for a given programming language
15
-
16
- * Java example where `$$schema$$.java` file looks like this:
17
- ```java
18
- package com.async.generated;
19
-
20
- public class {{schema.uid()}} {
21
-
22
- {%- for propertyName, property in schema.properties() %}
23
- public {{property.type() | toJavaType}} {{propertyName}};
24
- {%- endfor %}
25
- public {{schema.uid()}}(
26
- {%- set counter = 0 %}
27
- {%- for propertyName, property in schema.properties() %}
28
- {%- if property.required()%}
29
- {%- if counter == schema.properties().length %}
30
- {{ property.type() | toJavaType }} {{ propertyName }}
31
- {%- else %}
32
- {{ property.type() | toJavaType }} {{ propertyName }},
33
- {%- endif %}
34
- {%- set counter = counter +1 %}
35
- {%- endif %}
36
- {%- endfor %}) {
37
- {%- for propertyName, property in schema.properties() %}
38
- {%- if property.required()%}
39
- this.{{ propertyName }}={{ propertyName }};
40
- {%- endif %}
41
- {%- endfor %}
42
- }
43
- }
44
- ```
45
- The `toJavaType` filter:
46
- ```js
47
- Nunjucks.addFilter('toJavaType', jsonSchemaType => {
48
- switch (jsonSchemaType.toLowerCase()) {
49
- case 'string':
50
- return 'String';
51
- case 'integer':
52
- return 'Integer'
53
- case 'number':
54
- return 'Double';
55
- case 'boolean':
56
- return 'boolean';
57
- }
58
- });
59
- ```
60
- * Nodejs example where `$$schema$$.js` file looks like this:
61
- ```js
62
- export default class {{ schema.name() }} {
63
- {%- for propertyName, property in schema.properties() %}
64
- {%- if property.required()%}
65
- public {{ propertyName }}:{{ property.type() }};
66
- {%- else %}
67
- public {{ propertyName }}?:{{ property.type() }};
68
- {%- endif %}
69
- {%- endfor %}
70
- constructor(
71
- {%- set counter = 0 %}
72
- {%- for propertyName, property in schema.properties() %}
73
- {%- if property.required()%}
74
- {%- if counter == schema.properties().length %}
75
- {{ propertyName }}:{{ property.type() }}
76
- {%- else %}
77
- {{ propertyName }}:{{ property.type() }},
78
- {%- endif %}
79
- {%- set counter = counter +1 %}
80
- {%- endif %}
81
- {%- endfor %}
82
- ) {
83
- {%- for propertyName, property in schema.properties() %}
84
- {%- if property.required()%}
85
- this.{{ propertyName }}={{ propertyName }};
86
- {%- endif %}
87
- {%- endfor %}
88
- }
89
- }
90
- ```
91
-
92
- ### Displaying separate lists for different channels operations
93
-
94
- * HTML example that renders two separate containers, one with `publish` and second with `subscribe` operations:
95
- ```html
96
- {% for channelName, channel in asyncapi.channels() %}
97
- <div class="responsive-container">
98
- {% if channel.hasPublish() %}
99
- {{ channelName }}
100
- {{ channel | dump }}
101
- {% endif %}
102
- </div>
103
- <div class="responsive-container">
104
- {% if channel.hasSubscribe() %}
105
- {{ channelName }}
106
- {{ channel | dump }}
107
- {% endif %}
108
- </div>
109
- {% endfor %}
110
- ```